0

I want draw object rectangle with two texture and triangle with only one texture. I follow this website

LearnOpenGL.com - Textrues
https://learnopengl.com/code_viewer_gh.php?code=src/1.getting_started/4.2.textures_combined/textures_combined.cpp

With draw triangle I implement like below :

Shader ourShaderTriangle("vshader.glsl", "fshader.glsl");
float firstTriangle[] = {
    // positions         // colors          //textcoord
    -1.0f, 0.0f, 0.0f,  1.0f, 0.0f, 0.0f,   0.0f,   0.0f,   // bottom right
    -0.5f, 0.5f, 0.0f,  0.0f, 1.0f, 0.0f,   0.5f,   1.0f,   // bottom left
    -0.1f,  0.0f, 0.0f,  0.0f, 0.0f, 1.0f,  1.0f,   0.0f     // top 
};//first
unsigned int VBO1, VAO1;
glGenVertexArrays(1, &VAO1);
glGenBuffers(1, &VBO1);

glBindVertexArray(VAO1);
glBindBuffer(GL_ARRAY_BUFFER, VBO1);
glBufferData(GL_ARRAY_BUFFER, sizeof(firstTriangle), firstTriangle, GL_STATIC_DRAW);
//position
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
glEnableVertexAttribArray(0);
//color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);
//textCoord
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
glEnableVertexAttribArray(2);

Vertex Shader

#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor;
layout (location = 2) in vec2 aTexCoord;
out vec3 ourColor;
out vec2 TexCoord;
void main()
{
   gl_Position = vec4(aPos, 1.0);
   ourColor = aColor;
   TexCoord = vec2(aTexCoord.x, aTexCoord.y);
}

Fragment:

#version 330 core
out vec4 FragColor;
in vec3 ourColor;
in vec2 TexCoord;
uniform sampler2D textureTriangle;
void main()
{
   FragColor = texture(textureTriangle, TexCoord);
}

Load texture :i use other texture "container2.png".I store it in "texture3"

    glGenTextures(1, &texture3);
glBindTexture(GL_TEXTURE_2D, texture3);
// set the texture wrapping parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);   // set texture wrapping to GL_REPEAT (default wrapping method)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
// set texture filtering parameters
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
// load image, create texture and generate mipmaps
data = stbi_load(FileSystem::getPath("resources/textures/container2.png").c_str(), &width, &height, &nrChannels, 0);
if (data)
{
    // note that the awesomeface.png has transparency and thus an alpha channel, so make sure to tell OpenGL the data type is of GL_RGBA
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
}
else
{
    std::cout << "Failed to load texture" << std::endl;
}
stbi_image_free(data);

In draw function:

  //bind textures on corresponding texture units
    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D, texture1);
    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D, texture2);

    // render container
    ourShader.use();
    glBindVertexArray(VAO);
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);

    //
    ourShaderTriangle.use();
    glBindTexture(GL_TEXTURE_2D, texture3);     
    glBindVertexArray(VAO1);
    glDrawArrays(GL_TRIANGLES, 0, 3);
    //

But triangle still using of texture unit 0 (GL_TEXTURE0).Not using texture i want enter image description here

I have try to use "glDisable" ,and "glDeleteTextures" but it doesn't work.

Could you help me?

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
ledien
  • 529
  • 2
  • 8
  • 19
  • Where do you tell the fragment shader, by using `glUniform1i(...)`, about the texture to use (`uniform sampler2D textureTriangle`)? – Ripi2 Aug 29 '19 at 17:41
  • `texture3` is bound to texture unit 1, because the current texture unit isn't changed after `glActiveTexture(GL_TEXTURE1);`. If the texture sampler `"textureTriangle"` should be associated to texture unit 1, then you've to assign 1 to the texture sampler uniform, `GLint tex_loc=glGetUniformLocation(program, "textureTriangle");` `glUniform1i(tex_loc, 1);`. The uniform has to be set after `ourShaderTriangle.use();`. – Rabbid76 Aug 29 '19 at 17:42
  • Every time you call `glBindTexture` it puts that texture into the current *Active* texture. The last call to `glActiveTexture` changed the *active* texture to `GL_TEXTURE1`. Then you *bound* `texture2` to draw the quad, and then `texture3` for the triangle. The triangle shader is seeing `texture1` bound to `GL_TEXTURE0` and `texture3` bound to `GL_TEXTURE1`. Try adding a call to `glActiveTexture(GL_TEXTURE0)` before binding `texture3`. – Romen Aug 29 '19 at 17:43

1 Answers1

1

OpenGL is a state engine. The current texture unit which is set by glActiveTexture is a global state. So all the following calls to glBindTexture, bind the texture to texture unit 1.
If you want to bind texture3 to texture unit 0, then you've to change the texture unit before binding the texture to the texturing target:

ourShaderTriangle.use();
glActiveTexture(GL_TEXTURE0); // <---
glBindTexture(GL_TEXTURE_2D, texture3);     
glBindVertexArray(VAO1);
glDrawArrays(GL_TRIANGLES, 0, 3);

If you want to use a different texture unit then you've to change the binding point for the texture sampler uniform.

This can be done in shader code by Binding point Layout Qualifier (For this at least GLSL version 4.20 has to be used). e.g 1 for texture unit 1:

#version 420 core

layout(binding = 1) uniform sampler2D textureTriangle;

The alternative is to assign the texture unit (1) to the texture sampler uniform, after the program is installed by glUseProgram:

GLuint program = // program "ourShaderTriangle"
GLint texTriLoc = glGetUniformLocation(program, "textureTriangle"); 
// ...
glActiveTexture(GL_TEXTURE1);
// ...
ourShaderTriangle.use();
glUniform1i(texTriLoc, 1); // <----
glBindTexture(GL_TEXTURE_2D, texture3);     
glBindVertexArray(VAO1);
glDrawArrays(GL_TRIANGLES, 0, 3);
Rabbid76
  • 202,892
  • 27
  • 131
  • 174