The OpenGL Viewing Pipeline

plainspecialSoftware and s/w Development

Dec 14, 2013 (3 years and 8 months ago)

67 views

The Viewing Pipeline

Adapted from notes by
S. L. Abrams

http://deslab.mit.edu/DesignLab/courses/13.016/graphics/overview2.html

The viewing pipeline refers to the actions necessary to process the specified geometric primitives and show
them on the display d
evice. For 2D geometry this is easy. First, we specify the world coordinate window, a
region of the 2D plane in which we have defined the geometry. Next, we define the viewport, the region of
the 2D display screen onto which the world window is mapped. Thi
s mapping is potentially comprised of a
translation and a scaling.

For 3D geometry, the viewing pipeline is more complicated and is best explained using the analogy of a
camera. We start with an object and a camera, each of which can move freely in 3D spa
ce. We want to fix
the relative positions of the camera and object so that the camera is looking at the object. The camera then
performs a
projection
, converting the 3D object into a 2D image.



The movement of the object is called a
modeling

transformation
.



The movement of the camera is called a
viewing

transformation.



The conversion from 3D to 2D is called a
projection

transformation.

OpenGL provides functions that perform each of these operations.

Mathematically, the transformations are performed by c
onsidering each vertex of the geometric primitive as
a vector and multiplying it by a matrix that performs the specific transformation.

Note that although the modeling and viewing transformations can be considered
logically

separate
operations, OpenGL con
catenates all of the modeling and viewing transformations into a single matrix. A
separate matrix is provided to perform the projection transformation.

Matrix Manipulation

The various types of transformations that we want to use can be performed mathemati
cally by creating the
appropriate
transformation matrix
.

Some of the transformations only require a 3x3 matrix, but one transformation, translation, requires a 4x4
matrix. Because it is conceptually easier to understand these graphics operations with a si
ngle unified
mathematical model, OpenGL uses a 4x4 matrix for all operations. Also, many display devices can perform
these transformations efficiently using hardware optimized for 4x4 matrix operations.

Because all coordinates are stored as 4D values, we
can manipulate the coordinates with the 4x4
transformation matrix. For a homogeneous coordinate
v

and a matrix
M
:


v
' =
Mv

The OpenGL state maintains two separate transformation matrices, the
modelview

matrix and the
projection

matrix.



Modelview

o

Translation


o

Scaling

o

Rotation




Projection


o

Orthographic

o

Perspective



To specify which matrix you want to modify, use:


glMatrixMode(
mode
);


where
mode

is either GL_MODELVIEW or GL_PROJECTION.

The current value of the selected matrix can be initia
lized by:


glLoadIdentity();


which sets the matrix to the 4x4 identity matrix.




M

=
I

=


1 0 0 0




0 1 0 0



0 0 1 0



0 0 0 1

Recall that


v

=
Iv
.

To replace the current matrix
C

with a completely new matr
ix
M
:


float
m
[16]; /* or double
m
[16]; */


glLoadMatrixf(
m
); /* or glLoadMatrixd(
m
); */



C'

=
M

You can multiply a new matrix
M

onto the current matrix
C
:


float
m
[16]; /* or double
m
[16]; */


glMultMatrixf(
m
); /* or glMu
ltMatrixd(
m
); */



C'

=
CM

Note that the order of matrix multiplication is important, and in general, does
not

commute, i.e.
CM

!=
MC
. In
OpenGL, new matrices
M

are always multiplied onto the current matrix
C

from the right.

The current matrix can be sav
ed and restored by pushing to or popping from the matrix stack:


glPushMatrix(); /* save the current matrix on the stack */


glPopMatrix(); /* restore the current matrix from the stack */

To receive a copy of the current matrix, use the fol
lowing functions:


float
matrix
[16];


glGetFloatv(GL_MODELVIEW_MATRIX,
matrix
);


glGetFloatv(GL_PROJECTION,
matrix
);











Translation


glTranslate{
fd
}(
a
,
b
,
c
);



C'

=
CT

where


T

= 1 0 0
a



0 1 0
b



0 0 1
c




0 0 0 1


(
x
+
a
,
y
+
b
,
z
+
c
, 1) =
T

(
x
,
y
,
z
, 1)

Scaling


glScale{
fd
}(
a
,
b
,
c
);



C'

=
CS

where


S

=
a

0 0 0



0
b

0 0



0 0
c

0



0 0 0 1


(
xa
,
yb
,
zc
, 1) =
S

(
x
,
y
,
z
, 1)

Note that scaling is performed relative to the origin of
the current coordinate system.

Rotation


glRotate{
fd
}(
a
,
x
,
y
,
z
);

where
a

is the (right
-
handed) rotation angle, given in degrees, and (
x
,
y
,
z
) define the axis of rotation.


C'

=
CR

where


R

=


0




M



0





0




0 0 0 1

where
M

is a general 3x3 rotation matrix.

Note the following three special cases of rotation about the coordinate axes.

Rotation about the
x
-
axis





glRotatef(
a
, 1.0, 0.0, 0.0);



R

=

1 0


0


0



0 cos(
a
)
-
sin(
a
) 0




0 sin(
a
) cos(
a
) 0



0 0


0


1

Rotation about the
y
-
axis


glRotatef(
a
, 0.0, 1.0, 0.0);



R

= cos(
a
)

0

sin(
a
)


0



0


1


0


0



-
sin(
a
)


0


cos(
a
)



0



0




0



0


1

Rotation about the
z
-
axis

glRotatef(
a
, 0.0, 0.0, 1.0);



R

=


cos(
a
)

-
sin(
a
)

0

0



sin(
a
)


cos(
a
)

0


0



0


0


1

0



0


0


0

1

Like scali
ng, rotation is performed relative to the origin of the current coordinate system.

Viewing Transformations

The default OpenGL viewpoint is located at the origin, looking down the negative Z
-
axis. The geometry that
we wish to view must either by moved to a

position from which it can be seen from the default viewpoint, or
the viewpoint must be moved so that it can see the geometry.

Note that the modeling and viewing transformations have an inverse relationship: rotating the model
geometry in a positive dire
ction about the X
-
axis is equivalent to rotating the viewpoint in a negative direction
about the X
-
axis.

It is possible to build a viewing transformation by concatenating a series of translations and rotations,
however, this can be quite complex. Instead,

OpenGL provides a simplified function to define the
transformation.


double
eyeX
,
eyeY
,
eyeZ
; /* viewpoint */


double
referX
,
referY
,
referZ
; /* reference point */


double
upX
,
upY
,
upZ
; /* view up vector */


gluLookAt(
ey
eX
,
eyeY
,
eyeZ
,
referX
,
referY
,
referZ
,
upX
,
upY
,
upZ
);

where (
eyeX
,
eyeY
,
eyeZ
) is the viewpoint, (
referX
,
referY
,
referZ
) is a point along the desired line of sight (if
the point is at the center of the scene being looked at, it is usually referred to as the

reference point
), and
(
upX
,
upY
,
upZ
) is the view up vector.

The view up vector is necessary to correctly orient the viewing with regard to rotation about the viewing
direction. The coordinate system defined with the its origin at the viewpoint, its Z
-
axis

pointing from the
viewpoint to the reference point, its Y
-
axis in the direction of the view up vector, and its X
-
axis as necessary
to complete a right handed system, is called the
eye coordinate system
.


Projection Transformations

OpenGL provides two typ
es of projection transformations: orthographic and perspective. Each of these
transformation defines a volume of space called a
frustum
. Only geometry that is inside of the frusum is
displayed on the screen; any portion of geometry that is outside of the f
rustum is
clipped
.



Orthographic




double
left
,
right
,
bottom
,
top
,
near
,
far
;




glOrtho(
left
,
right
,
bottom
,
top
,
near
,
far
);

which defines a rectangular parallelpiped frustum.

An orthographic projection projects a 3D point
v

onto the 2D near clippi
ng plane (sometimes called
the
picture plane
) by constructing a ray through
v

that is parallel to the viewing direction, i.e. the Z
-
axis in the eye coordinate system. The (
x
,
y
) position on the picture plane where the ray intersects
the plane is the 2D proj
ection of
v
.

In other words, if
v

is expressed in the eye coordinate system as (
x
,
y
,
z
), then the orthographic
projection is (
x
,
y
).



Perspective




double
fov
,
aspect
,
near
,
far
;




gluPerspective(
fov
,
aspect
,
near
,
far
);

which defines a truncated pyram
id frustum.

A

perspective projection projects a 3D point
v

onto the 2D picture plane by constructing a ray
through
v

that passes through the viewpoint direction, i.e. the origin of the eye coordinate system.
The (
x
,
y
) position on the picture plane where t
he ray intersects the plane is the 2D projection of
v
.

In other words, if
v

is expressed in the eye coordinate system as (
x
,
y
,
z
), then the perspective
projection is (
near
*
x
/
z
,
near
*
y
/
z
).

Perspective projection produces images that appear more realistic;
it more closely mimics the operation of
the human eye.









Building the Pipeline

Because all of the transformation matrices are mutliplied on the right:


C
' =
CM

and the multiplication of a vertex coordinate with the transformation matrices also occ
urs on the right:


v
' =
Cv

the matrix that is farthest to the right is applied to the vertex first.

We can represent the viewing pipeline as follows:


v
' =
PMv

where
P

is the projection matrix, and
M

is the modelview matrix. Since the modelview matrix

can be though
of logically as separate viewing and modeling transformations:


v
' =
PVMv

where
V

is the viewing matrix and
M

is the modeling matrix.

Note that first we apply the modeling transformation to orient the geometric model, then we apply the
vi
ewing transformation to define the eye coordinate system, and finally we perform the projection from 3D to
2D.

The 2D picture plane forms the world coordinate window, which can be mapped to the screen viewport.

Since the order of the transformations is s
ignificant, we want to invoke the OpenGL functions is the proper
order, i.e. in the
reverse

order in which they will be applied.


glViewport(...); /* screen viewport */



glMatrixMode(GL_PROJECTION); /* specify the projection matrix
*/


glLoadIdentity(); /* initialize to identity */


gluPerspective(...); /* or glOrtho(...) */



glMatrixMode(GL_MODELVIEW); /* specify the modelview matrix */


glLoadIdentity(); /* initialize to identity
*/


gluLookAt(...); /* specify viewing transformation */



glTranslate(...); /* modeling transformations, */


glScale(...); /* as necessary */


glRotate(...);


...