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

来源:互联网 发布:淘宝网限制购买商品 编辑:程序博客网 时间:2024/05/20 05:53
  • 简介

这节课我们将讨论凹凸纹理技术,使用凹凸纹理可以让物体表面更有质感。本节课实现的其实是一种被称为浮雕纹理的技术(Emboss Bump Mapping),并不能算真正的凹凸纹理实现方式(It is a Hack)。

光滑的表面它上面各点法线的方向是一致的,凹凸纹理通过扰乱它表面的法线方向,在进行光照计算的时候(像素光照计算)会使得光滑表面产生明暗不同的颜色,从而"欺骗"我们的大脑,让我们以为它的表面是凹凸不平的。凹凸纹理最早是由James F. Blinn在1978年提的

NeHe课程中的实现原理可以参考凹凸纹理随笔, 在开始之前先说明一下NeHe课程中的实现方式:

NeHe教程中通过空格切换在三种模式下进行:

1. 未使用多重纹理(MultiTexture)技术进行凹凸纹理处理

2.使用多重纹理(MultiTexture)技术进行凹凸纹理处理

3.渲染不带凹凸纹理的场景

这三个过程分别对应doMesh1TexelUnits、doMesh1Texe2Units、doMeshNoBumps三个函数。本课只实现了在1情形下的凹凸纹理。2的实现也在源码中,但是未找到对应的OpenGL API,希望知道的读者指点一二。

下面简单说一下Emboss Bump Mapping的实现过程:

浮雕纹理需要对模型表面贴两次纹理,第一次纹理的纹理坐标不进行偏移、第二次的纹理坐标会在光照方向上进行偏移。偏移量的计算方法可以参考PPT Emboss Bump Mapping

  • 实现

首先和NeHe教程一下初始化我们需要的纹理:

这里面需要使用osg中的Image类和处理Image的ImageUtil中的内容:部分代码如下:

osg::Image *image1 = new osg::Image;image1 = osgDB::readImageFile("Data/Base.bmp");texture[0] = new osg::Texture2D;texture[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);texture[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);texture[0]->setImage(image1);texture[1] = new osg::Texture2D;texture[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);texture[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);texture[1]->setImage(image1);
另外我们需要把进行纹理贴图的图像亮度减半,代码如下:

osg::Image *image2 = new osg::Image;image2 = osgDB::readImageFile("Data/Bump.bmp");osg::offsetAndScaleImage(image2, osg::Vec4(), osg::Vec4(0.5, 0.5, 0.5, 1)); // RGB值都减半bump[0] = new osg::Texture2D;bump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);bump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);bump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);bump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);bump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));bump[0]->setImage(image2);
此外反转图像RGB值,使得凹的纹理变成凸的纹理:

osg::Image *image3 = osgDB::readImageFile("Data/Bump.bmp");osg::offsetAndScaleImage(image3, osg::Vec4(), osg::Vec4(0.5,0.5,0.5,1));osg::offsetAndScaleImage(image3, osg::Vec4(-128, -128, -128, 1), osg::Vec4(-1,-1,-1,1));invbump[0] = new osg::Texture2D;invbump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);invbump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);invbump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);invbump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);invbump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));invbump[0]->setImage(image3);
创建正常显示立方体的代码在createCube函数中。

为了进行凹凸纹理,我们先设置第一次纹理部分,代码如下:

可以看到这一次贴的纹理的纹理坐标并没有偏移,全部用到了data中的原始数据

osg::Geode* createUpMappingCube(){osg::Geode *cubeGeode = new osg::Geode;osg::Geometry *cubeGeometry = new osg::Geometry;osg::Vec3Array *vertices = new osg::Vec3Array;osg::Vec3Array *normals = new osg::Vec3Array;osg::Vec2Array *texcoords = new osg::Vec2Array;for (unsigned i = 0; i < 24; ++i){texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));  //第一次贴纹理不需要偏移vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));}cubeGeometry->setVertexArray(vertices);cubeGeometry->setTexCoordArray(0, texcoords);cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, bump[1]);osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);cubeGeode->addDrawable(cubeGeometry);return cubeGeode;}
在进行第二次贴纹理时由于要把光源位置变换到物体表面的切空间中,需要获取此时模型的模型视图矩阵,在设置中难以获得,在回调中获取:

//第二次贴纹理,这里面并没有纹理坐标,因为纹理坐标需要偏移,在回调中计算osg::Geode* createDownMappingCube(){osg::Geode *cubeGeode = new osg::Geode;osg::Geometry *cubeGeometry = new osg::Geometry;cubeGeometry->setUpdateCallback(new TextureCallback());osg::Vec3Array *vertices = new osg::Vec3Array;for (unsigned i = 0; i < 24; ++i){vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));}cubeGeometry->setVertexArray(vertices);cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));cubeGeode->addDrawable(cubeGeometry);return cubeGeode;}

接下来看看回调实现:(只给出部分代码)

virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable){osg::Geometry *geometry = drawable->asGeometry();if (!geometry)return;osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(0));if(textureArray)return;textureArray = new osg::Vec2Array;osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);               //获取当前模型视图矩阵osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();//反转模型视图矩阵                osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);//将光源变换到物体建模坐标系下                osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;//////////////////////////////////////////////////////////////////////////for (int i=0; i<4; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();                        //获取切空间中在S、T轴上的偏移量                        double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}
最后把这三次的结果添加到场景中
osg::Switch *switchNode = new osg::Switch;g_switch = switchNode;rotateYAxis->addChild(switchNode);switchNode->addChild(createUpMappingCube());switchNode->addChild(createDownMappingCube());switchNode->addChild(createCube());
在交互操作中设置显示和隐藏原始的模型:

if (ea.getKey() == osgGA::GUIEventAdapter::KEY_E){if (g_switch->getValue(2) == true){g_switch->setValue(2, false);}else{g_switch->setValue(2, true); }}
编译运行程序:


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

#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/LightSource>#include <osg/ImageUtils>#include <osg/Texture2D>#include <osg/BlendFunc>#include <osg/Depth>#include <osg/TexEnv>#include <osg/TexEnvCombine>//////////////////////////////////////////////////////////////////////////const float MaxEmboss = 0.008f;boolmultitextureSupported = false;bool useMultitexture = true;osgViewer::View *g_viewer;osg::Switch *g_switch;osg::Switch *g_switchMulti;GLfloatxrot;GLfloatyrot;GLfloat xspeed;GLfloat yspeed;GLfloatz=-5.0f;GLuintfilter=1;osg::Texture2D*texture[3];osg::Texture2D*bump[3];osg::Texture2D*invbump[3];osg::Texture2D*glLogo;osg::Texture2D*multiLogo;GLfloat LightAmbient[]= { 0.2f, 0.2f, 0.2f};GLfloat LightDiffuse[]= { 1.0f, 1.0f, 1.0f};GLfloat LightPosition[] = { 0.0f, 0.0f, 2.0f};GLfloat data[]= {// FRONT FACE0.0f, 0.0f,-1.0f, -1.0f, +1.0f,1.0f, 0.0f,+1.0f, -1.0f, +1.0f,1.0f, 1.0f,+1.0f, +1.0f, +1.0f,0.0f, 1.0f,-1.0f, +1.0f, +1.0f,// BACK FACE1.0f, 0.0f,-1.0f, -1.0f, -1.0f,1.0f, 1.0f,-1.0f, +1.0f, -1.0f,0.0f, 1.0f,+1.0f, +1.0f, -1.0f,0.0f, 0.0f,+1.0f, -1.0f, -1.0f,// Top Face0.0f, 1.0f,-1.0f, +1.0f, -1.0f,0.0f, 0.0f,-1.0f, +1.0f, +1.0f,1.0f, 0.0f,+1.0f, +1.0f, +1.0f,1.0f, 1.0f,+1.0f, +1.0f, -1.0f,// Bottom Face1.0f, 1.0f,-1.0f, -1.0f, -1.0f,0.0f, 1.0f,+1.0f, -1.0f, -1.0f,0.0f, 0.0f,+1.0f, -1.0f, +1.0f,1.0f, 0.0f,-1.0f, -1.0f, +1.0f,// Right Face1.0f, 0.0f,+1.0f, -1.0f, -1.0f,1.0f, 1.0f,+1.0f, +1.0f, -1.0f,0.0f, 1.0f,+1.0f, +1.0f, +1.0f,0.0f, 0.0f,+1.0f, -1.0f, +1.0f,// Left Face0.0f, 0.0f,-1.0f, -1.0f, -1.0f,1.0f, 0.0f,-1.0f, -1.0f,  1.0f,1.0f, 1.0f,-1.0f,  1.0f,  1.0f,0.0f, 1.0f,-1.0f,  1.0f, -1.0f};////////////////////////////////////////////////////////////////////////////FindFirstNamedNodeVisitor用来遍历寻找与指定名称相同的节点class FindFirstNamedNodeVisitor : public osg::NodeVisitor{public:FindFirstNamedNodeVisitor(const std::string& name):  osg::NodeVisitor(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN),  _name(name), _foundNode(NULL) {}  virtual void apply(osg::Node& node)  {  if (node.getName()==_name)  {  _foundNode = &node;  return;  }  traverse(node);  }  std::string _name;  osg::Node *_foundNode;};////////////////////////////////////////////////////////////////////////////RotateCallbackclass RotateCallback : public osg::NodeCallback{public:RotateCallback(osg::Vec3d rotateAxis, double rotateSpeed) :   osg::NodeCallback(),  _rotateAxis(rotateAxis),   _rotateSpeed(rotateSpeed),  _rotateAngle(0.0)  {  //Nop  }  void setRotateSpeed(double speed)  {  _rotateSpeed = speed;  }  double getRotateSpeed() const  {  return _rotateSpeed;  }  virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)  {  osg::MatrixTransform *currentMT = dynamic_cast<osg::MatrixTransform*>(node);  if (currentMT)  {  //获取当前的平移位置  osg::Vec3d currentTranslate = currentMT->getMatrix().getTrans();  osg::Matrix newMatrix = osg::Matrix::rotate(_rotateAngle, _rotateAxis) * osg::Matrix::translate(currentTranslate);  currentMT->setMatrix(newMatrix);  _rotateAngle += _rotateSpeed;  }  traverse(node, nv);  }private:osg::Vec3d _rotateAxis;//旋转轴double        _rotateSpeed;//旋转速度double        _rotateAngle;//当前旋转的角度};////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////class ManipulatorSceneHandler : public osgGA::GUIEventHandler{public:ManipulatorSceneHandler(){}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_Left){FindFirstNamedNodeVisitor fnv("yRotMT");root->accept(fnv);osg::Node *mtNode = fnv._foundNode;osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);if (!yRotMT)return false;RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());if (!rotCallback)return false;double speed = rotCallback->getRotateSpeed();speed += 0.02;rotCallback->setRotateSpeed(speed);}if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Right){FindFirstNamedNodeVisitor fnv("yRotMT");root->accept(fnv);osg::Node *mtNode = fnv._foundNode;osg::MatrixTransform *yRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);if (!yRotMT)return false;RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(yRotMT->getUpdateCallback());if (!rotCallback)return false;double speed = rotCallback->getRotateSpeed();speed -= 0.02;rotCallback->setRotateSpeed(speed);}if (ea.getKey() == osgGA::GUIEventAdapter::KEY_Up){FindFirstNamedNodeVisitor fnv("xRotMT");root->accept(fnv);osg::Node *mtNode = fnv._foundNode;osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);if (!xRotMT)return false;RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());if (!rotCallback)return false;double speed = rotCallback->getRotateSpeed();speed += 0.02;rotCallback->setRotateSpeed(speed);}if (ea.getKey()== osgGA::GUIEventAdapter::KEY_Down){FindFirstNamedNodeVisitor fnv("xRotMT");root->accept(fnv);osg::Node *mtNode = fnv._foundNode;osg::MatrixTransform *xRotMT = dynamic_cast<osg::MatrixTransform*>(mtNode);if (!xRotMT)return false;RotateCallback *rotCallback = dynamic_cast<RotateCallback*>(xRotMT->getUpdateCallback());if (!rotCallback)return false;double speed = rotCallback->getRotateSpeed();speed -= 0.02;rotCallback->setRotateSpeed(speed);}if (ea.getKey() == osgGA::GUIEventAdapter::KEY_E){if (g_switch->getValue(2) == true){g_switch->setValue(2, false);}else{g_switch->setValue(2, true); }}}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->setClearDepth(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 );addEventHandler(new ManipulatorSceneHandler);g_viewer = this;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;};////////////////////////////////////////////////////////////////////////////创建纹理:代码中只是用到第二个纹理bump[1]和invbmp[1]void initTextures(){osg::Image *image1 = new osg::Image;image1 = osgDB::readImageFile("Data/Base.bmp");texture[0] = new osg::Texture2D;texture[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);texture[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);texture[0]->setImage(image1);texture[1] = new osg::Texture2D;texture[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);texture[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);texture[1]->setImage(image1);texture[2] = new osg::Texture2D;texture[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);texture[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);texture[2]->setImage(image1);osg::Image *image2 = new osg::Image;image2 = osgDB::readImageFile("Data/Bump.bmp");osg::offsetAndScaleImage(image2, osg::Vec4(), osg::Vec4(0.5, 0.5, 0.5, 1));bump[0] = new osg::Texture2D;bump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);bump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);bump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);bump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);bump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));bump[0]->setImage(image2);bump[1] = new osg::Texture2D;bump[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);bump[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);bump[1]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);bump[1]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);bump[1]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));bump[1]->setImage(image2);bump[2] = new osg::Texture2D;bump[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);bump[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);bump[2]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);bump[2]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);bump[2]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));bump[2]->setImage(image2);osg::Image *image3 = osgDB::readImageFile("Data/Bump.bmp");osg::offsetAndScaleImage(image3, osg::Vec4(), osg::Vec4(0.5,0.5,0.5,1));osg::offsetAndScaleImage(image3, osg::Vec4(-128, -128, -128, 1), osg::Vec4(-1,-1,-1,1));invbump[0] = new osg::Texture2D;invbump[0]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::NEAREST);invbump[0]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::NEAREST);invbump[0]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);invbump[0]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);invbump[0]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));invbump[0]->setImage(image3);invbump[1] = new osg::Texture2D;invbump[1]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);invbump[1]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);invbump[1]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);invbump[1]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);invbump[1]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));invbump[1]->setImage(image3);invbump[2] = new osg::Texture2D;invbump[2]->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);invbump[2]->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR_MIPMAP_NEAREST);invbump[2]->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);invbump[2]->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);invbump[2]->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));invbump[2]->setImage(image3);osg::Image *glLogoAlpha = osgDB::readImageFile("Data/OpenGL_ALPHA.bmp");osg::Image *glLogoImage = osgDB::readImageFile("Data/OpenGL.bmp");osg::Image *glLogoCombo = new osg::Image;glLogoCombo->allocateImage(glLogoImage->s(), glLogoImage->t(), 1, GL_RGBA, glLogoImage->getDataType());unsigned char *comboData = glLogoCombo->data();for (int i = 0; i < glLogoImage->s() * glLogoImage->t(); ++i){comboData[4*i+3] = glLogoAlpha->data()[i*3];comboData[4*i] = glLogoImage->data()[i*3];comboData[4*i+1] = glLogoImage->data()[i*3+1];comboData[4*i+2] = glLogoImage->data()[i*3+2];}glLogo = new osg::Texture2D;glLogo->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);glLogo->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);glLogo->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);glLogo->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);glLogo->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));glLogo->setImage(glLogoCombo);osg::Image *glMultiAlpha = osgDB::readImageFile("Data/multi_on_alpha.bmp");osg::Image *glMultiImage = osgDB::readImageFile("Data/multi_on.bmp");osg::Image *glMultiCombo = new osg::Image;glMultiCombo->allocateImage(glLogoImage->s(), glLogoImage->t(), 1, GL_RGBA, glLogoImage->getDataType());unsigned char *multiComboData = glMultiCombo->data();for (int i = 0; i < glMultiImage->s() * glMultiImage->t(); ++i){multiComboData[4*i+3] = glMultiAlpha->data()[i*3];multiComboData[4*i] = glMultiImage->data()[i*3];multiComboData[4*i+1] = glMultiImage->data()[i*3+1];multiComboData[4*i+2] = glMultiImage->data()[i*3+2];}multiLogo = new osg::Texture2D;multiLogo->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);multiLogo->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);multiLogo->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP);multiLogo->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP);multiLogo->setBorderColor(osg::Vec4(0.5, 0.5, 0.5, 1.0));multiLogo->setImage(glMultiCombo);}osg::Group *createLogo(){osg::Group *logoGroup = new osg::Group;osg::Depth *depth = new osg::Depth(osg::Depth::ALWAYS);osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::SRC_ALPHA, osg::BlendFunc::ONE_MINUS_SRC_ALPHA);osg::Geode *logoGeode = new osg::Geode;osg::Geometry *logoGeometry = new osg::Geometry;osg::Vec3Array *logoVertices = new osg::Vec3Array;logoVertices->push_back(osg::Vec3(0.23f, -0.4f,-1.0f));logoVertices->push_back(osg::Vec3(0.53f, -0.4f,-1.0f));logoVertices->push_back(osg::Vec3(0.53f, -0.25f,-1.0f));logoVertices->push_back(osg::Vec3(0.23f, -0.25f,-1.0f));osg::Vec2Array *textureVertices = new osg::Vec2Array;textureVertices->push_back(osg::Vec2(0.0f,0.0f));textureVertices->push_back(osg::Vec2(1.0f,0.0f));textureVertices->push_back(osg::Vec2(1.0f,1.0f));textureVertices->push_back(osg::Vec2(0.0f,1.0f));logoGeometry->setVertexArray(logoVertices);logoGeometry->setTexCoordArray(0, textureVertices);logoGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));logoGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);logoGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);logoGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, glLogo);logoGeode->addDrawable(logoGeometry);osg::Geode *multiGeode = new osg::Geode;osg::Geometry *multiGeometry = new osg::Geometry;osg::Vec3Array *multiVertices = new osg::Vec3Array;multiVertices->push_back(osg::Vec3(-0.53f, -0.4f,-1.0f));multiVertices->push_back(osg::Vec3(-0.33f, -0.4f,-1.0f));multiVertices->push_back(osg::Vec3(-0.33f, -0.3f,-1.0f));multiVertices->push_back(osg::Vec3(-0.53f, -0.3f,-1.0f));osg::Vec2Array *tVertices = new osg::Vec2Array;textureVertices->push_back(osg::Vec2(0.0f,0.0f));textureVertices->push_back(osg::Vec2(1.0f,0.0f));textureVertices->push_back(osg::Vec2(1.0f,1.0f));textureVertices->push_back(osg::Vec2(0.0f,1.0f));multiGeometry->setVertexArray(multiVertices);multiGeometry->setTexCoordArray(0, tVertices);multiGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));multiGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);multiGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);multiGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, multiLogo);multiGeode->addDrawable(multiGeometry);logoGroup->addChild(logoGeode);logoGroup->addChild(multiGeode);return logoGroup;}osg::Geode*createCube(){osg::Geode *cubeGeode = new osg::Geode;osg::Geometry *cubeGeometry = new osg::Geometry;osg::Vec3Array *vertices = new osg::Vec3Array;osg::Vec3Array *normals = new osg::Vec3Array;osg::Vec2Array *texcoords = new osg::Vec2Array;for (unsigned i = 0; i < 24; ++i){texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));}normals->push_back(osg::Vec3(0.0f, 0.0f, +1.0f));normals->push_back(osg::Vec3(0.0f, 0.0f,-1.0f));normals->push_back(osg::Vec3(0.0f, 1.0f, 0.0f));normals->push_back(osg::Vec3(0.0f,-1.0f, 0.0f));normals->push_back(osg::Vec3(1.0f, 0.0f, 0.0f));normals->push_back(osg::Vec3(-1.0f, 0.0f, 0.0f));cubeGeometry->setVertexArray(vertices);cubeGeometry->setTexCoordArray(0, texcoords);cubeGeometry->setNormalArray(normals, osg::Array::BIND_PER_PRIMITIVE_SET);cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texture[1]);osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::DST_COLOR, osg::BlendFunc::SRC_COLOR);cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);osg::TexEnv *texEnv = new osg::TexEnv(osg::TexEnv::MODULATE);cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, texEnv);cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);cubeGeode->addDrawable(cubeGeometry);return cubeGeode;}osg::Geode* createUpMappingCube(){osg::Geode *cubeGeode = new osg::Geode;osg::Geometry *cubeGeometry = new osg::Geometry;osg::Vec3Array *vertices = new osg::Vec3Array;osg::Vec3Array *normals = new osg::Vec3Array;osg::Vec2Array *texcoords = new osg::Vec2Array;for (unsigned i = 0; i < 24; ++i){texcoords->push_back(osg::Vec2(data[5*i],data[5*i + 1]));vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));}cubeGeometry->setVertexArray(vertices);cubeGeometry->setTexCoordArray(0, texcoords);cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));cubeGeometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);cubeGeometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, bump[1]);osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);cubeGeometry->getOrCreateStateSet()->setAttributeAndModes(depth);cubeGeode->addDrawable(cubeGeometry);return cubeGeode;}class TextureCallback : public osg::Drawable::UpdateCallback{public:TextureCallback(){ }virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable){osg::Geometry *geometry = drawable->asGeometry();if (!geometry)return;osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(0));if(textureArray)return;textureArray = new osg::Vec2Array;osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;//////////////////////////////////////////////////////////////////////////for (int i=0; i<4; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=4; i<8; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(-1, 0, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=8; i<12; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(1, 0, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,0,-1) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=12; i<16; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, -1, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(-1,0,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=16; i<20; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, 0, -1) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=20; i<24; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, 0, 1) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}geometry->setTexCoordArray(0, textureArray);geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, invbump[1]);geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);osg::BlendFunc *blendFunc = new osg::BlendFunc(osg::BlendFunc::ONE, osg::BlendFunc::ONE);geometry->getOrCreateStateSet()->setAttributeAndModes(blendFunc);osg::Depth *depth = new osg::Depth(osg::Depth::LEQUAL);geometry->getOrCreateStateSet()->setAttributeAndModes(depth);}};osg::Geode* createDownMappingCube(){osg::Geode *cubeGeode = new osg::Geode;osg::Geometry *cubeGeometry = new osg::Geometry;cubeGeometry->setUpdateCallback(new TextureCallback());osg::Vec3Array *vertices = new osg::Vec3Array;for (unsigned i = 0; i < 24; ++i){vertices->push_back(osg::Vec3(data[5*i + 2], data[5*i +3], data[5*i + 4]));}cubeGeometry->setVertexArray(vertices);cubeGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, vertices->size()));cubeGeode->addDrawable(cubeGeometry);return cubeGeode;}////////////////////////////////////////////////////////////////////////////Method 2:Using MultiTexture to Render////TODO:使用MultiTexture的方式:// TODO: 未在OpenGL文档中查询到//glTexEnvf (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_EXT);//glTexEnvf (GL_TEXTURE_ENV, GL_COMBINE_RGB_EXT, GL_REPLACE);//不清楚是否是新的扩展,请读者指点//////////////////////////////////////////////////////////////////////////#if 0class MultiTextureUpdateCallback : public osg::Drawable::UpdateCallback{public:virtual void update(osg::NodeVisitor* nv, osg::Drawable* drawable){osg::Geometry *geometry = drawable->asGeometry();if (!geometry)return;osg::Vec2Array *textureArray = dynamic_cast<osg::Vec2Array*>(geometry->getTexCoordArray(1));if(textureArray)return;textureArray = new osg::Vec2Array;osg::Vec3Array *vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());osg::Vec3 lightPos(LightPosition[0], LightPosition[1], LightPosition[2]);osg::Matrix currentModelViewMatrix = computeLocalToWorld(nv->getNodePath()) * g_viewer->getCamera()->getViewMatrix();osg::Matrix currentInvModelViewerMatrix = osg::Matrix::inverse(currentModelViewMatrix);osg::Vec3 lightInObjectSpace = lightPos * currentInvModelViewerMatrix;//////////////////////////////////////////////////////////////////////////for (int i=0; i<4; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(1,0,0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=4; i<8; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(-1, 0, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=8; i<12; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(1, 0, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,0,-1) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=12; i<16; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, -1, 0) * MaxEmboss;double deltaT = orientation * osg::Vec3(-1,0,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=16; i<20; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, 0, -1) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}for (int i=20; i<24; i++) {osg::Vec3 pos = vertices->at(i);osg::Vec3 orientation = lightInObjectSpace - pos;orientation.normalize();double deltaS = orientation * osg::Vec3(0, 0, 1) * MaxEmboss;double deltaT = orientation * osg::Vec3(0,1,0) * MaxEmboss;textureArray->push_back(osg::Vec2(data[5*i]+deltaS,data[5*i + 1]+deltaT));}geometry->setTexCoordArray(1, textureArray);geometry->getOrCreateStateSet()->setTextureAttributeAndModes(1, invbump[1]);osg::TexEnv *tex2Env = new osg::TexEnv(osg::TexEnv::ADD);geometry->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex2Env);geometry->getOrCreateStateSet()->setMode(GL_LIGHTING, false);}};#endifosg::Node*buildScene(){initTextures();osg::Group *root = new osg::Group;osg::MatrixTransform *zoomMT = new osg::MatrixTransform;zoomMT->setMatrix(osg::Matrix::translate(0.0, 0.0, -5.0));osg::MatrixTransform *rotateXAxis = new osg::MatrixTransform;rotateXAxis->setName("xRotMT");RotateCallback *xRotCallback = new RotateCallback(osg::X_AXIS, 0.0);rotateXAxis->setUpdateCallback(xRotCallback);zoomMT->addChild(rotateXAxis);osg::MatrixTransform *rotateYAxis = new osg::MatrixTransform;rotateYAxis->setName("yRotMT");RotateCallback *yRotCallback = new RotateCallback(osg::Y_AXIS, 0.0);rotateYAxis->setUpdateCallback(yRotCallback);rotateXAxis->addChild(rotateYAxis);osg::Switch *switchNode = new osg::Switch;g_switch = switchNode;rotateYAxis->addChild(switchNode);switchNode->addChild(createUpMappingCube());switchNode->addChild(createDownMappingCube());switchNode->addChild(createCube());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();}



0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 小米5s手机黑屏打不开怎么办 小米5s黑屏只能开关机怎么办 手机拨号键没了怎么办 华为手机桌面拨号图标不见了怎么办 华为手机拨号图标不见了怎么办 小米4s屏幕显示黑屏怎么办 平板拨号键没了怎么办 华为手机拨号图标没了怎么办 华为荣耀手机进水了怎么办 华为畅享7黑屏怎么办 华为畅玩7x黑屏怎么办 华为手机打电话时黑屏怎么办 三星a8手机黑屏打不开怎么办 华为手机恢复出厂后黑屏怎么办 华为荣耀4c白屏怎么办 华为荣耀6手机信号不好怎么办 华为荣耀8手机音量小怎么办 无法激活触控id怎么办 魅蓝2卡顿怎么办 小米max2玩王者荣耀卡怎么办 小米4玩王者荣耀卡怎么办 华为荣耀7i卡顿怎么办 华为荣耀7卡的怎么办 荣耀8手机有孤独怎么办 红米note4玩游戏卡怎么办 红米note4x玩游戏卡怎么办 华为4c死屏怎么办 华为4c充电很慢怎么办? 华为4c突然死机了怎么办 华为畅玩4c内存不足怎么办 荣耀4c一直亮屏怎么办 华为手机返回键失灵怎么办 荣耀6p死机了怎么办 荣耀6主板烧坏了怎么办 虚拟运营商倒闭了号怎么办 买到二次放号怎么办 新运动鞋鞋穿着有点紧怎么办 一件代发被买家退货后怎么办? 洗了翻毛的鞋子怎么办 猫眼竹芋泡根了怎么办 双线花叶子卷了怎么办