Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple textures in GLSL - only one works

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 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. Fixed according to Bahbar's reply.

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.

like image 684
appas Avatar asked Aug 25 '10 18:08

appas


3 Answers

When compiling your shader to test, I found two errors:

  1. coords should be assigned the st portion of the 4-component gl_TexCoord, e.g.

    vec2 coords = gl_TexCoord[0].st;
    
  2. 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 via glGetShader and glGetShaderInfoLog.

like image 189
bosmacs Avatar answered Nov 02 '22 11:11

bosmacs


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

glUseProgram(program);

GLuint t1Location = glGetUniformLocation(program, "tex1");
GLuint t2Location = glGetUniformLocation(program, "tex2");

glUniform1i(t1Location, 0);
glUniform1i(t2Location, 1);

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.

like image 20
Jérémy Riviere Avatar answered Nov 02 '22 10:11

Jérémy Riviere


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.

like image 30
John Avatar answered Nov 02 '22 09:11

John