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

来源:互联网 发布:普通话考试准备软件 编辑:程序博客网 时间:2024/05/16 11:45
  • 简介

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

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

  • 实现

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

for(int i=-10;i<10;i++){for(int j=-10;j<10;j++){osg::MatrixTransform *transMT = new osg::MatrixTransform;transMT->addUpdateCallback(new TransCallback(i, j));osg::MatrixTransform *rotMT = new osg::MatrixTransform;rotMT->addUpdateCallback(new RotCallback);osg::Geode *geode = new osg::Geode;osg::Geometry *geometry = new osg::Geometry;osg::Vec3Array *vertexArray = new osg::Vec3Array;osg::Vec3Array *colorArray = new osg::Vec3Array;colorArray->push_back(osg::Vec3(1, 0, 0));vertexArray->push_back(osg::Vec3(i, j, 0.0));colorArray->push_back(osg::Vec3(0, 1, 0));vertexArray->push_back(osg::Vec3(i + 2.0f,j,0.0f));colorArray->push_back(osg::Vec3(0,0,1));vertexArray->push_back(osg::Vec3(i + 2.0f,j + 2.0f,0.0f));colorArray->push_back(osg::Vec3(1,1,1));vertexArray->push_back(osg::Vec3(i,j + 2.0f,0.0f));geometry->setVertexArray(vertexArray);geometry->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));geode->addDrawable(geometry);transMT->addChild(rotMT);rotMT->addChild(geode);root->addChild(transMT);}}

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

traits->sampleBuffers = ds->getMultiSamples();traits->samples = 4/*ds->getNumMultiSamples()*/;

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

class TransCallback : public osg::NodeCallback{public:TransCallback(float i, float j) : _i(i), _j(j){}virtual void operator()(osg::Node* node, osg::NodeVisitor* nv){osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);if(!mt)return;mt->setMatrix(osg::Matrix::translate(_i*2.0f,_j*2.0f,-5.0f));traverse(node, nv);}float _i;float _j;};

对节点启用多重采样:

osg::Multisample *ms = new osg::Multisample;ms->setHint(osg::Multisample::NICEST);root->getOrCreateStateSet()->setAttributeAndModes(ms, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);

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

if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space){if(!g_Root)return false;static bool flag = true;if (flag){g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, false);}else{g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, true);}flag = !flag;}

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


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

#include "../osgNeHe.h"#include <QtCore/QTimer>#include <QtGui/QApplication>#include <QtGui/QVBoxLayout>#include <osgViewer/Viewer>#include <osgDB/ReadFile>#include <osgQt/GraphicsWindowQt>#include <osg/MatrixTransform>#include <osg/Multisample>osg::Group*g_Root = NULL;class ManipulatorSceneHandler : public osgGA::GUIEventHandler{public:ManipulatorSceneHandler(){}public:virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa){osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);if (!viewer)return false;if (!viewer->getSceneData())return false;if (ea.getHandled()) return false;osg::Group *root = viewer->getSceneData()->asGroup();switch(ea.getEventType()){case(osgGA::GUIEventAdapter::KEYDOWN):{if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Space){if(!g_Root)return false;static bool flag = true;if (flag){g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, false);}else{g_Root->getOrCreateStateSet()->setMode(GL_MULTISAMPLE_ARB, true);}flag = !flag;}}break;default: break;}return false;}};class ViewerWidget : public QWidget, public osgViewer::Viewer{public:ViewerWidget(osg::Node *scene = NULL){QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,100,100), scene);QVBoxLayout* layout = new QVBoxLayout;layout->addWidget(renderWidget);layout->setContentsMargins(0, 0, 0, 1);setLayout( layout );connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );_timer.start( 10 );}QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene ){osg::Camera* camera = this->getCamera();camera->setGraphicsContext( gw );const osg::GraphicsContext::Traits* traits = gw->getTraits();camera->setClearColor( osg::Vec4(0.0, 0.0, 0.0, 1.0) );camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));this->setSceneData( scene );this->addEventHandler(new ManipulatorSceneHandler);return gw->getGLWidget();}osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name="", bool windowDecoration=false ){osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;traits->windowName = name;traits->windowDecoration = windowDecoration;traits->x = x;traits->y = y;traits->width = w;traits->height = h;traits->doubleBuffer = true;traits->alpha = ds->getMinimumNumAlphaBits();traits->stencil = ds->getMinimumNumStencilBits();traits->sampleBuffers = ds->getMultiSamples();traits->samples = 4/*ds->getNumMultiSamples()*/;return new osgQt::GraphicsWindowQt(traits.get());}virtual void paintEvent( QPaintEvent* event ){ frame(); }protected:QTimer _timer;};class TransCallback : public osg::NodeCallback{public:TransCallback(float i, float j) : _i(i), _j(j){}virtual void operator()(osg::Node* node, osg::NodeVisitor* nv){osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);if(!mt)return;mt->setMatrix(osg::Matrix::translate(_i*2.0f,_j*2.0f,-5.0f));traverse(node, nv);}float _i;float _j;};class RotCallback : public osg::NodeCallback{public:virtual void operator()(osg::Node* node, osg::NodeVisitor* nv){static float angle = 0.0;osg::MatrixTransform *mt = dynamic_cast<osg::MatrixTransform*>(node);if(!mt)return;mt->setMatrix(osg::Matrix::rotate(angle, osg::Z_AXIS));angle += osg::DegreesToRadians(0.001f);traverse(node, nv);}};osg::Node*buildScene(){osg::Group *root = new osg::Group;g_Root = root;osg::Multisample *ms = new osg::Multisample;ms->setHint(osg::Multisample::NICEST);root->getOrCreateStateSet()->setAttributeAndModes(ms, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);for(int i=-10;i<10;i++){for(int j=-10;j<10;j++){osg::MatrixTransform *transMT = new osg::MatrixTransform;transMT->addUpdateCallback(new TransCallback(i, j));osg::MatrixTransform *rotMT = new osg::MatrixTransform;rotMT->addUpdateCallback(new RotCallback);osg::Geode *geode = new osg::Geode;osg::Geometry *geometry = new osg::Geometry;osg::Vec3Array *vertexArray = new osg::Vec3Array;osg::Vec3Array *colorArray = new osg::Vec3Array;colorArray->push_back(osg::Vec3(1, 0, 0));vertexArray->push_back(osg::Vec3(i, j, 0.0));colorArray->push_back(osg::Vec3(0, 1, 0));vertexArray->push_back(osg::Vec3(i + 2.0f,j,0.0f));colorArray->push_back(osg::Vec3(0,0,1));vertexArray->push_back(osg::Vec3(i + 2.0f,j + 2.0f,0.0f));colorArray->push_back(osg::Vec3(1,1,1));vertexArray->push_back(osg::Vec3(i,j + 2.0f,0.0f));geometry->setVertexArray(vertexArray);geometry->setColorArray(colorArray, osg::Array::BIND_PER_VERTEX);geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size()));geode->addDrawable(geometry);transMT->addChild(rotMT);rotMT->addChild(geode);root->addChild(transMT);}}return root;}int main( int argc, char** argv ){QApplication app(argc, argv);ViewerWidget* viewWidget = new ViewerWidget(buildScene());viewWidget->setGeometry( 100, 100, 640, 480 );viewWidget->show();return app.exec();}

0 0
原创粉丝点击