PDA

View Full Version : glDrawElements binding understanding



Lauriane
09-06-2016, 02:21 AM
I'm using OpenGL 3.3 with Qt 5.6.

I'm loading a model with Assimp library and try to render it using glDrawElements(), because so far I was using glDrawArrays and it worked but now that I want to render a simple cube it does not draw the right faces.
My cube model is in Wavefront obj, contains 8 vertices and the faces.

Here are my buffers :


QOpenGLBuffer VBO ;
QOpenGLVertexArrayObject* VAO = new QOpenGLVertexArrayObject();
QOpenGLBuffer* EBO = new QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);

I'm settint them up like so :


if (!VAO->isCreated()) {
VAO->create();
}

VBO.create();
VBO.bind();
VBO.setUsagePattern(QOpenGLBuffer::StaticDraw);
VBO.allocate(vertices.data(), vertices.size()*sizeof(Vertex));


VAO->bind();
program->enableAttributeArray(0);
program->setAttributeBuffer(0, GL_FLOAT, Vertex::positionOffset(), Vertex::PositionTupleSize, Vertex::stride());
program->enableAttributeArray(1);
program->setAttributeBuffer(1, GL_FLOAT, Vertex::colorOffset(), Vertex::ColorTupleSize, Vertex::stride());

EBO->create();
EBO->bind(); //glBindBuffer(GL_ARRAY_BUFFER, ebo);
EBO->setUsagePattern(QOpenGLBuffer::StaticDraw);
EBO->allocate(indices.data(),indices.size()*sizeof(GLui nt));

And finally calling the drawing on the mesh :


EBO->bind();
glDrawElements(GL_TRIANGLES, indices.size(),GL_UNSIGNED_SHORT, (void*)0);


The result is the drawing of some triangles that does not even correspond to the faces of the cube.

Some my questions are :
- Should I bind the EBO before calling glDrawElements ? Because I believe the EBO only contains the information from the indices vector, aka the faces' numbers, but not the vertices positions that are in the VBO. With glDrawArrays I was binding VAO which seemed more logical, I don't seen how something can be drawn with only faces numbers...
- The last argument of glDrawElements is supposed to be " a pointer to the location where the indices are stored", which to me would be "&indices". However when I try this nothing is rendered, and I've seen (void*)0 a lot on the internet which I dont understand...

Silence
09-06-2016, 03:51 AM
- Should I bind the EBO before calling glDrawElements ? Because I believe the EBO only contains the information from the indices vector, aka the faces' numbers, but not the vertices positions that are in the VBO. With glDrawArrays I was binding VAO which seemed more logical, I don't seen how something can be drawn with only faces numbers...


There are not the face numbers, but the index of each vertices. This might be why you don't see what you expected.
When creating your VAO you should create and bind both the VBO and the EBO. For rendering you then only have to bind the VAO.



- The last argument of glDrawElements is supposed to be " a pointer to the location where the indices are stored", which to me would be "&indices". However when I try this nothing is rendered, and I've seen (void*)0 a lot on the internet which I dont understand...

This is the pointer from the GPU. When you create a buffer, the first pointer will point to the address 0x0. You should not use the address of your local storage, that won't work (this will look at an offset in the GPU from the first address from your buffer). It's exactly the same from when you were rendering without the EBO, but only with the VBO and setting the vertex attributes.

You should post more relevant code, that is, were you set the attributes, and in the order you are doing it.

Lauriane
09-06-2016, 04:06 AM
When you create a buffer, the first pointer will point to the address 0x0.
Ok so because I create VAO, then VBO, then EBO, I should not put 0x0 because it would correspond to VAO and not EBO, right ? How can I know the address of EBO on the GPU then ?
For now I just switch to creating it first (no change in the render).


You should post more relevant code, that is, were you set the attributes, and in the order you are doing it.
Not sure this is what you want to see, but this is my vertex structure :


struct Vertex_Struct {
// Position
QVector3D Position;
//Colors
QVector3D Colors ;
};


So thus for each mesh, I go through all the vertices and store into a Vertex_Struct its position and colors, then I push_back this struct in the vertices QVector.


EDIT : found my problem : in addition to binding EBO instead of VAO (thank you), the issue was with GL_UNISGNED_SHORT. Works when I'm using GL_UNSIGNED_INT, makes sense since my meshes are huge so a lot of indices.

Silence
09-06-2016, 04:49 AM
Ok so because I create VAO, then VBO, then EBO, I should not put 0x0 because it would correspond to VAO and not EBO, right ? How can I know the address of EBO on the GPU then ?

No. Each buffer should be treated as different buffers. So 0x0 is the start address for each of your buffers, meaning that there is no offset from the beginning of the storage of the current buffer. You will never have the real address where the data are stored in the graphic card.