Title: Projection, Viewing Hidden Surface Removal
1Projection, Viewing Hidden Surface Removal
2Orthogonal Projections
- The simplest of all projections, parallel project
onto view-plane. - Usually view-plane is axis aligned (often at z0)
3Parallel Projections in OpenGL
glOrtho(xmin, xmax, ymin, ymax, zmin, zmax)
Note we always view in -z direction need to
transform world in order to view in other
arbitrary directions.
4Perspective Projections
- Perspective projections are more complex and
exhibit fore-shortening (parallel appear to
converge at points). - Parameters
- centre of projection (COP)
- field of view (q, f)
- projection direction
- up direction
5Perspective Projections
Consider a perspective projection with the
viewpoint at the origin and a viewing direction
oriented along the positive -z axis and
the view-plane located at z -d
a similar construction for xp ?
d
y
yp
-z
divide by homogenous ordinate to map back to 3D
space
6Perspective Projections
glFrustrum(xmin, xmax, ymin, ymax, zmin, zmax)
7glFrustrum
- Note that all points on the line defined by
(xmin,ymin,-zmin) and COP are mapped to the lower
left point on the viewport. - Also all points on the line defined by
(xmax,ymax,-zmin) and COP are mapped to the upper
right corner of the viewport. - The viewing direction is always parallel to -z
- It is not necessary to have a symmetric frustrum
like - Non symmetric frustrums introduce obliqueness
into the projection. - zmin and zmax are specified as positive distances
along -z
glFrustrum(-1.0, 1.0, -1.0, 1.0, 5.0, 50.0)
8Perspective Projections
gluPerspective(fov, aspect, near, far)
9gluPerspective
- A utility function to simplify the specification
of perspective views. - Only allows creation of symmetric frustrums.
- Viewpoint is at the origin and the viewing
direction is the -z axis. - The field of view angle, fov, must be in the
range 0..180 - apect allows the creation of a view frustrum that
matches the aspect ratio of the viewport to
eliminate distortion.
10Perspective Projections
11Lens Configurations
10mm Lens (fov 122)
20mm Lens (fov 84)
35mm Lens (fov 54)
200mm Lens (fov 10)
12The Viewport
- The projection matrix defines the mapping from a
3D world co-ordinate to a 2D viewport
co-ordinate. - The viewport extents are defined as a parameter
of the projection - glFrustrum(l,r,b,t,n,f)?
- gluPerspective(f,a,n,f)?
(r,t,-n)
(l,b,-n)
(w,h,-n)
(-w,-h,-n)
13The Viewport
- We need to associate the 2D viewport co-ordinate
system with the screen co-ordinate system in
order to determine the correct pixel associated
with each vertex.
normalised device co-ordinates
window co-ordinates
14Viewport Transformation
- An affine planar transformation is used.
- After projection to the viewplane, all points are
transformed to normalised device co-ordinates
-11, -11 - glViewport used to relate the co-ordinate systems
glViewport(int x, int y, int width, int height)
15Viewport Transformation
- (x,y) location of bottom left of viewport
within the window - width,height dimension in pixels of the
viewport ? - normally we re-create the window after a window
resize event to ensure a correct mapping between
viewport and window dimensions
static void reshape(int width, int
height) glViewport(0, 0, width,
height) glMatrixMode(GL_PROJECTION) glLoadIden
tity() gluPerspective(85.0, 1.0, 5, 50)
16Aspect Ratio
- The aspect ratio defines the relationship between
the width and height of an image. - Using gluPerspective a viewport aspect ratio may
be explicitly provided, otherwise the aspect
ratio is a function of the supplied viewport
width and height. - The aspect ratio of the window (defined by the
user) must match the viewport aspect ratio to
prevent unwanted affine distortion
aspect ratio 0.5
aspect ratio 1.25
17Camera Viewing
Consider the scene to the left. In previous
discussions we have assumed the viewer positioned
at the origin looking down the negative z axis
scene1
In terms of the final image this would be
equivalent to the scene on the right which is a
lot easier to work with
scene2
18Viewing Transformation
- Effectively, viewing transformations involve
re-interpreting the scene so that we need only
deal with the simpler problem (viewer at origin) - The viewing transformation is applied to all
points in the scene before image is projected - Note that in terms of operations involved this is
not much different than the standard
transformations we have been using on our models
19What is the transformation required to transform
scene1 to scene2?
- Considering the viewer in the diagram a
translation by (ex, ey, ez) brings the eye to the
origin - Then (possibly) a number of rotations to swing
the viewing direction onto the z-axis (N.B. this
is not quite what is done in practice) and the up
direction onto the y-axis - If this transformation is applied to the whole
scene we have our simpler scene2
(ex, ey, ez)
Translate to origin
Align Z-axis
20OpenGL Viewing
- Apply viewing transformations, using the
MODELVIEW MATRIX, to determine positions of
vertices in Camera Coordinates - Default OpenGL camera is located at the origin
looking down the -z axis. - We then employ a projection matrix defined by
GL_PROJECTION to map this to 2D viewport
coordinates. - Finally, this 2D coordinate is mapped to device
coordinates using the viewport definition (given
by glViewport()).
21void display() glClear( GL_COLOR_BUFFER_BIT
GL_DEPTH_BUFFER_BIT ) glViewport(0, 0,
vpWidth/2, vpHeight/2) //bottom left
glPushMatrix() gluLookAt(1, 0, 0, 0, 0, 0,
0, 1, 0) //looking down x axis drawScene()
glPopMatrix() glViewport(vpWidth/2, 0,
vpWidth/2, vpHeight/2) //bottom right
glPushMatrix() gluLookAt(0, 0, 1, 0, 0, 0,
0, 1, 0) //looking down z axis drawScene()
glPopMatrix() glViewport(0, vpHeight/2,
vpWidth/2, vpHeight/2) //top left
glPushMatrix() gluLookAt(0, 1, 0, 0, 0, 0,
0, 0, 1) //down the y axis z-axis is up
drawScene() glPopMatrix()
////////next one drawn in perspective
glViewport(vpWidth/2, vpHeight/2,
vpWidth/2, vpHeight/2) //top right
glMatrixMode(GL_PROJECTION) glPushMatrix()
glLoadIdentity() gluPerspective(45, 1, 1,
10000) glMatrixMode(GL_MODELVIEW)
glPushMatrix() gluLookAt(5, 5, 5, 0, 0,
0, 0, 1, 0) drawScene() glPopMatrix()
glMatrixMode(GL_PROJECTION) glPopMatrix()
glPopMatrix() glFlush() glutSwapBuffers()
22 include "glut.h" //some variables int vpWidth,
vpHeight void init() glClearColor(1.0f,
1.0f, 1.0f, 1.0f) glColor3f(0, 0, 0)
glClearDepth(1) glMatrixMode(GL_PROJECTION)
glLoadIdentity() glOrtho(-2, 2, -2, 2, -2,
2) glMatrixMode(GL_MODELVIEW)
glLoadIdentity() void reshape (int w, int
h) vpWidth w vpHeight h
void drawScene() glColor3f(.5, .5, .5)
glPushMatrix() glTranslatef(0, -1, 0)
glBegin(GL_QUADS) glVertex3f(2, 0,
2) glVertex3f(2, 0, -2) glVertex3f(-2, 0,
-2) glVertex3f(-2, 0, 2) glEnd()
glPopMatrix() glColor3f(0, 0, 0)
glutWireTeapot(1)
23int main() vpWidth 800 vpHeight 800
glutInitDisplayMode(GLUT_SINGLE GLUT_RGBA
GLUT_DEPTH) glutInitWindowSize(vpWidth,
vpHeight) glutCreateWindow ("Sample
Viewports") init() glutDisplayFunc(display)
glutReshapeFunc(reshape) glutMainLoop()
return 0
24Hidden Surface Removal
25Hidden Surface Removal
- In 3d we must be concerned with whether or not
objects are obscured by other objects - Most objects are opaque so should obscure things
behind them - A.K.A. visible surface detection methods or
hidden surface elimination methods - Related problem Hidden Line Removal
26Hidden Surface Removal
? ?
27HSR Algorithms
- In OpenGL we use Backface Culling and Z-buffer
methods but they are many different approaches
varying in Efficiency w.r.t. time and storage
space - Object Precision Methods Based on Modelling
coordinates. Correct to the precision of the
machine (and the model) - Image Precision Per pixel, decide which colour
it should be drawn in. Correct to the precision
of screen window system.
28Back Face Culling
- quick test for fast elimination. It is not always
suitable and rarely sufficient but can reduce
workload considerably - we can choose to render only front facing
polygons
if -90 lt q lt 90 (or cos q gt 0) then the
polygon can be considered front facing and can be
drawn other wise it is culled
u
v
n
29Culling in OpenGL
- OpenGL uses winding to determine front and back
sides of polygons - It is important to wind in a consistent direction
when specifying polygons
glFrontFace(GL_CW) glEnable(GL_CULL_FACE)
30The Z-buffer Algorithm
- most widely used and easy to implement (hardware
or software) - image-space algorithm but loops over polygons
rather than pixels - we rasterize polygon by polygon and determine
which (parts of) polygons get drawn on the screen - Depth testing in OpenGL uses the z-buffer
algorithm
31The Z-buffer Algorithm
- initialize all depth(x,y) to 0 and refresh(x,y)
to background - for each pixel compare evaluated depth value z to
current depth(x,y) - if z gt depth(x,y)
- then
- depth(x,y)z
- refresh(x,y) Isurface(x,y)
32Depth Testing in OpenGL
- Support required for the z-buffer (you need to
enable this in GLUT) - Enable Depth testing in OpenGL
- Set a Clear Depth
- Clear Depth Buffer before displaying
- Glut Initialization
- glutInitDisplayMode(GLUT_DEPTH)
- OpenGL Initialization
- glEnable(GL_DEPTH_TEST)
- glClearDepth(1.0)
- glDepthFunc( )
- Start of display Function
- glClear(GL_DEPTH_BUFFER_BIT )
33No hidden surface removal
Backface Culling only correct in some places but
not adequate for objects which have holes, are
non convex or multiple objects
Culling can reduce workload for depth testing but
we need to ensure that objects are proper solids.
This teapot is not quite a proper solid and as a
result the image is incorrect. However, combining
backface culling with more expensive
depth-testing is usually a good practice.
Depth Testing Only
34 int main() glutInitDisplayMode(GLUT_SINGLE
GLUT_RGBA GLUT_DEPTH) //initialize GLUT
with a depth buffer glutInitWindowSize(vpWidth,
vpHeight) glutCreateWindow ("Sample")
init() glutDisplayFunc(display)
glutMainLoop() return 0
void init() // glClearDepth(1)
glEnable(GL_CULL_FACE) //enable backface
culling glFrontFace(GL_CW) //cull clockwise
wound polygons glEnable(GL_DEPTH_TEST)
//enable z-buffer depth testing void
display() glClear( GL_DEPTH_BUFFER_BIT
GL_COLOR_BUFFER_BIT) //clear both frame
buffer and z-buffer glutSolidTeapot(1.5)
glFlush()
35The Painters Algorithm
- Heedless Painters Algorithm sort by farthest
point and draw in order - sort polygons according to their z values and
render from back to front - we end up drawing over the polygons in the back
(more or less) - problems arise when polygons overlap or are
allowed to pierce one another - Depth sort improves on this by splitting up
overlapping polygons into less ambiguous pieces
36Depth Sort
Heedless Painter generates erroneous result
y
B
A
x
Front view
Far A
z
Far B
B
Ambigous Polygons Split Into two
A
x
Better Depth Sort Result
Top view
37Scan Line Algorithm
- Similar in some respects to the z-buffer method
but handles the image scan-line by scan-line - scanning across each line we determine the colour
of each pixel - default colour everything as background if we
encounter the edge of one polygon colour it
accordingly - for multiple edges do depth evaluation
38BSP Tree algorithm
Alternate eye
5
- Build a Binary Space Partition Tree
- Left child is inside, right outside
- Split faces if necessary
- Traverse the tree to draw the faces in proper
order
6
9b
9
7
8b
9a
1
8
10
8a
2
3
Eye