0% found this document useful (0 votes)
31 views

The OpenGL Viewing Pipeline Explained

Chapter 8 provides an overview of transformations in OpenGL, including the camera analogy, viewing and modeling transformations, and projection transformations. It details how to manipulate matrices within the OpenGL viewing pipeline, including the modelview, projection, and viewport matrices, and offers functions for defining these matrices. Additionally, it includes troubleshooting tips and examples for composing transformations effectively.

Uploaded by

kaleab
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
31 views

The OpenGL Viewing Pipeline Explained

Chapter 8 provides an overview of transformations in OpenGL, including the camera analogy, viewing and modeling transformations, and projection transformations. It details how to manipulate matrices within the OpenGL viewing pipeline, including the modelview, projection, and viewport matrices, and offers functions for defining these matrices. Additionally, it includes troubleshooting tips and examples for composing transformations effectively.

Uploaded by

kaleab
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 7

chapter 8

 "OVERVIEW: THE CAMERA ANALOGY" gives an overview of the transformation process


by describing the analogy of taking a photograph with a camera, presents a simple example
program that transforms an object, and briefly describes the basic OpenGL transformation
commands.
 "VIEWING AND MODELING TRANSFORMATIONS" explains in detail how to specify
and to imagine the effect of viewing and modeling transformations. These transformations orient
the model and the camera relative to each other to obtain the desired final image.
 "PROJECTION TRANSFORMATIONS" describes how to specify the shape and orientation
of the viewing volume. The viewing volume determines how a scene is projected onto the screen
(with a perspective or orthographic projection) and which objects or parts of objects are clipped
out of the scene.
 "VIEWPORT TRANSFORMATION" explains how to control the conversion of threedimensional
model coordinates to screen coordinates.
 "TROUBLESHOOTING TRANSFORMATIONS" presents some tips for discovering why
you might not be getting the desired effect from your modeling, viewing, projection, and
viewport transformations.
 "MANIPULATING THE MATRIX STACKS" discusses how to save and restore certain
transformations. This is particularly useful when you're drawing complicated objects that are built
up from simpler ones.
 "ADDITIONAL CLIPPING PLANES" describes how to specify additional clipping planes
beyond those defined by the viewing volume.
 "EXAMPLES OF COMPOSING SEVERAL TRANSFORMATIONS" walks you through a
couple of more complicated uses for transformations.

The OpenGL Viewing Pipeline


Now we will examine the viewing pipeline as it is defined and implemented by the OpenGL
graphics package. OpenGL defines 3 matrices in its viewing pipeline:
 The modelview matrix: This matrix combines the effects of the modelling and viewing
transformations in the general graphics pipeline. Before this transformation, each primitive
is defined in its own coordinate system. After it, all primitives should be in the viewing
coordinate system.
 The projection matrix: This represents the projection of 3-D viewing coordinate onto the
image plane. Like most graphics packages, OpenGL preserves the z-coordinate after
projection and normalises the resulting coordinate system. Clipping is performed
automatically based on the bounds we specify for the view volume.
 The viewport matrix: This matrix defines the part of the display that will be used for
drawing.

In the subsequent sections we will examine how we can define each of these matrices using
C++/OpenGL code. Remember that OpenGL will postmultiply any matrices we specify by the
current matrix (i.e. the one on top of the matrix stack). This means that if we want to specify a
sequence of transformations for any of the viewing pipeline matrices, we must define them in
reverse order.
3.1 The Modelview Matrix

We mentioned in the last chapter that OpenGL maintains a matrix stack that we can use to store
matrices that we may need later. In fact, OpenGL maintains one matrix stack for each matrix in
the viewing pipeline. In other words, there is one modelview matrix stack, one projection matrix
stack and one viewport matrix stack. Therefore, before making any modifications to our current
matrix (the top one on the stack) we must tell OpenGL which matrix we are talking about. The
following line of code specifies to OpenGL that any subsequent transformations that we specify
will apply to the modelview matrix:

glMatrixMode(GL_MODELVIEW);

Now we can use any of the following OpenGL functions to modify the current modelview matrix:
 glTranslate*
 glRotate*
 glScale*
 glLoadMatrix*
 glMultMatrix*
 gluLookAt
The first five of these we have already seen in the last chapter. These are typically used to define
the modelling part of the modelview matrix. That is, they are used to transform the primitives to
form our 3-D scene in world coordinates. However, the last, gluLookAt, needs further explanation.
This function is used to define the viewing part of the transformation. Recall that the viewing
transformation defines the position, direction and orientation of a virtual camera. The basic format
of gluLookAt is as follows:

gluLookAt(x0, y0, z0, xref, yref, zref, Vx, Vy, Vz)

The first three arguments define a position (x0, y0, z0) in 3-D world coordinates. This represents
the position of the virtual camera. The next three arguments define another position in 3-D world
coordinates: (xref, yref, zref). This is the position that the camera is ‘looking’ at. For example, if
we specified (0,0,-10) at the camera position and (0,0,0) as the ‘look’ position, our virtual camera
would be looking along the positive z-axis. Finally we have the last three arguments (Vx, Vy, Vz).
These three values form a 3-D ‘up’ vector that defines the orientation of the camera. If the vector
is not perpendicular to the ‘look’ direction then it is projected so that it is perpendicular.

For example, the following 3 lines define a virtual camera positioned at (8, 0, 8) in world
coordinates, looking at the origin, and with the y-axis as ‘up’.

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(8,0,8,0,0,0,0,1,0);

Note that we have initialised the current modelview matrix to the identity matrix before defining
the viewing matrix. It is always necessary to do this, because OpenGL matrix functions
postmultiply by the current matrix, so if this current matrix is not initialised the results will be
undefined.

If you do not specify a viewing matrix in OpenGL the default parameters are:
 (x0, y0, z0) = (0, 0, 0)
 (xref, yref, zref) = (0, 0, -1)
 (Vx, Vy, Vz) = (0, 1, 0)
That is, the camera is positioned at the origin, pointing along the negative z-axis, with the y-axis
as ‘up’. For many applications this may be sufficient, so sometimes OpenGL programs will not
define a viewing matrix.

Recall from Error! Reference source not found. that the viewing transformation occurs after the
modelling transformation. However, because OpenGL postmultiplies all matrices, it must be
specified before the modelling transformation. The viewing transformation, if specified, will
normally be common to all primitives in the scene. However, the modelling transformation is
normally different for each primitive. Therefore, it is normal to define a single viewing
transformation to begin with, and then to modify it with individual modelling transformations for
each primitive. But because we only have a single current matrix, whenever we define modelling
transformations for a given primitive it will overwrite the common viewing transformation, which
we need to keep for subsequent primitives. How can we ‘remember’ this viewing transformation
so that we don’t need to redefine it for each primitive?

The answer to this question is to use the matrix stack. We can remember the viewing
transformation by pushing it onto the modelview matrix stack, and then when we need it for the
next primitive, we pop it back again. The standard sequence of events is therefore:
 Define the viewing matrix
 For each primitive we want to draw:
o Push the viewing matrix onto the stack
o Postmultiply the viewing matrix by the modelling transformations for this primitive
o Draw the primitive(s)
o Pop the viewing matrix back from the stack

For example, the code example shown below displays two primitives (both 2-D rectangles) using
the same viewing transformation but different modelling transformations.
// initialize modelview matrix to identity
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

// virtual camera is at (8,0,8) looking at the origin


// with the y-axis as ‘up’
gluLookAt(8,0,8,0,0,0,0,1,0);
glClear(GL_COLOR_BUFFER_BIT); // clear screen

// draw primitives
glPushMatrix(); // remember viewing matrix
glRotatef(45,0,0,1); //rotate this primitive
glRecti(0,0,50,50); // draw rectangle
glPopMatrix(); // restore viewing matrix

glPushMatrix(); // remember viewing matrix


glTranslatef(200,0,0); // translate this primitive
glRecti(0,0,50,50); // draw rectangle
glPopMatrix(); // restore viewing matrix

glFlush(); // send all output to display

3.2 The Projection Matrix

Depending on the type of projection required, OpenGL provides 4 alternative functions for
specifying the projection matrix:
 gluOrtho2D
 glOrtho
 gluPerspective
 glFrustum

gluOrtho2D

OpenGL provides two functions for specifying orthographic parallel projections (it does not
support oblique projections). The gluOrtho2D function is intended for use with 2-D graphics only,
as it does not allow you to specify near and far clipping planes. The basic format of gluOrtho2D
is:

gluOrtho2D (xwmin, xwmax, ywmin, ywmax)

The four arguments specify the x-coordinates of the left and right clipping planes, and the y-
coordinates of the bottom and top clipping planes. All coordinates are specified in the viewing
coordinate system (i.e. the virtual camera is at the origin and looking along the negative z-axis,
and the y-axis is ‘up’). In 2-D graphics we just ignore the third coordinate (it is normally set to
zero), so orthographic projections are ideal and no near and far clipping planes are required.

For example, the lines of code shown below define a 2-D orthographic projection that will display
all primitives with x-coordinate between 0 and 640, and y-coordinate between 0 and 480. Note
that, just as with the modelview matrix, the first thing we have to do it tell OpenGL which matrix
we are referring to, and initialise it to the identity matrix.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluOrtho2D(0.0, 640.0, 0.0, 480.0);

glOrtho

An alternative function for defining orthographic projections is glOrtho. This is very similar to
gluOrtho2D except that it allows us to specify near and far clipping planes, in addition to the left,
right, bottom and top ones. The basic format is:

glOrtho (xwmin, xwmax, ywmin, ywmax, dnear, dfar)

Here the six arguments represent the x-coordinates of the left and right clipping planes, the y-
coordinates of the bottom and top clipping planes, and the z-coordinates of the near and far clipping
planes. Again, all coordinate are specified in the viewing coordinate system.

The following code specifies an orthographic projection that defines a view volume that is a
24x24x30 cuboid. The left and right bounds of this view volume are at x=-12 and x=+12, the
bottom and top bounds are at y=-12 and y=+12, the near clipping plane is at the virtual camera
position (z=0) and the far clipping plane is 30 units away from the camera in the viewing direction.
Since the viewing direction of the viewing coordinate system is the negative z-axis in OpenGL,
this means that the far clipping plane is positioned at z=-30 in this example.

glMatrixMode(GL_PROJECTION);
glLoadIdentity();
// arguments are left, right, bottom, top, near, far
glOrtho(-12, 12, -12, 12, 0, 30);

gluPerspective

If a perspective projection is required, OpenGL provides two alternative functions. The first is
gluPerspective. The basic format is:

gluPerspective (theta, aspect, dnear, dfar)

Here, theta represents the height angle of the perspective projection. The height angle is the
angle between the top and bottom bounds of the image (see Error! Reference source not found.).
The next argument, aspect, is the aspect ratio of the image (the ratio of the width to the height).
If OpenGL knows the height angle and the aspect ratio it is straightforward to determine the width
angle. The last two arguments, dnear and dfar, are the z-coordinates of the near and far clipping
planes.

As an example, the following code defines a perspective projection with a height angle of 45o. The
image has an aspect ratio of 1.0 – this means that the width of the image is the same as the height,
and therefore the width angle must also be 45o. The near clipping plane is positioned at z=0, or the
origin of the viewing coordinate system, and the far clipping plane is at a distance of 50 from the
camera. For same reasons given above, this positions it at z=-50.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45, 1.0, 0.0, 50.0);

glFrustum

Recall that perspective projections lead to a view volume in the shape of a frustum. The final
OpenGL perspective projection routine allows you to specify the vertices of this frustum directly.
The basic format is:

glFrustum (xwmin, xwmax, ywmin, ywmax, dnear, dfar)

Here, the first 4 arguments are the x and y coordinates of the left, right, bottom and top clipping
planes at the near clipping plane. The last two arguments, dnear and dfar, represent the z-
coordinates of the near and far clipping planes. Therefore the positions of the four corners of the
near clipping plane are (in viewing coordinates):
 (xwmin, ywmin, dnear)
 (xwmin, ywmax, dnear)
 (xwmax, ywmin, dnear)
 (xwmax, ywmax, dnear)
The positions of the corners of the far clipping plane can be determined from these coordinates,
the centre of projection (which is the origin) and the value of dfar.

For example, the code example given below specifies a perspective projection in which the near
clipping plane is defined by the four corners (-10, -10, -5), (-10, 10, -5), (10, -10, -5) and (10, 10,
-5). Note that the z-coordinates are negated. The dnear argument specifies the distance of the
near clipping plane from the virtual camera, and the virtual camera looks along the negative z-axis
of the viewing coordinate system. The far clipping plane is at a distance 50 from the camera so it
has a z-coordinate of -50.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluFrustum(-10,10,-10,10,5,50);
3.3 The Viewport Matrix

The viewport matrix is defined slightly differently to the modelview and projection matrices. There
is only one function for defining the viewport matrix so we do not need to use glMatrixMode to
tell OpenGL which matrix we are referring to – it is unambiguous. The function is glViewport and
its basic format is:

glViewport(xmin, ymin, xsize, ysize);

Referring to Error! Reference source not found., (xmin, ymin) is the bottom-left corner of the
viewport, in the coordinate system of the screen window (whose origin is at the bottom-left). The
arguments xsize and ysize are the size of the viewport in pixels.

For example, assuming that we have a screen window of size 640x480, the following line defines
the viewport to be of size 300x300 and centred in the screen window.

glViewport(160, 90, 300, 300);

You might also like