Jak mogę przechowywać wartości dodatnie i ujemne w teksturze?

Dec 03 2020

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

1 httpdigest Dec 03 2020 at 15:04

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_SNORMlub 16-bitowe zmiennoprzecinkowe GL_RGBA16Flub 32-bitowe zmiennoprzecinkowe GL_RGBA32Fwielkoś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.