Search code examples
c++opengltexturessfml

OpenGL 3.3 - I can only bind to GL_TEXTURE0


I've been trying to follow an OpenGL-3.3 tutorial for some time but it appears that I can only bind a texture to GL_TEXTURE0 otherwise I get a black square.

Example:

This works

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0 + 0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glUniform1i(glGetUniformLocation(shader.program, "our_texture1"), 0);

    shader.bind();

    glBindVertexArray(vertex_array);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

This doesn't

    glClearColor(0.2f, 0.3f, 0.3f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glUniform1i(glGetUniformLocation(shader.program, "our_texture1"), 1);

    shader.bind();

    glBindVertexArray(vertex_array);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glBindVertexArray(0);

Details:

shader.bind simply calls glUseProgram

Vertex Shader:

     #version 330 core

    layout (location = 0) in vec3 position;
    layout (location = 1) in vec3 color;
    layout (location = 2) in vec2 tex_coords;
    out vec4 our_color;
    out vec2 our_tex_coords;

    void main()
    {
        gl_Position = vec4(position, 1.0f);
        our_color = vec4(color, 1.0f);
        our_tex_coords = tex_coords;
    }

Fragment Shader:

    #version 330 core

    out vec4 color;
    in vec4 our_color;
    in vec2 our_tex_coords;

    uniform sampler2D our_texture1;

    void main()
    {
        color = texture(our_texture1, our_tex_coords);
    }

Texture Creation:

    GLuint texture1;

    glGenTextures(1, &texture1);
    glBindTexture(GL_TEXTURE_2D, texture1);

    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

    sf::Image image1;
    if (!image1.loadFromFile("../Assets/container.jpg"))
    {
        error();
    }

    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, image1.getSize().x, image1.getSize().y, 0, GL_RGBA, GL_UNSIGNED_BYTE, image1.getPixelsPtr());
    glGenerateMipmap(GL_TEXTURE_2D);

    glBindTexture(GL_TEXTURE_2D, 0);

From what I can inspect the file is loaded correctly. Any idea on what may be wrong?


Solution

  • The earlier answer tells you how to change the code to make it work, but gives the wrong explanation. In this sequence:

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glUniform1i(glGetUniformLocation(shader.program, "our_texture1"), 1);
    
    shader.bind();
    

    with shader.bind() calling glUseProgram(), there is indeed a problem with the sequence. But it has nothing to do with glActiveTexture(), which is completely unrelated to the currently bound program.

    The glUniform1i() call sets a uniform value on the currently bound program. So the key is that you call glUseProgram() before glUniform*(). For example, the following sequence will work:

    glActiveTexture(GL_TEXTURE0 + 1);
    glBindTexture(GL_TEXTURE_2D, texture1);
    
    shader.bind();
    glUniform1i(glGetUniformLocation(shader.program, "our_texture1"), 1);