这节课也是在场景中添加雾效的效果,与之类似的是第十六课,所不同的是这节课使用了雾坐标来计算雾效。为了能运行这一课,你的显卡必须支持GL_EXT_fot_coord扩展。
这节课的实现过程比较简单,在OSG中为几何体的顶点封装好了顶点的各项属性,包括顶点坐标、顶点纹理坐标、顶点颜色,当然也包括本课中的雾坐标。
首先我们还是添加顶点的各项数据:
osg::Geode *geode = new osg::Geode; osg::Geometry *geometry = new osg::Geometry; osg::Vec3Array *vertexArray = new osg::Vec3Array; osg::FloatArray *fogArray = new osg::FloatArray; osg::Vec2Array *textureArray = new osg::Vec2Array; vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,-15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); ......
osg::Texture2D *texture2D = new osg::Texture2D; texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); texture2D->setImage(osgDB::readImageFile("Data/Wall.bmp")); geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D);
osg::Fog *fog = new osg::Fog; fog->setMode(osg::Fog::LINEAR); fog->setColor(osg::Vec4(fogColor[0], fogColor[1],fogColor[2],fogColor[3])); fog->setStart(0.0f); fog->setEnd(1.0f); fog->setFogCoordinateSource(osg::Fog::FOG_COORDINATE);
附:本课源码(源码中可能存在错误和不足,仅供参考)
#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/Texture2D> #include <osg/Fog> GLfloat fogColor[4] = {0.6f, 0.3f, 0.0f, 1.0f}; osg::MatrixTransform *g_Trans = 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; switch (ea.getEventType()) { case(osgGA::GUIEventAdapter::KEYDOWN): { if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up) { if (!g_Trans) return false; osg::Vec3 trans = g_Trans->getMatrix().getTrans(); if(trans.z() < 14.0f) trans += osg::Vec3(0,0,1); g_Trans->setMatrix(osg::Matrix::translate(trans)); } if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Down) { if (!g_Trans) return false; osg::Vec3 trans = g_Trans->getMatrix().getTrans(); if(trans.z() >-19.0f) trans -= osg::Vec3(0,0,1); g_Trans->setMatrix(osg::Matrix::translate(trans)); } } 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, 0.5) ); 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, 0), osg::Vec3d(0, 0, -1), 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 = ds->getNumMultiSamples(); return new osgQt::GraphicsWindowQt(traits.get()); } virtual void paintEvent( QPaintEvent* event ) { frame(); } protected: QTimer _timer; }; osg::Node* buildScene() { osg::Group *root = new osg::Group; osg::MatrixTransform *zoomMT = new osg::MatrixTransform; zoomMT->setMatrix(osg::Matrix::translate(0,0,-19.0)); g_Trans = zoomMT; osg::Geode *geode = new osg::Geode; osg::Geometry *geometry = new osg::Geometry; osg::Vec3Array *vertexArray = new osg::Vec3Array; osg::FloatArray *fogArray = new osg::FloatArray; osg::Vec2Array *textureArray = new osg::Vec2Array; vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,-15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(0.0f); fogArray->push_back(0.0f); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); fogArray->push_back(1.0f); fogArray->push_back(1.0f); fogArray->push_back(0.0f); fogArray->push_back(0.0f); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,15.0f)); vertexArray->push_back(osg::Vec3(2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(2.5f,-2.5f,-15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); fogArray->push_back(0.0f); fogArray->push_back(0.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,2.5f,-15.0f)); vertexArray->push_back(osg::Vec3(-2.5f,-2.5f,-15.0f)); textureArray->push_back(osg::Vec2(0.0f, 0.0f)); textureArray->push_back(osg::Vec2(0.0f, 1.0f)); textureArray->push_back(osg::Vec2(1.0f, 1.0f)); textureArray->push_back(osg::Vec2(1.0f, 0.0f)); fogArray->push_back(0.0f); fogArray->push_back(0.0f); fogArray->push_back(1.0f); fogArray->push_back(1.0f); geometry->setVertexArray(vertexArray); geometry->setTexCoordArray(0, textureArray); geometry->setFogCoordArray(fogArray, osg::Array::BIND_PER_VERTEX); geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF); osg::Texture2D *texture2D = new osg::Texture2D; texture2D->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); texture2D->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR); texture2D->setImage(osgDB::readImageFile("Data/Wall.bmp")); geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture2D); osg::Fog *fog = new osg::Fog; fog->setMode(osg::Fog::LINEAR); fog->setColor(osg::Vec4(fogColor[0], fogColor[1],fogColor[2],fogColor[3])); fog->setStart(0.0f); fog->setEnd(1.0f); fog->setFogCoordinateSource(osg::Fog::FOG_COORDINATE); geometry->getOrCreateStateSet()->setAttributeAndModes(fog); geometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertexArray->size())); geode->addDrawable(geometry); zoomMT->addChild(geode); root->addChild(zoomMT); 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(); }