Be Friendly
Search This Site for Tutorials About...

Learn to draw OpenGL primitives (points, lines, triangles, polygons, quads, fans and strips) using glBegin and glVertex commands

Just for fun: How to Make French Toast

Drawing OpenGL Primitives using glVertex command is simple. This tutorial will explain drawing every possible type of primitive in OpenGL except points and lines because they are trivial to understand. If you are still a bit uncertain, please see my previous OpenGL tutorial for an example of how it is done. I will start with polygons because this is the next type of a primitive on the complexity scale after lines. But before I do I need to mention one important point. If you're making a jump from 2D graphics to 3D like many people do, you need to completely forget about the 2D coordinate system. It's time to think in 3D, which can be a little frustrating in the beginning. To refresh your memory here is the coordinate system that OpenGL uses which is the 3D Cartesian Coordinate System.

Remember that when OpenGL is initialized and the projection is set up we are initially looking down the negative Z space as seen on the image above. The point x=0, y=0, z=0 is in the exact center of the screen. Keep this image in your head when you write primitive-rendering code. Before we continue, I'd like to point out that I have learned much of this from some of these OpenGL books, available at other sites like Amazon and/or Barnes and Nobles.

Open up my OpenGL base code and bring up glmain.cpp into the main view. That's where the function RenderFrame is located. This function executes once per frame or a single run through the main execution loop. Here you will usually want to draw everything and process the rest of your program. Since we are only practicing to draw primitives, you will only use this function to merely display some simple stuff.

Initially, the base code has a single line in that function referring to clearing the contents of the video and depth buffers. This call should generally be there before you add any drawing code since it clears the back (video) buffer as well as the depth buffer; just think of it as clearing the screen to start drawing "from scratch". The reason you clear the depth buffer is that there might be some garbage from the previous frame and you wouldn't want it there. The video buffer clear color is specified by the function glClearColor which is called during initialization. Its parameters specify the R G B and A (alpha) values of the clearing color. How they are specified is the topic of the next tutorial entitled "Colors" and you shouldn't be bothered by it at this point. Just think about it as when you pass all parameters as 0.0f, the clear color is black. Also note that by default, all primitives' color is white even if you don't specify their color (which we won't for now, and which is also one of the topics of the next tutorial where I explain how to add some color to your primitives). In this tutorial we will be constrained to drawing plain white primitives.

Well, it's time to draw something on the screen. You're about to draw your first polygon! Type the following lines inside the RenderFrame function after the call to glClear.



void RenderFrame (void)
{
	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

	
	glBegin(GL_TRIANGLES);

	glVertex3f(-1.0f, -0.5f, -4.0f);    // lower left vertex
	glVertex3f( 1.0f, -0.5f, -4.0f);    // lower right vertex
	glVertex3f( 0.0f,  0.5f, -4.0f);    // upper vertex

	glEnd();
	
}

Compile and run the program. You should see a white polygon centered on the screen with given coordinates. Note that the z value is always -4.0f, this means the triangle is drawn a little further into the screen, otherwise it would be too close to the camera. This glBegin-glEnd sequence can be used to create any other type of primitives. In this example, if you change the GL_ TRIANGLES flag to, say, GL_POINT you will see 3 points positioned at the ending points of the triangle. Try it. If you specify the GL_TRIANGLES flag and list 4 vertices instead of required 3, the last vertex will be ignored. However, if you specify 6 vertices, TWO triangles will be rendered. Here's an example of drawing two triangles. Add 3 more vertices to the list you already have as in the following example:


	glBegin(GL_TRIANGLES);

	glVertex3f(-1.0f, -0.5f, -4.0f);    // lower left vertex
	glVertex3f( 1.0f, -0.5f, -4.0f);    // lower right vertex
	glVertex3f( 0.0f,  0.5f, -4.0f);    // upper vertex

	glVertex3f(-0.5f, -1.5f, -4.0f);
	glVertex3f( 0.5f, -1.5f, -4.0f);
	glVertex3f( 0.0f, -1.0f, -4.0f);

	glEnd();

Recompile this code and run it. One more, smaller triangle appears at the bottom of the first one. As you can see this way you can save time on glBegin and glEnd calls and draw multiple triangles using only one glBegin and one glEnd calls. This is true for all primitives. Say you want to draw 3 lines, then you will specify GL_LINES as the parameter of glBegin and specify 6 vertices one by one. Each 2 vertices in a consequent order will specify the starting and ending points of the 3 lines. Same goes for the rest of primitives specified by following flags: GL_POINTS, GL_LINES, GL_TRIANGLES, GL_QUADS, GL_POLYGON. Just apply the same rules when using glBegin with these flags to draw points, lines, triangles, quads and n-sided polygons.

STRIPS

As you can imagine a call to glVertex takes some time to process. It is possible to minimize the number of calls to glVertex while drawing the same amount of primitives be it a line or a triangle or a quad. For this purpose there are 3 additional flags which are

GL_LINE_STRIP
GL_TRIANGLE_STRIP
GL_QUAD_STRIP

These types of rendering can greatly increase performance of large models! I will demonstrate only one type of strips in theory - GL_TRIANGLE_STRIP. The same rules will apply to the other two types of strips, only with a different number of vertices. Let's take a look at this image generated by following code.

And here's the according code to generate this image:

	glBegin(GL_TRIANGLE_STRIP);

	glVertex3f(-1.0f, -0.5f, -4.0f);    // A
	glVertex3f( 1.0f, -0.5f, -4.0f);    // B

	glVertex3f( 0.0f,  0.5f, -4.0f);    // C
	glVertex3f(1.5f,  0.0f, -4.0f);     // D
	glVertex3f(2.0f, -1.5f, -4.0f);     // E

	glEnd();

Compare coordinates of this code with the corresponding image above; I named vertices with letters A through E to make it easier to compare the code with the visual output and also connected them with red lines so you can see the triangles. You see, when you will get to the point of creating 3D objects out of triangles, you will realize that many triangles share the same vertices. These points would normally be listed as separate vertices, with the same coordinates. But why call glVertex twice? This is the whole point of primitive strips. To initialize a triangle strip you will need to at least specify one initial triangle. In the example above, this triangle is ABC. From then on, as you add new vertices (D and E), you add a new triangle to the "strip" with only ONE vertex. And this is the idea behind triangle strips. This technique can also be applied to both line strips and quad strips. Using this technique can improve the speed of your 3D model rendering loops. With only 5 calls to glVertex you can make 3 triangles.

LINE LOOPS

Another unique type of rendering is called a line loop. You cannot create triangle loops or quad loops. This will only work with lines. The flag you will use to generate it is GL_LINE_LOOP. A line loop is the same thing as a line strip. The only difference is that the last and the first vertices specified in the list are also connected.

FANS

The next and the last type of rendering triangles are fans. Fans also can only be used with triangles and no other type of primitive and are identified by the GL_TRIANGLE_FAN flag. A triangle fan has one origin indicated by the first vertex, and an initial triangle, indicated by the first 3 vertices including the origin. As you add the 4th and 5th vertices to you fan, you continue it just like you did with a triangle strip. The difference is that all consequent triangles are tied to one origin point and do not extend into a line (or a strip) of triangles. Here is an example of a triangle fan and code to generate it.



	glBegin(GL_TRIANGLE_FAN);

	glVertex3f(-1.0f, -0.5f, -4.0f);    // A
	glVertex3f( 1.0f, -0.5f, -4.0f);    // B
	glVertex3f( 0.0f,  0.5f, -4.0f);    // C

	glVertex3f(-1.5f,  0.0f, -4.0f);    // D
	glVertex3f(-1.8f, -1.0f, -4.0f);    // E
	glVertex3f( 0.2f, -1.5f, -4.0f);    // F

	glVertex3f( 1.0f, -0.5f, -4.0f);    // G

	glEnd();

A triangle fan doesn't have to be closed as in this example, just remember that all triangles in a triangle fan share the same vertex which is the origin. As you see here, with only 7 calls to glVertex it was possible to create FIVE triangles as opposed to 6 vertices per 2 triangles when using GL_TRIANGLES flag. The limitation of this is of course that you cannot have a whole model made out of ONE triangle fan because it only has one origin! To use this type of rendering you need to parse the model data in a special way. Well this seems to cover all types of rendering primitives. I didn't demonstrate drawing quads (GL_QUADS) but it is trivial to understand; as I said before, just follow the same rules. There is no source code for this tutorial, just remember all possible flags and practice, practice, practice.

Don't forget to check out some of these OpenGL books

Did this article help you learn something new?

I enjoy writing for the Internet audiences because my thoughts are instantly published to the entire world. My work consists of writing educational articles about making websites to help people learn. If you enjoyed reading this article, or learned something new, then I have succeeded.

If the content on this website somehow helped you to learn something new, please let others know about it by sharing it on your website or on your Facebook page with your friends. In addition you can help by making a donation or bookmarking this site.