diff --git a/panda/src/doc/howto.control_render_order b/panda/src/doc/howto.control_render_order deleted file mode 100644 index addd7b6860..0000000000 --- a/panda/src/doc/howto.control_render_order +++ /dev/null @@ -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. - - diff --git a/panda/src/doc/howto.control_render_order.txt b/panda/src/doc/howto.control_render_order.txt new file mode 100755 index 0000000000..e47aac92e9 --- /dev/null +++ b/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. + diff --git a/panda/src/doc/howto.fix_transparency_issues.txt b/panda/src/doc/howto.fix_transparency_issues.txt new file mode 100755 index 0000000000..5f23806666 --- /dev/null +++ b/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.