My problem is getting more than one texture accessible in a GLSL shader. Here's what I'm doing:
Shader:
uniform sampler2D sampler0;
uniform sampler2D sampler1;
uniform float blend;
void main( void )
{
vec2 coords = gl_TexCoord[0];
vec4 col = texture2D(sampler0, coords);
vec4 col2 = texture2D(sampler1, coords);
if (blend > 0.5){
gl_FragColor = col;
} else {
gl_FragColor = col2;
}
};
So, I simply choose between the two color values based on a uniform variable. Simple enough (this is a test), but instead of the expected behavior, I get all black when blend <= 0.5.
OpenGL code:
m_sampler0location = m_shader.FindUniform("sampler0");
m_sampler1location = m_shader.FindUniform("sampler1");
m_blendlocation = m_shader.FindUniform("blend");
glActiveTexture(GL_TEXTURE0);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler0location, 0);
glBindTexture(GL_TEXTURE_2D, Texture0.Handle);
glActiveTexture(GL_TEXTURE1);
glEnable(GL_TEXTURE_2D);
m_extensions.glUniform1iARB(m_sampler1location, 1);
glBindTexture(GL_TEXTURE_2D, Texture1.Handle);
glBegin(GL_QUADS);
//lower left
glTexCoord2f(0, 0);
glVertex2f(-1.0, -1.0);
//upper left
glTexCoord2f(0, maxCoords0.t);
glVertex2f(-1.0, 1.0);
//upper right
glTexCoord2f(maxCoords0.s, maxCoords0.t);
glVertex2f(1.0, 1.0);
//lower right
glTexCoord2f(maxCoords0.s, 0);
glVertex2f(1.0, -1.0);
glEnd()
The shader is compiled and bound before all this. All the sanity checks in that process indicate that it goes ok.
As I said, the value of Fixed according to Bahbar's reply.col
in the shader program reflects fragments from a texture; the value of col2
is black. The texture that is displayed is the last active texture - if I change the last glBindTexture
to bind Texture0.Handle
, the texture changes.
As it is, the scene renders all black, even if I add something like gl_FragColor.r = blend;
as the last line of the shader. But, if I comment out the call glActiveTexture(GL_TEXTURE1);
, the shader works again, and the same texture appears in both sampler0 and sampler1.
What's going on? The line in question, glActiveTexture(GL_TEXTURE1);
, seems to work just fine, as evidenced by a subsequent glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)
. Why does it break everything so horribly? I've already tried upgrading my display drivers.
When compiling your shader to test, I found two errors:
coords
should be assigned thest
portion of the 4-componentgl_TexCoord
, e.g.The shader should not end with a semicolon.
Are you checking anywhere in your main program that shader compiles correctly? You may want to look at
GL_COMPILE_STATUS
viaglGetShader
andglGetShaderInfoLog
.It sounds like your
glActiveTexture
call does not work. Are you sure you set up the function pointer correctly ?Verify by calling
glGetIntegerv(GL_ACTIVE_TEXTURE, &anint)
after having called your glActiveTexture(GL_TEXTURE1).Also
glEnable(GL_TEXTURE_2D)
are not useful. The shader itself specifies what texture units to use, and which target of each unit to "enable".Edit to add:
Well, your new situation is peculiar. The fact that you can't even show red is weird, in particular (well, did you set alpha to 1 just to make sure ?).
That said, you should restore GL_TEXTURE0 as the
glActiveTexture
after you're done setting the texture unit 1 (i.e. after theglBindTexture
call).Just to help other people who might be interested in using multiple textures and will feel hopeless after days searching for an answer. I found that you need to call
In that order for it to work (glUseProgram is the last instruction for 99% of the sample code I've found online). Now it may be only the case for me and not affect anyone else on Earth, but just in case I thought I'd share.
Quite late reply, but for anybody encountering this - I encountered same problem and after short fiddling, I realized that calling
glActiveTexture(GL_TEXTURE0)
fixes the issue. It seems something down the line gets confused if active texture unit is not 'reset' to zero. This could be system-dependent behavior; I'm running 64bit Archlinux with Mesa 8.0.4.Here's a basic GLUT example (written on OS X, adapt as needed) that generates two checkerboard textures, loads a shader with two samplers and combines them by tinting each (one red, one blue) and blending. See if this works for you:
Hopefully the result will look something like this (you can comment out the
glUseProgram
call to see the first texture drawn without the shader):