Solution suggestion: StateSetSwitchNode
 
Motivation:     - I need to render with different shader-programs and 
state-sets, on the same geometry, during one tick.    - Example of when I need 
this is explained in the EXAMPLE section below.
I hope from this e-mail to get feedback:    - Is this solution ok?    - Can it 
be improved?    - Can I submit it to OSG? And supported in the .ive file format?
Solution:==========I use Group instances to hold the StateSets.Need to store 
Group pointers in an array:
 
    class StateSetSwitchNode : public Group    {       ...
    private:        std::vector<Group*> _nodeArray;    };
Need to override the accept function:
 
    void StateSetSwitchNode::accept( osg::NodeVisitor& nv )    {         if( 
nv.validNodeMask( *this ))         {             if( osg::Group* group = 
_nodeArray[ INDEX ] )            {                // Apply the Group holding 
the StateSet instead of 'this' pointer                nv.pushOntoNodePath( 
group );                 nv.apply( *group );                 
nv.popFromNodePath();            }        }    }
I will explain the INDEX and array size later in this e-mail.
 
Each Group pointer in the _nodeArray:    - must be set up with the same 
children as the StateSetSwitchNode instance has.    - will not have any parents 
(unless the element point to the StateSetSwithNode instance).    - will by 
default point to the StateSetSwitchNode instance.
 
The StateSetSwitchNode's own StateSet is the default StateSet.
 
I am conserned about how smart it is to have nodes that is not tied to a 
parent, but that links to multiple children in the node-tree. It will not 
affect performance when traversing children, but any parent traversal will go 
into all of the extra nodes stored in the _nodeArray. They do not have parents, 
so it is not a large performance penalty.
The class will also need function overrides for adding/removing/replacing 
children as we would need to ensure that each element in the array point to the 
same children as the StateSetSwitchNode.
 
We do not need to do any code changes to OSG (except for supporting the class 
in file formats, and to add the class to OSG).Cull-traveresal does not suffer a 
performance-hit, unless you actually use the StateSetSwitchNode.Using the 
StateSetSwitchNode comes with a minimal performance-hit for StateSet switching 
(bitvise and operation + an array lookup).
 
INDEX (and the array size):============================We need some way to 
select what array index we want to use. My need is to have multiple camera's 
render the scene in different ways (by using different state-sets and 
shader-programs).
I decided to do it in a way that need no new code, except for the indexing 
inside my new class. So I use the traversal-mask which automatically makes it 
possible for my camera's to decide what StateSets to render the scene with. I 
allocate some of the least significant bits in the node-mask to be StateSet 
selectors. So if I use 4 bits for this, then I get a total of 16 different 
StateSet possibilities in each StateSetSwitchNode. 
We do not want to check array size during cull-traverse, the size of the array 
should be in the power of two so that we can bitvise and the index before we 
read the array. All elements in the array thus need to point to an instance.Any 
not used elements will point to the default instance (which is the 
StateSetSwitchNode instance itself). This must be enforced in the 
StateSetSwitchNode constructor.
 
INDEX (in the above code) is thus replaced by this:    (nv.getTraversalMask() & 
(_arraySize-1))
 
 
EXAMPLE:=========Currently we render our scene three times each tick: - One 
pre-render camera that render the scene and generate a water-surface reflection 
image. - One pre-render camera that render the scene and generate a sub-sea 
refraction image. - One camera that render the scene and use the two textures 
above to display a good looking sea surface.
 
The pre-render cameras renders only parts of the scene (those nodes that 
actually need to be in the reflective image and those that is underneath water).
Our terrain use four different shaders: - High detail shader on the lod's that 
are close to camera. - Low detail shader on distant lods. - Lower detail shader 
on the reflection surface both for close and distant lods. - Special fog shader 
and lower detail both for close and distant lods when under water.
The same goes for vegetation and buildings (which has different shaders than 
then terrain).
We can optionally switch to even simpler shaders when the water-surface start 
to have higher waves. So dynamically we will be able to speed up reflection and 
underwater rendering based on wave-height. This would be a matter of changing 
the cull-mask on the pre-render cameras and writing even simpler shaders. 
 
We use the StateSetSwitchNode to select which shaders to render with, and this 
is controlled by setting the lower bits in the camera's cull-mask.We use bit 
0,1 and 2 to select shader.We use bit 3,4 and 5 to select scene (normal, 
reflection and underwater).
Doing this has proven to be a performance boost for our scene. We can write as 
simple as possible shaders to use at need. The reflection and underwater does 
not need high detail. In the future we will also use this to render the 
shadow-caster scene with super-simple shaders too.
Regards,Viggo
_________________________________________________________________
Få Windows Live Messenger på mobilen.
http://windowslivemobile.msn.com/Homepage.aspx?lang=nb-no&ocid=30032
_______________________________________________
osg-users mailing list
[email protected]
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to