Featured Posts

8. Bump Mapping in GLSL8. Bump Mapping in GLSL Introduction Bump mapping is essential in todays computer games, and computer graphics in general. Would you like to know the best thing about it? It is extremely simple to implement. Bump mapping works...

Read more

Swiftless GLSL Shader DeveloperSwiftless GLSL Shader Developer Swiftless GLSL Shader Developer   Version 0.1a Currently Swiftless GLSL Shader Developer is in it's first public release, and is currently in alpha status, meaning it is not complete and may contain...

Read more

Wordpress Optimization Wordpress Website Optimizations Introduction Wordpress itself is a fairly wonderful tool. Since switching to it, I find it is a lot quicker to make changes to my website and it is also quicker to get...

Read more

36. OpenGL Framebuffers36. OpenGL Framebuffers Introduction Frame buffers are one of those mythical things that we have all heard of, but many beginner OpenGL developers avoid because there is not much information about them, and they can be confusing...

Read more

1. Terrain Class1. Terrain Class Terrain is one of those things that so far, hasn't been perfectly recreated in computer graphics. But it is almost there! Looking over a beautiful landscape can be one of the most amazing feelings in the...

Read more

  • Prev
  • Next

4. OpenGL Primitives – Square (Version 2.0)

Posted on : 25-03-2010 | By : Swiftless | In : OpenGL

Tags: , , , , ,

11

Introduction

Drawing shapes is one of those crucial things we do in OpenGL, because if we don’t draw anything, we don’t see anything. This tutorial was originally very simple, we drew a simple square, but I am going to extend it further and actually show how a bunch of different primitive types work, but don’t worry, we will still get to draw our square.

Different Drawing Types

OpenGL provides us with several different types of shapes that we can draw in order to get the geometry we want on the screen. In brief, they are:

  • GL_LINES
  • GL_LINE_STRIP
  • GL_LINE_LOOP
  • GL_POINTS
  • GL_POLYGON
  • GL_QUADS
  • GL_QUAD_STRIP
  • GL_TRIANGLES
  • GL_TRIANGLE_FAN
  • GL_TRIANGLE_STRIP

Let me give you a brief rundown of these shapes.

GL_LINES

As the name implies, this draws a line from one point to another in 3D space.

GL_LINE_STRIP

A line strip is a series of lines, where each point in the line has a point before it and after it, except for the end points. This is useful if you want to draw a series of lines, maybe you want to draw a circle and a circle is a set of lines.

GL_LINE_LOOP

This is similar to the GL_LINE_STRIP, except the end points double back to each other. So the first point will automatically connect to the end point via one line.

GL_POINTS

Draws a series of points in 3D space, their size can also be changed.

GL_POLYGON

A polygon is a 3D shape with any number of vertices, it is a filled surface.

GL_QUADS

A quad is similar to a polygon, but it limits the number of vertices to 4. This allows OpenGL to break it up into two triangles quite simply for faster processing. In short, a quad is a shape with 4 sides.

GL_QUAD_STRIP

A quad strip is a line of quads, where each quad shares two vertices with the quad before, and after it.

GL_TRIANGLES

Triangles are the ultimate shape in 3D geometry, this is because you can quickly and efficiently calculate how to fill them. GL_TRIANGLES takes a series of 3 vertices; each 3 vertices describe the points for a triangle.

GL_TRIANGLE_FAN

A triangle fan has one central vertex, and all other vertices form triangles extending from this point. Very useful for drawing filled circles.

GL_TRIANGLE_STRIP

A triangle strip is similar to a quad strip and a line strip, but it uses triangles, where two of the three vertices are shared with a triangle before and after itself.

Coding

So let’s stop babbling and get on to drawing a square. I am going to implement a new method, in order to keep our code nice and tidy. This method will be called renderPrimitive and will take no parameters.

void renderPrimitive (void) {

}

Now inside of our display method, we are going to want to call this, so before our glFlush line, make a call to render Primitive.

void display (void) {
…
renderPrimitive(); // Render the primitive
glFlush(); // Flush the OpenGL buffers to the window
}

Ok, good, we have a method we can fill to draw our shape, and we are calling it in our render loop. Next up, we aren’t going to go straight to drawing our shape, but we are going to add a line above our renderPrimitive call, and I’ll explain why. The default position for the camera in OpenGL is at the world origin, which is (0, 0, 0) in 3D space. Because we have a near plane at 1.0, anything drawn between the values of 0.0 and 1.0 on the z axis will be culled automatically. In other words, it won’t be drawn. In order to make sure we can see our shape, instead of positioning further along the z-axis when I set the vertices, I am going to move the entire scene back 5 units, so anything we draw at (0, 0, 0) will actually be drawn at (0, 0, 5). This may sound a little complicated, but trust me on this, and it will be explained a little more in the camera tutorial as the camera tutorial consists of 4 calls we do, before any of our rendering, to make sure we can see what we want.

Now, you can go ahead and add a line before our call to renderPrimitive which will translate (move) our scene 5 units in front of us. This is done with a call to glTranslate which takes three parameters, each one relating to how much we want to move everything on the x, y and z axis.

void display (void) {
…
glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive
renderPrimitive(); // Render the primitive
glFlush(); // Flush the OpenGL buffers to the window
}

And finally everything is now set up for us to actually draw our square. When we want to tell OpenGL we are drawing some geometry, we need to make two calls, one at the start to tell OpenGL we now want to draw a shape, and one at the end, telling OpenGL we have finished drawing our shape.

These calls are glBegin and glEnd, relating to the beginning and the ending of our shape drawing, and glBegin takes one of the geometry types I mentioned earlier as a parameter. Because we are drawing a square, I am going to settle for GL_QUADS, although it would be more efficient to go for a GL_TRIANGLE_STRIP and supply 5 vertices to OpenGL to get the performance of triangles, I am going for simplicity and using only 4 vertices for a quad.

void renderPrimitive (void) {
glBegin(GL_QUADS); // Start drawing a quad primitive
glEnd();
}

At the moment, OpenGL will happily accept this code, but we won’t see anything on the screen. This is because we need to supply the vertex data for each corner of the quad to OpenGL. To make a call to create a vertex we use glVertex. glVertex can take either two or three parameters, and the types for the parameters can change, depending on the type of glVertex call. For example, if we want to draw a 2D vertex using float values, we would call glVertex2f. If we want to create a 3D vertex using double values, we would call glVertex3d. The same also works for integer values, and even arrays of data.

To be clear, the centre of the window, because I have only moved the camera back, is at the location (0, 0, 0). To draw our quad, we are going to create 4 vertices that revolve around this point. I am first going to declare the bottom left corner, followed by the top left, top right and bottom right. This is because it makes it simple to follow how texture coordinates will be assigned later on, as they go in this order.

In between our glBegin and glEnd calls, create the vertex calls like so:

glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

You should now be able to compile and run this, and have it draw a white square in the middle of your window.

Go ahead and experiment with the other geometry types. You should be able to create the square, both filled and outlined, using any of the geometry types above.

If you have any questions, please email me at swiftless@gmail.com

Here are some examples of other geometry types:

Points

void renderPrimitive (void) {
glPointSize(20.0f);
glBegin(GL_POINTS); // Start drawing a point primitive
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
}

Line Loop

void renderPrimitive (void) {
glBegin(GL_LINE_LOOP); // Start drawing a line primitive
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glEnd();
}

Triangle Strips

void renderPrimitive (void) {
glBegin(GL_TRIANGLE_STRIP); // Start drawing a triangle strip primitive
// The first triangle
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
// The end of the second triangle
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner
glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glEnd();
}

Tutorial Code

#include <GL/glew.h> // Include the GLEW header file
#include <GL/glut.h> // Include the GLUT header file

bool* keyStates = new bool[256]; // Create an array of boolean values of length 256 (0-255)

void keyOperations (void) {
if (keyStates[GLUT_KEY_LEFT]) { // If the left arrow key has been pressed
// Perform left arrow key operations
}
}

void renderPrimitive (void) {
glBegin(GL_QUADS); // Start drawing a quad primitive

glVertex3f(-1.0f, -1.0f, 0.0f); // The bottom left corner
glVertex3f(-1.0f, 1.0f, 0.0f); // The top left corner
glVertex3f(1.0f, 1.0f, 0.0f); // The top right corner
glVertex3f(1.0f, -1.0f, 0.0f); // The bottom right corner

glEnd();
}

void display (void) {
keyOperations();

glClearColor(1.0f, 0.0f, 0.0f, 1.0f); // Clear the background of our window to red
glClear(GL_COLOR_BUFFER_BIT); //Clear the colour buffer (more buffers later on)
glLoadIdentity(); // Load the Identity Matrix to reset our drawing locations

glTranslatef(0.0f, 0.0f, -5.0f); // Push eveything 5 units back into the scene, otherwise we won't see the primitive

renderPrimitive(); // Render the primitive

glFlush(); // Flush the OpenGL buffers to the window
}

void reshape (int width, int height) {
glViewport(0, 0, (GLsizei)width, (GLsizei)height); // Set our viewport to the size of our window
glMatrixMode(GL_PROJECTION); // Switch to the projection matrix so that we can manipulate how our scene is viewed
glLoadIdentity(); // Reset the projection matrix to the identity matrix so that we don't get any artifacts (cleaning up)
gluPerspective(60, (GLfloat)width / (GLfloat)height, 1.0, 100.0); // Set the Field of view angle (in degrees), the aspect ratio of our window, and the new and far planes
glMatrixMode(GL_MODELVIEW); // Switch back to the model view matrix, so that we can start drawing shapes correctly
}

void keyPressed (unsigned char key, int x, int y) {
keyStates[key] = true; // Set the state of the current key to pressed
}

void keyUp (unsigned char key, int x, int y) {
keyStates[key] = false; // Set the state of the current key to not pressed
}

int main (int argc, char **argv) {
glutInit(&argc, argv); // Initialize GLUT
glutInitDisplayMode (GLUT_SINGLE); // Set up a basic display buffer (only single buffered for now)
glutInitWindowSize (500, 500); // Set the width and height of the window
glutInitWindowPosition (100, 100); // Set the position of the window
glutCreateWindow ("You’re first OpenGL Window"); // Set the title for the window

glutDisplayFunc(display); // Tell GLUT to use the method "display" for rendering

glutReshapeFunc(reshape); // Tell GLUT to use the method "reshape" for reshaping

glutKeyboardFunc(keyPressed); // Tell GLUT to use the method "keyPressed" for key presses
glutKeyboardUpFunc(keyUp); // Tell GLUT to use the method "keyUp" for key up events

glutMainLoop(); // Enter GLUT's main loop
}
VN:F [1.9.3_1094]
Please rate so I know where to improve the site. 1 means needs a lot of improvement, 10 means perfect. If you leave a low rating, please state why. I don't want people just coming to bash the site.
Rating: 8.6/10 (17 votes cast)
VN:F [1.9.3_1094]
Rating: +7 (from 7 votes)
4. OpenGL Primitives - Square (Version 2.0), 8.6 out of 10 based on 17 ratings

Related posts:

  1. 5. OpenGL Color (Version 2.0)
  2. 6. OpenGL Cube (Version 2.0)
  3. 26. OpenGL Vertex Alphas
  4. 25. OpenGL Vertex Coloring
  5. 7. OpenGL Rotation and Translation (Version 2.0)

Comments (11)

It seems for some reason using this code that the line: if (keyStates[GLUT_KEY_LEFT]) always returns true.

It does also not change when I press the left key. It also does not seem to work with the ‘a’ key, and neither if I just enter the ascii code number.

Any ideas why this happens?

VA:F [1.9.3_1094]
Rating: 5.0/5 (1 vote cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Got it working now – seems the booleans where set to have true as default.

Glut_KEY_LEFT is not working yet though. Only if I specify the ascii code from it, which is fine for me.

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hey Ruud,

I thought I had fixed this tutorial up, but apparently not.

GLUT_KEY_LEFT and other special keys don’t actually work with glutKeyboardFunc, they only work with glutSpecialFunc.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

in later programmes also this particular line is creating a problem…wherein the line is not required i tried deleted it and tried to run the programmes and it was successful…can you jus check and let me noe becauz my other programmes are also not running in this tutorial…

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

all the errors that i am getting are related to this line

bool* keyStates = new bool[256];

missing ‘{‘ before ‘*’
‘new’ : undeclared identifier
initializer is not a constant
syntax error : missing ‘;’ before identifier ‘bool’
‘true’ : undeclared identifier
‘false’ : undeclared identifier

these are the errors displayed when i compile my code in VS2010 after complying it from here…

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

i am not able to compile the above code. its giving an error with the 4th line of your code…i am using VS2010 and GLUT.can you tell me what is going wrong ?

I am thinking of doing Something in OpenGL
A object for example a mobile which i can rotate and also rotate the view.how many tutorials should i go through so as to do this project can u suggest any good e-book..mail me if possible thank you…

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi Varun,

What is the error you are getting? I have all of the version 2.0 tutorials successfully running in VS2010. As long as you have created a standard c++ win32 console application, everything should be fine.

You will want to look at the third camera tutorial for rotating around an object. But I don’t have any tutorials on model loading.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

good tutorial,

few doubts?

in the example you have declared viewport equal to window size.. e.g. my window size – 100, 100. so viewport will be equal to 0-100 width and 0-100 height.

so why not point have coordinateds like
glVertex3f(-10.0f, -10.0f, 0.0f);
why it is
glVertex3f(-1.0f, -1.0f, 0.0f);

why the coordinates range is ~-2.5 to 2.5.

Regards,
Aman

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Hi Aman,

This has to do with the maths behind projection matrices. It’s a little complicated to say off the top of my head, so if you fully want to understand it, have a quick search around on Google, there is a lot information around.

Also, I’ll point out that OpenGL does not use it’s measurement in pixels, it uses units which can be any length depending on the implementation.

You will also notice, that the further back into the scene an object is, the more you can move it to the left/right and top/bottom and still see it because of the perspective view.

Cheers,
Donald

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

First of all: Really great tutorials! :)

My question: Why is there a “f” behind every number?
glTranslatef(0.0f, 0.0f, -5.0f);

I learned to write this way:
glTranslatef(0.0, 0.0, -5.0);

I thought it is set to float by the first “f”.

Greetings

VA:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VA:F [1.9.3_1094]
Rating: +1 (from 1 vote)

Hey Illu,

The glTranslatef with an f on the end is just the OpenGL method that takes float values. Putting an f on the end, is a c++ way of saying this is a float and not a double. Some languages need you to declare the f on the end to distinguish between a float and a double.

Cheers,
Swiftless

VN:F [1.9.3_1094]
Rating: 0.0/5 (0 votes cast)
VN:F [1.9.3_1094]
Rating: 0 (from 0 votes)

Write a comment

Improve the web with Nofollow Reciprocity.