简体   繁体   中英

Multiple texture units with fragment shader not working

I need to display some indexed graphic file, that additionally has per-pixel alpha channel. Also, I need to make sure that I can change the palette at any time and the resulting image will also change. For this, I first used software pixel precomputing, but that was just too slow for realtime rendering, so I decided to write a shader that will handle indexed textures on GPU-side. The problem is that the second texture (rec_colors) doesn't load (at least it seems like so — every texel read from that sampler appears completely empty).

Data from zero texture reads correctly, resulting in black image with right alpha :)

Shader-initializing-related code:

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);

And rendering-related:

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();

Shader code:

#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
}

Googled a lot, any similar posts I found were solved by fixing texture unit IDs in glUniform1i call, but for me that looks absolutely normal (at least, TEXTURE0 loads correctly into rec).

Do you check for errors anywhere with glGetError ? I belive you're doing something incorrectly. glGetUniformLocation is supposed to be executed against a linked program, not a shader. You're calling glGetUniformLocation before your program is linked.

See relevant text from man page: 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.

You should always at the very least check for opengl errors with glGetError once per frame during development. It will alert you to these problems before you have to go online to ask for help.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM