CS 450: Computer Graphics Course and Syllabus Overview

CS 450: COMPUTER GRAPHICS
VISIBLE SURFACE DETECTION
SPRING 2015
DR. MICHAEL J. REALE
INTRODUCTION
• We’ve talked about drawing surfaces, but what happens when a surface is hidden?
•
E.g., at the back of an object, obscured by another surface, etc.
• We need to determine which surfaces (or parts of surfaces) are visible
• Two general categories (which sometimes overlap):
•
Object-space approaches  deal with objects/primitives themselves
•
Image-space approaches  deal with projected primitives at pixel level
OVERVIEW
• In this slide deck, we will cover the following approaches:
•
Back-face detection
•
Depth-buffer/Z-buffer
•
A-buffer
•
BSP trees
•
Octrees
•
Ray-casting
BACK-FACE DETECTION
BACK-FACE CULLING
• If the normal is facing away from the camera, then the surface is probably behind an object
• In other words, given a normal N and a view direction V, if:
V N 0
•
…the surface is pointing away from the camera and can be removed
• If we’ve already performed the view transform, we only need look at the z coordinate of the normal:
Nz  0
• Back-face culling = removing polygons that are facing away from the camera
BACK-FACE CULLING
• All non-overlapping, convex shapes done! 
• Concave shapes  may obscure themselves  more work to do
• Overlapping shapes (convex or concave)  still more work to do
• However, it is always a good preprocessing step to other approaches  generally cuts the total number
of polygons to render in half
OPENGL FACE CULLING
• To enable or disable face culling in OpenGL:
•
glEnable(GL_CULL_FACE);
•
glDisable(GL_CULL_FACE);
• Notice I said FACE culling (not back-face culling). In OpenGL, you can specify what you want culled with
glCullFace:
•
glCullFace(GL_BACK)  cull back faces (default)
•
glCullFace(GL_FRONT)  cull front faces
•
glCullFace(GL_FRONT_AND_BACK)  cull front AND back faces  no faces drawn (but lines/points still drawn)
• NOTE: Remember that vertices should be in COUNTERclockwise order!
DEPTH-BUFFER/Z-BUFFER
DEPTH-BUFFER/Z-BUFFER
• Depth-buffer/Z-buffer approach
•
Pretty much the standard for depth sorting in almost all applications
•
•
Implemented in graphics hardware
Have depth buffer = separate buffer that holds depth values
•
Initialize to 1.0 (remember: normalized device coordinates)
•
If projected pixel z < depth[x,y]:
• Depth[x,y] = z
• Color[x,y] = pixel’s color
•
Otherwise, ignore pixel
DEPTH-BUFFER/Z-BUFFER
DEPTH-BUFFER/Z-BUFFER
• Advantages:
•
Very easy to implement
•
For opaque surfaces, does not matter what order they are rendered in!
• Disadvantages:
•
Does not work properly with transparent or semi-transparent surfaces (if drawn out of order)
•
Can be a little inefficient  might already have nearest pixel, but still have to check every other overlapping
polygon on that pixel
DEPTH-BUFFER/Z-BUFFER IN OPENGL
• To enable/disable depth-buffer/z-buffer testing in OpenGL:
•
glEnable(GL_DEPTH_TEST);
•
glDisable(GL_DEPTH_TEST);
• You can also set how the z-buffer works with glDepthFunc()
• When clearing your color buffer, you should also clear out your depth buffer:
•
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
• In GLUT, you also have to make sure you have a depth-buffer, so you have to pass in GLUT_DEPTH to
glutInitDisplayMode():
•
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
A-BUFFER
A-BUFFER
• A-buffer
•
Extension of the z-buffer
•
Unlike the z-buffer, can store multiple fragments per pixel
•
Each position in A-buffer has two fields:
•
•
•
Depth field = stores real-number value (positive, negative, or zero)
•
Surface data field = stores surface data OR a pointer
If (depth field >= 0):
•
Depth field = depth of surface
•
Surface data field = color (and other info) of fragment
Otherwise:
•
•
Surface data field = linked list of surface data (RGB, depth, opacity, percent of area coverage, surface identifier, etc.)
Final rendering  merge lists appropriately to get final color
ACCUMULATION BUFFER
• The buffer used for the A-buffer approach is called an accumulation buffer
• That said, accumulation buffers in OpenGL are implemented as a buffer with a single color value per
pixel
•
Do not draw directly into; copy/add whole color buffer into it
•
Use glAccum(GLenum op, GLfloat value); values of op:
•
•
GL_ACCUM = read from color buffer, multiply by value, and add to accumulation buffer
•
GL_LOAD = same as GL_ACCUM, except it REPLACES the values in the accumulation buffer
•
GL_RETURN = takes values from the accumulation buffer, multiplies them by value, and places the result in the color
buffer(s) enabled for writing.
•
GL_ADD /GL_MULT = simply add or multiply the value of each pixel in the accumulation buffer by value and then return
it to the accumulation buffer. For GL_MULT, value is clamped to be in the range [-1.0,1.0]. For GL_ADD, no clamping
occurs.
Used for anti-aliasing and motion blur
BSP TREES
BSP TREES
• BSP Trees = Binary Space Partitioning Trees
•
Used for depth sorting objects
•
Also used for collision detection and intersection calculations (e.g., for ray tracing)
•
Two varieties: axis-aligned and polygon-aligned
•
Basic idea:
•
•
Use plane to divide space in two
•
Sort geometry into these two spaces
•
Repeat process recursively
Traverse trees in a certain way  contents sorted from front-to-back from any point of view
•
Sorting approximate for axis-aligned and exact for polygon-aligned BSPs
AXIS-ALIGNED BSP TREES
• Enclose whole scene in axis-aligned bounding
box (AABB)
• Recursively subdivide that box into smaller
boxes
•
Splitting plane may split box exactly in half OR may shift a little in position
•
Each child box contains some number of objects  repeat splitting until some criteria met
• What plane should we use?
•
Can cycle through each axis for each plane (first x, then y, then z, then x again, and so on)  k-d trees
•
Can pick largest side of box and split along this direction
• Want to avoid splitting objects if possible; if object is split, you can either:
•
Store at current level of tree  only one copy of object in tree, but not as efficient if small objects get stuck up
in upper levels
•
Store in both child nodes  tighter bounds for larger objects, but objects in multiple locations
AXIS-ALIGNED BSP TREES
• To traverse tree:
•
Start at root node
•
Recursively pick branch on same side as viewer
•
When you reach the bottom, go back and do other side of tree
• Effectively a depth-first traversal
• Not EXACTLY sorted front-to-back, since:
•
Contents of leaf nodes may not be sorted themselves
•
Objects may be in multiple nodes of the tree, depending on how splitting is done
POLYGON-ALIGNED
BSP TREES
• Particularly useful for rendering static/rigid
geometry in an exact sorted order
•
Popular for games like Doom, back when
there was no hardware Z-buffer
•
Still used for collision detection
• Polygons = dividing planes
•
Start with one polygon as root
•
Divide all other polygons into inside and outside plane of polygon
•
If other polygon intersects plane  split polygon
•
Choose another polygon in each half-space as divider
•
Repeat process recursively until all polygons in BSP tree
• Time-consuming process  usually create tree once and store for further use
http://vignette2.wikia.nocookie.net/doom/imag
es/b/b3/Imp.png/revision/latest/scale-towidth/256?cb=20050113171050
POLYGON-ALIGNED BSP TREES
• Challenge: ideally want balanced BSP tree  i.e., depth of all branches is the same
• Useful property: for a given view, tree can be traversed in strictly back to front (or front to back) order
•
Determine on which side the root plane the camera is located
•
Go down branch on other side of camera
•
Repeat process recursively
•
Go back up to other branches when hit bottom
POLYGON-ALIGNED BSP TREES
• Example above (back to front):
•
Start at A  C on other side
•
At C  G on other side
•
Output G  go back up tree
•
Output C  go down other branch F
•
Output F  go back up tree
•
Go back up to A
•
Output A  go down other branch B
•
At B  E on other side
•
Output E  go back up tree
•
Output B  go down other branch D
•
Output D
• Final drawing order: G, C, F, A, E, B, D
OCTREES
OCTREES
• Octrees
•
Similar to axis-aligned BSP tree
•
Enclosed entire area in minimal axis-aligned box
•
Split simultaneously in all 3 axes  split point at center of box  makes eight new boxes
•
Keep splitting recursively until max depth is reached or have certain number of objects in box
•
3D version of a quadtree:
•
Example: split until box is 1) empty or 2) contains only one object
OCTREES
• What if object straddles two leaf nodes?
•
Just store in both leaf nodes
•
Use smallest box that contains entire object  inefficient for a small object in the center of a large node
•
E.g., star object in example above
•
Split objects  introduces more primitives
•
Have pointer to object  less efficient and makes editing octree more difficult
OCTREES VS. BSP TREES
• BSP tree can partition things the same way as an octree
• Octree doesn’t need to store additional plane information like BSP trees
• BSP trees can be more efficient because of better splitting
RAY-CASTING
RAY-CASTING
• Ray-casting = shooting a ray from the camera through each position in the projection plane and
checking what object(s) we intersect with  nearest one is used as color for a pixel
•
Alternative (non-real-time) rendering approach
•
Works with polygonal objects as well as implicit objects (e.g., F(x,y,z) = 0)
•
Must intersect ray with ALL objects in scene and pick nearest point  inefficient
•
Partial solution: use BSP trees or similar approaches to reduce intersection computations
RAY-CASTING VS. RAY-TRACING
• Ray-casting = shooting ray to nearest object; special case of ray-tracing
• Ray-tracing = traces multiple ray paths to get global reflection, refraction, etc.