Version 4 (modified by osg, 10 years ago)


How do StateSets work?

(Wiki editing note: Add link to complete source code at bottom)

A scene graph manager traverses a scene graph to determine what geometry needs to be sent to the grapics pipeline for rendering. During this traversal, the scene graph manager can also collect information on how that geometry should be rendered. This information is stored in osg::StateSet instances. StateSets contain lists of OpenGL attribute/value pairs. These StateSets can be associated with nodes of the scenegraph. During pre-render traversal, StateSets are accumulated from the root to leaf nodes. State attributes that are not changed at a node are simply inherited from above.

A few additional features allow more control and flexibility. A state's attribute value can be set to OVERRIDE. This means that all the children of that node - regardless of what the children's attribute value is - will inherit the parent node's attribute value. This OVERRIDE can be, well, over-ridden. If one of the child nodes set that attributes value to PROTECTED, they can set this attribute value regardless of the parent's setting.

An example

The following scene demonstrates how states affect a scene graph. The root node has a basic state with texture BLEND mode. This basic state will be inherited by all children unless that state parameter is changed. The right subtree off the root node shows this. No state is assigned to the right child and it's rendering using the same state as the root node. For node (6), the texture blend mode has not been changed but a new texture is used.
In the left subtree of the root node the texture mode is set to DECAL. All other parameters are the same and so are inherited from the root node. In node (3) FOG is turned ON and set to OVERRIDE. The left child on this node - node (3) - FOG is set to OFF. Since it is not PROTECTED and the parent is set to OVERRIDE, FOG remains ON as defined by the parent. The right child (4) sets the Fog attribute value to PROTECTED, and thus can override the parent's setting.

Copy of the screenshot of the NPS tutorial on statesets

That's nice, but what about the code?

The code to manipulate state settings and associate these states with nodes is below.

   // Set an osg::TexEnv instance's mode to BLEND,
   //    make this TexEnv current for texture unit 0 and assign
   //    a valid texture to texture unit 0

   // For state five, change the texture associated with texture unit 0
   //    all other attributes will remain unchanged as inherited from above.
   //    (texture mode will still be BLEND)

   // Set the mode of an osg::TexEnv instance to DECAL
   //    Use this mode for stateOneDecal.

   // For stateTwo, turn FOG OFF and set to OVERRIDE.
   //    Descendants in this sub-tree will not be able to change FOG unless
   //    they set the FOG attribute value to PROTECTED
   stateTwoFogON_OVRD->setAttribute(fog, osg::StateAttribute::ON); 
   stateTwoFogON_OVRD->setMode(GL_FOG, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); 

   // For stateThree, try to turn FOG OFF.  Since the attribute is not PROTECTED, and
   //    the parents set this attribute value to OVERRIDE, the parent's value will be used.
   //    (i.e. FOG will remain ON.)
   stateThreeFogOFF->setMode(GL_FOG, osg::StateAttribute::OFF); 

   // For stateFour, set the mode to PROTECTED, thus overriding the parent setting
   stateFourFogOFF_PROT->setMode(GL_FOG, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); 

   // apply the StateSets above to appropriates nodes in the scene graph.

Continue with tutorial File loading and transforms