Reputation: 45
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).
Upvotes: 0
Views: 1038
Reputation: 35923
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.
Upvotes: 5