A "renderer" is a collection of algorithms that takes as its input a {@link renderer.scene.Scene} data structure and produces as its output a {@link renderer.framebuffer.FrameBuffer} data structure.
{@code
Renderer
+--------------+
Scene | | FrameBuffer
data ====> | Rendering | ====> data
structure | algorithms | structure
| |
+--------------+
}
A {@link renderer.scene.Scene} data structure contains information that describes a "virtual scene" that we want to take a "picture" of. The renderer is kind of like a digital camera and the {@link renderer.framebuffer.FrameBuffer} is the camera's film. The renderer takes (calculates) a picture of the Scene and stores the picture in the FrameBuffer data structure. The FrameBuffer holds the pixel information that describes the picture of the scene.
The rendering algorithms can be implemented in hardware (a graphics card or GPU) or in software. In this class we will write a software renderer using the Java programming language.
Our software renderer is made up of four "packages" of Java classes. Each package is contained in its own directory. The name of the directory is the name of the package.
The first package is the collection of input data structures. This is called the {@link renderer.scene} package. The data structure files in the scene package are:
The {@link renderer.scene.primitives.Primitive}, {@link renderer.scene.primitives.LineSegment}, and {@link renderer.scene.primitives.Point} classes are in a sub-package called "primitives".
The second package is the output data structure. It is called the {@link renderer.framebuffer} package and contains the file
The third package is a collection of algorithms that manipulate the data structures from the other two packages. This package is called the {@link renderer.pipeline} package. The algorithm files are:
The fourth package is a library of geometric models. This package is called the {@link renderer.models_L} package. It contains a number of files for geometric shapes such as {@link renderer.models_L.Sphere}, {@link renderer.models_L.Cylinder}, {@link renderer.models_L.Cube}, {@link renderer.models_L.Cone}, {@link renderer.models_L.Pyramid}, {@link renderer.models_L.Tetrahedron}, {@link renderer.models_L.Dodecahedron}, and mathematical curves and surfaces.
There is also a fifth package, a collection of client programs that use the renderer. These files are in a folder called clients_r1.
Here is a brief description of the data structures from the {@link renderer.scene} and {@link renderer.framebuffer} packages.
Here is a brief overview of how the rendering algorithms process a {@link renderer.scene.Scene} data structure to produce the pixels that fill in a {@link renderer.framebuffer.FrameBuffer.Viewport} within a {@link renderer.framebuffer.FrameBuffer} object.
First of all, remember that:
The main job of the renderer is to "draw" in the {@link renderer.framebuffer.FrameBuffer}'s {@link renderer.framebuffer.FrameBuffer.Viewport} appropriate pixels for each {@link renderer.scene.primitives.LineSegment} (or {@link renderer.scene.primitives.Point}) in each {@link renderer.scene.Model} from the {@link renderer.scene.Scene}. The "appropriate pixels" are the pixels "seen" by the {@link renderer.scene.Camera}. At its top level, the renderer iterates through the {@link renderer.scene.Scene} object's list of {@link renderer.scene.Position} objects, and for each {@link renderer.scene.Model} object the renderer iterates through the {@link renderer.scene.Model} object's list of {@link renderer.scene.primitives.Primitive} objects. When the renderer has drilled down to a {@link renderer.scene.primitives.LineSegment} (or {@link renderer.scene.primitives.Point}) object, then it can render the line segment (or point) into the framebuffer's viewport.
The renderer does its work on a {@link renderer.scene.Model} object in a "pipeline" of stages. This simple renderer has just four pipeline stages. The stages that a {@link renderer.scene.Model} object passes through in this renderer are:
Here is another way to summarize the four pipeline stages.
To understand the algorithms used in the rendering process, we need to trace through the rendering pipeline what happens to each {@link renderer.scene.Vertex} and {@link renderer.scene.primitives.Primitive} object from a {@link renderer.scene.Model}.
Start with a {@link renderer.scene.Model}'s list of vertices.
{@code
v_0 ... v_n A Model's list of Vertex objects
\ /
\ /
|
| model coordinates (of v_0 ... v_n)
|
+-------+
| |
| P1 | Model-to-camera transformation (of the vertices)
| |
+-------+
|
| camera coordinates (of v_0 ... v_n)
|
+-------+
| |
| P2 | Projection transformation (of the vertices)
| |
+-------+
|
| image-plane coordinates (of v_0 ... v_n)
|
+-------+
| |
| P3 | Viewport transformation (of the vertices)
| |
+-------+
|
| pixel-plane coordinates (of v_0 ... v_n)
|
/ \
/ \
/ \
| P4 | Rasterization, clipping & anti-aliasing (of each line segment)
\ /
\ /
\ /
|
| shaded pixels (for each clipped, anti-aliased line segment)
|
\|/
FrameBuffer.ViewPort
}