这个主要是理论了。抄一抄。
最常用到场景管理方式时场景节点树结构,场景树顶点的叶节点osg::Geode包含了各种需要渲染的几何体的顶点和渲染状态信息;而组节点osg::Group及其派生出的各种特殊功能节点则作为场景树的各个枝节节点 ,它们也可以拥有不同的渲染状态;有且只有一个节点可以直接作为整个场景的根节点,使用setSceneData将其设置为场景的视景器系统,即等同于将整个场景树传递给OSG的渲染和显示系统。
而保存节点和几何体的各种渲染属性(osg::StateAttribute,例如纹理、雾效、材质,alpha校验等)和模式开关,则使用节点所附带渲染状态集osg::StateSet,一个状态集中可以包含多种不同的渲染属性和开关,处于场景树顶端的节点将继承并综合各级父节点的渲染状态,实现几何形状的正确渲染。
OSG渲染后台的主体是场景视图SceneView,它同样实现了树状结构的管理方式,并据此实现了多个专用于渲染工作的内部类。
osgUtil::CullVisitor筛选器:.当使用它遍历场景图形的各个节点时,CullVIsitor将会对每个遇到的节点执行场景筛选的工作,判断它是否会超出视截锥体外,过于渺小,或者被遮挡节点OcculuderNode挡住,从而将无助于场景浏览的物体筛选并剔除,降低场景绘制的资源消耗。也可以构建自己设计的筛选访问器,但是在系统渲染后台之外的化境使用CullVisitor通常无用处。
osg::RenderInfo:渲染信息管理器。
osgUtil::StateGraph:状态节点。可以对比场景树的组节点,可以将StateGraph理解为OSG渲染后台的组节点。它的组织结构与场景图形的节点结构类似,但是状态树的构建主要以节点的渲染状态集StateSet为依据:设置了StateSet的场景节点,其渲染状态会被记录到状态节点中,并保持它在原场景树中的相对位置。状态节点采用映射表std::map来组织它的子节点,同一层次的子节点如果渲染状态相同,则合并到同一个状态节点中。
StateGraph可以时是状态树中的任意深度的节点,可以有子节点。但不是整棵树,而是树上的某个节点,可以当作组。与对应场景树的位置保持一致,把状态放到渲染后台状态树对应位置。即两棵树,场景树放场景节点,另一棵树的同一位置是该场景节点的状态节点。
osgUtil::RenderLeaf:渲染叶。渲染叶是OSG渲染后台状态树的叶节点,但不是场景树的Geode节点,而是Geode的各个drawables(以及与之相关的投影矩阵,模型视点矩阵等信息)。每个状态节点中都包含了一个渲染叶的列表,但是只有最末端的状态节点会记录场景中的渲染叶。
即,状态树由状态节点StageGraph和渲染叶节点RenderLeaf组成。
osgUtil::RenderStage:渲染台。osg的渲染后台除了使用状态树来组织和优化节点的渲染状态之外,还有另外一种用于场景实际渲染的组织结构,称之为渲染树,渲染树的根节点就是渲染台。
通常来说,由于osg后台只有一个渲染树结构,因此应当也只有一个渲染台存在,不过OSG还提供了设置摄像机渲染顺序的功能,即
设置为PRE_RENDER的摄像机子树将在主摄像机之前执行渲染,通常,可以实现如纹理烘焙(render to texture)的高级功能;设置为Post_render的摄像机子树将在主摄像机之后执行渲染,一些必须在最后进行渲染的场景对象,比如HUD显示牌,可以置为这类摄像机的子节点。
把视景器viewer的主从摄像机设置为PRE_RENDER或Post_render往往没有意义。所谓从摄像机组,主要功能主要是实现同一场景的分窗口及分屏幕显示。如果希望实现如HUD显示等功能,则应当向场景树中添加新的摄像机节点,并设置与主摄像机不同的观察矩阵和投影矩阵。
一般对于没有特殊要求的场景渲染来说,更多的渲染树分支也许并不需要;场景中需要渲染的元素及其渲染属性被保存到各个状态节点和渲染叶中;渲染树只要按照遍历的顺序,把这些数据记录到作为根节点的渲染台中,(即分别保存在std::vector成员量RenderBin::_stateGraphList和RenderBin::_renderLeafList中,注意RenderStage派生自RenderBin),就可以执行场景的绘制工作了。
如果正常渲染,从场景树中,相对位置不变可以获得状态树,状态树由状态组成的状态节点和drawable组成的渲染叶组成;再把状态节点挪到渲染台即可。默认渲染顺序为0,即
stateset->setRenderBinDetails(0,"");
然而,事情不那么简单,比如透明的和不透明的节点,绘制顺序不同的节点,这样引入了下面的
osgUtil::RenderBin:渲染元,是OSG渲染树的分支节点,用于某些几何体在其它对象之前绘制,
设置顺序时,整数表示以0为标准,小于0的渲染状态集(即包含了这个StateSet的StateGraph状态节点)将排列在前,大于0的排列在后。
字符串参数"RenderBin"表示在渲染树中新建分支进行渲染,可用于不透明物体;按升序渲染;
字符串参数"DepthSortedBin"表示新建渲染树分支,并且所有要渲染的顺序将按照深度值降序进行排列,按降序渲染。
即三个分支:正常为0的,Renderbin排序的不透明和DepthSortedBin排序的透明物体。
顺序是先渲染不透明的,再渲染透明的;
那么先渲染RenderBin中负数,从小到大;再渲染正常的;再渲染RenderBin中正数的从小到大;再按降序渲染DepthSortedBin中透明的。理论上应该这么排序。
当然,也可以简单地按照次序去排,前提是保证次序不错。
比如stateSet->setRenderBinDetails(-1,"RenderBiin");
stateSet->setRenderBinDetails(10,"DepthSortedBin");
对于不透明的物体,可以设置为
stateSet->setRenderingHint(OPAQUE_BIN);
对于透明的物体,可以设置为
stateSet->setRenderingHint(TRANSPARENT_BIN);
这是目前的理解,看看下一天的内容,是不是正确的。