Title: CSC48206820 Computer Graphics Algorithms Ying Zhu Georgia State University
1CSC4820/6820 Computer Graphics AlgorithmsYing
ZhuGeorgia State University
- Lecture 08 and 09
- View Projection
2Outline
- Camera and view transformation
- View volume and projection transformation
- Orthographic projection
- Perspective projection
- Perspective division
- View port transformation
3Outline
43D Scenes and Camera
- In computer graphics, we often use terms that are
analog to theatre or photography - A virtual world is a scene
- Objects in the scene are actors
- There is a camera to specify viewing position
and viewing parameters. - Viewing and projection is about how to position
the camera and project the 3D scene to a 2D
screen.
5Viewing
- In modeling tools, you can create multiple
cameras - But in OpenGL, there is only one camera
- Camera can be animated too
- The 3D scene is rendered through the viewpoint of
the camera - Its important to make sure your objects are
visible through the camera - Note the difference between a camera in computer
graphics and a real camera
6Camera in computer graphics
- Computer graphics uses the pinhole camera model
- This results in perfectly sharp images
- No depth of field or motion blur
- Real cameras use lenses with variable aperture
sizes - This causes depth-of-field out-of-focus objects
appear blurry
7Depth of field
- Depth of view is an important part of the
storytelling process - Direct viewers eyes to a certain area of the
scene - Depth of view can be faked in CG, but needs extra
work
8Motion Blur
- Camera in computer graphics does not generate
motion blur either - Again, it can be faked in CG but performance may
suffer
9Aspects of Viewing
- There are three aspects of the viewing process
- Positioning the camera
- Setting the model-view matrix
- Selecting a lens
- Setting the projection matrix
- Clipping
- Setting the view volume
10Positioning the camera
- Each camera has a location and a direction
- The purpose of viewing transformation is to
position the camera. - In OpenGL, by default the camera is located at
origin and points in the negative z direction
11Positioning the camera
- What if your camera is not at the origin, facing
Z axis? - You use gluLookAt() function call to specify
camera location and orientation - http//pyopengl.sourceforge.net/documentation/manu
al/gluLookAt.3G.html - Note the need for setting an up direction
- Example
glMatrixMode(GL_MODELVIEW) glLoadIdentity() gluL
ookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0., 1.0. 0.0)
12Viewing Transformation in OpenGL
- gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx,
upy, upz) - atx, aty, atz will be mapped to the center of the
2D window
13Moving the Camera
- No matter where the camera is initially,
eventually it needs to be transformed to the
origin, facing Z axis - in order to make the subsequent stages in the
graphics pipeline very efficient - But the picture taken by the (virtual) camera
should be the same before and after the camera
transformation - How to achieve this?
- Construct a view transformation matrix to
transform the camera to the origin, facing -Z - Apply the view transformation matrix to every
object in the virtual scene - This view transformation is not visible
- Internally gluLookAt() creates such a matrix
14What does gluLookAt() do?
- gluLookAt(eyex, eyey, eyez, atx, aty, atz, upx,
upy, upz) is equivalent to - glMultMatrixf(M) // post-multiply M with current
model-view matrix - glTranslated(-eyex, -eyey, -eyez)
- Where M
- u, n, v are unit vectors.
15What does gluLookAt() do?
- Internally OpenGL creates a view matrix and
post-multiplies it with the current model-view
matrix (normally an identity matrix) - void reshape (int w, int h)
-
- glViewport (0, 0, (GLsizei) w, (GLsizei) h)
- glMatrixMode (GL_PROJECTION)
- glLoadIdentity ()
- gluPerspective(65.0, (GLfloat) w/(GLfloat) h,
1.0, 20.0) - glMatrixMode(GL_MODELVIEW)
- glLoadIdentity()
- gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.,
1.0. 0.0) -
- Current_MV_matrix ? current_MV_matrix
view_matrix
16gluLookAt()
- gluLookAt() should be called before any OpenGL
model transformation function calls - Thats why gluLookAt() is normally placed in
reshape() because reshape() is called before
display() - Normally model transformation calls are placed in
display() function - If you place transforms calls in other functions,
pay attention to the call sequence
17gluLookAt()
- Why?
- Because the view transformation matrix needs to
be applied to every object (vertices) in the
virtual scene - All the model transformations have to be finished
before the view transformation. - Otherwise the realism is lost
- That means the view transformation matrix must be
post-multiplied to the current modelview matrix
before any model transformations - p I x V x T x R x p
18View transformation
- Again, there are matrix multiplications behind
each gluLookAt() call - Normally at the start of your display() function,
your current model-view matrix should be the view
matrix - Be careful when you call glLoadIdentity() in you
display() function, you may unintentionally wipe
out the view matrix
19Example
- void reshape (int w, int h)
- glViewport (0, 0, (GLsizei) w, (GLsizei) h)
- glMatrixMode (GL_PROJECTION)
- glLoadIdentity ()
- gluPerspective(65.0, (GLfloat) w/(GLfloat) h,
1.0, 20.0) - glMatrixMode(GL_MODELVIEW)
- glLoadIdentity()
- gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0., 1.0.
0.0) -
- void display(void)
-
- glLoadIdentity() // You just wipe out the view
matrix -
20A safer approach
- void reshape (int w, int h)
- glViewport (0, 0, (GLsizei) w, (GLsizei) h)
- glMatrixMode (GL_PROJECTION)
- glLoadIdentity ()
- gluPerspective(65.0, (GLfloat) w/(GLfloat) h,
1.0, 20.0) - glMatrixMode(GL_MODELVIEW)
- glLoadIdentity()
- gluLookAt(1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0., 1.0.
0.0) // current model-view matrix is view matrix -
- void display(void)
-
- glPushMatrix() // current model-view matrix
(i.e. view matrix) is pushed into matrix stack -
- glPopMatrix() // current model-view matrix is
view matrix again -
21The bottom line
- Understanding the transformations (and matrix
multiplications) behind the OpenGL calls can save
you a lot of trouble - Dont blindly follow the code pattern in sample
programs - Understand the relationship among
- Current model-view matrix
- Camera transformations
- Model transformations
- OpenGL matrix stack
- You should be able to trace the current
model-view matrix in your code, if needed - E.g. Assignment 1, question 2
22Projection Transformation
- Viewing transformation transform the camera to
the origin and look-at direction with negative Z
axis. - Before one can actually render a scene, all
relevant objects in the scene must be projected
to some kind of plane or into some kind of simple
volume - After that, clipping and rendering are performed
- Projection transformation maps all 3D objects
onto the viewing plane to create a 2D image.
23Projection Transformation
- The previous section described how to compose the
desired modelview matrix so that the correct
modeling and viewing transformations are applied.
- Now we explain how to define the desired
projection matrix, which is also used to
transform the vertices in your scene
24Projection transformation
25View volume (frustum)
- We need to define a view volume for projection
- Everything inside the view volume will be
projected to the 2D plane - Everything outside the view volume will be
clipped and ignored - The job of projection transformation is to
transform the view volume (and everything in it)
to a canonical view volume - Canonical view volume a unit cube centered at
origin - It has minimum corner of (-1, -1, -1) and maximum
corner of (1, 1, 1)
26View volume (frustum)
27Canonical view volume
- The coordinates in this volume is called
Normalized Device Coordinates (NDC) - The reason for transforming into the canonical
view volume is that clipping is more efficiently
performed there - especially in hardware implementation
- The canonical view volume can also be
conveniently mapped to 2D window by view port
transformation
28Projection transformation
- Two basic projections in OpenGL
- Orthographic projections
- Useful in applications where relative length
judgment are important - Can also yield simplifications where perspective
would be too expensive, e.g. in some medical
visualization applications - Perspective projections
- Used in most interactive 3D applications
29Orthographic Projection
- Projection lines are orthogonal to projection
surface
30Orthographic Projection
- Projection plane parallel to principal face
- Usually form front, top, side views
isometric (not multiview orthographic view)
front
in CAD and architecture, we often display three
multiviews plus isometric
side
top
31Orthographic Projection
- Preserves both distances and angles
- Shapes preserved
- Can be used for measurements
- Building plans
- Manuals
- Cannot see what object really looks like because
many surfaces hidden from view - Often we add the isometric view
32Orthographic Projection in OpenGL
- Specify an orthographic view volume in OpenGL
- glOrtho(left,right,bottom,top,near,far)
- Anything outside the viewing frustum is clipped.
near and far are distances from camera
33Orthographic Projection in OpenGL
- The orthographic view volume is a rectangular
volume - The orthographic view volume is along the
negative Z axis - Remember that projection transformation happens
after the view transformation - At this point, the camera is at the origin,
pointing to the negative Z axis
34What does glOrtho() do?
- Internally OpenGL will create the following
matrix -
- where
- tx - (right left) / (right - left)
- ty - (top bottom) / (top - bottom)
- tz - (zFar zNear) / (zFar - zNear)
- The current projection matrix is multiplied by
this matrix and the result replaces the current
projection matrix
35glOrtho()
- There is a current projection matrix in OpenGL
- Before calling glOrtho(), you need to tell OpenGL
that you are modifying the projection matrix. - glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- glOrtho(left, right, bottom, top, near, far)
- glMatrixMode(GL_MODELVIEW)
-
- After calling glOrtho(), you want to set the
current matrix to GL_MODELVIEW matrix so the
subsequent transformation calls wont affect the
projection matrix
36Orthographic projection
- The matrix created by glOrtho() will transform
the orthographic view volume to canonical view
volume - A cube that extends from -1 to 1 in x, y, z.
- This is often called the clip space.
- The next steps are clipping, perspective
division, and view port transformation - Well discuss clipping later
37Perspective Projection
- Projectors converge at center of projection
38Advantages Disadvantages
- Objects further from viewer are projected smaller
than the same sized objects closer to the viewer - Make images look realistic
- Equal distances along a line are not projected
into equal distances - Angles preserved only in planes parallel to the
projection plane - More difficult to construct by hand than
orthographic projection (but not more difficult
by computer)
39Perspective Projection in OpenGL
- We define the perspective view volume by calling
- glFrustum(left,right,bottom,top,near,far)
- Again, near and far are distances from camera
- However, with glFrustum it is often difficult to
get the desired view
40Perspective Projection in OpenGL
- gluPerpective(fovy, aspect, near, far) often
provides a better interface - However, it assumes that viewing window is
centered about the negative Z axis
aspect w/h
41Perspective Projection
- Unlike the orthographic view volume, the
perspective view volume is a like truncated
pyramid - The perspective view volume is also along the
negative Z axis - Remember that projection transformation happens
after the view transformation - At this point, the camera is at the origin,
pointing to the negative Z axis
42Perspective Projection
- The job of perspective projection is to transform
this view volume (and everything in it) to a
canonical view volume - Everything outside of this volume will be clipped
and ignored
43Perspective Projection
- Unfortunately there is no 4x4 matrix that can
achieve the perspective transformation - But there is a workaround called perspective
division - Use a 4x4 matrix to generate a different kind of
homogeneous points. - Then divide the first 3 components with the 4th
component (w) - This is why homogeneous coordinates are used in
3D graphics it allows matrix multiplications
being used in projection transformation - Well see an example later
44What does glFrustum() do?
- Internally OpenGL creates the following matrix
- A (right left) / (right - left)
- B (top bottom) / (top - bottom)
- C -(zFar zNear) / (zFar - zNear)
- D (-2 zFar zNear) / (zFar - zNear)
- The current projection matrix is multiplied by
this matrix and the result replaces the current
projection matrix
45What does gluPerspective() do?
- Internally OpenGL creates the following matrix
- The current projection matrix is multiplied by
this matrix and the result replaces the current
matrix
46Perspective Projection in OpenGL
- There is a current projection matrix in OpenGL
- Before calling gluPerspective(), you need to tell
OpenGL that you are modifying the projection
matrix - The following code would normally be part of the
initialization routine - glMatrixMode(GL_PROJECTION)
- glLoadIdentity()
- gluPerspective(fovy, aspect, near, far)
- glMatrixMode(GL_MODELVIEW)
47Aspect Ratio
- The aspect ratio in gluPerspective should match
the aspect ratio of the associated viewport - Normally, gluPerspective(fov, w/h, near, far)
- W is the width of your window, h is the height of
your window - You want the aspect ratio of your perspective
view volume to match the aspect ratio of your
window - Otherwise, your final image will look distorted
- E.g. if you set aspect ratio to be a constant
value, then when you resize your window, your
image will look distorted
48Perspective projection
- The matrix created by glFrustum() or
gluPerspective() will transform the perspective
view volume to a canonical view volume - A cube that extends from -1 to 1 in x, y, z.
- This is often called the clip space.
- The next steps are clipping, perspective
division, and view port transformation - Well discuss clipping later
49The journey of a vertex so far
- The vertex will be transformed first by the
model-view matrix and then by the projection
matrix - p P x V x M x p
E.g. glTranslatef() glRotatef()
E.g. gluLookAt()
E.g. gluPerspective()
50After the perspective projection
- As the result of the these transformations,
vertex p is transformed to p - After perspective projection, the 4th element of
the homogenous coordinates of p may not be 1 any
more - We have to homogenize it to get the real
coordinates - Divide every element by the 4th element (called
w)
Normalized Device Coordinates
After perspective transformation
51Perspective division
- This operation is also called perspective
division - The homogenized coordinates are called Normalized
Device Coordinates - This is the coordinates for point p in the
canonical view volume - Now we are ready to map this point to the window
52View port transformation
53View port transformation
- View port transformation transforms x and y from
normalized device coordinates to window
coordinates - Note that z value of the normalized device
coordinates are not transformed in this stage - Because z axis is orthogonal to the window (2D
plane) and Z values have no effect in the mapping - Remember our eye is looking down negative Z
- But this z value is not lost. It will be passed
down to the rasterizer stage - Will be used in scan conversion and depth buffer
test
54View port transformation in OpenGL
- glViewport(GLint x, GLint y, GLsizei width,
GLsizei height) - x, y Specify the lower left corner of the
viewport rectangle, in pixels. The initial value
is (0,0). - width, height Specify the width and height of
the viewport.
55What does glViewport() do?
- Let (xnd, ynd) be normalized device coordinates.
Then the window coordinates (xw, yw) are computed
as follows - xw (xnd 1)(width / 2) x
- yw (ynd 1)(height / 2) y
- Its a matrix multiplication too.
- Now we know where to place this particular vertex
in the final 2D image
56glViewport()
- glViewport(GLint x, GLint y, GLsizei width,
GLsizei height) - X and y are normally set to (0, 0)
- Width and height are normally set to window width
and height - This means your 2D image size matches your window
size - You can make your image smaller or bigger than
the window by adjusting those values - E.g. put multiple images in one window
57The journey of a vertex
58Why do we spend so much time on transformations?
- Because thats where many people find OpenGL
programs hard to understand - You need to know those low level details when you
write vertex shader programs - Your vertex shader, not OpenGL, are supposed to
handle the model, view, and projection
transformations - In your vertex shader, youll have to deal
directly with transformation matrices and matrix
multiplications
59Example
- / planet.c/
- include ltGL/glut.hgt
- static int year 0, day 0
- void init(void)
-
- // Specify the color (black) used to clear the
frame buffer (but not actually do it) - glClearColor (0.0, 0.0, 0.0, 0.0)
- glShadeModel (GL_FLAT) // choose shading
model -
60Example
- void display(void)
-
- glClear (GL_COLOR_BUFFER_BIT) // Actually
clear the frame buffer - glColor3f (1.0, 1.0, 1.0) // set the color
for each vertex - glPushMatrix() // current modelview matrix is
the view matrix - glutWireSphere(1.0, 20, 16) // draw sun,
internally call glVertex3f() - glRotatef ((GLfloat) year, 0.0, 1.0, 0.0) //
Multiply modelview matrix with a //
rotation matrix - glTranslatef (2.0, 0.0, 0.0) // Multiply
current modelview matrix with a - // translation matrix
- glRotatef ((GLfloat) day, 0.0, 1.0, 0.0) //
Multiply current modelview matrix // with a
rotation matrix - glutWireSphere(0.2, 10, 8) // draw smaller
planet, internally call // glVertex3f() - glPopMatrix() // current modelview matrix is
view matrix again - glutSwapBuffers() // swap double buffers
-
61Example
- void reshape (int w, int h)
-
- glViewport (0, 0, (GLsizei) w, (GLsizei) h)
// Define view port transformation -
- glMatrixMode (GL_PROJECTION) // Were going
to modify current projection matrix - glLoadIdentity () // initialize projection
matrix to the identity matrix - // create perspective projection matrix and
post-multiply it with the current // projection
matrix gluPerspective(60.0, (GLfloat)
w/(GLfloat) h, 1.0, 20.0) -
- glMatrixMode(GL_MODELVIEW) // Were going to
modify current model-view matrix - glLoadIdentity() // initialize modelview
matrix to identity matrix - // place camera, internally generates a view
matrix and - // then post-multiply the current modelview
matrix with the view matrix - gluLookAt (0.0, 0.0, 5.0, 0.0, 0.0, 0.0, 0.0,
1.0, 0.0) -
62Example
- void keyboard (unsigned char key, int x, int y)
-
- switch (key)
- case 'd'
- day (day 10) 360
- glutPostRedisplay() // force a call to
display() - break
- case 'D'
- day (day - 10) 360
- glutPostRedisplay()
- break
- case 'y'
- year (year 5) 360
- glutPostRedisplay()
- break
- case 'Y'
- year (year - 5) 360
- glutPostRedisplay()
- break
63Example
- int main(int argc, char argv)
-
- glutInit(argc, argv)
- glutInitDisplayMode (GLUT_DOUBLE GLUT_RGB)
- glutInitWindowSize (500, 500)
- glutInitWindowPosition (100, 100)
- glutCreateWindow (argv0)
- init () // clear frame buffer and select
shading model - glutDisplayFunc(display) // register event
handlers - glutReshapeFunc(reshape)
- glutKeyboardFunc(keyboard)
- glutMainLoop() // Start the event loop
- return 0
-
64Summary
- Viewing and projection is about how to position
the camera and project the 3D scene to a 2D
screen. - In OpenGL, view transformation is conducted by
manipulating modelview matrix. - Projection transformation is conducted by
manipulating projection matrix. - Viewport transformation is conducted by
glViewport()
65Readings
- OpenGL Programming Guide chapter 3
- OpenGL FAQ on Viewing
- http//www.opengl.org/resources/faq/technical/view
ing.htm
66Next Lecture
- Lighting and shading
- Now we know where to place the vertices in the
final 2D image, the next step is to calculate
their colors