Search code examples
c++openglglslshadertextures

Why binding 2 openGL sampler1d texture doesn't work?


I want to pass two 1d textures into my fragment shader. I am creating two sampler1d textures, bind them to my shader program but seems that both samplers use same texture. When I use sampling texelFetch for texture1 it takes wrong color I have defined in texture2.

Following Shader program returns me GREEN screen when I expect to see RED one. Playing parameters I see that any changes in buf for texture1 changes color for texture2. Any ideas how to fix?

#version 330 core

out vec4 FragColor;
in vec2 TexCoord;

uniform sampler2D texture0; //this is default-bound texture0, works fine
uniform sampler1D texture1; //this is bound manually with constant RED color
uniform sampler1D texture2; //this is bound manually with constant GREEN color

void main()
{
    vec4 col1 = texelFetch(texture1, 0, 0);
    FragColor = col1; //should be Red, but in reality it returns GREEN from texture2 =(
}

Heres is my code binding shader samplers to real textures:

GLuint tex1Id;    
glGenTextures(1, &tex1Id );
glBindTexture(GL_TEXTURE_1D, tex1Id);

GLuint tex2Id ;
glGenTextures(1, &tex2Id );
glBindTexture(GL_TEXTURE_1D, tex2Id );

//red color for texture1
GLsizei size = 1;
uint8_t* buf = new uint8_t[size * 4];
buf[0] = 255;
buf[1] = 0;
buf[2] = 0;
buf[3] = 100;

//green color for texture1
uint8_t* buf2 = new uint8_t[size * 4];
buf2[0] = 0;
buf2[1] = 255;
buf2[2] = 0;
buf2[3] = 100;

GLint tex1loc = glGetUniformLocation(shader->ID, "texture1");
GLint tex2loc = glGetUniformLocation(shader->ID, "texture2");

glUniform1i(tex1loc, 1); // RED for texture1
glUniform1i(tex2loc, 2); // GREEN for texture2

glActiveTexture(GL_TEXTURE0 + 1); //RED
glBindTexture(GL_TEXTURE_1D, tex1Id);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf);

glActiveTexture(GL_TEXTURE0 + 2); //GREEN
glBindTexture(GL_TEXTURE_1D, tex2Id);
glTexImage1D(GL_TEXTURE_1D, 0, GL_RGBA, size, 0, GL_RGBA, GL_UNSIGNED_BYTE, buf2);

delete[] buf;
delete[] buf2;

Solution

  • Actually, the bind point for both texture sampler uniforms (texture1 and texture2) is the default (0) as the bind point is never set. glUniform specify the value of a uniform variable in the default uniform block of the currently installed program object. The uniform location is just a number that addresses a uniform in a program, but does not specify the program.
    Since tex2Id is the 2nd texture created, it is bound to texture units 0 and 2. Hence both samplers (texture1 and texture2) look up in the texture object tex2Id.

    You must install the program with glUseProgram before calling glUniform1i:

    glUseProgram(shader->ID);
    glUniform1i(tex1loc, 1); // RED for texture1
    glUniform1i(tex2loc, 2); // GREEN for texture2
    

    As of OpenGL 4.1 you can alternatively use glProgramUniform:

    glProgramUniform1i(shader->ID, tex1loc, 1); // RED for texture1
    glProgramUniform1i(shader->ID, tex2loc, 2); // GREEN for texture2