1. 定义
状态管理类
OSG 提供了一种机制,用以保存场景图形所需的OpenGL 渲染状态。在拣选遍历中,同一状态的几何体将被组合集中到一起以使状态的改变呈最小化。在绘制遍历中,状态管理代码将记录当前状态的历史轨迹,以清除冗余的渲染状态变更。
SateSet类:保存一组定义状态数据(模式和属性)。场景中任何osg::Node都可以与一个StateSet相关联。
Modes(模式):与OpenGL中glEnable()和glDisable()相似。用于打开或关闭OpenGL 固定功能(fixed-function)的渲染管道,例如灯光,混合和雾效。方法 osg::StateSet::setMode()在StateSet 中保存一个模式信息。
Attibutes(属性):使用属性来指定状态参数,例如混和函数,材质属性,雾颜色等。方法osg::StateSet::setAttribute()在StateSet 中保存属性信息。
纹理模式和属性:纹理模式和属性可应用在OpenGL 多重纹理的某个指定纹理单元上。应用程序必须在设定纹理模式和属性时提供纹理单元的信息,StateSet类的方法setTextureMode()和 setTextureAttribute()用于设定状态参量以及纹理单元信息。
继承标志:OSG 提供了一些标志量,用于控制场景图形遍历中的状态值。缺省情况下,子节点中的状态集合将重载父节点的状态集合。
2. 使用场景图形在遍历场景的过程中,会自动判断哪一些几何体要送入图形管道进行渲染。在遍历过程中,场景图形还要收集几何体渲染状态的信息。这些信息就保存在osg::StateSet实例中。StateSet包含了一个OpenGL属性/值的列表,它可以与场景中的节点相关联。在渲染之前的遍历过程中,StateSet会从根节点一直向叶节点进行积累。如果某个节点只是简单地继承上一节点的状态,那么与它关联的StateSet也不会发生改变。
我们可以使用一些附加的特性来提升工作的灵活性。渲染状态所保存的属性可以设置为OVERRIDE,也就是说,该节点的所有子节点,无论其渲染状态是什么,都将继承父节点的渲染属性。但是OVERRIDE也可能存在一种例外,如果某个子节点的渲染属性设置为PROTECTED,那么它将忽略父节点的相应属性,而使用自己设定的属性值。
下面的例子演示了渲染状态对场景图形的影响。根节点使用BLEND模式。如果它的子节点没有改变任何渲染属性值,则子节点的渲染状态也不会发生改变,如根节点的右子树所示。右子树的节点没有指定渲染状态,因此它的渲染方式与根节点相同。而对于节点5来说,虽然纹理的混合模式没有改变,但是它已经关联了新的纹理。
根节点的左子树设置纹理模式为DECAL,其它的渲染属性与根节点相同。节点3将FOG属性设置为ON并指定为OVERRIDE。对于节点2的左子节点(节点3),其FOG属性设置为OFF,但是由于没有指定PROTECTED方式,且父节点为OVERRIDE方式,因此FOG属性依然为ON。而对于右子节点(节点4),其FOG属性使用PROTECTED方式并设定为OFF,此时它将忽略父节点的相应设置。
下面的代码用于控制渲染状态的设定并将其关联到节点。
//设置osg::TexEnv实例为BLEND模式,将TexEnv属性和一幅纹理关联到纹理单元0 blendTexEnv->setMode(osg::TexEnv::BLEND); stateRootBlend->setTextureAttribute(0,blendTexEnv,osg::StateAttribute::ON); stateRootBlend->setTextureAttributeAndModes(0,ocotilloTexture,osg::StateAttribute::ON); // 对于节点5,重新设置其渲染单元0的纹理。其它的渲染属性将继承父节点的属性(渲染模式属性仍为BLEND) stateFiveDustTexture->setTextureAttributeAndModes(0,dustTexture,osg::StateAttribute::ON); // 设置osg::TexEnv实例为DECAL模式,将其关联到stateOneDecal decalTexEnv->setMode(osg::TexEnv::DECAL); stateOneDecal->setTextureAttribute(0,decalTexEnv,osg::StateAttribute::ON); // 对于stateTwo,设置FOG属性为ON并设置OVERRIDE,所有的子树将自动继承它的渲染状态,除非设置了PROTECTED标志 stateTwoFogON_OVRD->setAttribute(fog, osg::StateAttribute::ON); stateTwoFogON_OVRD->setMode(GL_FOG, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); // stateThree试图关闭FOG属性,但是由于父节点的渲染状态设置为OVERRIDE,因此FOG的设置没有发生变化(仍为ON) stateThreeFogOFF->setMode(GL_FOG, osg::StateAttribute::OFF); // stateFour设置了PROTECTED标志,因此它可以重载父节点的渲染状态了 stateFourFogOFF_PROT->setMode(GL_FOG, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED); // 将上面的各个渲染状态实例应用到场景图形的节点上 root->setStateSet(stateRootBlend); mtOne->setStateSet(stateOneDecal); mtTwo->setStateSet(stateTwoFogON_OVRD); mtThree->setStateSet(stateThreeFogOFF); mtSix->setStateSet(stateFiveDustTexture); mtFour->setStateSet(stateFourFogOFF_PROT);