Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does it make sense to have indices and normals in VBOs

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 ?

like image 562
Laurent Crivello Avatar asked Dec 05 '16 19:12

Laurent Crivello


People also ask

What are OpenGL indices?

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).

What is Ebo in OpenGL?

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.

How do you use VBO?

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().


1 Answers

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.

like image 98
Yakov Galka Avatar answered Oct 24 '22 03:10

Yakov Galka