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