View Full Version : flat shaded polygons (fe-mesh) with VBO ?

D.K Lee
11-26-2011, 01:39 AM

I have some difficulties to render FE-meshes consist of lots
of nodes (vertex points) and elements (quad or tria polygons).

In fact, I want to draw flat shaded polygon meshes using vertex
buffer object(VBO). but don't know how to specify each polygon
face normal vectors efficiently in VBO.

With vertex array of size N and corresponding normal vector
array of size N (for each vertex), I think GL_N3F_V3F method
cannot get flat shaded result.

Do I need to create duplicated vertices and normal vectors for each faces ?

Is there any method to specify face normal vectors efficiently with VBO ?

thanks in advance.

11-26-2011, 03:51 AM
Since OpenGL doesn't allow multiple indices for a specific group of vertex attributes, you'll have to duplicate each normal for a specific face 4 times, regardless of the primitive type. The vertices don't have to be duplicated.

D.K Lee
11-26-2011, 08:17 AM
I'm not good at using VBO yet. How can I use vertices without duplication ?
If I use interleaved array with GL_N3F_V3F, I think I have to duplicate all vertices 4 times also.
If I have 100 vertices and 80 rectangular faces, I need 80 * 4 = 240 normal vectors.
So, array size of vertices is 100 and 240 for normal vectors.
This means different array index number for vertex and normal vectors.
How do I use the normal vector index and vertex index separately with glDrawElement() ?

11-26-2011, 09:05 AM
There's a couple of ways to do this:
If you use an attribute with a frequency at something other than shared-vertex, you'll need to promote all attributes to non-shared-vertex frequency. In your above example, you have 100 shared vertices, 240 vertex elements (non-shared), and 80 primitives. So, you'd have to duplicate both your vertex positions and normals multiple times, so that your VBO is 240 elements long. On the upside, you no longer need an element buffer - you can just call glDrawArrays(GL_QUADS, ...). However, if you have good knowledge of how the quads are laid out (say in a regular mesh), you can carefully place the normal vectors within the VBO and use the flat output qualifier in a vertex shader to avoid interpolation. The provoking vertex mode will allow you to specify if the normal is taken from first or last vertex, and that vertex is where you'll place the normals. You'll want to tessellate your quads to triangles to do this, to avoid the driver doing it for you. You can use glShadeModel(GL_FLAT) if you're not using shaders. Not all meshes can be solved this way; it depends on their connectivity. And the last, most complex solution is to use a geometry shader and its gl_PrimitiveIDIn variable to access a texture buffer object or texture containing your 80 normals. However, this requires a lot of setup, only works with solely triangles or solely quads, and is slower than the other methods. It's generally not worth it for small models where duplicating data on the CPU is inexpensive.

D.K Lee
11-26-2011, 07:50 PM
Thanks maxlander.

My models are vehicle body FE-meshes, very complex shape with lots of holes, consist of 400~500 panels.
And further more, vertices and faces are create or deleted frequently in the program.
I think it's very hard to define the mesh sequence with this kind of objects.
It is bit disappointing because I thought that there must be the simplest and faster way to do this...

I think I can use only the first method you've suggested.
But I'm afraid that VBO cannot store huge amount of data.

Size is matter. In general, my fe-model is composed of more than 4 million meshes.
This means VBO array size is at least 4,000,000 x 2 (vertex and normal) x 4 (quad or tria) x 4 (float bytes) = 128 MBytes.
And I need another VBO arrays for free-edges, feature lines, and many more other purposes.

11-27-2011, 07:07 AM
If the normals you're computing for the quad aren't perturbed or special in any way, you can use a geometry shader to compute them. Draw the quads as lines_adjacency and have the geometry shader produce a triangle strip. If the quads are always planar, you only need to take the cross product of a pair of edges at a vertex to determine the normal. If the points in the quad aren't coplanar, you can take the cross product of the edges at each vertex, and average the result.

Then, just apply the computed normal to each vertex's normal in the tristrip you output from the geometry shader.