Jak mogę przechowywać wartości dodatnie i ujemne w teksturze?
Tworzę program, w którym używam GPU do wykonywania obliczeń (za pomocą fragmentów shaderów) i muszę przechowywać podpisane wartości w teksturach.
Moja tekstura jest inicjalizowana za pomocą GL_FLOAT, na przykład:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
Z tego, co rozumiem na temat opengl, poszczególne teksele muszą znajdować się w zakresie [0,1], gdy używany jest GL_FLOAT (kiedy eksperymentowałem z glClear, moje wartości byłyby przycinane do tego zakresu). Więc to, co robiłem do tej pory, to skalowanie moich wartości do zakresu [-1,1] w oparciu o ich rzeczywisty zakres, a następnie konwertowanie tego na [0,1] przed zapisaniem z powrotem do tekstury. Następny moduł cieniujący, który musi pracować z danymi, odczytuje wartość texel i przenosi ją do [-1,1] przed kontynuowaniem i tak dalej ...
Moje pytanie brzmi: czy to właściwy sposób radzenia sobie z wartościami negatywnymi? Jestem prawie pewien, że powtarzające się konwersje powodują kumulację błędów FP, co oczywiście nie jest dobre dla dokładności.
Dziękuję Ci
Odpowiedzi
Zobacz też: Różnica między formatem a formatem wewnętrznym
Wewnętrzny format (trzeci parametr glTexImage2D
) decyduje, jak sklepy GPU i interpretuje te wartości, a nie rodzaj parametru glTexImage2D
(sekundy do ostatniego parametru). Ten parametr decyduje o tym, jak sterownik powinien interpretować pamięć po stronie klienta / hosta podczas przesyłania do tekstury, której obecnie nie używasz nullptr
.
Można użyć podpisanego 8-bitowe GL_RGBA8_SNORM
lub 16-bitowe zmiennoprzecinkowe GL_RGBA16F
lub 32-bitowe zmiennoprzecinkowe GL_RGBA32F
wielkości formatu wewnętrznego na fakturze.
Ogólnie rzecz biorąc, należy zawsze używać rozmiaru wewnętrznego formatu, aby jasno określić, czego chcesz i co otrzymujesz.
Zobacz tabelę: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
Więc jeśli potrzebujesz tylko rozdzielczości 8-bitowej i wartości z zakresu [-1, 1], możesz użyć:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_SNORM, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
Przedostatni argument jest właściwie nieistotny, ponieważ nie przesyłamy żadnych danych texel do tekstury.