CS184 Lecture 41 summary

Standard Graphics Pipeline

You may hear about the graphics "pipeline" that a certain 3D rendering system uses. Normally, the term refers to a hardware rendering engine, but it can also describe the sequence of operations in a software-only renderer. A low-level 3D language like OpenGL makes strong assumptions about the pipeline, but its still possible to perform operations in different orders in different  implementations of OpenGL. For VRML, rendering sequence is hardly constrained at all.

Here is a typical rendering pipeline, taken from Foley and Van Dam's book:

Scene
Graph
Traversal
Transform to
World coords
Coarse reject/
Backface cull
Lighting Viewing
Transformation
View volume
Clipping
Projection Rasterization

Scene graph traversal involves working down the scene graph by DFS and finding all the polygons and accumulated transforms.

Transform to World coordinates applies these transforms.

Coarse rejection removes primitives that are clearly outside the viewing volume, e.g. because they have a bounding box outside that volume.

Lighting is surface illumination. In this pipeline, we assume flat or Gouraud shading. At this step we compute the illumination of the whole surface (flat shading), or of the vertices (for Gouraud shading). If Phong shading is used, it must be applied per pixel and therefore postponed to the rasterization step.

Viewing transformation transforms from world to viewer-centered coordinates.

Clipping is normal volume clipping to the view volume.

Projection is division by the z coordinate in view coordinates.

Rasterization is insertion of a polygon into a Z-buffer, using scan conversion, and interpolation of its shading and depth values from the vertex values.

Space Partitions and Ray-Casting

We move now away from hardware-accelerated graphics like OpenGL/VRML to high-quality rendering. For Ray-tracing and radiosity calculation, one key step and usually the most expensive is ray-casting. That is, sending a ray out from some point in the scene and determining what surface it hits first. This step typically consumes 80% or more of the calculation for ray-tracing.

Intersecting a ray with a single surface is easy. We leave the ray-plane intersection equations to you. For ray-sphere intersection, notice the following:

A ray passing through point p in direction v can be represented parametrically as

p + u v

where u is a scalar parameter > 0, and assume v is a unit vector. The ray intersects a circle of radius r centered at point q if and only if the closest point on the ray to q is less that r away. The vector from q to that closest point is:

(q - p) - ((q - p) . u) u

and the ray will intersect the sphere if the length of this vector is less than r. That is, if

||q - p||2 - ((q - p) . u)2  <  r2

Because the sphere test is so simple, spheres are often used as bounding volumes to simplify testing of more complex shapes.

But the difficulty with ray-casting is not individual surface tests. When we cast a ray, we dont know which of the surfaces (possibly many thousands) in the scene it will hit. Unless we do something first, we would need to try all of them. That is completely impractical. Two kinds of data structures are suitable for "walking" the ray through space and testing it against only a very small number of objects.

Octrees

Octrees are recursively subdivided cubes. Each cube represents a node in the octree. This cube can be subdivided into 8 cubes of equal size, and those nodes form the cubes children in the octree. Octrees are non-uniform in general. That is, the level of subdivision varies from one cube to the next. It adapts to the geometry so that, for example, there might be only two or three (or some other constant number) of surfaces in any node in the octree. Any cube (node) containing more than three surfaces would be subdivided until it contains only three.

Now to perform ray-casting, we first figure out which octree node contains the start point p of the ray. We can do this by starting from the root of the octree and descending to the child containing p until we reach a leaf. Then we test the ray against the surfaces in that leaf. If there are no intersections, we find the point p' which is the exit point of the ray from the current cube.

Then we use p' to find the adjacent cube in the direction of the ray v. We test the ray against the surfaces in that cube for intersections. If there are none, we compute the exit point p'' for the ray etc.

Roughly speaking, if there are N3 cubes in the octree, a ray-casting step only needs to pass through about N of them. So only a small fraction of the object surfaces are tested against the ray.

Binary Space Partitions

Binary space partitions (BSPs) are similar to octrees in that shapes are recursively subdivided by planes. But whereas octrees use only planes that are parallel to the sides of a cube, BSPs use planes through the object faces. An example of a BSP for a set of line segments in the plane will be given in lecture. The goal is to generate regions in the plane which are empty of line segments.

Ray casting through a BSP is similar to an octree. While BSPs are more complex to represent than octrees, the number of regions is smaller and is directly related to the number of surfaces in the environment. For octrees, it is more complicated to figure out the number of nodes.