¿Cómo puedo almacenar valores positivos y negativos en una textura?
Estoy creando un programa en el que estoy usando la GPU para hacer cálculos (a través de sombreadores de fragmentos) y necesito almacenar valores firmados dentro de las texturas.
Mi textura se inicializa con GL_FLOAT, así:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);
Y por lo que entiendo sobre opengl, los texels individuales deben estar en el rango [0,1] cuando se usa GL_FLOAT (cuando experimenté con glClear, mis valores se recortarían a este rango). Entonces, lo que he estado haciendo hasta ahora es escalar mis valores al rango [-1,1] basado en su rango real, luego convertirlo a [0,1] antes de volver a escribirlo en la textura. El siguiente sombreador que necesita trabajar con los datos lee el valor de texel y lo mueve a [-1,1] antes de continuar y así sucesivamente ...
Mi pregunta es, ¿es esta la forma correcta de lidiar con los valores negativos? Estoy bastante seguro de que las conversiones repetidas están haciendo que se acumulen errores de fp, lo que obviamente no es bueno para la precisión.
Gracias
Respuestas
Ver también: Diferencia entre formato y formato interno
El formato interno (tercer parámetro de glTexImage2D
) decide cómo la GPU almacena e interpreta esos valores, no el parámetro de tipo de glTexImage2D
(penúltimo parámetro). Ese parámetro decide cómo debe interpretar el controlador la memoria del lado del cliente / host al cargar la textura, que actualmente no usa nullptr
.
Puede utilizar el formato interno de tamaño de coma flotante firmado de 8 bits GL_RGBA8_SNORM
o de 16 bits o de coma flotante de GL_RGBA16F
32 bits para la textura.GL_RGBA32F
Por lo general, siempre se debe usar un tamaño de formato interno a ser explícito en lo que quiere y obtener.
Vea la tabla en: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml
Entonces, si solo necesita una resolución de 8 bits y valores en el rango [-1, 1], entonces puede usar:
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_SNORM, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
El penúltimo argumento es realmente irrelevante, porque no estamos cargando ningún dato de texto a la textura.