3

I'm working on some examples, and I was trying to pass a texture to a shader.

To build a VAO, I have this piece of code:

void PlaneShaderProgram::BuildVAO()
{
    // Generate and bind the vertex array object
    glGenVertexArrays(1, &_vao);
    glBindVertexArray(_vao);

    // Generate and bind the vertex buffer object
    glGenBuffers(1, &_vbo);
    glBindBuffer(GL_ARRAY_BUFFER, _vbo);
    glBufferData(GL_ARRAY_BUFFER, 12 * sizeof(GLfloat), _coordinates, GL_STATIC_DRAW);

    // Generate and bind the index buffer object
    glGenBuffers(1, &_ibo);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _ibo);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6 * sizeof(GLuint), _indexes, GL_STATIC_DRAW);

    // Generate and bind texture
    _texture = LoadTexture("floor.bmp");

    LoadAttributeVariables();

    glBindVertexArray(0);
}

This is how I load the shader attributes:

void PlaneShaderProgram::LoadAttributeVariables()
{
    GLuint VertexPosition_location = glGetAttribLocation(GetProgramID(), "vPosition");
    glEnableVertexAttribArray(VertexPosition_location);

    glVertexAttribPointer(VertexPosition_location, 3, GL_FLOAT, GL_FALSE, 0, 0);
}

void PlaneShaderProgram::LoadUniformVariables()
{
    // OpenGL Matrices
    GLuint ModelViewProjection_location = glGetUniformLocation(GetProgramID(), "mvpMatrix");
    glUniformMatrix4fv(ModelViewProjection_location, 1, GL_FALSE, glm::value_ptr(_ModelViewProjection));

    // Floor texture
    // glActiveTexture(GL_TEXTURE0);
    // glBindTexture(GL_TEXTURE_2D, _texture);
    // GLint Texture_location = glGetUniformLocation(GetProgramID(), "texture");
    // glUniform1i(Texture_location, 0);
}

And my LoatTexture:

GLuint ProgramManager::LoadTexture(const char* imagepath)
{
    unsigned char * data = LoadBMP(imagepath, &width, &height);

    GLuint textureID;
    glGenTextures(1, &textureID);
    glBindTexture(GL_TEXTURE_2D, textureID);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGR, GL_UNSIGNED_BYTE, data);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);

    return textureID;
}

Finally, my draw function, which is called in the OpenGL main loop, is the following:

void PlaneShaderProgram::DrawPlane(const glm::mat4 &Projection, const glm::mat4 &ModelView)
{
    _ModelViewProjection = Projection * ModelView;
    _ModelView = ModelView;

    Bind();

    glBindVertexArray(_vao);
    LoadUniformVariables();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

    UnBind();
}

What I didn't get is that even if I didn't set the uniform texture (commented in the code) used by my shader, the plane is still draw using the texture. This makes no sense for me. Once the shader requires a sample2D, I think this shouldn't work and return some error.

Vertex Shader:

uniform mat4 mvpMatrix;
in vec4 vPosition;

smooth out vec2 uvCoord;

void main() 
{
   uvCoord = vPosition.xz;
   gl_Position = mvpMatrix * vPosition;
}

Frag Shader:

uniform sampler2D texture;
in vec2 uvCoord;

out vec4 fragColor;
void main()
{ 
    fragColor.rgb = texture(texture, uvCoord).rgb;
};

Am I missing something? Somehow this works I don't understand why, but I really like to.

1 Answer 1

3

The sampler data types in GLSL reference the texture unit, not a texture object. By default, uniforms will be initialized to 0, so if you don't set the sampler uniforms, they will sample from texture unit 0 (which is also the default unit). In your ProgramManager::LoadTexture() method, you bind the newly created texture, and very likely you are still using GL_TEXTURE0 as the currently active texture unit. You never seem to unbind it, so it is still bound at the time of the draw call, and the shader can access it.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, @derhass. Completely understood now. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.