osgforest例子

来源:互联网 发布:python get请求 编辑:程序博客网 时间:2024/05/09 06:42
这个例子很长,我们还是要从main函数开始,一点点的研究。
ForestTechniqueManager这个类是主要内容,里面有个Tree类和一个Cell类。
Tree属性有位置,颜色,长宽和类型。
Cell里面管理所有的Tree,并且管理着一颗Cell树状结构。
createTerrain函数创建一个地形。
createTreeList函数创建了很多的Tree,通过和地形求交获取Tree的位置。该函数只是把Tree读
到了TreeList中,并没有在场景中显示。
createSprite函数创建了一个四边形,用来承载一棵树。
createOrthogonalQuads函数创建了一个两个十字交叉的四边形,也用来承载一棵树。
createOrthogonalQuadsNoColor与createOrthogonalQuads相同,只是没有颜色。
createBillboardGraph函数实现Billboard方式,Billboard我们之前研究过,一直对准视点的。
该函数还根据Cell的属性方式实现分组管理。
createXGraph函数逻辑与createBillboardGraph相同,只是创建十字交叉的树,并用Geode管理。
createTransformGraph函数也相同,应用MatrixTransform添加树。
最后一种方式使用shader添加树。
来看看createHUDWithText这个函数,创建了一个HUD显示一些信息,之前我们接触过的HUD是用
相机节点创建出来的,但这里不是,我们仔细的看看他里面的代码。
创建一个HUD的几个要求,第一、始终在最前端显示,只需设置文字关闭深度测试;第二、节点
不受操作器的影响。这里使用了一个MatrixTransform和Projection投影节点实现HUD。
createShaderGraph该函数使用shader的方式创建树,首先createOrthogonalQuadsNoColor创建
一个十字交叉无颜色的节点,定义了ShaderGeometry这个类,继承自Drawable,重写
drawImplementation进行绘制,把Tree的位置和高作为颜色写入了。
四种方式创建Tree都已经分析完,下面看看是如何调度的。
进入createScene这个函数,
 osg::ref_ptr<osg::Node> terrain = createTerrain(origin,size);创建地形
createTreeList(terrain.get(),origin,size,numTreesToCreates,trees);收集Tree到TreeList
中。
osg::ref_ptr<Cell> cell = new Cell;
    cell->addTrees(trees);
    cell->divide();
创建Cell树状结构。
osg::Texture2D *tex = new osg::Texture2D;
    tex->setWrap( osg::Texture2D::WRAP_S, 
osg::Texture2D::CLAMP );
    tex->setWrap( osg::Texture2D::WRAP_T, 
osg::Texture2D::CLAMP );
    tex->setImage(osgDB::readImageFile
("Images/tree0.rgba"));
创建一个树的二维纹理。
dstate->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON );
dstate->setTextureAttribute(0, new osg::TexEnv );
        dstate-
>setAttributeAndModes( new osg::BlendFunc, osg::StateAttribute::ON );
osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
        alphaFunc->setFunction
(osg::AlphaFunc::GEQUAL,0.05f);
        dstate->setAttributeAndModes( alphaFunc, 
osg::StateAttribute::ON );
让图片
没有树的部分在场景中透明渲染。
 dstate->setMode( GL_LIGHTING, osg::StateAttribute::OFF );
        dstate-
>setRenderingHint( osg::StateSet::TRANSPARENT_BIN );
关闭光照,设置渲染优先级。
_techniqueSwitch是一个Switch节点,加入了Billboard、十字交叉、MatrixTransform、shader
这几种绘制方法。
我们着重看看shader绘制方式。
 osg::StateSet* stateset = new osg::StateSet(*dstate, osg::CopyOp::DEEP_COPY_ALL);
首先深拷贝了一下状态,
"!!ARBvp1.0\n"
               
                "ATTRIB vpos = vertex.position;\n"

           "ATTRIB vcol = vertex.color;\n"
                "ATTRIB tc = 
vertex.texcoord[" << 0 << "];"
                "PARAM mvp[4] = { state.matrix.mvp };
\n"
                "PARAM one = { 1.0, 1.0, 1.0, 1.0 };"
                "TEMP 
position;\n"
                 // vec3 position = gl_Vertex.xyz * 
gl_Color.w + gl_Color.xyz;
                "MAD position, vpos, vcol.w, vcol;\n"
          // gl_Position     = gl_ModelViewProjectionMatrix * vec4(position,1.0);
            "MOV position.w, one;\n"
                "DP4 result.position.x, mvp[0], 
position;\n"
                "DP4 result.position.y, mvp[1], position;\n"
   "DP4 result.position.z, mvp[2], position;\n"
                "DP4 
result.position.w, mvp[3], position;\n"
                // gl_FrontColor = vec4
(1.0,1.0,1.0,1.0);
                "MOV result.color.front.primary, one;\n"
      // texcoord = gl_MultiTexCoord0.st;
                "MOV result.texcoord, tc;
\n"
                "END\n";
以上是shader的汇编代码,虽然很难看懂,但是都通glsl的代码注释了。
下面的glsl代码和上面的汇编相同,我们直接解读下面的glsl代码。
vec3 position = gl_Vertex.xyz * gl_Color.w + gl_Color.xyz;这句代码对应了上面我们分析
得到的,把tree的xyz位置和高作为颜色传入,这里用颜色值重新计算了位置,
gl_Position     = gl_ModelViewProjectionMatrix * vec4(position,1.0);
 gl_FrontColor = vec4(1.0,1.0,1.0,1.0);
设置颜色为白色,texcoord = gl_MultiTexCoord0.st;纹理坐标。
片源着色器中
gl_FragColor = texture2D( baseTexture, texcoord);
读取指定坐标的纹理。
这样这个Switch节点加入了这几种渲染树的方法,通过TechniqueEventHandler进行转换。
原创粉丝点击