碎片着色器不起作用的多个纹理单元

Multiple texture units with fragment shader not working

本文关键字:纹理 单元 不起作用 碎片      更新时间:2023-10-16

我需要显示一些索引图形文件,该文件还具有每个像素的alpha通道。此外,我需要确保我可以随时更改调色板,生成的图像也会更改。为此,我首先使用软件像素预计算,但这对于实时渲染来说太慢了,所以我决定编写一个着色器,在GPU端处理索引纹理。问题是第二个纹理(rec_colors)没有加载(至少看起来是这样——从采样器读取的每个texel看起来都是空的)。

来自零纹理的数据读取正确,导致具有右alpha的黑色图像:)

着色器初始化相关代码:

Application::Display->GetRC();
glewInit();
if(!GLEW_VERSION_2_0) return false;
char* code_frag = loadCode("shader.frag");
char* code_verx = loadCode("shader.verx");
aShader_palette = glCreateShader(GL_FRAGMENT_SHADER);
//glShaderSource(aShader_palette, 1, &aShaderProgram_palette, NULL);
glShaderSource(aShader_palette, 1, (const GLchar**)&code_frag, NULL);
glCompileShader(aShader_palette);
GLint compiled = 0;
glGetShaderiv(aShader_palette, GL_COMPILE_STATUS, &compiled);
if(!compiled)
{
    /* error-handling */
}
GLuint texloc = glGetUniformLocation(aShader_palette, "rec");
glUniform1i(texloc, 0);
texloc = glGetUniformLocation(aShader_palette, "rec_colors");
glUniform1i(texloc, 1);
glsl_palette_Program = glCreateProgram();
glAttachShader(glsl_palette_Program, aShader_palette);
glLinkProgram(glsl_palette_Program);

与渲染相关:

glPushAttrib(GL_CURRENT_BIT);
glColor4ub(255, 255, 255, t_a); // t_a is overall alpha of sprite displayed
glUseProgram(glsl_palette_Program); // this one is a compiled/linked shader declared above
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->m_SpriteData[idx].texture);
glActiveTexture(GL_TEXTURE1); // at this point, it looks like texture unit is actually changed (I checked that via glGetIntegerv)
glBindTexture(GL_TEXTURE_RECTANGLE_ARB, this->m_PaletteTex);
glTexSubImage2D(GL_TEXTURE_RECTANGLE_ARB, 0, 0, 0, 256, 1, GL_RGBA, GL_UNSIGNED_BYTE, palette); // update possibly changed palette on each render
glActiveTexture(GL_TEXTURE0);
glBegin(GL_QUADS);
    glTexCoord2i(0, 0);
    glVertex2i(x, y);
    glTexCoord2i(0, this->GetHeight(idx));
    glVertex2i(x, y+this->GetHeight(idx));
    glTexCoord2i(this->GetWidth(idx), this->GetHeight(idx));
    glVertex2i(x+this->GetWidth(idx), y+this->GetHeight(idx));
    glTexCoord2i(this->GetWidth(idx), 0);
    glVertex2i(x+this->GetWidth(idx), y);
glEnd();
glActiveTexture(GL_TEXTURE1);
glUnbindTexture(GL_TEXTURE_RECTANGLE_ARB); // custom macro
glActiveTexture(GL_TEXTURE0);
glUnbindTexture(GL_TEXTURE_RECTANGLE_ARB);
glUseProgram(0);
glPopAttrib();

着色器代码:

#extension GL_ARB_texture_rectangle : enable
uniform sampler2DRect rec;
uniform sampler2DRect rec_colors;
void main(void)
{
    vec4 oldcol = texture2DRect(rec, gl_TexCoord[0].st);
    vec4 newcol = texture2DRect(rec_colors, vec2(oldcol.r*255.0, 0.0)); // palette index should be*255 bcs rectangle coordinates aren't normalized
    gl_FragColor.rgb = newcol.rgb;
    gl_FragColor.a = oldcol.g; // alpha from green part
}

在谷歌上搜索了很多,我发现的任何类似的帖子都是通过修复glUniform1i调用中的纹理单元ID来解决的,但对我来说,这看起来绝对正常(至少,TEXTURE0正确加载到rec中)。

是否使用glGetError检查任何位置的错误?我相信你做错了什么。glGetUniformLocation应该针对链接程序而不是着色器执行。在链接程序之前,您正在调用glGetUniformLocation

请参阅手册页中的相关文本:http://www.opengl.org/wiki/GLAPI/glGetUniformLocation

The actual locations assigned to uniform variables are not known until the program object is linked successfully. After linking has occurred, the command glGetUniformLocation can be used to obtain the location of a uniform variable. Uniform variable locations and values can only be queried after a link if the link was successful.

在开发过程中,您至少应该使用glGetError每帧检查一次opengl错误。它会在你必须上网寻求帮助之前提醒你这些问题。