OSG 学习第三天:渲染状态

来源:互联网 发布:网络红歌2016流行歌曲 编辑:程序博客网 时间:2024/06/01 22:49
OSG 渲染状态


前言:撸了两天代码,决定换一种学习方式试试。


渲染状态(Rendering State) 

OSG支持绝大部分的OpenGL 固定功能管道(fixed function pipeline)渲染,例如 Alpha 检验,Blending 融合, 剪切平面,颜色蒙板,面拣选(face culling),深度和模板检验,雾效,点和线 的光栅化(rasterization),等等。OSG 的渲染状态也允许应用程序指定顶点着色(vertex shader)和片段着色(fragment shader)。 用户的应用程序需要在 osg::StateSet 中设置渲染状态。

OSG 将渲染状态分成两个部分,渲染属性(attribute)和渲染模式(mode)。 
渲染属性也就是控制渲染特性的状态变量。例如,雾的颜色,或者 Blend 融合函 数都是 OSG 的状态属性。
OSG 中的渲染模式和 OpenGL 的状态特性几乎是一一 对应的,这些特性在 OpenGL 中通过函数 glEnable()和 glDisable()进行控制。用程序可以设置模式量以允许或禁止某个功能,例如纹理映射、灯光等。简单来说,渲染模式是指渲染的某个功能,而渲染属性是这个功能的控制变量和参数。

渲染的步骤如下:
1.设置渲染属性(Attribute)
如果要设置一项属性,首先将要修改的属性类实例化。设置该类的数值,然 后用 osg::StateSet::setAttribute()将其关联到 StateSet。下面的代码段用于实现面剔 除(face culling)的属性: 
// 获取变量 geom 的 StateSet 指针。osg::StateSet* state = geom->getOrCreateStateSet(); // 创建并添加 CullFace 属性类。 osg::CullFace* cf = new osg::CullFace( osg::CullFace::BACK ); state->setAttribute( cf ); 
在上面的代码段中,geom 是一个 Geometry 几何类对象(当然也可以是任何 其它派生自 Drawable 和 Node 的对象)。获取 geom 的 StateSet 指针后,代码创建 了一个新的 osg::CullFace 对象,并将其关联到状态量。

2.设置渲染模式(Mode)
用户可以使用 osg::StateSet::setMode()允许或禁止某种模式。例如,下面的代 码将打开雾效模式的许可:
// 获取一个 StateSet 实例。 osg::StateSet* state = geom->getOrCreateStateSet(); // 允许这个 StateSet 的雾效模式。 state->setMode( GL_FOG, osg::StateAttribute::ON ); 
setMode()的第一个输入参数可以是任何一个在 glEnable()或 glDisable()中合 法的 OpenGL 枚举量 GLenum。第二个输入参数可以是 osg::StateAttribute::ON 或 osg::StateAttribute::OFF。
 
3.设置渲染属性和模式
OSG 提供了一个简单的可以同时设置属性和模式的单一函数接口。在许多 情况下,属性和模式之间都存在显著的关系。例如,CullFace 属性的对应模式为 GL_CULL_FACE。如果要将某个属性关联到一个 StateSet,同时打开其对应模式 的许可,那么可以使用 osg::StateSet::setAttributeAndModes()方法。下面的代码段 将关联 Blend 融合检验的属性,同时许可颜色融合模式。 
// 创建一个 BlendFunc 属性。 osg::BlendFunc* bf = new osg::BlendFunc(); // 关联 BlendFunc 并许可颜色融合模式 state->setAttributeAndMode( bf ); 
setAttributeAndModes()的第二个输入参数用于允许或禁止第一个参数中渲 染属性对应的渲染模式。其缺省值为 ON。这样用户的应用程序只需用一个函数, 就可以方便地指定某个渲染属性,并许可其对应的渲染模式。 


附上书上的一段代码:
//渲染状态(ClipeNode)#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>#include <osg/Group>#include <osg/ClipNode>#include <osg/PolygonMode>#include <osg/MatrixTransform>#include <osg/PositionAttitudeTransform>#include <osg/AnimationPath>#include <osgDB/ReadFile>#include <osgDB/WriteFile>#include <osgUtil/Optimizer>#include <iostream>osg::ref_ptr<osg::Node> createClipeNode(osg::ref_ptr<osg::Node> subgraph){osg::ref_ptr<osg::Group> root = new osg::Group();osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();//多边形线形绘制模式,正面和反面都绘制osg::ref_ptr<osg::PolygonMode> polymode = new osg::PolygonMode();polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::FILL);//启用多边形线形绘制模式,并指定状态继承属性为OVERRIDEstateset->setAttributeAndModes(polymode,osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);//多边形线形绘制节点osg::ref_ptr<osg::Group> wrieframe_subgraph = new osg::Group;//设置渲染状态wrieframe_subgraph->setStateSet(stateset.get());wrieframe_subgraph->addChild(subgraph.get());root->addChild(wrieframe_subgraph.get());/*osg::ref_ptr<osg::MatrixTransform> transform = new osg::MatrixTransform;//更新回调,实现动态裁剪osg::ref_ptr<osg::NodeCallback> nc = new osg::AnimationPathCallback(subgraph->getBound().center(),osg::Vec3(0.0f, 0.0f, 1.0f), osg::inDegrees(45.0f));transform->setUpdateCallback(nc.get());//创建裁剪节点osg::ref_ptr<osg::ClipNode> clipnode = new osg::ClipNode;osg::BoundingSphere bs = subgraph->getBound();bs.radius() *= 0.4f;//设置裁剪节点的包围圈osg::BoundingBox bb;bb.expandBy(bs);//根据前面指定的包围盒创建6个裁剪平面clipnode->createClipBox(bb);//禁用拣选clipnode->setCullingActive(false);transform->addChild(clipnode.get());root->addChild(transform.get());//创建未被裁剪的节点osg::ref_ptr<osg::Group> clippedNode = new osg::Group;clippedNode->setStateSet(clipnode->getStateSet());clippedNode->addChild(subgraph.get());root->addChild(clippedNode.get());*/return root.get();}int main(){//创建Viewer对象osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();//osg::ref_ptr<osg::Group> root = new osg::Group();osg::ref_ptr<osg::Node> root = new osg::Node();//加载模型osg::ref_ptr<osg::Node> node = osgDB::readNodeFile("cessna.osg");root = createClipeNode(node.get());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());//设置场景数据viewer->setSceneData(root.get());//初始化并创建窗口viewer->realize();//开始渲染viewer->run();return 0;}

运行出来是一个飞机的模型,大家也可以把注释代码打开看看效果;

改变一下模式,看看输出什么样的飞机:
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::LINE);   //线
polymode->setMode(osg::PolygonMode::FRONT_AND_BACK,osg::PolygonMode::POINT);  //点



下面简单介绍贴二维纹理映射:

创建二维纹理的步骤如下:
1.指定用户几何体的纹理坐标
2.创建纹理属性对象并保存纹理图形数据
3.为StateSet设置合适的纹理属性和模式

附上一段代码:
#include <osgViewer/Viewer>#include <osg/Node>#include <osg/Geode>#include <osg/Geometry>#include <osg/Group>#include <osg/Image>#include <osg/TexGen>#include <osg/Texture1D>#include <osg/TexEnv>#include <osg/StateSet>#include <osgDB/ReadFile>#include <osgDB/WriteFile>#include <osgUtil/Optimizer>//创建一个四边形节点osg::ref_ptr<osg::Node> createNode(){osg::ref_ptr<osg::Geode> geode = new osg::Geode();osg::ref_ptr<osg::Geometry> geom = new osg::Geometry();//设置顶点osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array();vc->push_back(osg::Vec3(0.0f, 0.0f, 0.0f));vc->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));vc->push_back(osg::Vec3(1.0f, 0.0f, 1.0f));vc->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));geom->setVertexArray(vc.get());//设置纹理坐标osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array();vt->push_back(osg::Vec2(0.0f, 0.0f));vt->push_back(osg::Vec2(1.0f, 0.0f));vt->push_back(osg::Vec2(1.0f, 1.0f));vt->push_back(osg::Vec2(0.0f, 1.0f));//第一个参数是纹理单元号, 第二个参数是纹理坐标数组geom->setTexCoordArray(0, vt.get());//设置法线  法线和光照有关osg::ref_ptr<osg::Vec3Array> nc = new osg::Vec3Array();nc->push_back(osg::Vec3(0.0f, -1.0f, 0.0f));geom->setNormalArray(nc.get());//法线绑定方式:用一条法线绑定所有的顶点geom->setNormalBinding(osg::Geometry::BIND_OVERALL);//添加图元geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));//绘制geode->addDrawable(geom.get());return geode.get();}//创建二维纹理状态对象osg::ref_ptr<osg::StateSet> createTexture2DState(osg::ref_ptr<osg::Image> image){//创建状态集对象osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();//创建二维纹理对象osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D();texture->setDataVariance(osg::Object::DYNAMIC);//设置贴图texture->setImage(image.get());stateset->setTextureAttributeAndModes(0, texture.get(), osg::StateAttribute::ON);return stateset.get();}int main(){osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();osg::ref_ptr<osg::Group> root = new osg::Group();//读取贴图文件osg::ref_ptr<osg::Image> image = osgDB::readImageFile("Images/primitives.gif");osg::ref_ptr<osg::Node> node = createNode();//创建状态集对象osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();stateset = createTexture2DState(image.get());//使用二维纹理node->setStateSet(stateset.get());root->addChild(node.get());//优化场景数据osgUtil::Optimizer optimizer;optimizer.optimize(root.get());//设置场景数据viewer->setSceneData(root.get());//初始化并创建窗口viewer->realize();//开始渲染viewer->run();return 0;}

原创粉丝点击