|
|
@@ -0,0 +1,157 @@
|
|
|
+Panda has two primary modes of rendering: with or without a separate
|
|
|
+"Cull" traversal.
|
|
|
+
|
|
|
+In the simplest case, Panda renders directly, without a separate Cull
|
|
|
+traversal. In this case, the scene graph is traversed with a simple
|
|
|
+depth-first, left-to-right in-order traversal, and GeomNodes are sent
|
|
|
+to the graphics engine as they are encountered.
|
|
|
+
|
|
|
+When operating in this mode, the only way to control render order is
|
|
|
+to adjust the order of nodes within the hierarchy. It is possible to
|
|
|
+do this by either building the hierarchy in a specific order (each
|
|
|
+reparenting operation in the scene graph appends the new node to the
|
|
|
+end of its parent's children list), or more explicitly, by setting a
|
|
|
+sort order on each arc as it is created or moved (the NodePath
|
|
|
+reparenting methods support an optional sort parameter, and the
|
|
|
+NodeRelation class has a set_sort() method). Normally the sort order
|
|
|
+on each arc is zero, but it may be explicitly set to any integer. A
|
|
|
+node's list of children will always be kept in order from lowest to
|
|
|
+highest sort order, and where siblings have an equal sort order, they
|
|
|
+will be arranged in the order in which they were added.
|
|
|
+
|
|
|
+More commonly, Panda is operated using a Cull traversal. This
|
|
|
+traversal makes a complete pass through the scene graph before
|
|
|
+rendering anything, collecting together all the GeomNodes that are to
|
|
|
+be rendered and arranging them in a suitable order before passing them
|
|
|
+to the graphics engine. It is somewhat inappropriately named;
|
|
|
+although it does do view-frustum culling, so does the simpler direct
|
|
|
+traversal; it should more properly be called the State Sorting
|
|
|
+traversal.
|
|
|
+
|
|
|
+When the Cull traversal is in use, the hierarchy order is irrelevant.
|
|
|
+Instead, the Cull traversal uses a binning system to support user
|
|
|
+control of the order in which things are rendered.
|
|
|
+
|
|
|
+As the Cull traversal encounters GeomNodes, it assigns each one to a
|
|
|
+particular bin, identified by name. These bins are selected by
|
|
|
+setting a GeomBinTransition above the arc in question, or by calling
|
|
|
+NodePath::set_bin().
|
|
|
+
|
|
|
+After all the GeomNodes have been identified, the various bins are
|
|
|
+sorted in order according to each bin's sort index, which is specified
|
|
|
+by GeomBin::set_sort(). This is an arbitary integer assigned to each
|
|
|
+bin, and the lower-number bins are drawn first. Each bin is then
|
|
|
+responsible for drawing its contents--the set of GeomNodes assigned to
|
|
|
+it--in whatever order it likes. The various kinds of bins render
|
|
|
+their GeomNodes in different ways:
|
|
|
+
|
|
|
+ GeomBinStateSorted -- collects together all GeomNodes that share a
|
|
|
+ common state and renders them at once, before switching to the
|
|
|
+ next group of GeomNode with a common state. Attempts to minimize
|
|
|
+ the state changes between groups of GeomNodes. The goal of this
|
|
|
+ bin is to minimize the number of state changes sent to the
|
|
|
+ graphics engine, and so reduce rendering overhead.
|
|
|
+
|
|
|
+ GeomBinBackToFront -- renders everything in order from the furthest
|
|
|
+ away to the closest. This is generally necessary for correct
|
|
|
+ transparent and semitransparent rendering. The ordering is based
|
|
|
+ on the center of each GeomNode's bounding volume, relative to the
|
|
|
+ camera plane.
|
|
|
+
|
|
|
+ GeomBinNormal -- assigns each GeomNode to one of two sub-bins:
|
|
|
+ transparent geometry is assigned to a GeomBinBackToFront, while
|
|
|
+ opaque geometry is assigned to a GeomBinStateSorted. This is the
|
|
|
+ kind of bin that 'default' is defined to be; it is the bin that
|
|
|
+ all GeomNodes are assigned to when no other bin is explicitly
|
|
|
+ specified.
|
|
|
+
|
|
|
+ GeomBinUnsorted -- renders everything in no particular order.
|
|
|
+
|
|
|
+ GeomBinFixed -- renders everything according to a user-specified
|
|
|
+ order, potentially per GeomNode. Each GeomBinTransition that
|
|
|
+ specifies a GeomBinFixed bin may also include an optional sort
|
|
|
+ order (this is an optional second parameter to the
|
|
|
+ GeomBinTransition constructor, as well as to NodePath::set_bin());
|
|
|
+ the GeomBinFixed will render low-number nodes before high-number
|
|
|
+ nodes.
|
|
|
+
|
|
|
+If no bin is explicitly specified, each GeomNode is assigned to a bin
|
|
|
+named 'default', which is of type GeomBinNormal; this bin is created
|
|
|
+at startup and contains two sub-bins, one for transparent geometry and
|
|
|
+one for nontransparent geometry. The nontransparent bin is rendered
|
|
|
+first, with its contents in state-sorted order, followed by the
|
|
|
+transparent bin, with its contents in order from back to front. This
|
|
|
+usually provides correct behavior for transparent and semitransparent
|
|
|
+objects, which must generally be rendered after everything behind them
|
|
|
+has already been rendered.
|
|
|
+
|
|
|
+However, this sometimes fails, particularly with large, flat polygons
|
|
|
+stacked closely in front of one another. In cases like these it may
|
|
|
+be necessary to explicitly specify an ordering.
|
|
|
+
|
|
|
+There is another predefined bin available called 'fixed'. Nothing
|
|
|
+will ever be rendered in 'fixed' (or any other bin, other than
|
|
|
+'default') unless it is explicitly assigned to it. The 'fixed' bin is
|
|
|
+of type GeomBinFixed, and renders its objects according to a fixed
|
|
|
+ordering, specified as the second parameter to the GeomBinTransition
|
|
|
+constructor, or to NodePath::set_bin(). There is also another
|
|
|
+predefined bin called 'background', which is another bin of type
|
|
|
+GeomBinFixed.
|
|
|
+
|
|
|
+The order of all the predefined bins (and their predefined sort
|
|
|
+orders) is as follows:
|
|
|
+
|
|
|
+ 10 - 'default' : GeomBinNormal (opaque sub-bin)
|
|
|
+ 20 - 'background' : GeomBinFixed
|
|
|
+ 30 - 'default' : GeomBinNormal (transparent sub-bin)
|
|
|
+ 40 - 'fixed' : GeomBinFixed
|
|
|
+
|
|
|
+Thus, the 'fixed' bin can be used for things that must be rendered
|
|
|
+correctly relative to each other, but should render after all other
|
|
|
+things in the scene graph, while the 'background' bin can be used for
|
|
|
+things that must render before other transparent things in the scene
|
|
|
+graph (it's particularly useful for large, flat polygons on the
|
|
|
+horizon).
|
|
|
+
|
|
|
+Other bins may easily be defined, either at run time or via a line in
|
|
|
+a Configrc file. It is also possible to redefine any of the
|
|
|
+predefined bins by defining a new bin with the same name.
|
|
|
+
|
|
|
+To define a bin via the Configrc file, add a line beginning with
|
|
|
+"cull-bin" and consisting of three space-separated fields: the name of
|
|
|
+the bin, the bin sort order, and the type of bin. For example, to
|
|
|
+create an bin called 'shadow' to render shadows in no particular
|
|
|
+order, but before any other transparent objects are rendered, you may
|
|
|
+add the line:
|
|
|
+
|
|
|
+ cull-bin shadow 15 unsorted
|
|
|
+
|
|
|
+The valid bin types are normal, unsorted, state-sorted, fixed, or
|
|
|
+back-to-front.
|
|
|
+
|
|
|
+To define a bin at run time, you simply create a bin of the
|
|
|
+appropriate type using its constructor, and then assign it to the
|
|
|
+current render traverser via GeomBin::set_traverser(). To do this,
|
|
|
+you must get a pointer to the current traverser via
|
|
|
+GraphicsStateGuardian::get_render_traverser(). This will either be a
|
|
|
+DirectRenderTraverser or a CullTraverser.
|
|
|
+
|
|
|
+A GeomBin may only be assigned to a CullTraverser. If the current
|
|
|
+render traverser is not a CullTraverser, then Panda is operating
|
|
|
+without a Cull traversal, and you cannot meaningfully assign things to
|
|
|
+GeomBins anyway.
|
|
|
+
|
|
|
+For example, the following Python code creates the same GeomBin
|
|
|
+defined above:
|
|
|
+
|
|
|
+ shadowBin = GeomBinUnsorted('shadow')
|
|
|
+ shadowBin.setSort(15)
|
|
|
+ try:
|
|
|
+ shadowBin.setTraverser(win.getGsg().getRenderTraverser())
|
|
|
+ except:
|
|
|
+ pass
|
|
|
+
|
|
|
+The try .. except block is a good idea to protect against the case in
|
|
|
+which getRenderTraverser() does not return a CullTraverser.
|
|
|
+
|
|
|
+
|