Browse Source

render order documents

David Rose 21 years ago
parent
commit
eead112d48

+ 0 - 168
panda/src/doc/howto.control_render_order

@@ -1,168 +0,0 @@
-NOTE: As of April 2002, we have rewritten the primary scene graph
-interface to Panda, which invalidates almost all of the contents of
-this document.  We hope to be providing an updated document soon.  In
-the meantime, this document remains, and may be useful for historical
-purposes.
-
-
-
-
-
-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 - 'background'  : GeomBinFixed
-  20 - 'opaque'      : GeomBinNormal (opaque sub-bin of 'default')
-  30 - 'transparent' : GeomBinNormal (transparent sub-bin of 'default')
-  40 - 'fixed'       : GeomBinFixed
-  50 - 'unsorted'    : GeomBinUnsorted
-
-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 25 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.
-
-

+ 126 - 0
panda/src/doc/howto.control_render_order.txt

@@ -0,0 +1,126 @@
+HOW TO CONTROL RENDER ORDER
+
+In most simple scenes, you can naively attach geometry to the scene
+graph and let Panda decide the order in which objects should be
+rendered.  Generally, it will do a good enough job, but there are
+occasions in which it is necessary to step in and take control of the
+process.
+
+To do this well, you need to understand the implications of render
+order.  In a typical OpenGL- or DirectX-style Z-buffered system, the
+order in which primitives are sent to the graphics hardware is
+theoretically unimportant, but in practice there are many important
+reasons for rendering one object before another.
+
+Firstly, state sorting is one important optimization.  This means
+choosing to render things that have similar state (texture, color,
+etc.) all at the same time, to minimize the number of times the
+graphics hardware has to be told to change state in a particular
+frame.  This sort of optimization is particularly important for very
+high-end graphics hardware, which achieves its advertised theoretical
+polygon throughput only in the absence of any state changes; for many
+such advanced cards, each state change request will completely flush
+the register cache and force a restart of the pipeline.
+
+Secondly, some hardware has a different optimization requirement, and
+may benefit from drawing nearer things before farther things, so that
+the Z-buffer algorithm can effectively short-circuit some of the
+advanced shading features in the graphics card for pixels that would
+be obscured anyway.  This sort of hardware will draw things fastest
+when the scene is sorted in order from the nearest object to the
+farthest object, or "front-to-back" ordering.
+
+Finally, regardless of the rendering optimizations described above, a
+particular sorting order is required to render transparency properly
+(in the absence of specialized hardware support that few graphics
+cards provide).  Transparent and semitransparent objects are normally
+rendered by blending their semitransparent parts with what has already
+been drawn to the framebuffer, which means that it is important that
+everything that will appear behind a semitransparent object must have
+already been drawn before the object itself is drawn.  This implies
+that all semitransparent objects must be drawn in order from farthest
+away to nearest, or in "back-to-front" ordering, and furthermore that
+the opaque objects should all be drawn before any of the
+semitransparent objects.
+
+Panda achieves these sometimes conflicting sorting requirements
+through the use of bins.
+
+CULL BINS
+
+The CullBinManager is a global object that maintains a list of all of
+the cull bins in the world, and their properties.  Initially, there
+are five default bins, and they will be rendered in the following
+order:
+
+    Bin Name        Sort  Type
+    --------------  ----  ----------------
+    "background"     10   BT_fixed
+    "opaque"         20   BT_state_sorted
+    "transparent"    30   BT_back_to_front
+    "fixed"          40   BT_fixed
+    "unsorted"       50   BT_unsorted
+
+When Panda traverses the scene graph each frame for rendering, it
+assigns each Geom it encounters into one of the bins defined in the
+CullBinManager.  (The above lists only the default bins.  Additional
+bins may be created as needed, using either the
+CullBinManager::add_bin() method, or the Config.prc "cull-bin"
+variable.)
+
+You may assign a node or nodes to an explicit bin using the
+NodePath::set_bin() interface.  set_bin() requires two parameters, the
+bin name and an integer sort parameter; the sort parameter is only
+meaningful if the bin type is BT_fixed (more on this below), but it
+must always be specified regardless.
+
+If a node is not explicitly assigned to a particular bin, then Panda
+will assign it into either the "opaque" or the "transparent" bin,
+according to whether it has transparency enabled or not.  (Note that
+the reverse is not true: explicitly assigning an object into the
+"transparent" bin does not automatically enable transparency for the
+object.)
+
+When the entire scene has been traversed and all objects have been
+assigned to bins, then the bins are rendered in order according to
+their sort parameter.  Within each bin, the contents are sorted
+according to the bin type.
+
+The following bin types may be specified:
+
+  BT_fixed
+
+    Render all of the objects in the bin in a fixed order specified by
+    the user.  This is according to the second parameter of the
+    NodePath::set_bin() method; objects with a lower value are drawn
+    first.
+
+  BT_state_sorted
+
+    Collects together objects that share similar state and renders
+    them together, in an attempt to minimize state transitions in the
+    scene.  Note: at the moment, this mode is not actually implemented
+    in Panda, and defaults to the same behavior as BT_unsorted.  This
+    does limit the performance of Panda for extremely complex scenes
+    on very high-end graphics cards, but has little impact on most
+    consumer-level cards.
+
+  BT_back_to_front
+
+    Sorts each Geom according to the center of its bounding volume, in
+    linear distance from the camera plane, so that farther objects are
+    drawn first.  That is, in Panda's default right-handed Z-up
+    coordinate system, objects with large positive Y are drawn before
+    objects with smaller positive Y.
+
+  BT_front_to_back
+
+    The reverse of back_to_front, this sorts so that nearer objects
+    are drawn first.
+
+  BT_unsorted
+
+    Objects are drawn in the order in which they appear in the scene
+    graph, in a depth-first traversal from top to bottom and then from
+    left to right.
+

+ 83 - 0
panda/src/doc/howto.fix_transparency_issues.txt

@@ -0,0 +1,83 @@
+HOW TO FIX TRANSPARENCY ISSUES
+
+Usually transparency works as expected in Panda automatically, but
+sometimes it just seems to go awry, where a semitransparent object in
+the foreground seems to partially obscure a semitransparent object
+behind it.  This is especially likely to happen with large flat
+polygon cutouts, or when a transparent object is contained within
+another transparent object, or when parts of a transparent object can
+be seen behind other parts of the same object.
+
+The fundamental problem is that correct transparency, in the absence
+of special hardware support involving extra framebuffer bits, requires
+drawing everything in order from farthest away to nearest.  This means
+sorting each polygon--actually, each pixel, for true correctness--into
+back-to-front order before drawing the scene.
+
+It is, of course, too expensive to split up every transparent object
+into individual pixels or polygons for sorting individually, so Panda
+sorts objects at the Geom level, according to the center of the
+bounding volume.  This works well 95% of the time.
+
+You run into problems with large flat polygons, though, since these
+tend to have parts that are far away from the center of their bounding
+volume.  The bounding-volume sorting is especially likely to go awry
+when you have two or more large flats close behind the other, and you
+view them from slightly off-axis.  (Try drawing a picture, of the two
+flats as seen from the top, and imagine yourself viewing them from
+different directions.  Also imagine where the center of the bounding
+volumes is.)
+
+Now, there are a number of solutions to this sort of problem.  No one
+solution is right for every situation.
+
+First, the easiest thing to do is to use M_dual transparency.  This is
+a special transparency mode in which the completely invisible parts of
+the object aren't drawn into the Z-buffer at all, so that they don't
+have any chance of obscuring things behind them.  This only works well
+if the flats are typical cutouts, where there is a big solid part
+(alpha == 1.0) and a big transparent part (alpha == 0.0), and not a
+lot of semitransparent parts (0.0 < alpha < 1.0).  It is also a
+slightly more expensive rendering mode than the default of M_alpha, so
+it's not enabled by default in Panda.  But egg-palettize will turn it
+on automatically for a particular model if it detects textures that
+appear to be cutouts of the appropriate nature, which is another
+reason to use egg-palettize if you are not already.
+
+Second, an easy thing to do is to chop up one or both competing models
+into smaller pieces, each of which can be sorted independently by
+Panda.  For instance, you can split one big polygon into a grid of
+little polygons, and the sorting is more likely to be accurate for
+each piece (because the center of the bounding volume is closer to the
+pixels).  You can draw a picture to see how this works.  In order to
+do this properly, you can't just make it one big mesh of small
+polygons, since Panda will make a mesh into a single Geom of
+tristrips; instead, it needs to be separate meshes, so that each one
+will become its own Geom.  Obviously, this is slightly more expensive
+too, since you are introducing additional vertices and adding more
+objects to the sort list; so you don't want to go too crazy with the
+smallness of your polygons.
+
+A third option is simply to disable the depth write on your
+transparent objects.  This is most effective when you are trying to
+represent something that is barely visible, like glass or a soap
+bubble.  Doing this doesn't improve the likelihood of correct sorting,
+but it will tend to make the artifacts of an incorrect sorting less
+obvious.  You can achieve this by using the transparency option
+"blend_no_occlude" in an egg file, or by explicitly disabling the
+depth write on a loaded model with node_path.set_depth_write(false).
+You should be careful only to disable depth write on the transparent
+pieces, and not on the opaque parts.
+
+A final option is to make explicit sorting requests to Panda.  This is
+often the last resort because it is more difficult, but it does have
+the advantage of not adding additional performance penalties to your
+scene.  It only works well when the transparent objects can be sorted
+reliably with respect to everything else behind them.  For instance,
+clouds in the sky can reliably be drawn before almost everything else
+in the scene, except the sky itself.  Similarly, a big flat that is up
+against an opaque wall can reliably be drawn after all of the opaque
+objects, but before any other transparent object, regardless of where
+the camera happens to be placed in the scene.  See
+howto.control_render_order.txt for more information about explicitly
+controlling the rendering order.