• osg利用osgShadow库添加阴影


    纲要:渲染的时候只要标记出  阴影投影对象 和 阴影接收对象 就行了,其他的交给引擎就可以了。

      实现步骤:

    1. 创建ShadowedScene对象。
    2. 标明 投射者和被投射者。
    3. 选择一种阴影渲染技术,如 ShadowMapShadowVolumeShadowTextureSoftShadowMap等。
    4. 标明哪个物体是投射着哪个是被投射者。
    5. 之后将两者及光照添加到ShadowedScene中进行渲染,参照http://www.osgchina.org/show.php?id=54。
    #include <osg/Texture2D>
    #include <osg/Geometry>
    #include <osg/Geode>
    #include <osgDB/ReadFile>
    #include <osgUtil/SmoothingVisitor>
    #include <osgViewer/Viewer>
    #include <osg/PositionAttitudeTransform>
    #include <osg/MatrixTransform>
    #include <osgGA/TrackballManipulator>
    #include <osg/Material>
    
    #include <osgShadow/ShadowedScene>
    #include <osgShadow/ShadowVolume>
    #include <osgShadow/ShadowTexture>
    #include <osgShadow/ShadowMap>
    #include <osgShadow/SoftShadowMap>
    #include <osgShadow/ParallelSplitShadowMap>
    
    #include <osgUtil/Optimizer>
    
    osg::Vec4 lightPos(30.0f,-10.0f,20.0f,1.0f);
    
    //标识阴影接收对象
    const int ReceivesShadowTraversalMask = 0x1;
    //标识阴影投影对象
    const int CastsShadowTraversalMask = 0x2;
    
    
    class RotateCallback : public osg::NodeCallback
    {
    public:
        RotateCallback() : _rotateZ(0.0) {}
    
        virtual void operator()( osg::Node* node, osg::NodeVisitor* nv )
        {
            osg::PositionAttitudeTransform* pat = dynamic_cast<osg::PositionAttitudeTransform*>( node );
            if ( pat )
            {
                osg::Quat quat( osg::DegreesToRadians(_rotateZ), osg::Z_AXIS );
                pat->setAttitude( quat );
                _rotateZ += 1.0;
            }
            traverse( node, nv );
        }
    
    protected:
        double _rotateZ;
    };
     
    //创建灯光
    void createLight(osg::ref_ptr<osg::Group> lightRoot)
    {
        //lightRoot->addChild(node);
    
        //开启光照
        osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet();
        stateset = lightRoot->getOrCreateStateSet();
        stateset->setMode(GL_LIGHTING,osg::StateAttribute::ON);
        stateset->setMode(GL_LIGHT0,osg::StateAttribute::ON);
    
        //创建一个Light对象
        osg::ref_ptr<osg::Light> light = new osg::Light();
        light->setLightNum(0);
        //设置方向
        light->setDirection(osg::Vec3(1.0f,1.0f,-1.0f));
        //设置位置
        light->setPosition(lightPos);
        //设置环境光的颜色
        light->setAmbient(osg::Vec4(0.01f,0.01f,0.01f,1.0f));
        //设置散射光的颜色
        light->setDiffuse(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
    
         ////设置恒衰减指数
         //light->setConstantAttenuation(1.0f);
         ////设置线形衰减指数
         //light->setLinearAttenuation(0.0f);
         ////设置二次方衰减指数
         //light->setQuadraticAttenuation(0.0f);
    
        //创建光源
        osg::ref_ptr<osg::LightSource> lightSource = new osg::LightSource();
        lightSource->setLight(light.get());
    
        lightRoot->addChild(lightSource.get());
    
        return ;
    }
    //创建墙壁
    osg::Drawable* createHouseWall()
    {
        // House vertices
        osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
        //前面
        vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) );  // 0
        vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) );  // 1
        vertices->push_back( osg::Vec3( 4.0, 0.0, 4.0) );  // 2
        vertices->push_back( osg::Vec3( 4.0, 0.0, 0.0) );  // 3
        //右面
        vertices->push_back( osg::Vec3( 4.0, 4.0, 4.0) );  // 4
        vertices->push_back( osg::Vec3( 4.0, 4.0, 0.0) );  // 5
        //后面
        vertices->push_back( osg::Vec3( 0.0, 4.0, 4.0) );  // 6
        vertices->push_back( osg::Vec3( 0.0, 4.0, 0.0) );  // 7
        //左面
        vertices->push_back( osg::Vec3( 0.0, 0.0, 4.0) );  // 8
        vertices->push_back( osg::Vec3( 0.0, 0.0, 0.0) );  // 9
        
        // House normals
        osg::ref_ptr<osg::Vec3Array> normals = new osg::Vec3Array( 10 );
        //左前
        (*normals)[0].set(-1.0,-1.0, 0.0 );
        (*normals)[1].set(-1.0,-1.0, 0.0 );
        //右前
        (*normals)[2].set( 1.0,-1.0, 0.0 );
        (*normals)[3].set( 1.0,-1.0, 0.0 );
        //右后
        (*normals)[4].set( 1.0, 1.0, 0.0 );
        (*normals)[5].set( 1.0, 1.0, 0.0 );
        //左后
        (*normals)[6].set(-1.0, 1.0, 0.0 );
        (*normals)[7].set(-1.0, 1.0, 0.0 );
        //左前
        (*normals)[8].set(-1.0,-1.0, 0.0 );
        (*normals)[9].set(-1.0,-1.0, 0.0 );
        
        // House texture coordinates
        osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array( 10 );
        //前面的左0.3
        (*texcoords)[0].set( 0.0, 1.0 );
        (*texcoords)[1].set( 0.0, 0.0 );
        (*texcoords)[2].set( 1.0, 1.0 );
        (*texcoords)[3].set( 1.0, 0.0 );
    
        //右面0.2
           (*texcoords)[4].set( 0.0, 1.0 );
        (*texcoords)[5].set( 0.0, 0.0 );
    
        //后面0.3
        (*texcoords)[6].set( 1.0, 1.0 );
        (*texcoords)[7].set( 1.0, 0.0 );
        //左边0.2
        (*texcoords)[8].set( 0.0, 1.0 );
        (*texcoords)[9].set( 0.0, 0.0 );
    
        // House texture coordinates
        /*osg::ref_ptr<osg::Vec2Array> texcoords2 = new osg::Vec2Array( 10 );
    
    
          //右面0.2
    
        (*texcoords2)[4].set( 0.0, 1.0 );
        (*texcoords2)[5].set( 0.0, 0.0 );
        
    
        //后面0.3
        (*texcoords2)[6].set( 1.0, 1.0 );
        (*texcoords2)[7].set( 1.0, 0.0 );
        //左边0.2
        (*texcoords2)[8].set( 0.0, 1.0 );
        (*texcoords2)[9].set( 0.0, 0.0 );*/
    
        
        // Create wall geometry
        osg::ref_ptr<osg::Geometry> houseWall = new osg::Geometry;
        houseWall->setVertexArray( vertices.get() );
        houseWall->setTexCoordArray( 0, texcoords.get() );
        // houseWall->setTexCoordArray( 1, texcoords2.get() );
        houseWall->setNormalArray( normals.get() );
        houseWall->setNormalBinding( osg::Geometry::BIND_PER_VERTEX );
        houseWall->addPrimitiveSet( new osg::DrawArrays(osg::DrawArrays::QUAD_STRIP, 0, 10) );
        
        houseWall->getOrCreateStateSet()->setTextureAttribute( 0,new osg::Texture2D(osgDB::readImageFile("C:\55.jpg")));
        houseWall->getOrCreateStateSet()->setTextureMode(0,GL_TEXTURE_2D,osg::StateAttribute::ON);
        houseWall->setNodeMask(CastsShadowTraversalMask);
    
        // houseWall->getOrCreateStateSet()->setTextureAttributeAndModes( 1,new osg::Texture2D(osgDB::readImageFile("C:\55.jpg")) );
    
        return houseWall.release();
    } 
    //创建大地
    osg::Geometry* createGround(){
    
        osg::ref_ptr<osg::Vec3Array> vertices = new osg::Vec3Array;
        vertices->push_back(osg::Vec3(50,-50,-10));
        vertices->push_back(osg::Vec3(50,50,-5));
        vertices->push_back(osg::Vec3(-50,50,-5));
        vertices->push_back(osg::Vec3(-50,-50,-10));
    
        osg::ref_ptr<osg::Vec3Array> colours = new osg::Vec3Array;
        colours->push_back(osg::Vec3(255,255,0));
        colours->push_back(osg::Vec3(0,255,0));
        colours->push_back(osg::Vec3(0,255,0));
        colours->push_back(osg::Vec3(0,255,0));
    
    
        osg::Geometry *ground = new osg::Geometry;
        ground->setVertexArray(vertices);
        ground->addPrimitiveSet(new osg::DrawArrays(osg::DrawArrays::QUADS,0,4));
        ground->setColorArray(colours,osg::Array::BIND_PER_PRIMITIVE_SET);
        ground->setNodeMask(CastsShadowTraversalMask);
        return ground;
    
    }
    
    int main( int argc, char** argv )
    {
        osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer();
    
        osg::ref_ptr<osg::Group> root = new osg::Group();
    
        //创建一个阴影节点,并标识接收对象和投影对象
        osg::ref_ptr<osgShadow::ShadowedScene> shadowedScene = new osgShadow::ShadowedScene();
        shadowedScene->setReceivesShadowTraversalMask(ReceivesShadowTraversalMask);
        shadowedScene->setCastsShadowTraversalMask(CastsShadowTraversalMask);
    
        //创建阴影纹理
        osg::ref_ptr<osgShadow::ShadowMap> st = new osgShadow::ShadowMap();
        //osg::ref_ptr<osgShadow::ShadowTexture> st = new osgShadow::ShadowTexture();
        //关联阴影纹理
        shadowedScene->setShadowTechnique(st);
    
        //添加光照
        osg::ref_ptr<osg::Group> lightRoot = new osg::Group;
        createLight(lightRoot);
        shadowedScene->addChild(lightRoot.get());
    
        //物体
        osg::ref_ptr<osg::Geode> geode = new osg::Geode;
        geode->addDrawable( createHouseWall() );
    
        //旋转物体
        osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;
        pat->addChild( geode );
        pat->setUpdateCallback( new RotateCallback );
    
        shadowedScene->addChild(pat);
        shadowedScene->addChild(createGround());
    
        root->addChild(shadowedScene);
    
        osgUtil::Optimizer optimizer ;
        optimizer.optimize(root.get()) ;
    
        viewer->setUpViewInWindow(20,20,400,400);
        viewer->setSceneData(root.get());
        viewer->setCameraManipulator(new osgGA::TrackballManipulator);
        return viewer->run();
    }

    效果:

  • 相关阅读:
    SAP分析云及协同计划
    使用SSH命令行远程登录运行在CloudFoundry上的应用
    如何远程调试部署在CloudFoundry平台上的nodejs应用
    Apache httpclient的execute方法调试
    如何用Java代码在SAP Marketing Cloud里创建contact数据
    nodejs request module里的json参数的一个坑
    如何在调用Marketing Cloud contact创建API时增加对扩展字段的支持
    Efim and Strange Grade
    Vitya in the Countryside
    Anatoly and Cockroaches
  • 原文地址:https://www.cnblogs.com/airduce/p/9996956.html
Copyright © 2020-2023  润新知