|
Rendering Pipeline NotesThe rendering pipeline of Aviatrix3D is a relatively simple structure. In fact, if you picked up a 3D graphics architecture book and compared the idealised version to our code, you'll see a very strong correspondence in the designs. At the lowest level, the pipeline setup is a simple design with extensibility being the primary design goal. Because 3D content can vary so dramatically, various parts of a pipeline may cause unneeded overhead or have a huge performance increase. We choose the extensibility route because it allows the end user to select the culling and sorting algorithms that are most appropriate to their content's needs.
Classes and InterfacesBecause code may find itself in any number of different rendering situations, all of the rendering pipeline is expressed as a collection of interfaces. Individual expressions of parts of the pipeline are then implemented as classes that implement these interfaces. In this way pieces can be mixed and matched in a way that minimises the need to re-implement the same code as hardware and system requirements change. For example, on single processor machines, it's typically not worthwhile having the rendering pipeline be multithreaded, so the pipeline is implemented as a single thread. However, moving the code to run on a multiprocessor machine means just replacing the pipeline management implementation without needing to replace the culling and sorting implemenation, nor the output device handling.Parts of the PipelineIn a classic 3D graphics pipeline, there are 3 basics parts, typically refered to as: APP, CULL and DRAW stages. Our design uses this basic principle and divides the CULL stage in two separate sub stages - SORT and CULL. The SORT stage sits after CULL and before DRAW, and takes care of any sorting that may need to be done after the culling has taken place. Typical examples are state sorting and depth sorting for transparency rendering.
The APP stage is represented by the
Once the user-level code has been processed, the CULL stage is represented
by the
At the end of the rendering process is some sort of surface to draw onto. The
implementation of the surface is represented by the
RenderPipelineManagerTheRenderPipelineManager interface handles all of the
synchronisation and timing between the user code and the rest of the rendering
process. The implementation of this interface can vary depending on the
required usage. As part of the standard classes we've provided implementations
that are single threaded and multithreaded. The single-threaded instance is
typical of the gamer-style rendering architecture as it sequentially calls user
code, processes the changes, fires the rendering pipeline and finally tells the
surface to draw the results. The multi-threaded version creates separate
threads for each pipeline and keeps them all in check.
Available MethodsThe idea behind the design of the interface methods is to allow as much freedom as possible, with API calls to provide the essential information.
Firstly there are methods to add and remove pipeline implementations. Depending
on the type of manager, this may be a set/delete operation rather than
add/remove. The manager should not assume a particular implementation of the
Controlling the rendering is the other aspect of this interface. Three methods
are provided for this task:
Internal supporting interfacesInternal to the implementation of theRenderPipelineManager are
other important interfaces. These are used to communicate between the manager
implementation and node implementations. These interfaces are used as an
abstraction so that implementations can be separated from the basic
functionality without requiring either cyclic compile dependencies or
direct knowledge of a particular node structure and scene graph relationships.
The
The
The RenderPipelineEncapsulating all of the internal processing to go from a scene graph to the OpenGL commands is the job of an implementation of theRenderPipeline interface. As input, the root of the scene graph
to be rendered is taken, and as output, a collection of drawing commands are
issued.
In reality, the implementation of this interface is quite trivial - most of the
hard work is performed by the two working interface stages -
CullStageHandling the basics of culling unneeded parts of the scene graph is the job of theCullStage implementation. This class implements the first part
of the geometry pipeline that performs culling operations on the scene graph
to render the parts you need. Most typically, this involves view frustum
culling, but it may also involve other operations that have to depend on the
scene graph traversal.
Apart from the basic culling, the main requirement of this class implementation
is to take the heirarchical structure of the scene graph and push it down into
a collection of flat structures that basically consists of a single
transformation matrix, the Since this stage is traversing and flattening the scene graph, it is also possible to include other inherent behavioural capabilities. For example, if you wanted to implement a LOD node that should automatically change the selected geometry based on the distance of the viewpoint from the geometry, this would be the place to do it. While you could do it outside in the normal application space, the disadvantage is that if it is under a shared graph then only a single level would be viewable by all paths. Implementing the behaviour here would allow the selection of different levels of detail depending on which path from the root of the scene graph was being evaluated. Such behaviour is not included as part of the default toolkit. It may be offered as part of the utility code at a later date. SortStageAfter the scene graph has been reduced to a flat structure, then sorting needs to take place. The job of sorting it to improve performance and/or visual correctness as well as organise the data into a form that can be processed by the drawing surface(s).
During the sort stage, it may require disassembly of the incoming culled data
into smaller chunks. The most popular form of this is state sorting - reducing
the number of times you turn on and off state while rendering the geometry.
There are various different ways of doing this, but the most popular forms
of sorting have already been taken care of at the node level by implementing
the
The output of the sorting is a list of rendering commands and references to
objects to be rendered. The rendering commands available are defined in the
DrawableSurfaceThe last part of the pipeline is the surface. This takes the sorted output and then (almost) blindly applies it at the right time to the GL context. The surface implementation needs to carefully deal with combining all the elements of the rendering process together. Backgrounds, viewpoints, fog and the various rendering operations must be ordered in the correct order. Because the node implementations only care about their specific rendering instructions the surface will still need to do a lot of work in preparation for each of these.
|
[ Home ]
[ License ]
[ javadoc ]
[ Online Examples ]
[ Download ]
[ j3d.org ] [ Aviatrix3D ] [ Code Repository ] [ Java3D ] [ OpenGL ] [ Books ] [ Contact Us ] Last Updated: $Date: 2007-01-29 20:23:45 $ |