PDA

View Full Version : What is a Vertex Array anyway?



darkrappey
02-07-2007, 06:19 PM
I'm looking for ways to make my basic game engine run more efficiently. In paticular, rendering of objects that are not display lists. (I call them dynamic meshes, if thats a good term)

Using the glBegin(), loop glVertex3f(), glEnd() seems pretty slow. The engine does fine as far FPS is concerned until an object is created that uses a dynamic mesh. The FPS plummets.

Are Vertex Arrays used for making this more efficient? I'm having a hard time finding out what exactly they are.

Can a vertex array's contents be modified after they are created? In contrast to a display list.

V-man
02-08-2007, 12:38 AM
There are plenty of books and online sites about the subject.

In summary:
1. yes VA that are in RAM are faster then glBegin/glEnd. You can modify.
2. VBO are even better. In your case, you need to have a dynamic VBO.
Or perhaps you can do your morphing calculations in a shader and use a static VBO (don't change VBO contents).

You can forget about glBegin/glEnd and display lists when using VBO.
Also, VBO has been around for a few years and all cards support them. It's core in GL 1.5

RigidBody
02-08-2007, 01:36 AM
simple example:

float vertex_array[4][3] = { {-1., -1., 0.} , {1., -1., 0.} , {1., 1., 0.} , {-1., 1., 0.} };
float color_array[4][3] = { { 1., 0., 0.} , {0., 1., 0.} , {1., 1., 0.} , { 1., 1., 1.} };

glEnableClientState(GL_VERTEX_ARRAY);
glVertexPointer(3, GL_FLOAT, 0, vertex_array);
glEnableClientState(GL_COLOR_ARRAY);
glColorPointer(3, GL_FLOAT, 0, color_array);
glDrawArrays(GL_QUADS, 0, 4); specify a vertex array and a color array; the call to glDrawArrays will- in this case- use 4 vertices from the vertex array and 4 color values from the color array to draw a quad. (you could have a normal array, too, but that's not necessary. a color array in fact isn't mandatory either.).

as you can see, it is at any time possible to change the values in the vertex or color array, because the arrays will always be accessible for your program. a change will cost no time (except the time you need to calculate the changes), because the vertex array does not need to be compiled after a change like a display list.

songho
02-08-2007, 07:00 AM
Vertex Array is a method to store vertex data (vertex coords, normals, texture coords, etc) into arrays, and then to access the data with their array indices.

The advantages of Vertex Array over immediate mode are 2 things;
VA can reduce the number of drawing calls, so it improve the performance. In RigidBody's example, there is only 1 glDrawArrays() call to draw a quad. But in immediate mode, you need 4 glVertex*() and 4 glColor*() calls, so total 8 function calls are needed.

Second, VA can minimize the redundant usage of shared vertices. Not only it saves memory space, but also it boosts up data transfer rates from system memory to OpenGL.

Here is some notes about Vertex Array (http://songho.ca/opengl/gl_vertexarray.html) .

halo
02-08-2007, 08:00 AM
Unfortunately, no one can be told what a vertex array is. You have to see it for yourself.

darkrappey
02-08-2007, 03:03 PM
Ok that makes a good deal of sense. Thanks.

A few questions though:



Second, VA can minimize the redundant usage of shared vertices.
How? If each 3 values are one vertex then wouldn't it always be 9 vertices for 2 triangles?

Also, are other drawing methods available with VAs. Like how would it be possible to do Triangle Fans? (or not possible)

I'll look into VBOs also thanks for the tip.

@halo, Really? songho, Rigid Body, and V-man did a pretty good job lol

RigidBody
02-08-2007, 11:25 PM
there are 2 different ways of using a vertex array:

1. provide an array with vertex data and use for instance glDrawArrays(GL_QUADS, 0, vertex_number). the driver will take 12 float values from the array (4 vertices * 3 coordinates per vertex) and draw a quad from them; then the next 12 float values and draw another quad; and so on. since a regular mesh usually has 4 quads connected to a vertex, the same vertex will be in the array 4 times.

2. provide a vertex array, in which each vertex occurs only once, then use glDrawElements. this function needs a pointer to an index array, in which the connectivity between the vertices is defined. example:


float vertex_array[8][3] = { { -1., -1., -1. }, { 1., -1., -1. }, { 1., 1., -1. }, { -1., 1., -1. },
{ -1., -1., 1. }, { 1., -1., 1. }, { 1., 1., 1. }, { -1., 1., 1. } };

short index_array[6][4] = { { 0, 1, 2, 3 }, { 4, 5, 6, 7 }, { 0, 1, 5, 4 }, { 1, 2, 6, 5 }, { 2, 3, 7, 6 }, { 3, 0, 4, 7 } };the vertices are a cube's corner points; they are numbered from 0 to 7 (internally, by the driver). the index array defines the 6 faces, referring to the nodes' position in the vertex array.

one advantage of an index array is that vertex array + index array need less memory. in this example: 8 vertices * 3 coordinates * sizeof(float) + 6 faces * 4 indices * sizeof(short) = 96 bytes + 48 bytes = 144 bytes.

if you draw the cube with a "normal" vertex array, you need: 6 faces * 4 vertices * 3 coordinates * sizeof(float) = 288 bytes.

another "plus" for the index array is the fact that it may be possible that if a quad is drawn, 2 of its vertices do not need to be transformed by the graphics card, because they were used before and are still in the cache.

darkrappey
02-08-2007, 11:46 PM
That's great to know (index arrays) I think it will be a smooth process to adapt the engine to work with them as it already uses that form in the data types for storing geometry.

Ok well I think thats pretty much enough to get me started, thanks for the help!

You can check out the progress of the game/engine at
www.sf.net/projects/identityengine (http://www.sf.net/projects/identityengine)