This is the first in a sequence of educational 3D graphics renderers.

Basic Renderer

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.

Data Structures

Here is a brief description of the data structures from the {@link renderer.scene} and {@link renderer.framebuffer} packages.

Renderer

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:

  1. transformation of the model's vertices from model space to camera space,
  2. projection of the model's vertices from camera space to the image-plane,
  3. transformation of the model's vertices from image-plane to pixel-plane,
  4. rasterizer of the model's primitives into a Viewport.

Here is another way to summarize the four pipeline stages.

  1. Place each vertex from a model in front of the camera (using the model's translation vector).
  2. Project each vertex onto the camera's two-dimensional image-plane (using the mathematical projection formulas).
  3. Transform each projected vertex to a pixel in the viewport (actually, a logical pixel in the pixel-plane).
  4. For each primitive (line segment of point) from the model, determine which pixels in the viewport (actually, logical pixels in the pixel-plane) are in that primitive.

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
}