OpenSceneGraph实现的NeHe OpenGL教程 - 第四十六课

  • 简介

NeHe教程在这节课向我们介绍了OpenGL的扩展(ARB_MULTISAMPLE)多重采样技术。利用这种技术可以实现全屏反走样。这样可以使图形看起来更美观。

在OSG中多重采样是作为节点的StateSet来开启和关闭的,实现过程十分简单。

  • 实现

首先添加四边形到场景中,这一过程前面已经重复很多遍了,代码如下:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. for(int i=-10;i<10;i++)  
  2. {  
  3.     for(int j=-10;j<10;j++)  
  4.     {  
  5.         osg::MatrixTransform *transMT = new osg::MatrixTransform;  
  6.         transMT->addUpdateCallback(new TransCallback(i, j));  
  7.         osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  8.         rotMT->addUpdateCallback(new RotCallback);  
  9.         osg::Geode *geode = new osg::Geode;  
  10.         osg::Geometry *geometry = new osg::Geometry;  
  11.         osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  12.         osg::Vec3Array *colorArray = new osg::Vec3Array;  
  13.         colorArray->push_back(osg::Vec3(1, 0, 0));  
  14.   
  15.         vertexArray->push_back(osg::Vec3(i, j, 0.0));  
  16.         colorArray->push_back(osg::Vec3(0, 1, 0));  
  17.         vertexArray->push_back(osg::Vec3(i + 2.0f,j,0.0f));  
  18.         colorArray->push_back(osg::Vec3(0,0,1));  
  19.         vertexArray->push_back(osg::Vec3(i + 2.0f,j + 2.0f,0.0f));  
  20.         colorArray->push_back(osg::Vec3(1,1,1));  
  21.         vertexArray->push_back(osg::Vec3(i,j + 2.0f,0.0f));  
  22.   
  23.         geometry->setVertexArray(vertexArray);  
  24.         geometry->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);  
  25.         geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  26.         geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  27.         geode->addDrawable(geometry);  
  28.   
  29.         transMT->addChild(rotMT);  
  30.         rotMT->addChild(geode);  
  31.   
  32.         root->addChild(transMT);  
  33.     }  
  34. }  

在创建窗口Traits的时候需要将窗口采样值设置为4,这样才能开启多重采样:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. traits->sampleBuffers = ds->getMultiSamples();  
  2. traits->samples = 4/*ds->getNumMultiSamples()*/;  

之后为了让这些四边形旋转和移动,在节点中添加若干的回调:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. class TransCallback : public osg::NodeCallback  
  2. {  
  3. public:  
  4.     TransCallback(float i, float j) : _i(i), _j(j){}  
  5.   
  6.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  7.     {  
  8.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  9.         if(!mt)  
  10.             return;  
  11.         mt->setMatrix(osg::Matrix::translate(_i*2.0f,_j*2.0f,-5.0f));  
  12.         traverse(node, nv);  
  13.     }  
  14.     float _i;  
  15.     float _j;  
  16. };  

对节点启用多重采样:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Multisample *ms = new osg::Multisample;  
  2. ms->setHint(osg::Multisample::NICEST);  
  3. root->getOrCreateStateSet()->setAttributeAndModes(ms, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);  

与键盘交互中切换多重采样的开启和关闭模式:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  2. {  
  3.     if(!g_Root)  
  4.         return false;  
  5.     static bool flag = true;  
  6.     if (flag){  
  7.         g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, false);  
  8.     }else{  
  9.         g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, true);  
  10.     }  
  11.     flag = !flag;  
  12. }  

编译运行程序,可以看到在按下空格的时候四边形的边缘锯齿感有明显的变化:


附:本课源码(源码中可能存在错误和不足之处,仅供参考)

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include "../osgNeHe.h"  
  2.   
  3. #include <QtCore/QTimer>  
  4. #include <QtGui/QApplication>  
  5. #include <QtGui/QVBoxLayout>  
  6.   
  7. #include <osgViewer/Viewer>  
  8. #include <osgDB/ReadFile>  
  9. #include <osgQt/GraphicsWindowQt>  
  10.   
  11. #include <osg/MatrixTransform>  
  12. #include <osg/Multisample>  
  13.   
  14. osg::Group  *g_Root = NULL;  
  15.   
  16. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  17. {  
  18. public:  
  19.     ManipulatorSceneHandler()  
  20.     {  
  21.     }  
  22.   
  23. public:  
  24.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  25.     {  
  26.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  27.         if (!viewer)  
  28.             return false;  
  29.         if (!viewer->getSceneData())  
  30.             return false;  
  31.         if (ea.getHandled())   
  32.             return false;  
  33.   
  34.         osg::Group *root = viewer->getSceneData()->asGroup();  
  35.   
  36.         switch(ea.getEventType())  
  37.         {  
  38.   
  39.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  40.             {  
  41.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space)  
  42.                 {  
  43.                     if(!g_Root)  
  44.                         return false;  
  45.                     static bool flag = true;  
  46.                     if (flag){  
  47.                         g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, false);  
  48.                     }else{  
  49.                         g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, true);  
  50.                     }  
  51.                     flag = !flag;  
  52.                 }  
  53.             }  
  54.             break;  
  55.   
  56.         defaultbreak;  
  57.         }  
  58.         return false;  
  59.     }  
  60. };  
  61.   
  62. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  63. {  
  64. public:  
  65.     ViewerWidget(osg::Node *scene = NULL)  
  66.     {  
  67.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);  
  68.   
  69.         QVBoxLayout* layout = new QVBoxLayout;  
  70.         layout->addWidget(renderWidget);  
  71.         layout->setContentsMargins(0, 0, 0, 1);  
  72.         setLayout( layout );  
  73.   
  74.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  75.         _timer.start( 10 );  
  76.     }  
  77.   
  78.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  79.     {  
  80.         osg::Camera* camera = this->getCamera();  
  81.         camera->setGraphicsContext( gw );  
  82.   
  83.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  84.   
  85.         camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );  
  86.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  87.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  88.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  89.   
  90.         this->setSceneData( scene );  
  91.         this->addEventHandler(new ManipulatorSceneHandler);  
  92.         return gw->getGLWidget();  
  93.     }  
  94.   
  95.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  96.     {  
  97.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  98.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  99.         traits->windowName = name;  
  100.         traits->windowDecoration = windowDecoration;  
  101.         traits->x = x;  
  102.         traits->y = y;  
  103.         traits->width = w;  
  104.         traits->height = h;  
  105.         traits->doubleBuffer = true;  
  106.         traits->alpha = ds->getMinimumNumAlphaBits();  
  107.         traits->stencil = ds->getMinimumNumStencilBits();  
  108.         traits->sampleBuffers = ds->getMultiSamples();  
  109.         traits->samples = 4/*ds->getNumMultiSamples()*/;  
  110.   
  111.         return new osgQt::GraphicsWindowQt(traits.get());  
  112.     }  
  113.   
  114.     virtual void paintEvent( QPaintEvent* event )  
  115.     {   
  116.         frame();   
  117.     }  
  118.   
  119. protected:  
  120.   
  121.     QTimer _timer;  
  122. };  
  123.   
  124.   
  125. class TransCallback : public osg::NodeCallback  
  126. {  
  127. public:  
  128.     TransCallback(float i, float j) : _i(i), _j(j){}  
  129.   
  130.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  131.     {  
  132.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  133.         if(!mt)  
  134.             return;  
  135.         mt->setMatrix(osg::Matrix::translate(_i*2.0f,_j*2.0f,-5.0f));  
  136.         traverse(node, nv);  
  137.     }  
  138.     float _i;  
  139.     float _j;  
  140. };  
  141.   
  142.   
  143. class RotCallback : public osg::NodeCallback  
  144. {  
  145. public:  
  146.       
  147.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  148.     {  
  149.         static float angle = 0.0;  
  150.   
  151.         osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);  
  152.         if(!mt)  
  153.             return;  
  154.   
  155.         mt->setMatrix(osg::Matrix::rotate(angle, osg::Z_AXIS));  
  156.         angle += osg::DegreesToRadians(0.001f);  
  157.   
  158.         traverse(node, nv);  
  159.     }  
  160.   
  161.   
  162. };  
  163.   
  164.   
  165.   
  166. osg::Node*  buildScene()  
  167. {  
  168.     osg::Group *root = new osg::Group;  
  169.     g_Root = root;  
  170.     osg::Multisample *ms = new osg::Multisample;  
  171.     ms->setHint(osg::Multisample::NICEST);  
  172.     root->getOrCreateStateSet()->setAttributeAndModes(ms, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);  
  173.   
  174.     for(int i=-10;i<10;i++)  
  175.     {  
  176.         for(int j=-10;j<10;j++)  
  177.         {  
  178.             osg::MatrixTransform *transMT = new osg::MatrixTransform;  
  179.             transMT->addUpdateCallback(new TransCallback(i, j));  
  180.             osg::MatrixTransform *rotMT = new osg::MatrixTransform;  
  181.             rotMT->addUpdateCallback(new RotCallback);  
  182.             osg::Geode *geode = new osg::Geode;  
  183.             osg::Geometry *geometry = new osg::Geometry;  
  184.             osg::Vec3Array *vertexArray = new osg::Vec3Array;  
  185.             osg::Vec3Array *colorArray = new osg::Vec3Array;  
  186.             colorArray->push_back(osg::Vec3(1, 0, 0));  
  187.   
  188.             vertexArray->push_back(osg::Vec3(i, j, 0.0));  
  189.             colorArray->push_back(osg::Vec3(0, 1, 0));  
  190.             vertexArray->push_back(osg::Vec3(i + 2.0f,j,0.0f));  
  191.             colorArray->push_back(osg::Vec3(0,0,1));  
  192.             vertexArray->push_back(osg::Vec3(i + 2.0f,j + 2.0f,0.0f));  
  193.             colorArray->push_back(osg::Vec3(1,1,1));  
  194.             vertexArray->push_back(osg::Vec3(i,j + 2.0f,0.0f));  
  195.   
  196.             geometry->setVertexArray(vertexArray);  
  197.             geometry->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);  
  198.             geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  199.             geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));  
  200.             geode->addDrawable(geometry);  
  201.   
  202.             transMT->addChild(rotMT);  
  203.             rotMT->addChild(geode);  
  204.   
  205.             root->addChild(transMT);  
  206.         }  
  207.     }  
  208.   
  209.     return root;  
  210. }  
  211.   
  212.   
  213.   
  214. int main( int argc, char** argv )  
  215. {  
  216.     QApplication app(argc, argv);  
  217.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  218.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  219.     viewWidget->show();  
  220.     return app.exec();  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值