Graphics – MGP – Tessellation

23 05 2010

Now that we have all the points necessary we want to draw these as a surface and the first step in this is to generate a set of vertices to get them displayed.

Before we create the vertices we need to know the draw command that we will be using with OpenGL as this will determine the order in which we need them. For our purposes it makes the most sense to use GL_TRIANGLE_STRIP, which needs an order of vertices alternating between two parallel tracks. Remembering that in GL_TRIANGLE_STRIP we use the last 2 vertices and the next supplied one to define a triangle this is equivalent to needing vertex co-ordinates in the order of the diagram below.

Triangle Strip Ordering

With this in mind, and given a particular resolution we can use the following to get the set we need:

float vertices_l[(resT+1)*resS*6];
int vertexCount = (resT+1)*resS*2;
int index = 0;
NSPoint3 vertex, normal;
for(int lt=0; lt < resT; lt++)
	for(int ls=0; ls < resS; ls++)
		index = (lt*(resS) + ls)*6;
		vertex = [self pointOnSurfaceT: (lt+1)/(double)resT S: ls/(double)resS];
		vertices_l[index + 0] = vertex.x;
		vertices_l[index + 1] = vertex.y;
		vertices_l[index + 2] = vertex.z;
		index += 3;

		vertex = [self pointOnSurfaceT: (lt)/(double)resT S: ls/(double)resS];
		vertices_l[index + 0] = vertex.x;
		vertices_l[index + 1] = vertex.y;
		vertices_l[index + 2] = vertex.z;
		index += 3;

Now of course we could keep this as an array and use immediate mode (the ol’ glBegin() / glEnd() combination) and iterate over it each frame but this would be terribly inefficient. To be a bit smarter we will use vertex arrays and load the data into the graphics card, which is not only faster but also sets us up for the final stage in the project where we transform the vertex data on the GPU.

Using vertex arrays is almost as easy as using immediate mode and follows 3 basic steps:

  1. Create the array reference
  2. Load the vertex data into the array
  3. Use the array whenever we want to draw the object

The first two steps are done only once with the reference being used whenever we need it. The code to perform these two steps is:

// generate the buffer
// fill the buffer
glBindBuffer(GL_ARRAY_BUFFER, drawRef);
glBufferData(GL_ARRAY_BUFFER, numberVerts * 3 * sizeof(float), &vertices, GL_STATIC_DRAW);

Whenever we want to use this buffer to draw any object we can do this as follows:

// let it know which buffer we are talking about
glBindBuffer(GL_ARRAY_BUFFER, drawRef);
// let it know offsets
glVertexPointer(3, GL_FLOAT, 0, 0);
// tell it to draw the specified number of vertices
glDrawArrays(GL_TRIANGLE_STRIP, 0, numberVerts);
// turn stuff off again

Which is dropped in wherever you would normally do the glBegin()/glEnd() bit.

You can see where the GL_TRIANGLE_STRIP bit comes in and how many fewer instructions need to be sent to the graphics driver each draw. And I do say graphics driver because it is up to it where it stores the stuff. You can give it a hint, however, which is what the GL_STATIC_DRAW is doing in the first code snippet. The STATIC means we intend to modify it once and will be drawing it many times and strongly suggest that the data should be kept in VRAM.

With all this work we get the following image:


Which isn’t really that impressive but there is a ways to go yet… next time: normals and lighting




One response

7 10 2010
Graphics – MGP – Rendering Geometry to an FBO « NSH + Graphics & Photography

[…] now the how… Back in the post on tessellation we described how we were uploading the data onto the graphics card so that each time we wanted to […]

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s

%d bloggers like this: