内部格式为 GL_RGBA8 的纹理在片段着色器中显示为浮点数

Posted

技术标签:

【中文标题】内部格式为 GL_RGBA8 的纹理在片段着色器中显示为浮点数【英文标题】:texture with internal format GL_RGBA8 turns up in fragment shader as float 【发布时间】:2021-02-04 00:06:40 【问题描述】:

我用这个调用创建了一个纹理:

glTexImage2D(GL_TEXTURE_2D, 0,GL_RGBA8, w, h, 0,GL_RGBA, GL_UNSIGNED_BYTE, 0);

我用深灰色渲染纹理:

glColor3ub(42, 42, 42);
glBegin()...

现在我使用自定义着色器将此纹理渲染到后台缓冲区。在片段中,我像这样访问纹理:

#version 130
#extension GL_EXT_gpu_shader4 : require
uniform usampler2D text_in;

并使用以下方法获取数据:

uvec4 f0 = texture(text_in, gl_TexCoord[0].st);

我希望f0[0] 中的值是42u,但它是1042852009u,恰好是

float x = 42/255.0f;
unsigned i = *reinterpret_cast<int*>(&x);

我做错了什么?我想使用整数纹理,以便在片段着色器中可以将像素值与精确的整数值进行比较。我知道渲染到纹理效果很好,因为如果我在没有自定义着色器的情况下将纹理渲染到后台缓冲区,我会得到预期的 42 灰色。

【问题讨论】:

【参考方案1】:

RGBA8 格式是无符号的normalized 格式。因此,当您读取/写入它时,它会被视为浮点格式,其值限制在 [0, 1] 范围内。归一化值基本上只是压缩的浮点数。

如果您想要unsigned integer format,您正在寻找GL_RGBA8UI。请注意,使用glTexImage2D 时,还必须在pixel transfer format field 中使用GL_RGBA_INTEGER

【讨论】:

...纹理是透明的。 glCheckFramebufferStatus 不报告任何错误。 glClearColor(0,1,0,1);glClear(GL_COLOR_BUFFER_BIT); 实际上按预期将纹理清除为[0,255,0,255],但glColor3ub + glBegin... 不会修改纹理。 现在可以了。我还需要一个自定义片段着色器来渲染整数纹理。但是我还是不知道glColor设置的颜色是怎么从shader里面获取的,所以我用glGetUniformLocationglUniform4ui来设置颜色。 @XPlatformer: "我仍然不知道如何从着色器内部访问 glColor 设置的颜色" 如果您正在使用整数纹理等功能,那么是时候抛弃兼容 GL 的世界了(比如glBegin/glColor)并编写核心 OpenGL 的东西。

以上是关于内部格式为 GL_RGBA8 的纹理在片段着色器中显示为浮点数的主要内容,如果未能解决你的问题,请参考以下文章

在着色器中解释纹理数据

片段着色器中未使用纹理数据 - OpenGL

在片段着色器中丢失纹理定义

纹理上的片段着色器

从片段着色器中的地形高程数据计算法线

在着色器中使用 glTexture