Title: Perspective Projection
1Perspective Projection
- Overview
- Perspective projection
- OpenGL Perspective Matrix
- Orthographic viewing volume to canonical volume
- Canonical to window viewport transformation
2Perspective Projection
- Looking along X axis, similar triangles gives
y
P(x,y,z)
P(xp,yp)
o
-z
d
View Plane
3Perspective Projection
- Looking along Y axis, similar triangles gives
x
P(x,y,z)
P(xp,yp)
o
-z
d
View Plane
4Perspective Projection
- Foreshortening the farther an object is from the
camera, the smaller it appears in the final image - The viewing volume is used to clip objects that
lie outside of it the six sides of the frustum
correspond to the six clipping planes
5Perspective Projection
Q
yV
camera
zQ
zVP
zC
zV
view plane
looking along x-axis
6Perspective Projection
Q
P
yV
camera
zQ
zVP
zV
zC
view plane
By similar triangles, yP / yQ (zC - zVP) / (zC
- zQ) yP yQ (zC - zVP) / (zC - zQ) yP yQ
d / (zC - zQ)
7Perspective Projection
Q
xV
camera
zQ
zVP
zC
zV
view plane
looking along y-axis
8Perspective Projection
Q
P
xV
camera
zV
zC
zQ
zVP
view plane
By similar triangles, xP /xQ (zC - zVP) / (zC
- zQ) xP xQ (zC - zVP) / (zC - zQ) xP xQ
d / (zC - zQ)
9OpenGL Viewing Pipeline
local coords
world coords
view coords
normalized projection coordinates
window coordinates
10View to Canonical Transformation
- In OpenGL, view space is a coordinate system with
the viewer looking down the z axis, with x to
the right and y up - The Projection matrix, or View to Canonical
matrix, takes points in view space and converts
them to points in normalised or canonical space - In the canonical space everything to be drawn is
inside the 2x2x2 cube X-1,1, Y-1,1, and
Z-1,1 - Only parallel projection is needed within the
canonical space
11OpenGL Perspective Matrix
- The matrix contains transformations that convert
view/camera/eye coordinates to projection
coordinates and to normalised/canonical
coordinates (a 2x2x2 cube centred at origin)
12OpenGL Perspective Matrix
- From
- We can expect
- d is the distance to near plane. Later on we
change d to n and let w-z
13OpenGL Perspective Matrix
- We map xp and yp in projection coordinates to xn
and yn in normalised coordinates, using l, r
? -1, 1, b, t ? -1, 1
14OpenGL Perspective Matrix
- Substitute xp and yp into the equations we have
- So now the perspective matrix is
15OpenGL Perspective Matrix
- We now need to get a and b
zha z b, so zn because when z-n, zn -1,
when z-f, zn 1 therefore (-anb)/-n -1
and (-afb)/-f 1 solving the equations for
a, b we have a(fn) / (f-n) b -2fn / (f-n)
16OpenGL Perspective Matrix
- So finally we have the OpenGL perspective matrix
- When perspective projection is called, all 3D
vertices are transformed by this matrix
17Orthographic View Volume
- We have a coordinate system with viewer looking
in the z direction, with x horizontal to the
right and y up - The view volume is a rectilinear box for
orthographic projection - The view volume has
- a near plane at zn
- a far plane at zf
- a left plane at xl
- a right plane at xr
- a top plane at yt
- a bottom plane at yb
18Orthographic View Volume to Canonical
translation matrix
scaling matrix
(
)
(
)
-
-
ù
é
ù
é
ù
é
l
r
l
r
x
2
0
0
1
0
0
0
2
canonical
ú
ê
ú
ê
ú
ê
(
)
(
)
-
-
b
t
b
t
y
2
0
1
0
0
0
2
0
ú
ê
ú
ê
ú
ê
canonical
(
)
(
)
ú
ê
ú
ê
ú
ê
-
f
n
f
n
z
2
1
0
0
0
2
0
0
canonical
ú
ê
ú
ê
ú
ê
1
0
0
0
1
0
0
0
1
û
ë
û
ë
û
ë
(
)
(
)
(
)
-
-
-
l
r
l
r
l
r
ù
é
0
0
2
ú
ê
(
)
(
)
(
)
-
-
-
b
t
b
t
b
t
0
2
0
ú
ê
(
)
(
)
(
)
ú
ê
-
-
f
n
f
n
f
n
2
0
0
ú
ê
y
1
0
0
0
û
ë
A translation followed by a scaling
transformation
-z
x
block centre ( (rl)/2, (tb)/2, -(nf)/2 )
19Finally...
- The last step is to position the picture on the
display surface - This is done by a viewport transformation where
the normalized projection coordinates are
transformed to display coordinates - The parameters of OpenGL glViewport() describe
the origin of the available screen space within
the window and the width and height of the
available screen area, all measured in pixels on
the screen. If the window changes size, the
viewport needs to change accordingly
20Canonical to Viewport Transform
(1,1)
(xmax,ymax)
0
(xmin,ymin)
(-1,-1)
21OpenGL Perspective
- Set matrix mode
- glMatrixMode(GL_PROJECTION)
- Define frustum
- glFrustum(left, right, bottom, top, near, far)
- this describes a perspective matrix that
produces a perspective projection. The current
matrix is multiplied by this matrix and the
result replaces the current matrix - gluPerspective(fov, ratio, near, far)
- Field of view, fov, in y direction (vertical
field of view) - Aspect ratio, a, should match window aspect ratio
- Near and far planes, n and f
- Defines a symmetric view volume
- Specify viewing direction
- gluLookAt(ex,ey,ez,rx,ry,rz,ux,uy,uz)
- Specify where to put canonical view volume
- glViewport(minx, miny, maxx, maxy)
22OpenGL Code
- Void display ()
- glClear(GL_COLOR_BUFFER_BIT GL_DEPTH_BUFFER_BIT
) - glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- glFrustrum(-3, 3, -3, 3, 6, 12)
- glMatrixMode(GL_MODELVIEW)
- glLoadIdentity()
- glTranslatef(0, 0, -9)
- glRotatef(yrot, 0, 1, 0) //COMMENT assume yrot
is a global variable - -gt glPushMatrix()
- glTranslatef(-1.5, 0, 0)
- glutSolidCube(0.5)
- glPopMatrix()
- -gt glPushMatrix()
- glTranslatef(1.5, 0, 0)
- glutSolidCube(0.5)
- glPopMatrix()
- glutWireSphere(2.5, 20, 20)
01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16
17 18 19 20 21
23Explanation
- Line 2 The color buffer and the depth buffer are
cleared - Line 3 We are now modifying the matrix at the
top of the projection matrix stack - Line 4 We set it to be the identity
- Line 5 We compose that identity transformation
with a perspective projection defined so that the
viewing volume is a cone that converges to the
origin, whose lower base is the rectangle of
opposite corners (-3, -3, 6) and (3,3,6), whose
near clipping plane is at z-6 and whose far
clipping plane is at z-12. - Line 6 We are now modifying the matrix at the
top of the modelview matrix stack - Line 7 We set it to be the identity
transformation - Line 8 We compose it with a translation
transformation of vector (0, 0, -9), so that
current local coordinate system has its origin
moved to coordinates (0, 0, -9) (in the absolute
coordinate system) - Line 9 We rotate this new local coordinate
system around the Y axis by an angle yrot - Line 10 We push a new matrix on top of the
modelview stack, it is equal to the one that was
there (and that is now underneath), meaning that
we are still working in the same local coordinate
system. - Line 11 We translate the local coordinate
further with vector (-1.5, 0, 0), thus its origin
is now at (-1.5, 0, -9) - Line 12 We draw a filled cube of size 0.5, glut
creates shapes centered on the current local
coordinate system, so the center of the cube is
at (-1.5, 0, -9), since the coordinate system it
is drawn in was rotated, the cube itself is drawn
rotated.
24Explanation
- Line 13 We remove the top matrix from the
modelview matrix stack. The matrix that was
underneath comes back to the top. The effect is
that the transformations since the last
glPushMatrix() (line 10) are forgotten. Therefore
the current local coordinate systems origin is
back at (0, 0, -9), and still rotated by yrot
around y. - Line 14 We push a new matrix on top of the
stack, saving the current local coordinate system - Line 15 We translate the local coordinate system
by (1.5, 0, 0), its origin is now at (1.5, 0, -9)
- Line 16 We draw another cube of size 0.5 there
- Line 17 We go back to the saved local coordinate
system - Line 18 We draw a sphere of radius 2.5 with 20
subdivisions in longitude and 20 subdivisions in
latitude. It is drawn with its center at the
origin of the local coordinate system, I.e. (0,
0, -9) - Line 19 We force OpenGL to perform all the
preceding drawing operations now - Line 20 We seem to be in a double buffered
context We swap the front and back frame
buffers. What we just drew gets displayed on the
screen, and we are now ready to draw again on the
back buffer.
25Summary
- Modelling Transformation is analogous to
positioning the objects - Viewing Transformation is analogous to
positioning the camera - Projection Transformation is analogous to
choosing a lens for the camera - it determines
what the field of view or viewing volume is. In
addition, it determines how objects are projected
onto the screen - Viewport Transformation is analogous to post
processing the image, e.g., scaling. - Together, the projection transformation and the
viewport transformation determine how a scene
gets mapped onto the computer screen
26Summary - Projection Transformation
- Two basic types of projections are provided by
OpenGL. One type is orthographic, which maps
objects directly onto the screen without
affecting their relative size. Orthographic
projection is used in architectural and
computer-aided design applications where the
final image needs to reflect the measurements of
objects rather than how they might look - The other type of projection is perspective
projection. Foreshortening occurs with this type
of projection because the viewing volume for a
perspective projection is a frustum of a pyramid
(a truncated pyramid whose top has been cut off
by a plane parallel to its base). Objects that
fall within the viewing volume are projected
toward the apex of the pyramid, where the camera
or viewpoint is
27Putting it together
include "GL/glut.h" void init() GLfloat
light_amb 1, 1, 1, 0
glEnable(GL_DEPTH_TEST) glShadeModel(GL_SMOOTH)
glLightfv(GL_LIGHT0, GL_AMBIENT,
light_amb) glEnable(GL_LIGHTING)
glEnable(GL_LIGHT0) glShadeModel(GL_SMO
OTH) glClearColor(1, 1, 1, 0) void
display() glClear(GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT) glLoadIdentity()
gluLookAt(0, 2, 3, 0, 0, 0, 0, 1, 0)
glColor3f(1, 0, 0) glutSolidTeapot(1)
glFlush() void reshape(int w, int h)
glViewport(0, 0, (GLsizei)w, (GLsizei) h)
glMatrixMode(GL_PROJECTION) glFrustum(-1.0,
1.0, -1.0, 1.0, 1, 10.0) glMatrixMode(GL_MODE
LVIEW)
int main(int argc, char argv)
glutInit(argc, argv) glutInitDisplayMode(GLUT_
SINGLE GLUT_RGB GLUT_DEPTH)
glutInitWindowSize(640, 480)
glutInitWindowPosition(100, 100)
glutCreateWindow("Teapot Transformation")
init() glutDisplayFunc(display)
glutReshapeFunc(reshape) // glutFullScreen()
glutMainLoop() return 0
28Putting it together