Reputation: 94
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.
Upvotes: 1
Views: 933
Reputation: 94
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();
}
Upvotes: 0
Reputation: 58929
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.
Upvotes: 5