The first step is to initialize the window. There are two ways to do this. The first is to use windows code to set up the window, and the other way is to use GLUT which stands for GL Utility Toolkit. This greatly simplifies window creation and makes porting very easy. In this tutorial we will be using GLUT to initialize the window to minimize confusion.
You will first have to install GLUT if you have not already done so, you can obtain pre-compiled binaries form here: http://www.xmission.com/~nate/glut.html .
Don't forget to link OpenGL32.lib, GLu32.lib and GLUT32.lib otherwise your OpenGL programs won't compile.
Now that you have installed GLUT we are ready to start coding.
#ifdef _WIN32
#include
#endif
#include
#include
#include
The first 3 lines check if we are using windows and if so it includes "windows.h" which is required in a windows OpenGL application. The next 3 lines are the headers nessesary for us to use OpenGL in our program.
int main(int argc, char *argv[])
{
glutInit (&argc,argv);
glutInitDisplayMode (GLUT_DOUBLE|GLUT_RGB);
glutInitWindowSize (640, 480);
glutInitWindowPosition (0, 0);
glutCreateWindow ("OpenGL lesson 1");
init ();
glutDisplayFunc (render);
glutReshapeFunc (reshape);
glutMainLoop ();
return 0;
}
GLUT requires that you initialize it in the main() function which is what we are doing here. The first line simply initializes GLUT. The second line tells GLUT what kind of a display we want to use. The two parameters we send to it are GLUT_DOUBLE which means that we want a double buffered window and GLUT_RGB. Then we specify the window size and window position. The two calls 'glutDisplayFunc' and 'glutReshapeFunc' tell GLUT which of our functions to call when it needs to draw the scene and reshape the window. Functions that you pass to GLUT like this must be voids and not accept extra parameters unless they are supposed to. The next call tells GLUT to enter its main loop where it automaticaly calls functions like reshape and render when needed, it does not return once called.
void init(void)
{
glClearColor(0.0 , 0.0 , 0.0 , 0.0);
glShadeModel(GL_SMOOTH);
glClearDepth(1.0f);
glEnable(GL_DEPTH_TEST);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}
This function is called during initialization before the main loop is entered. The first line sets the clear colour, the colour with which the screen is cleared, to black. The first 3 numbers are the intensities of red, green and blue. The fourth number is the alpha value but dont worry about that when clearing the screen. The second line tells OpenGL that we want to use smooth shading on our polygons which means that colours will be 'spread' accross polygons rather then looking flat. The middle 3 lines set up the depth buffer. The depth buffer is what sorts out which objects to draw first so that if there is an object in front of another object it is drawn that way. The final line improves the look of the perspective.
void render(void)
{
glClear(GL_COLOR_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0, 0.0, -4.0);
glBegin(GL_TRIANGLES);
glVertex3f(-1.0, -1.0, 0.0);
glVertex3f(1.0, -1.0, 0.0);
glVertex3f(0.0, 1.0, 0.0);
glEnd();
glutSwapBuffers();
}
This is where the stuff gets drawn on to the screen. First the scene is cleared with the colour we specified in our init()function, which in our case is black. 'glLoadIdentity()' tells OpenGL to reset the current matrix which is the modelview matrix.
The model view matrix contains data for the current position and rotation of the camera. A matrix is a 2D array of numbers which are used to store information. The next line tells OpenGL to move the camera back by 4.0 measurments.
In OpenGL the camera looks down the Z axis by default, so moving negatively along the Z axis will result in the camera moving backwards. The reason we do this is that because the triangle we are about to draw will be drawn at position 0,0,0 by default, where the camera starts off, so if we dont move the camera back we won't be able to see it.
Next we put something on the screen. To do this we first have to specify the type of objects we want to draw, we do this with 'glBegin(GL_TRIANGLES)' which tells OpenGL that we want to draw triangles. The next 3 lines specify positions in space where points should be plotted, when using GL_TRIANGES every 3 points that are specified are linked together to draw a triangle, if for example only 5 points are specified only one trialnge will be drawn using the first 3 points. The points are specified as X,Y,Z. 'glEnd()' tells OpenGL that we have finished specifing points.
Remember how we told GLUT to use double buffer mode? well this is where it comes into effect. First the objects are drawn onto the unseen buffer, then the buffers are swaped to reveal what was drawn.
void reshape(GLint width, GLint height)
{
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(65.0, (float)width / height, 1, 1000);
glMatrixMode(GL_MODELVIEW);
}
This function is called by GLUT when the window needs to be reshaped. The first line resets the viewport to the new size of the window. Then the projection matrix is reset in the next 2 lines and after that the perspective matrix is set up. The perspective matrix is what adds perspective to the scene, meaning that things get smaller in the distance. Then the model view matrix is reset.
The code in this tutorial should produce a white, static triangle in the middle of a black scene. I hope you have enjoyed reading this tutorial and have gained something from it."
This article was originally written by barnseyboy |