1

I have a problem about activating a single texture to multiple buffer objects. I am trying to draw two different graphical objects that using the same texture. However could not make it bind.

After searchs so far, I could find an answer that fits to my question in this (Re-using one texture for multiple OpenGL Quads) link. I tried this method in my code by using the glBindTexture() function before the main opengl render loop, and also inside of the render loop but it did not bind. Also it is said that, bind the texture before the draw call, in here (OpenGl all models are with the same texture). But this way also did not work for me.

How can I use the exact same texture which is named texture1 for second buffer object?

I use two buffer objects and two vertex array objects for different graphical objects. What I really want to accomplish to describe only one texture after the first buffer array and then use the exact same texture for the second object. But when I try to bind the texture after vertex array object it does not work.

By the way I do not load any images for the texture. The main purpose that I use texture in order to utilize the texture coordinates. I do necessary works in the fragment shader.

#shader vertex
#version 330 core

layout (location=0) in vec3 position;
layout (location=1) in vec2 TextureCoords;

out vec2 TexCoord;
void main()
{   
  TexCoord = vec2(TextureCoords.x, TextureCoords.y);
  gl_Position = vec4(position, 1.0);
};


#shader fragment
#version 330 core

out vec4 fragColor;
in vec2 TexCoord;

void main()
{
  vec2 xy = TexCoord.xy;
  vec4 color = vec4(vec3(xy.x), 1.0);
  fragColor = color;
};

float vertexArray1[] = {
 //      Vertex Position | Texture Coords
 //       x     y     z     x      y
         0.9f, 0.9f, 0.0f, 1.0f, 1.0f,
         0.9f, 0.2f, 0.0f, 1.0f, 0.0f,
         0.2f, 0.2f, 0.0f, 0.0f, 0.0f,

         0.2f, 0.9f, 0.0f, 0.0f, 1.0f,
         0.9f, 0.9f, 0.0f, 1.0f, 1.0f,
         0.2f, 0.2f, 0.0f, 0.0f, 0.0f,
    };

float vertexArray2[] = {

        -0.2f, 0.9f, 0.0f, 1.0f, 1.0f,
        -0.2f, 0.2f, 0.0f, 1.0f, 0.0f,
        -0.9f, 0.2f, 0.0f, 0.0f, 0.0f,

        -0.9f, 0.9f, 0.0f, 0.0f, 1.0f,
        -0.2f, 0.9f, 0.0f, 1.0f, 1.0f,
        -0.9f, 0.2f, 0.0f, 0.0f, 0.0f,
 };


unsigned int buffer;
unsigned int VAO;

glGenBuffers(1, &buffer);
glGenVertexArrays(1, &VAO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray1), vertexArray1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);

unsigned int 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);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

unsigned int buffer2;
unsigned int VAO2;
glGenBuffers(1, &buffer2);
glGenVertexArrays(1, &VAO2);

glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray2), vertexArray2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);

// I want to use the previously described texture1 in here, but it does not bind.
glBindTexture(GL_TEXTURE_2D, texture1); 

while(!glfwWindowShouldClose(window)){

    processInput(window);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shader);
    glBindVertexArray(VAO);
    glDrawArrays(GL_LINES, 0, 6*3*1);

    glBindVertexArray(VAO2);
    glDrawArrays(GL_LINES, 0, 6*3*1);

    glfwSwapBuffers(window);
    glfwPollEvents();
}

Note: When I create another different texture for the buffer2 object it works like a charm. I mean texture1 for buffer1, texture2 for buffer2... But I want to keep the number of the texture as possible as minimum. Maybe in future developments, I will have to create more than 50 buffer object, thus I do not want to create different textures for every single buffer object.

EDIT: I have changed my misunderstanding of "binding a texture to a vertex array" to "enabling attributes of a texture for other objects". I've also included my shader scripts for debugging purposes.

7
  • 3
    glBindTexture does not "bind a texture to a buffer". It binds the texture to the global context. Drawing uses that currently bound texture, no matter what the current buffer is. There is no association between buffers and textures. Commented Jul 13, 2021 at 17:54
  • "By the way I do not load any images for the texture. The main purpose that I use texture in order to utilize the texture coordinates." You don't need to bind a texture in this case. You don't need a texture bound to use UV coordinates. Commented Jul 13, 2021 at 17:56
  • I see, your first comment made lots of things brighter for me @ColonelThirtyTwo. On the other hand, even though I bind 'glBindTexture()' before the drawing call in render loop, that does not bind the texture as current texture. What can cause this situation, any idea? Commented Jul 13, 2021 at 18:34
  • @AhmetFurkan since you said you do not use the texture, how can you tell it's not bound? Commented Jul 13, 2021 at 18:44
  • 2
    @AhmetFurkan: You didn't answer the question: how do you know it is "not bound"? You say you get a black screen, but why do you think that is the fault of a texture binding problem? Commented Jul 13, 2021 at 18:59

2 Answers 2

5
  • Textures are not bound to buffer objects. When you draw something, it uses the currently bound texture, not one from a buffer.

  • Textures are not bound to VAOs either so there's no need to worry about that.

  • To use a texture, you do need to have a sampler in your shader, bind the texture unit (not the texture) to the sampler with glUniform1i, and call the texture function in the shader and do something with the return value.

  • Since you say your shader isn't doing anything with your texture anyway, I wonder how you can tell whether it's bound or not.

  • In fact, there's no reason to have a texture if you don't have a shader that does something with it! There is no magical texture-shader interaction. A texture is something you have to specifically query (by calling texture) or else it doesn't do anything by itself.

  • You don't need to have a texture to have texture coordinates.

  • Since you haven't shown your shaders, it's impossible to debug them for you.

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

4 Comments

All right I will be taking consideration about using the sampler in my shader. And I draw many small objects that is why I use uv coordinates to play around some color value with the help of 'smoothstep()' function for objects in fragment shader. So I use uv coordinates to determine which colors go which way by specifying some conditional statements on coordinates.
@AhmetFurkan The sampler is how you read the colours from the texture. If you don't want the colours, you don't need the sampler, or the texture. Textures don't do anything just by existing. The point of a texture is so that you can read colours from it in the fragment shader - if you don't want to read colours from it in the fragment shader, then you don't need it!
Thank you for the informations. I have search a little bit about the sampler and found this link. Here it is said about the sampler, "to access two textures in the same shader at the same time…". And what I want to achieve is to create only one texture and use it multiple times.
@AhmetFurkan What you want to achieve is to create zero textures and use them zero times. If I understand you correctly.
0

After I review my code again and search once more, I came across a solution for my question.

And I guess where I was wrong was trying to bind a texture which was already bound to the global context, as @ColonelThirtyTwo pointed out in the comment.

As I understood, instead of trying to bind the same texture I should have called the glVertexAttribPointer() and enable with glEnableVertexAttribArray() for bounded texture.

Since in the answer of this question (glVertexAttribPointer clarification), it is said that:

"A Vertex Array Object or VAO is used to store the state of all the glVertexAttribPointer calls and the VBOs that were targeted when each of the glVertexAttribPointer calls were made."

So I came up to this solution and it worked:

unsigned int buffer;
unsigned int VAO;

glGenBuffers(1, &buffer);
glGenVertexArrays(1, &VAO);

glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, buffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray1), vertexArray1, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);

unsigned int 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);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);


unsigned int buffer2;
unsigned int VAO2;

glGenBuffers(1, &buffer2);
glGenVertexArrays(1, &VAO2);

glBindVertexArray(VAO2);
glBindBuffer(GL_ARRAY_BUFFER, buffer2);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertexArray2), vertexArray2, GL_STATIC_DRAW);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(float) * 5, 0);
glEnableVertexAttribArray(0);

// Inseted of the bind call,
// I called the glVertexAttribPointer() and glEnableVertexAttribArray() here.
// And if I am not wrong these calls use the currently bounded texture which is texture1.
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(float), (void*)(3 * sizeof(float)));
glEnableVertexAttribArray(1);

while(!glfwWindowShouldClose(window)){

    processInput(window);
    glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glUseProgram(shader);
    glBindVertexArray(VAO);
    glDrawArrays(GL_LINES, 0, 6*3*1);

    glBindVertexArray(VAO2);
    glDrawArrays(GL_LINES, 0, 6*3*1);

    glfwSwapBuffers(window);
    glfwPollEvents();
}
 

5 Comments

The call is correct, but the reason is wrong. glVertexAttribPointer and glEnableVertexAttribArray DO NOT CARE ABOUT TEXTURES. I have to write it like that, because you keep saying that your texture is doing something, when it is not!
If you delete the texture from your code, does it still work?
Yeah it also works, okay I got what you meant right know @user253751. I supposed that in order to use the UV Coordinates, I should have some textures, but it is not necessary as you said. I really thank you, it really helped me a lot to understand some concepts or what is really going on behind the scene!
Consider that: OpenGL has no idea your coordinates are called "UV". There's no glUVPointer, there's no GL_COORD_TYPE_UV. For all it knows, they could be a normal vector or a specular colour.
All right I will bear in mind these tips. It is appreciated so much. Thanks once more!

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.