![]() |
Using OpenGL in Visual C++: Part II Simple 2-D Graphics by Alan Oursland [Download the example source] Simple 2-D Graphics The sample program presented in this section will show you how to create the viewport, set up matrix modes, and draw some simple 2-D images. Start by creating a new project named GLSample2 and setting it up for OpenGL like you did with the first program, or use the first program as your starting point. Use ClassWizard to add an OnSize function to CGLSample2View in response to a WM_SIZE message. Edit OnSize to look like this: void CGLSample2View::OnSize(UINT nType, int cx, int cy) Now use ClassWizard to add an OnPaint function to CGLSample2View in response to a WM_PAINT message. Edit OnPaint to look like this: void CGLSample2View::OnPaint() { // device context for painting (added by ClassWizard) CPaintDC dc(this); glLoadIdentity(); glClear(GL_COLOR_BUFFER_BIT); glBegin(GL_POLYGON); glColor4f(1.0f, 0.0f, 0.0f, 1.0f); glVertex2f(100.0f, 50.0f); glColor4f(0.0f, 1.0f, 0.0f, 1.0f); glVertex2f(450.0f, 400.0f); glColor4f(0.0f, 0.0f, 1.0f, 1.0f); glVertex2f(450.0f, 50.0f); glEnd(); glFlush(); } Compile and run the program. You should see a black window with a large multicolored triangle in it. Try resizing the window and watch the triangle resize along with it. OnSize defines the viewport and the viewing coordinates. The viewport is the area of the window that the OpenGL commands can draw into. It is set in this program by calling glViewport(0, 0, width, height); This sets the lower left hand corner of the viewport to the lower left hand corner of the window and sets the height and width to that of the window. The parameters passed into the function are in screen coordinates. Try changing the glViewport command in OnSize to the following. Then compile and run the program to see what happens. glViewport(width/4, height/4, width/2, height/2); Make the window taller than it is wide. Because the viewport is smaller than the screen, part of the triangle will be clipped. Change the code back to the way it was originally The next command called in OnSize is glMatrixMode(GL_PROJECTION). OpenGL maintains three internal matrices to control various transformations. These matrices are name Projection, ModelView, and Texture. The Projection matrix handles transformations from the eye coordinates to clip coordinates. The ModelView matrix converts object coordinates to eye coordinates. The Texture matrix converts textures from the coordinates they are defined in to the coordinates needed to map them onto a surface. glMatrixMode sets which of these matrices will be affected by matrix operations. Don't worry if you don't understand these right now, I'll explain them as needed. We call glLoadIdentity to initialize the project matrix. gluOrtho2D sets the project matrix to display a two dimension orthogonal image. The numbers passed into this function define the space within which you may draw. This space is known as the world coordinates. We now initialize the ModelView matrix and leave OpenGL in this matrix mode. Matrix operations (which include transformations) carried out while in the ModelView mode will affect the location and shape of any object drawn. For example if we called "glRotated(30, 0, 0, 1)" just before our glBegin call in OnPaint, our triangle would be rotated 30 degrees around the lower left corner of the screen. We will look at this more a little later. (For those of you who have used IRIS GL, we have just set up the equivalent of calling mmode(MSINGLE). There is an entire section in the VC++ online documentation detailing the differences between IRIS GL and OpenGL for those who are interested.) OnPaint is the beast that actually draws our triangle. First
we clear our ModelView matrix. This isn't really necessary since we aren't
doing any transformations, but I added it just in case we decide to do
any. Next we clear the color buffer (which in this case happens to be the
screen, but could be a print buffer or bitmap depending on the type of
device context you used to create rendering context ). The next call is
glBegin(GL_POLYGON). This function changes the state of the rendering context.
From an object oriented perspective, it creates an internal object of
type GL_POLYGON, which is defined by all commands issued until glEnd()
is called. We make three glColor4f and three glVertex2f calls to define
our triangle. Let me take a moment at this point to discuss the naming conventions OpenGL uses. All OpenGLcommands use the prefix "gl". There are also a number of "glu" commands which are considered "GL Utilities". These "glu" commands are simply combinations of "gl" commands that perform commonly useful tasks - like setting up 2-D orthographic matrices. Most "gl" commands have a number of variants that each take different data types. The glVertex2f command, for instance, defines a vertex using two floats. There are other variants ranging from four doubles to an array of two shorts. Read the list of glVertex calls in the online documentation and you will feel like you are counting off an eternal list. glVertex2d, glVertex2f, glVertex3i, glVertex3s, glVertex2sv, glVertex3dv... The definition for our triangle uses the following technique. We call glColor4f(1.0f, 0.0f, 0.0f, 1.0f). This sets the current color to Red by specifying the Red component to 1 and the Green and Blue components to 0. We then define a vertex at point (100,50) in our world coordinates by calling glVertex2f(100.0f, 50.0f). We now have a red vertex at point (100,50). We repeat this process, setting the color to Green and Blue respectively, for the next two vertices. The call to glEnd ends the definition of this polygon. At this point there should still be nothing on the screen. OpenGL will save the list of commands in a buffer until you call glFlush. glFlush causes these commands to be executes. OpenGL automatically interpolates the colors between each of the points to give you the multihued triangle you see on the screen. Play with some of the different shapes you can create with glBegin. There is a list of modes and valid commands to create shapes below. In the next version of this program, we will move our drawing routines into the document class. I will also show you how to use the basic transforms and the importance of pushing and popping matrices onto and off of the matrix stack. glBegin(GLenum mode) parameters: GL_POINTS, GL_LINES, GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLES, GL_QUADS, Functions that are valid between glBegin and glEnd: glVertex, glColor, glIndex, glNormal, glTexCoord, glEvalCoord,
|
![]() |