碎片着色器的纹理值错误

Texture wrong value in fragment shader

本文关键字:纹理 错误 碎片      更新时间:2023-10-16

我正在加载自定义数据到2D纹理GL_RGBA16F:

glActiveTexture(GL_TEXTURE0);
int Gx = 128;
int Gy = 128;
GLuint grammar;
glGenTextures(1, &grammar);
glBindTexture(GL_TEXTURE_2D, grammar);
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA16F, Gx, Gy);
float* grammardata = new float[Gx * Gy * 4](); // set default to zero
*(grammardata) = 1; 
glTexSubImage2D(GL_TEXTURE_2D,0,0,0,Gx,Gy,GL_RGBA,GL_FLOAT,grammardata);
int grammarloc = glGetUniformLocation(p_myGLSL->getProgramID(), "grammar");
if (grammarloc < 0) {
    printf("grammar missing!n");
    exit(0);
}
glUniform1i(grammarloc, 0);

当我在GLSL中读取uniform sampler2D语法的值时,它返回0.25而不是1。如何解决缩放问题?

if (texture(grammar, vec2(0,0) == 0.25) {
    FragColor = vec4(0,1,0,1);
} else
{
    FragColor = vec4(1,0,0,1);
}

默认情况下纹理插值设置为以下值:

GL_TEXTURE_MIN_FILTER = GL_NEAREST_MIPMAP_LINEAR,
GL_TEXTURE_MAG_FILTER = GL_LINEAR
GL_WRAP[R|S|T] = GL_REPEAT

这意味着,在屏幕上纹理和像素之间的映射不匹配的情况下,硬件插值将为您进行插值。有两种情况:

  • 纹理显示比实际小:在这种情况下,在两个mipmap级别之间执行插值。如果没有生成mipmaps,这些将被视为0,这可能导致0.25。

  • 纹理显示的比实际大(我认为这将是这里的情况):在这里,硬件不会在mipmap级别之间插入,而是在纹理中相邻的纹理之间插入。现在的问题是,纹理坐标中的(0,0)是不是像素[0,0]的中心,而是它的左下角。

看一下下面的图,它说明了纹理坐标是如何定义的(这里有4个纹理)

tex-coord:   0          0.25        0.5         0.75         1
texels       |-----0-----|-----1-----|-----2-----|-----3-----|

正如你所看到的,0是在一个texel的边界上,而第一个texels的中心是(1/(2 * |texels|))。

这对你来说意味着,将wrap模式设置为GL_REPEAT,纹理坐标(0,0)将在纹理[0,0],[-1,0],[-1,-1],[0,-1]之间均匀地插值。由于-1 == 127(由于重复)和除[0,0]之外的所有内容都为0,因此结果为

([0,0] + [-1,0] + [-1,-1] + [0,-1]) / 4 =
   1   +    0   +    0    +   0   ) / 4 = 0.25