3D Coordinates

3D graphics adds a Z coordinate

OpenGL coordinate system is right-handed - +X to the right, +Y up, +Z out of screen

Other software or application domains may use other coordinate systems






3D Viewing

An orthographic 3D viewing volume is defined by glOrtho.
This is an axis-aligned box containing the region to be drawn.



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

Note that near and far can be confusing - they are the negatives of the Z values for the corresponding planes.






glOrtho


glOrtho(-5, 8, -4, 4, -1, 3)






3D Transformations

All OpenGL transformation functions are 3D; we can now use the Z coordinate

glTranslatef(x, y, z)

Moves objects by (x, y, z) units.


glRotatef(angle, x, y, z)

Rotates objects around the axis (x, y, z), by angle degrees.

Note that "the axis (x, y, z)" means a line that from the origin (0, 0, 0) through the point (x, y, z)


glScalef(x, y, z)

Resizes objects by the factor x in the X direction, y in the Y direction, and z in the Z direction.






Hidden Surfaces

Hidden surfaces provide occlusion depth cue






Hidden Surface Algorithms

Many different algorithms developed over the years






Ray Tracing


CC-BY-SA diagram by Henrik





Depth Buffering

Rendering a polygon means filling pixels

Color buffer contains RGB color of each pixel drawn

Depth buffer contains depth of each pixel drawn

ColorDepth





Depth Buffer






Depth Buffer

When drawing a new pixel, compare new depth to what's stored in depth buffer

ColorDepth

Polygons can be drawn in any order
Polygons can intersect






OpenGL Depth Buffering

Space must be allocated for the depth buffer:

glutInitDisplayMode(GLUT_RGB|GLUT_DOUBLE|GLUT_DEPTH)

Depth buffering must be enabled:

glEnable(GL_DEPTH_TEST)

Depth buffer must be cleared each frame:

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)





Depth Fighting

Depth values have limited resolution

i.e. the numbers are not infinitely precise

Rounding errors occur when polygons are filled

Polygon overlap can cause "depth-fighting"






Perspective & Camera Movement






Perspective Projection


CC-BY-SA image by Alex Sandri





Orthographic vs Perspective

Orthographic projection : projects rectilinear box onto display
Objects will not appear to change size with distance






Orthographic vs Perspective

Perspective projection : projects frustum (truncated pyramid) onto display
Near objects appear larger, distant objects appear smaller






Perspective






glFrustum






Perspective Projection

GL's perspective projection is, conceptually, a pin-hole camera, located at origin, looking down -Z axis


Camera has a field-of-view - angle of region viewed

Small angle = narrow field-of-view = telephoto lens
Large angle = wide field-of-view = wide-angle lens






gluPerspective



CC-BY-SA image by Martin Kraus





gluPerspective

    gluPerspective( fovy, aspect, zNear, zFar )

fovy = field of view, in Y direction, in degrees

aspect = aspect ratio (X:Y) of window

zNear = distance to near clipping plane

zFar = distance to far clipping plane

The "eye-point" of the perspective projection is at (0,0,0)


Example:

    gluPerspective(45, 1.333, 0.1, 100)





Sidebar: using glFrustum

Computing the frustum for a viewpoint relative to a desired virtual viewing plane






glFrustum






glFrustum

Stereoscopic projection frusta - two different viewpoints, common viewing plane.






glFrustum

Depth-of-field - average many frusta with common focus plane






Camera Movement

The OpenGL camera is always positioned at the origin, looking down the -Z axis.

The camera itself never moves.



Looking at the final image produced, moving a camera is equivalent to moving the world in the opposite direction.

e.g. moving everything to the right is will produce the same image as moving the camera to the left.






Camera Movement

To give the effect of moving the perspective viewpoint in OpenGL, use a transformation at the beginning of the frame, which affects all objects.

For example, to move the camera 10 units from the origin in the +Z direction, translate the world by -10 in Z:

def draw():
    glMatrixMode(GL_PROJECTION)
    glLoadIdentity()
    gluPerspective(fovy, 1, 0.1, 100)

    glMatrixMode(GL_MODELVIEW)
    glLoadIdentity()
    glTranslatef(0, 0, -10)

    drawObjects()





Camera Movement

For general camera movement:

def draw():
    global cameraPos
    global cameraHeading

    glLoadIdentity()
    glRotatef(-cameraHeading, 0, 1, 0)
    glTranslatef(-cameraPos[0], -cameraPos[1],
                 -cameraPos[2])

    drawObjects()





Inverting a Transformation

Inverse of glTranslatef(x, y, z) is glTranslatef(-x, -y, -z)

Inverse of glRotatef(angle, x, y, z) is glRotatef(-angle, x, y, z)

Inverse of glScalef(x, y, z) is glScalef(1.0/x, 1.0/y, 1.0/z)


Inverse of a series of transformations is the inverses of the individual transformations, in reverse order.






gluLookAt

Alternative method of camera control
gluLookAt computes and applies an appropriate translation & rotation


    gluLookAt(cameraX, cameraY, cameraZ,
              lookX, lookY, lookZ,
              upX, upY, upZ)

cameraX, cameraY, cameraZ is camera location - point to look from

lookX, lookY, lookZ is point to look at

upX, upY, upZ is "up-direction" for the camera - affects camera roll



Creative Commons License
This document is by Dave Pape, and is released under a Creative Commons License.