如何在纹理中存储正值和负值?

How can I store positive and negative values in a texture?

我正在创建一个程序,我在其中使用 GPU 进行计算(通过片段着色器)并且需要在纹理中存储带符号的值。

我的纹理是用 GL_FLOAT 初始化的,像这样:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_FLOAT, nullptr);

根据我对 opengl 的了解,当使用 GL_FLOAT 时,单个纹素必须在 [0,1] 范围内(当我尝试使用 glClear 时,我的值将被剪裁到这个范围内)。所以到目前为止我一直在做的是根据它们的实际范围将我的值缩小到范围 [-1,1],然后在将其写回纹理之前将其转换为 [0,1]。下一个需要处理数据的着色器读取纹素值并将其移动到 [-1,1],然后继续等等...

我的问题是,这是处理负值的正确方法吗?我很确定重复转换会导致 fp 错误累积,这显然不利于准确性。

谢谢

另请参阅:

内部格式glTexImage2D的第三个参数)决定GPU如何存储和解释这些值,而不是类型 glTexImage2D 的参数(倒数第二个参数)。该参数决定驱动程序在上传到纹理时应如何解释您的 client/host-side 内存,您目前不使用 nullptr.

您可以使用带符号的 8 位 GL_RGBA8_SNORM 或 16 位浮点 GL_RGBA16F 或 32 位浮点 GL_RGBA32F 大小的 内部格式 用于纹理。

一般来说,您应该始终使用大小的内部格式来明确您想要什么和得到什么。

查看 table 上的内容:https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glTexImage2D.xhtml

因此,如果您只需要 8 位分辨率,并且值在 [-1, 1] 范围内,那么您可以使用:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8_SNORM, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);

倒数第二个参数实际上是无关紧要的,因为我们没有向纹理上传任何纹素数据。