Reputation: 546
I am trying to use instanced rendering to render a simple mesh (a textured quad made of 2 triangles) multiple times in a single draw call. When rendering, I don't see my instanced meshes, and when analyzing a frame with renderdoc, all vertices positions are set to the position of the first vertex of the mesh, same for texture coordinates, so I tend to think I have an issue with vertex data uploading, but I can't figure out what.
My main source of inspiration for instanced rendering has been this tutorial, and the OpenGL documentation.
Here are the relevant parts of my code:
// This is part of the instanced mesh object initialization code.
// VAO, VBO, and EBO are unsigned int private members of the object.
glGenVertexArrays(1, &VAO);
glGenBuffers(1, &VBO);
glGenBuffers(1, &EBO);
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
// I could confirm in a debug session that vertices contains the data I expect it to contain
glBufferData(GL_ARRAY_BUFFER,
static_cast<GLsizeiptr>(sizeof(float) * vertices.size()),
vertices.data(),
GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
// Same as vertices, I could confirm indices contains the data I expect.
glBufferData(GL_ELEMENT_ARRAY_BUFFER,
static_cast<GLsizeiptr>(sizeof(unsigned int) * indices.size()),
indices.data(),
GL_STATIC_DRAW);
GLsizei vertexStride = static_cast<GLsizei>(7 * sizeof(float));
// vertex coordinates (only x and y, so the size of 2 is ok here)
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, vertexStride, 0);
glVertexAttribDivisor(0, 1);
glEnableVertexAttribArray(0);
// color
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 2);
glVertexAttribDivisor(1, 1);
glEnableVertexAttribArray(1);
// texture coordinates
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, vertexStride, 5);
glVertexAttribDivisor(2, 1);
glEnableVertexAttribArray(2);
glBindVertexArray(0);
// This is the rendering code.
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, texture.id);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, palette.id);
glBindVertexArray(VAO);
// As advised by learnopengl.com, 4th argument is set to 0 since I'm using an element buffer
glDrawElementsInstanced(GL_TRIANGLES, indices.size(), GL_UNSIGNED_INT, 0, instances.size());
glBindVertexArray(0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE1);
glBindTexture(GL_TEXTURE_1D, 0);
// vertex shader
#version 330 core
layout (location = 0) in vec2 vertex_pos;
layout (location = 1) in vec3 vertex_color;
layout (location = 2) in vec2 vertex_tex_coord;
out vec2 tex_coord;
out vec3 color;
uniform mat4 viewproj;
void main()
{
gl_Position = viewproj * vec4(vertex_pos, 0.0, 1.0);
tex_coord = vertex_tex_coord;
color = vertex_color;
}
// fragment shader
#version 330 core
out vec4 fragment_color;
in vec2 tex_coord;
in vec3 color;
uniform sampler2D tex;
uniform sampler1D palette;
void main()
{
float base_index = texture(tex, tex_coord).r;
fragment_color = texture(palette, base_index) * vec4(color, 1);
}
Here is what I get :
I have the correct number of vertices, the indices are ok too and the color seems ok (color is set to glm:vec3(1.0f, 1.0f, 1.0f)
earlier in the code. However, vertex_pos
and vertex_tex_coord
values are all the same. The values are coherent, but all the same.
I would have expected something like that:
Considering I get the correct values for the indices, I think the EBO is ok, but there may be a problem with my VBO, and since data is correct in my vertices
vector just before uploading it, and incorrect just before rendering it, I'm lost ^^' and I don't know where to go from here.
Upvotes: 2
Views: 614
Reputation: 210908
You have misunderstood what glVertexAttribDivisor
does. glVertexAttribDivisor
is used for instance attributes. Instance attributes are attributes that change for instances, not the vertices of an instance. The vertex coordinate, color and texture coordinate are not instance attributes, but vertex attributes. Hence you must remove the calls to glVertexAttribDivisor
(or set the divisor argument to 0):
glVertexAttribDivisor(0, 1);
If a named buffer object is bound to the GL_ARRAY_BUFFER
target, the last argument of glVertexAttribPointer
is treated as a byte offset into the buffer objects data store. Therefore, the offset of the color and texture coordinates attribute must be 2*sizeof(float)
and 5*sizeof(float)
instead of 2 and 5:
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 2);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, (void*)(2*sizeof(float)));
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, 5);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, vertexStride, (void*)(5*sizeof(float)));
Upvotes: 2