I am writing a plugin which renders some meshes in OpenGL.
I have a Vertices array in a VBO and an Indices array in another VBO. I now want to store Normals. As a vertex, being shared between multiple faces, has different normals, it seems that I must replicate vertices multiples times, and therefore lose the use of indices.
As an example, to store a cube with vertices and indices, I need 8 vertices and 24 indices (4 per face). However if I want to store normals, do I need to store 24 vertices (8 having each 3 faces), 24 indices (all sequential) and 24 normals ?
Do I see it right, and therefore Indices become useless, or is there a way to not duplicate vertices and anyway have multiple normals per vertex ?
The indices control what order the vertices are received in, and indices can specify the same array element more than once. If you use the above array as a stream, OpenGL will receive and process these three vertices in order (left-to-right).
An EBO is a buffer, just like a vertex buffer object, that stores indices that OpenGL uses to decide what vertices to draw. This so called indexed drawing is exactly the solution to our problem.
Creating a VBO requires 3 steps; Generate a new buffer object with glGenBuffers(). Bind the buffer object with glBindBuffer(). Copy vertex data to the buffer object with glBufferData().
Not so easy. Indices have a great feature called a primitive restart index. It lets you describe your shape with, e.g. GL_TRIANGLE_STRIP
, thus using less indices for the same mesh. Further, smooth parts of your model share some vertices, and usually you have more shared data than duplicated vertices, so in the end it's a net win.
Consider now your cube example. Let I
be the size of the index type and V
be the size of the vertex data. Lets take I = sizeof(uint) = 4
and V = 3*sizeof(float) + 4*sizeof(byte) = 16
(three floats for position and a low-precision normal).
glDrawArrays
with GL_TRIANGLES
needs two triangles per face, that is 2*3*6*V = 512
bytes.
glDrawElements
with GL_TRIANGLE_STRIP
needs four indices per face plus a restart index, that is 5*6*I = 120
bytes, and four vertices per face, which is 4*6*V = 384
bytes. That is 504 bytes in total.
As you see even with that cube example and some conservative type choices the indexed approach still wins on the memory footprint. In reality you're able to use short
indices and might need higher precision normal, which will bias even more towards the indexed approach.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With