About Sorting about sorting (EN)
Выдержка из оригинальной справки. (NDL Gamebryo 1.1)
Sort Adjust Nodes (добавление в 3д МАХ) (актуально только ниф файлов 10ой версии, для 4.0-4.2 в пролете)
In some cases an artist may wish to override how alpha blended objects are sorted in the scene. In Gamebryo, all alpha blended objects are sorted from back to front when rendered. This sorting order may change as the camera moves through the world, causing visual pops or other anomalies in the alpha blended objects. This is especially true in the cases where several alpha blended objects are layered on top of each other, as in hair or terrain. Please see the samples documentation, Sort Adjust Nodes for Max file examples of this.
To specify an NiSortAdjustNode, create a new dummy node and edit the User-Defined Properties for the new dummy node to contain the text "NiSortAdjustNode = XXXXXX". The string, "XXXXXX", should be one of the following options listed in the table below.
Sorting Mode Behaviors
NiSortAdjustNodes have three possible sorting modes:
Mode
|
Behavior
|
SORTING_INHERIT
|
Acts just like an NiNode.
|
SORTING_OFF
|
If there is an accumulator attached to the renderer, this mode causes the node to remove the accumulator from the renderer prior to rendering the node's children, and then returns the accumulator to the renderer when the node's children have been rendered. In essence, this mode turns off sorting for the child objects of the node.
|
SORTING_SUBSORT
|
Replaces the accumulator (even if it was the NULL accumulator) that the renderer was using prior to rendering this node. The node restores the original accumulator when it finishes rendering its children. The accumulator the node uses as the replacement when drawing its children is the one set with SetSubSorter. This mode can be used to force sorting on even if the renderer has not had a sorter attached globally. It can also be used to substitute a different accumulator for a given subtree. If this mode is used with a SubSorter of NULL, then the mode is equivalent to SORTING_OFF.
|
Из справки к Нифскопу + примечание.
0 = SORTING_INHERIT
Inherit. Acts identical to NiNode.
1 = SORTING_OFF
Disables sort on all geometry under this node.
Object Sorting
Along with Z-buffering and Binary Separating Planes, Gamebryo supports a third system for visible surface determination called object sorting. Object sorting can allow some scenes to be drawn without Z-buffering, which can raise frame rate on some renderers (rarely hardware, but commonly software). More importantly, in the presence of partially transparent (i.e. alpha blended) objects, artifacts can occur if the objects are not drawn back-to-front — the Z-buffer cannot resolve these issues. Object sorting allows dynamic and static objects to be sorted back-to-front or front-to-back each frame. Sorting is enabled for the entire scene graph by attaching a sorter (or "accumulator") to the renderer that is to be used to draw the scene.
Note that the exact behavior of each NiAVObject with respect to sorting is class-specific (although most common Gamebryo objects conform to a standard set of sorting behaviors). Also, note that the Gamebryo sorting system supports object-level sorting only — polygons within a single object will not be sorted with respect to each other, nor will polygons within multiple objects be sorted with respect to each other.
Basic sorting works quite simply. Each renderer may have a single NiAccumulator-derived object attached as its sorter. If the sorter is NULL, then no sorting is done. During a Click pass over the scene graph, the traversal works normally until a leaf geometry object that is to be drawn is encountered. At this point, if there is no sorter attached to the renderer, the object is drawn immediately (in this way, if no sorter is attached, the objects are drawn strictly in traversal order). If a sorter is attached to the renderer, then the leaf geometry object is sent to the sorter's RegisterObject function, which decides internally if the object is to be sorted or not. If the sorter decides not to sort the object (it does not "register" the object), the object is drawn immediately, as if there was no sorter. However, if the sorter decides to sort the object (it "registers" the object), it returns this information to the rendering pass, which does not render the object at that time. It continues on to the next object in the scene graph.
At the end of the Click pass, the renderer calls a function in the sorter (if there is a sorter) that draws all of the objects that the renderer "registered". It is up to the particular sorter to decide upon the order in which it will draw the objects. In fact, a sorter may even decide at this point to skip some or all of the registered objects, although this is rare.
The most commonly used sorter in Gamebryo is the NiAlphaAccumulator. It is derived from NiAccumulator, and uses a simple form of back-to-front sorting (sorting by depth of the bounding sphere center), but it does not register all objects in the scene graph. As the Click pass traverses the scene graph, the NiAlphaAccumulator looks at the set of rendering properties that are attached to each leaf geometry object. If a geometry object has alpha blending turned off, then the object is not registered — it is sent to the renderer immediately for drawing. Objects that have alpha blending turned on are registered for later rendering in back-to-front order. As a result, the NiAlphaAccumulator draws all opaque objects first in the order traversed (letting the Z-buffer take care of sorting them), and then draws all of the alpha blended objects second, in back-to-front order. This makes the sorter faster than a full scene graph sort, as it only sorts the (generally few) translucent objects, and draws the others immediately.
Hierarchical Sorting and Multiple Sorters
Advanced applications may find that having to use a single sorter for a whole scene graph (or for that matter, even sorting the whole scene graph) is too limiting. For these cases, Gamebryo defines a subclass of NiNode that allows sorting to be turned off or another sorter substituted in mid-scene graph. This object is the NiSortAdjustNode. It behaves like an NiNode in every way but one: it can change the sorting behavior used when drawing its children.
The NiSortAdjustNode has three different modes, each with a different sorting behavior:
· SORTING_INHERIT: In this mode, the node acts just like any node, without changing the sorting state in any way.
· SORTING_OFF: In this mode, the node basically turns off sorting for the subtree under it — all children are drawn immediately, with no sorting. When the Click traversal reaches an NiSortAdjustNode in this mode, the node stores the renderer's current sorter (if any), sets the renderer's sorter to NULL (no sorting), renders its children (drawn immediately with no sorting), and then replaces the original sorter in the renderer.
· SORTING_SUBSORT: In this mode, the node basically "pushes" a new (application-supplied) sorter that is used for the node's subtree only, drawing all of the children in sorted order before "popping" the sorter and continuing with the traversal. When the Click pass reaches an NiSortAdjustNode in this mode, the node stores the renderer's current sorter. Then, it attaches a locally stored (application-supplied) sorter, initializes it and sets it as the renderer's sorter. Then, it draws its children (using the new sorter). Finally, it has the new sorter draw all of its registered objects and then replaces the original sorter back on the renderer and returns.
The diagram below shows each of the three cases applied to a sorted scene, as well as a baseline example of the scene rendered without sorting.
Examples of Hierarchical Sorting Adjustment
Hierarchical modifications to the sorting traversal must be done with care. For example, consider using an NiSortAdjustNode in the middle of a scene graph in SORTING_SUBSORT mode with an attached NiAlphaAccumulator. NiAlphaAccumulators draw all of their alpha-blended objects when they are "finished" or "closed". If an NiAlphaAccumulator is set globally on the renderer and no NiSortAdjustNode are in the scene graph, then the NiAlphaAccumulator is not "closed" until the entire scene graph has been traversed. As a result, the alpha blended objects will be drawn after all of the opaque ones, as expected. However, if an NiAlphaAccumulator is "pushed" in the middle of a scene graph by an NiSortAdjustNode, then the accumulator will be "closed" as soon as the children of the NiSortAdjustNode have been traversed, and the alpha blended children of that node will be drawn at that time. If there are opaque objects later in the scene graph, they will be drawn after alpha blended objects, which can lead to visual anomalies.
As a further example, note the final case in the diagram above. Here, we have an NiAlphaAccumulator at the root of the scene graph, and another accumulator in the middle of the scene graph. As a result of this, note that all of the alpha blended objects are not drawn last (alpha blended object E and F are drawn prior to opaque objects I and J). While some applications may require this behavior (for example to force the ordering of "backdrop" or "sky dome" effects), in other applications this same behavior could cause visual problems. Application developers must consider such interactions when using hierarchical adjustments to sorting.