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

  • 简介

这节课主要介绍了如何使用OpenGL中的模板缓冲区和裁剪平面来产生镜子反射的效果,关于模板缓冲区的内容可以参考另一篇文章OpenGL模板缓冲区---Stencil Buffer

  • 实现

首先我们需要在模板缓冲区中将地面(类似镜子)绘制出来,同时并不会在颜色缓冲区中绘制出镜面。通过设置颜色掩码glColorMask可以做到这一点

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //创建模板缓冲区中的镜面(不可见)  
  2. //深度测试关闭意味着深度测试总是通过  
  3. osg::Geode *stencilFloorGeode = createFloor();  
  4. osg::Stencil *floorStencil = new osg::Stencil;  
  5. floorStencil->setFunction(osg::Stencil::ALWAYS, 1, 1);  
  6. floorStencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);  
  7. osg::ColorMask *colorMask1 = new osg::ColorMask(0, 0, 0, 0);  
  8. stencilFloorGeode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  9. stencilFloorGeode->getOrCreateStateSet()->setAttribute(colorMask1, osg::StateAttribute::ON);  
  10. stencilFloorGeode->getOrCreateStateSet()->setAttributeAndModes(floorStencil);  
  11. stencilFloorGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  

此时在模板缓冲区中存在这一个地面(全部为1,其他模板缓冲区的部分都是0),这时候我们在绘制球体在镜面中的镜像,我们让所有是1的地方进行绘制,这样绘制的球体只有在镜面的地方才能绘制出来,其他地方都无法绘制。

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Group *reflectionBall = createSphere();  
  2.   
  3. osg::Stencil *stencilBall  = new osg::Stencil;  
  4. stencilBall->setFunction(osg::Stencil::EQUAL, 1, 1);  
  5. stencilBall->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);  
  6.   
  7. osg::ClipPlane *clipPlane = new osg::ClipPlane(0, 0.0, -1.0, 0.0, 0.0);  
  8.   
  9. reflectionBall->getOrCreateStateSet()->setAttributeAndModes(stencilBall, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);  
  10. reflectionBall->getOrCreateStateSet()->setAttributeAndModes(clipPlane);  
接下来在颜色缓冲区(可见的屏幕上)绘制真实的地面(镜子)

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Geode *colorBufferFloor  = createFloor();  
  2. osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
  3. osg::Geometry *floorGeometry = colorBufferFloor->getDrawable(0)->asGeometry();  
  4. if (floorGeometry)  
  5. {  
  6.     osg::Vec4Array *colorArray = new osg::Vec4Array;  
  7.     colorArray->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 0.8f));  
  8.     floorGeometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  9.     floorGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  10.     floorGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  11. }  
最后我们绘制出真实的球体:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::Group *realBall = createSphere();  
  2. transMT->addChild(rotateX);  
  3. rotateX->addChild(rotateY);  
  4. rotateY->addChild(realBall);  

将所有绘制好的部分添加到根节点下面:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. //所有部分添加到场景节点  
  2. root->addChild(tiltMT);  
  3. tiltMT->addChild(stencilFloorGeode);  
  4. tiltMT->addChild(reflectScaleMT);  
  5. tiltMT->addChild(colorBufferFloor);  
  6. tiltMT->addChild(transMT);  

在我们操作真实球体的时候,镜像的球体实际上也在跟着上下运动,通过反转Y轴实现了这样的效果:

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. osg::MatrixTransform *reflectScaleMT = new osg::MatrixTransform;  
  2. reflectScaleMT->setMatrix(osg::Matrix::scale(1.0, -1.0, 1.0));  
与键盘交互部分的代码与第二十五课中一样

编译运行程序:


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

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. /************************************************************************\ 
  2.  * osgNeHe - Copyright (C) 2013-2014 Frank He 
  3.  * 
  4.  * This library is open source and may be redistributed and/or modified under 
  5.  * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
  6.  * (at your option) any later version.  The full license is in LICENSE file 
  7.  * included with this distribution, and on the openscenegraph.org website. 
  8.  * 
  9.  * This library is distributed in the hope that it will be useful, 
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of 
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
  12. * 
  13. *   A HUGE thanks to NeHe for the OpenGL tutorials< http://nehe.gamedev.net > 
  14. * 
  15. *  If you've found this code useful, Please let me know. 
  16. *  My E-mail: < hzhxfrank@gmail.com > 
  17. *  My Blog: < http://blog.youkuaiyun.com/csxiaoshui > 
  18. * 
  19. \************************************************************************/  
  20.   
  21.   
  22. #include "../osgNeHe.h"  
  23.   
  24. #include <QtCore/QTimer>  
  25. #include <QtGui/QApplication>  
  26. #include <QtGui/QVBoxLayout>  
  27.   
  28. #include <osgViewer/Viewer>  
  29. #include <osgDB/ReadFile>  
  30. #include <osgQt/GraphicsWindowQt>  
  31.   
  32. #include <osg/MatrixTransform>  
  33. #include <osg/ShapeDrawable>  
  34.   
  35. #include <osg/TexGen>  
  36. #include <osg/BlendFunc>  
  37. #include <osg/Texture2D>  
  38.   
  39. #include <osg/ColorMask>  
  40. #include <osg/Stencil>  
  41. #include <osg/ClipPlane>  
  42.   
  43. //  
  44. static GLfloat LightAmb[] = {0.7f, 0.7f, 0.7f, 1.0f};  
  45. static GLfloat LightDif[] = {1.0f, 1.0f, 1.0f, 1.0f};  
  46. static GLfloat LightPos[] = {4.0f, 4.0f, 6.0f, 1.0f};  
  47.   
  48.   
  49. GLfloat     xrot        =  0.0f;  
  50. GLfloat     yrot        =  0.0f;  
  51. GLfloat     xrotspeed   =  0.0f;  
  52. GLfloat     yrotspeed   =  0.0f;  
  53. GLfloat     zoom        = -7.0f;      
  54. GLfloat     height      =  2.0f;  
  55.   
  56. osg::MatrixTransform *g_ZoomMT = NULL;  
  57.   
  58. osg::MatrixTransform *g_ReflectTrans = NULL;  
  59. osg::MatrixTransform *g_ReflectRotX = NULL;  
  60. osg::MatrixTransform *g_ReflectRotY = NULL;  
  61.   
  62. osg::MatrixTransform *g_Trans = NULL;  
  63. osg::MatrixTransform *g_RotX = NULL;  
  64. osg::MatrixTransform *g_RotY = NULL;  
  65.   
  66.   
  67. osg::Group* createSphere()  
  68. {  
  69.     osg::Group *sphereGroup = new osg::Group;  
  70.     osg::Geode *sphereGeode1 = new osg::Geode;  
  71.     osg::Geode *sphereGeode2 = new osg::Geode;  
  72.       
  73.     osg::ShapeDrawable *shapeDrawable1 = new osg::ShapeDrawable;  
  74.     shapeDrawable1->setShape(new osg::Sphere(osg::Vec3(0,0,0), 0.5f));  
  75.     shapeDrawable1->setColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));  
  76.     osg::Texture2D *texture1 = new osg::Texture2D;  
  77.     texture1->setImage(osgDB::readImageFile("Data/Ball.bmp"));  
  78.     texture1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  79.     texture1->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  80.     shapeDrawable1->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture1);  
  81.     sphereGeode1->addDrawable(shapeDrawable1);  
  82.       
  83.     osg::ShapeDrawable *shapeDrawable2 = new osg::ShapeDrawable;  
  84.     shapeDrawable2->setShape(new osg::Sphere(osg::Vec3(0,0,0), 0.5f));  
  85.     shapeDrawable2->setColor(osg::Vec4(1.0f, 1.0f, 1.0f, 0.4f));  
  86.     osg::Texture2D *texture2 = new osg::Texture2D;  
  87.     texture2->setImage(osgDB::readImageFile("Data/EnvRoll.bmp"));  
  88.     texture2->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  89.     texture2->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  90.     shapeDrawable2->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2);  
  91.     osg::BlendFunc *blendFunc = new osg::BlendFunc(GL_SRC_ALPHA, GL_ONE);  
  92.     shapeDrawable2->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  93.     osg::TexGen *texGen = new osg::TexGen;  
  94.     texGen->setMode(osg::TexGen::SPHERE_MAP);  
  95.     shapeDrawable2->getOrCreateStateSet()->setTextureAttributeAndModes(0, texGen);  
  96.     sphereGeode2->addDrawable(shapeDrawable2);  
  97.       
  98.     sphereGroup->addChild(sphereGeode1);  
  99.     sphereGroup->addChild(sphereGeode2);  
  100.   
  101.     return sphereGroup;  
  102. }  
  103.   
  104.   
  105. osg::Geode* createFloor()  
  106. {  
  107.     osg::Geode *geode1 = new osg::Geode;  
  108.     osg::Geometry *geometry1 = new osg::Geometry;  
  109.   
  110.     osg::Vec3Array *vertexArray1 = new osg::Vec3Array;  
  111.     vertexArray1->push_back(osg::Vec3(-2.0, 0.0, 2.0));  
  112.     vertexArray1->push_back(osg::Vec3(-2.0, 0.0,-2.0));  
  113.     vertexArray1->push_back(osg::Vec3(2.0, 0.0,-2.0));  
  114.     vertexArray1->push_back(osg::Vec3(2.0, 0.0, 2.0));  
  115.     geometry1->setVertexArray(vertexArray1);  
  116.     osg::Vec2Array *textureArray1 = new osg::Vec2Array;  
  117.     textureArray1->push_back(osg::Vec2(0.0f, 1.0f));  
  118.     textureArray1->push_back(osg::Vec2(0.0f, 0.0f));  
  119.     textureArray1->push_back(osg::Vec2(1.0f, 0.0f));  
  120.     textureArray1->push_back(osg::Vec2(1.0f, 1.0f));  
  121.     osg::Texture2D *texture1 = new osg::Texture2D;  
  122.     texture1->setImage(osgDB::readImageFile("Data/EnvWall.bmp"));  
  123.     texture1->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);  
  124.     texture1->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);  
  125.   
  126.     geometry1->setTexCoordArray(0, textureArray1);  
  127.     geometry1->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));  
  128.     geometry1->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture1);  
  129.   
  130.     geode1->addDrawable(geometry1);  
  131.       
  132.     return geode1;  
  133. }  
  134.   
  135. //  
  136.   
  137.   
  138. //  
  139. class RotAxisCallback : public osg::NodeCallback  
  140. {  
  141. public:  
  142.     RotAxisCallback(const osg::Vec3& axis, double rotSpeed = 0.0, double currentAngle = 0.0)  
  143.         : _rotAxis(axis), _rotSpeed(rotSpeed), _currentAngle(currentAngle){ }  
  144.   
  145.     virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  
  146.     {  
  147.         osg::MatrixTransform *rotMT = dynamic_cast<osg::MatrixTransform*>(node);  
  148.         if (!rotMT)  
  149.             return;  
  150.         rotMT->setMatrix(osg::Matrix::rotate(_currentAngle, _rotAxis));  
  151.         _currentAngle += _rotSpeed;  
  152.   
  153.         traverse(node, nv);  
  154.     }  
  155.   
  156.     void setRotateSpeed(double speed)  
  157.     {  
  158.         _rotSpeed = speed;  
  159.     }  
  160.   
  161.     double getRotateSpeed() const  
  162.     {  
  163.         return _rotSpeed;  
  164.     }  
  165.   
  166.   
  167. private:  
  168.     osg::Vec3       _rotAxis;  
  169.     double          _currentAngle;  
  170.     double          _rotSpeed;  
  171. };  
  172.   
  173.   
  174. //  
  175. class ManipulatorSceneHandler : public osgGA::GUIEventHandler  
  176. {  
  177. public:  
  178.     ManipulatorSceneHandler()  
  179.     {  
  180.     }  
  181.   
  182.     virtual bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa)  
  183.     {  
  184.         osgViewer::Viewer *viewer = dynamic_cast<osgViewer::Viewer*>(&aa);  
  185.         if (!viewer)  
  186.             return false;  
  187.         if (!viewer->getSceneData())  
  188.             return false;  
  189.         if (ea.getHandled())   
  190.             return false;  
  191.   
  192.         osg::Group *root = viewer->getSceneData()->asGroup();  
  193.   
  194.         switch(ea.getEventType())  
  195.         {  
  196.         case(osgGA::GUIEventAdapter::KEYDOWN):  
  197.             {  
  198.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Left)  
  199.                 {  
  200.                     if (!g_RotY|| !g_ReflectRotY)  
  201.                         return false;  
  202.   
  203.                     RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotY->getUpdateCallback());  
  204.                     RotAxisCallback *rotCallbackReflect = dynamic_cast<RotAxisCallback*>(g_ReflectRotY->getUpdateCallback());  
  205.                     if (!rotCallback || !rotCallbackReflect)  
  206.                         return false;  
  207.   
  208.                     double speed = rotCallback->getRotateSpeed();  
  209.                     speed -= 0.02;  
  210.                     rotCallback->setRotateSpeed(speed);  
  211.                       
  212.                     speed = rotCallbackReflect->getRotateSpeed();  
  213.                     speed -= 0.02;  
  214.                     rotCallbackReflect->setRotateSpeed(speed);             
  215.                 }  
  216.   
  217.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right)  
  218.                 {  
  219.                     if (!g_RotY|| !g_ReflectRotY)  
  220.                         return false;  
  221.   
  222.                     RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotY->getUpdateCallback());  
  223.                     RotAxisCallback *rotCallbackReflect = dynamic_cast<RotAxisCallback*>(g_ReflectRotY->getUpdateCallback());  
  224.                     if (!rotCallback || !rotCallbackReflect)  
  225.                         return false;  
  226.   
  227.                     double speed = rotCallback->getRotateSpeed();  
  228.                     speed += 0.02;  
  229.                     rotCallback->setRotateSpeed(speed);  
  230.   
  231.                     speed = rotCallbackReflect->getRotateSpeed();  
  232.                     speed += 0.02;  
  233.                     rotCallbackReflect->setRotateSpeed(speed);         
  234.                 }  
  235.   
  236.                 if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up)  
  237.                 {  
  238.                     if (!g_RotX|| !g_ReflectRotX)  
  239.                         return false;  
  240.   
  241.                     RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotX->getUpdateCallback());  
  242.                     RotAxisCallback *rotCallbackReflect = dynamic_cast<RotAxisCallback*>(g_ReflectRotX->getUpdateCallback());  
  243.                     if (!rotCallback || !rotCallbackReflect)  
  244.                         return false;  
  245.   
  246.                     double speed = rotCallback->getRotateSpeed();  
  247.                     speed -= 0.02;  
  248.                     rotCallback->setRotateSpeed(speed);  
  249.   
  250.                     speed = rotCallbackReflect->getRotateSpeed();  
  251.                     speed -= 0.02;  
  252.                     rotCallbackReflect->setRotateSpeed(speed);         
  253.                 }  
  254.   
  255.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down)  
  256.                 {  
  257.                     if (!g_RotX|| !g_ReflectRotX)  
  258.                         return false;  
  259.   
  260.                     RotAxisCallback *rotCallback = dynamic_cast<RotAxisCallback*>(g_RotX->getUpdateCallback());  
  261.                     RotAxisCallback *rotCallbackReflect = dynamic_cast<RotAxisCallback*>(g_ReflectRotX->getUpdateCallback());  
  262.                     if (!rotCallback || !rotCallbackReflect)  
  263.                         return false;  
  264.   
  265.                     double speed = rotCallback->getRotateSpeed();  
  266.                     speed += 0.02;  
  267.                     rotCallback->setRotateSpeed(speed);  
  268.   
  269.                     speed = rotCallbackReflect->getRotateSpeed();  
  270.                     speed += 0.02;  
  271.                     rotCallbackReflect->setRotateSpeed(speed);         
  272.                 }  
  273.   
  274.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Page_Up)  
  275.                 {     
  276.                     if (!g_Trans || !g_ReflectTrans)  
  277.                         return false;  
  278.   
  279.                     osg::Matrix transMatrix = g_Trans->getMatrix();  
  280.                     transMatrix.setTrans(transMatrix.getTrans() + osg::Vec3(0, 0.1, 0));  
  281.                     g_Trans->setMatrix(transMatrix);  
  282.   
  283.                     osg::Matrix reflectTransMatrix = g_ReflectTrans->getMatrix();  
  284.                     reflectTransMatrix.setTrans(reflectTransMatrix.getTrans() + osg::Vec3(0, 0.1, 0));  
  285.                     g_ReflectTrans->setMatrix(reflectTransMatrix);  
  286.                 }  
  287.   
  288.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Page_Down)  
  289.                 {  
  290.                     if (!g_Trans || !g_ReflectTrans)  
  291.                         return false;  
  292.   
  293.                     osg::Matrix transMatrix = g_Trans->getMatrix();  
  294.                     transMatrix.setTrans(transMatrix.getTrans() + osg::Vec3(0, -0.1, 0));  
  295.                     g_Trans->setMatrix(transMatrix);  
  296.   
  297.                     osg::Matrix reflectTransMatrix = g_ReflectTrans->getMatrix();  
  298.                     reflectTransMatrix.setTrans(reflectTransMatrix.getTrans() + osg::Vec3(0, -0.1, 0));  
  299.                     g_ReflectTrans->setMatrix(reflectTransMatrix);  
  300.                 }  
  301.   
  302.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_A)  
  303.                 {  
  304.                     if (!g_ZoomMT)  
  305.                         return false;  
  306.   
  307.                     osg::Matrix transMatrix = g_ZoomMT->getMatrix();  
  308.                     transMatrix.setTrans(transMatrix.getTrans() + osg::Vec3(0, 0, -0.1));  
  309.                     g_ZoomMT->setMatrix(transMatrix);  
  310.                 }  
  311.   
  312.                 if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Z)  
  313.                 {  
  314.                     if (!g_ZoomMT)  
  315.                         return false;  
  316.   
  317.                     osg::Matrix transMatrix = g_ZoomMT->getMatrix();  
  318.                     transMatrix.setTrans(transMatrix.getTrans() + osg::Vec3(0, 0, 0.1));  
  319.                     g_ZoomMT->setMatrix(transMatrix);  
  320.                 }  
  321.             }  
  322.         defaultbreak;  
  323.         }  
  324.         return false;  
  325.     }  
  326. };  
  327.   
  328. //  
  329. //  
  330.   
  331.   
  332. class ViewerWidget : public QWidget, public osgViewer::Viewer  
  333. {  
  334. public:  
  335.     ViewerWidget(osg::Node *scene = NULL)  
  336.     {  
  337.         QWidget* renderWidget = getRenderWidget( createGraphicsWindow(0,0,640,480), scene);  
  338.   
  339.         QVBoxLayout* layout = new QVBoxLayout;  
  340.         layout->addWidget(renderWidget);  
  341.         layout->setContentsMargins(0, 0, 0, 1);  
  342.         setLayout( layout );  
  343.   
  344.         connect( &_timer, SIGNAL(timeout()), this, SLOT(update()) );  
  345.         _timer.start( 10 );  
  346.     }  
  347.   
  348.     QWidget* getRenderWidget( osgQt::GraphicsWindowQt* gw, osg::Node* scene )  
  349.     {  
  350.         osg::Camera* camera = this->getCamera();  
  351.         camera->setGraphicsContext( gw );  
  352.   
  353.         const osg::GraphicsContext::Traits* traits = gw->getTraits();  
  354.   
  355.         camera->setClearColor( osg::Vec4(0.2f, 0.5f, 1.0f, 1.0f) );  
  356.         camera->setViewport( new osg::Viewport(0, 0, traits->width, traits->height) );  
  357.         camera->setProjectionMatrixAsPerspective(45.0f, static_cast<double>(traits->width)/static_cast<double>(traits->height), 0.1f, 100.0f );  
  358.         camera->setViewMatrixAsLookAt(osg::Vec3d(0, 0, 1), osg::Vec3d(0, 0, 0), osg::Vec3d(0, 1, 0));  
  359.         unsigned int clearMask = camera->getClearMask();    
  360.         camera->setClearMask(clearMask | GL_STENCIL_BUFFER_BIT);   
  361.   
  362.         this->setSceneData( scene );  
  363.         this->addEventHandler(new ManipulatorSceneHandler);  
  364.         return gw->getGLWidget();  
  365.     }  
  366.   
  367.     osgQt::GraphicsWindowQt* createGraphicsWindow( int x, int y, int w, int h, const std::string& name=""bool windowDecoration=false )  
  368.     {  
  369.         osg::DisplaySettings* ds = osg::DisplaySettings::instance().get();  
  370.         osg::ref_ptr<osg::GraphicsContext::Traits> traits = new osg::GraphicsContext::Traits;  
  371.         traits->windowName = name;  
  372.         traits->windowDecoration = windowDecoration;  
  373.         traits->x = x;  
  374.         traits->y = y;  
  375.         traits->width = w;  
  376.         traits->height = h;  
  377.         traits->doubleBuffer = true;  
  378.         traits->alpha = ds->getMinimumNumAlphaBits();  
  379.         traits->stencil = ds->getMinimumNumStencilBits();  
  380.         traits->sampleBuffers = ds->getMultiSamples();  
  381.         traits->samples = ds->getNumMultiSamples();  
  382.   
  383.         return new osgQt::GraphicsWindowQt(traits.get());  
  384.     }  
  385.   
  386.     virtual void paintEvent( QPaintEvent* event )  
  387.     {   
  388.         frame();   
  389.     }  
  390.   
  391. protected:  
  392.   
  393.     QTimer _timer;  
  394. };  
  395.   
  396.   
  397. osg::Node*  buildScene()  
  398. {  
  399.     osg::Group *root = new osg::Group;  
  400.   
  401.     osg::Light *light = new osg::Light;  
  402.     light->setAmbient(osg::Vec4(LightAmb[0], LightAmb[1], LightAmb[2], LightAmb[3]));  
  403.     light->setDiffuse(osg::Vec4(LightDif[0], LightDif[1], LightDif[2], LightDif[3]));  
  404.     light->setPosition(osg::Vec4(LightPos[0], LightPos[1], LightPos[2], LightPos[3]));  
  405.     light->setLightNum(0);  
  406.     osg::LightSource *lightSource = new osg::LightSource;  
  407.     lightSource->setLight(light);  
  408.   
  409.     osg::MatrixTransform *tiltMT = new osg::MatrixTransform;  
  410.     g_ZoomMT = tiltMT;  
  411.     tiltMT->setMatrix(osg::Matrix::translate(0.0f, -0.6f, -7.0f));  
  412.   
  413.     tiltMT->addChild(lightSource);  
  414.     //创建模板缓冲区中的镜面(不可见)  
  415.     //深度测试关闭意味着深度测试总是通过  
  416.     osg::Geode *stencilFloorGeode = createFloor();  
  417.     osg::Stencil *floorStencil = new osg::Stencil;  
  418.     floorStencil->setFunction(osg::Stencil::ALWAYS, 1, 1);  
  419.     floorStencil->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::REPLACE);  
  420.     osg::ColorMask *colorMask1 = new osg::ColorMask(0, 0, 0, 0);  
  421.     stencilFloorGeode->getOrCreateStateSet()->setMode(GL_DEPTH_TEST, false);  
  422.     stencilFloorGeode->getOrCreateStateSet()->setAttribute(colorMask1, osg::StateAttribute::ON);  
  423.     stencilFloorGeode->getOrCreateStateSet()->setAttributeAndModes(floorStencil);  
  424.     stencilFloorGeode->getOrCreateStateSet()->setMode(GL_LIGHTING, false);  
  425.   
  426.     //创建镜面中的球体(球体镜像)  
  427.     osg::MatrixTransform *reflectScaleMT = new osg::MatrixTransform;  
  428.     reflectScaleMT->setMatrix(osg::Matrix::scale(1.0, -1.0, 1.0));  
  429.     reflectScaleMT->addChild(lightSource);  
  430.     osg::MatrixTransform *reflectTransMT = new osg::MatrixTransform;  
  431.     reflectTransMT->setMatrix(osg::Matrix::translate(0.0, 2.0, 0.0));  
  432.     g_ReflectTrans = reflectTransMT;  
  433.     osg::MatrixTransform *reflectRotateX = new osg::MatrixTransform;  
  434.     g_ReflectRotX = reflectRotateX;  
  435.     reflectRotateX->addUpdateCallback(new RotAxisCallback(osg::X_AXIS));  
  436.     osg::MatrixTransform *reflectRotateY = new osg::MatrixTransform;  
  437.     g_ReflectRotY = reflectRotateY;  
  438.     reflectRotateY->addUpdateCallback(new RotAxisCallback(osg::Y_AXIS));  
  439.     osg::Group *reflectionBall = createSphere();  
  440.       
  441.     osg::Stencil *stencilBall  = new osg::Stencil;  
  442.     stencilBall->setFunction(osg::Stencil::EQUAL, 1, 1);  
  443.     stencilBall->setOperation(osg::Stencil::KEEP, osg::Stencil::KEEP, osg::Stencil::KEEP);  
  444.   
  445.     osg::ClipPlane *clipPlane = new osg::ClipPlane(0, 0.0, -1.0, 0.0, 0.0);  
  446.   
  447.     reflectionBall->getOrCreateStateSet()->setAttributeAndModes(stencilBall, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);  
  448.     reflectionBall->getOrCreateStateSet()->setAttributeAndModes(clipPlane);  
  449.       
  450.     reflectScaleMT->addChild(reflectTransMT);  
  451.     reflectTransMT->addChild(reflectRotateX);  
  452.     reflectRotateX->addChild(reflectRotateY);  
  453.     reflectRotateY->addChild(reflectionBall);  
  454.   
  455.     //创建颜色缓冲区镜面(可见)  
  456.     osg::Geode *colorBufferFloor  = createFloor();  
  457.     osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
  458.     osg::Geometry *floorGeometry = colorBufferFloor->getDrawable(0)->asGeometry();  
  459.     if (floorGeometry)  
  460.     {  
  461.         osg::Vec4Array *colorArray = new osg::Vec4Array;  
  462.         colorArray->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 0.8f));  
  463.         floorGeometry->setColorArray(colorArray, osg::Array::BIND_OVERALL);  
  464.         floorGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);  
  465.         floorGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);  
  466.     }  
  467.     osg::MatrixTransform *transMT = new osg::MatrixTransform;  
  468.     transMT->setMatrix(osg::Matrix::translate(0, 2, 0));  
  469.     g_Trans = transMT;  
  470.     osg::MatrixTransform *rotateX = new osg::MatrixTransform;  
  471.     g_RotX = rotateX;  
  472.     rotateX->addUpdateCallback(new RotAxisCallback(osg::X_AXIS));  
  473.     osg::MatrixTransform *rotateY = new osg::MatrixTransform;  
  474.     g_RotY = rotateY;  
  475.     rotateY->addUpdateCallback(new RotAxisCallback(osg::Y_AXIS));  
  476.     osg::Group *realBall = createSphere();  
  477.     transMT->addChild(rotateX);  
  478.     rotateX->addChild(rotateY);  
  479.     rotateY->addChild(realBall);  
  480.   
  481.     //所有部分添加到场景节点  
  482.     root->addChild(tiltMT);  
  483.     tiltMT->addChild(stencilFloorGeode);  
  484.     tiltMT->addChild(reflectScaleMT);  
  485.     tiltMT->addChild(colorBufferFloor);  
  486.     tiltMT->addChild(transMT);  
  487.   
  488.     return root;  
  489. }  
  490.   
  491.   
  492.   
  493. int main( int argc, char** argv )  
  494. {  
  495.     QApplication app(argc, argv);  
  496.     ViewerWidget* viewWidget = new ViewerWidget(buildScene());  
  497.     viewWidget->setGeometry( 100, 100, 640, 480 );  
  498.     viewWidget->show();  
  499.     return app.exec();  
  500. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值