osg结合shader写的shadowmap

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/dancing_night/article/details/53100983

简介

shadowmap示例,根据http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/教程用osg写的demo
原理在教程上说的很清楚了

代码

/*
*shadowmap示例,根据http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/教程用osg写的demo
*缪国凯
*MK([email protected])
*/

#include "../Common/Common.h"
#include <osg/AlphaFunc>
#include <osg/Texture2D>
#include <osg/Shape>
#include <osg/ShapeDrawable>

#define AREA 10

#define SM_TEXTURE_WIDTH 4096

void loadShaders( osg::StateSet* ss, std::string filepath = "shader")
{
    osg::Shader *fragShader=new osg::Shader(osg::Shader::FRAGMENT); 
    osg::Shader *vertShader=new osg::Shader(osg::Shader::VERTEX);
    if(!fragShader->loadShaderSourceFromFile(filepath+".frag"))
    {
        printf("加载%s失败\n",(filepath+".frag").c_str());
    };
    printf("加载%s成功\n", (filepath + ".frag").c_str());
    if(!vertShader->loadShaderSourceFromFile(filepath+".vert"))
    {
        printf("加载%s失败\n", (filepath + ".vert").c_str());
    };   
    printf("加载%s成功\n", (filepath + ".vert").c_str());

    osg::ref_ptr<osg::Program> program = new osg::Program;
    program->addShader( vertShader);
    program->addShader( fragShader);

    if ( ss )
        ss->setAttributeAndModes( program.get(), osg::StateAttribute::ON );
}


osg::Node* CreateModel(osg::Texture2D* tex, osg::Image *img, int width = 4.0, osg::Vec4 tmpColor = osg::Vec4(1.0, 1.0, 1.0, 1.0))
{
    osg::Geometry *_geo = new osg::Geometry;

    osg::Vec3Array * pCoords = new osg::Vec3Array;

    osg::Vec3Array * pNormals = new osg::Vec3Array;
    pNormals->push_back(osg::Vec3(0.0f, 0.0f, 1.0f));

    osg::Vec4Array * pColors = new osg::Vec4Array;
    pColors->push_back(tmpColor);

    _geo->setNormalArray(pNormals);
    _geo->setNormalBinding(osg::Geometry::BIND_OVERALL);
    _geo->setColorArray(pColors);
    _geo->setColorBinding(osg::Geometry::BIND_OVERALL);

    osg::ref_ptr<osg::Vec2Array> _coords = new osg::Vec2Array;
    _geo->setTexCoordArray(0, _coords);

    pCoords->push_back(osg::Vec3(-width/2, width/2, 0.0));              
    _coords->push_back(osg::Vec2(0.0, 0.0));

    pCoords->push_back(osg::Vec3(width/2, width/2, 0.0));               
    _coords->push_back(osg::Vec2(1.0, 0.0));

    pCoords->push_back(osg::Vec3(width/2, -width/2, 0.0));              
    _coords->push_back(osg::Vec2(1.0, 1.0));

    pCoords->push_back(osg::Vec3(-width/2, -width/2, 0.0));             
    _coords->push_back(osg::Vec2(0.0, 1.0));

    _geo->setVertexArray(pCoords);
    _geo->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, pCoords->size()));

    osg::Geode *_geo_LocalPlane = new osg::Geode;
    _geo_LocalPlane->addDrawable(_geo);

    {
        osg::StateSet* stateset = _geo_LocalPlane->getOrCreateStateSet(); 
        stateset->setMode(GL_BLEND, osg::StateAttribute::ON); 
        stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF | osg::StateAttribute::PROTECTED);

        osg::ref_ptr<osg::BlendFunc> blendFunc = new osg::BlendFunc();  
        blendFunc->setSource(osg::BlendFunc::SRC_ALPHA); 
        blendFunc->setDestination(osg::BlendFunc::ONE_MINUS_SRC_ALPHA);  
        osg::AlphaFunc* alphaFunc = new osg::AlphaFunc;
        alphaFunc->setFunction(osg::AlphaFunc::GEQUAL, 0.5f);
        stateset->setAttributeAndModes(alphaFunc, osg::StateAttribute::ON);

        if (NULL != tex && img == NULL)
        {
            stateset->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
        }
        else if (NULL != img)
        {
            osg::ref_ptr<osg::Texture2D> texture = new osg::Texture2D;

            texture->setImage(img);

            texture->setFilter(osg::Texture2D::MIN_FILTER, osg::Texture2D::NEAREST);
            texture->setFilter(osg::Texture2D::MAG_FILTER, osg::Texture2D::NEAREST);
            texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
            texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);

            stateset->setTextureAttributeAndModes(0, texture, osg::StateAttribute::ON);
        }
    }

    return _geo_LocalPlane;
}

osg::Texture2D* CreateDepthTexture(int width, int height)
{
    osg::Texture2D* _texture = new osg::Texture2D;
    _texture->setTextureSize(width, height);
    _texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
    _texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
    _texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR);
    _texture->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
    _texture->setInternalFormat(GL_DEPTH_COMPONENT);
    _texture->setSourceFormat(GL_DEPTH_COMPONENT);
    _texture->setSourceType(GL_FLOAT);
    //tex->setShadowComparison(true);
    _texture->setShadowTextureMode(osg::Texture2D::LUMINANCE);

    return _texture;
}

osg::Image* CreateDepthImg(int width, int height)
{
    osg::Image *depthImg = new osg::Image;
    depthImg->allocateImage(width, height, GL_DEPTH_COMPONENT16, GL_DEPTH_COMPONENT, GL_FLOAT);

    return depthImg;
}

osg::Camera*  CreateShadowMapCamera(int x, int y, int w, int h, osg::Texture2D *_texture2D)
{   
    osg::ref_ptr<osg::Camera> _camera = new osg::Camera;

    _camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
    _camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
    _camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
    _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
    _camera->setViewport(0,0,w, h);
    _camera->setRenderOrder(osg::Camera::PRE_RENDER);
    _camera->setProjectionMatrixAsOrtho(-AREA, AREA, -AREA, AREA, -AREA, 3*AREA);
    osg::Vec3 tmpEyeps(0, 9, 15);
    _camera->setViewMatrixAsLookAt(tmpEyeps, osg::Vec3(0, 0, 0), osg::Vec3(0, 1, 0));
    _camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
    _camera->attach(osg::Camera::DEPTH_BUFFER, _texture2D);

    return _camera.release();
}

osg::Camera*  initCamera(int x, int y, int w, int h)
{   
    osg::Camera * _camera = new osg::Camera;

    _camera = new osg::Camera;
    _camera->setName("CCTV");

    _camera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    _camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    _camera->setNearFarRatio(0.000001);
    //_camera->setClearColor(osg::Vec4f(0.0,0.0,0.0,0.25));
    _camera->setProjectionMatrixAsPerspective(30.0, (float)w/(float)h, 1,10000.0);

    _camera->setViewport(x, y, w, h);   

    _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);

    return _camera;
}


osg::ref_ptr<osg::Camera> createTestHUD(int x, int y, int w, int h, osg::Texture2D *tex)
{
    osg::ref_ptr<osg::Camera> hudCamera = new osg::Camera;
    hudCamera->setProjectionMatrixAsOrtho2D(0, 1, 0, 1);
    hudCamera->setViewMatrix(osg::Matrix::identity());
    hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
    hudCamera->setClearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    hudCamera->setClearColor(osg::Vec4(1.0, 1.0, 1.0, 1.0));
    hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
    hudCamera->setAllowEventFocus(false);
    hudCamera->setViewport(x, y, w, h);
    hudCamera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;


    osg::ref_ptr<osg::Geometry> geom = new osg::Geometry;
    osg::ref_ptr<osg::Vec3Array> vc = new osg::Vec3Array;
    vc->push_back(osg::Vec3d(0, 0, 0));
    vc->push_back(osg::Vec3d(1, 0, 0));
    vc->push_back(osg::Vec3d(1, 1, 0));
    vc->push_back(osg::Vec3d(0, 1, 0));
    geom->setVertexArray(vc.get());
    osg::ref_ptr<osg::Vec2Array> vt = new osg::Vec2Array;
    vt->push_back(osg::Vec2(0, 0));
    vt->push_back(osg::Vec2(1, 0));
    vt->push_back(osg::Vec2(1, 1));
    vt->push_back(osg::Vec2(0, 1));
    geom->setTexCoordArray(0, vt.get());
    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS, 0, 4));
    geode->addDrawable(geom.get());

    hudCamera->addChild(geode.get());
    osg::StateSet *stateset = geode->getOrCreateStateSet();  

    if (NULL != tex)
    {
        stateset->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
    }
    return hudCamera;
}

void main()
{
    osg::ref_ptr<osgViewer::Viewer> viewer = new osgViewer::Viewer;
    osg::ref_ptr<osg::Group> root = new osg::Group; 
    osg::Group * tmpGroup = new osg::Group;

    osg::Node *roomNode = osgDB::readNodeFile("room.ive");
    roomNode->getOrCreateStateSet()->setTextureAttributeAndModes(0,new osg::Texture2D(osgDB::readImageFile("meinv.bmp")));

    viewer->getCamera()->getOrCreateStateSet()->setMode(GL_LIGHTING,osg::StateAttribute::OFF | osg::StateAttribute::OVERRIDE);

    osg::ref_ptr<osg::Texture2D> tmpTexture = CreateDepthTexture(SM_TEXTURE_WIDTH, SM_TEXTURE_WIDTH);

    osg::ref_ptr<osg::Camera> shadowMapCamera = CreateShadowMapCamera(0, 0, SM_TEXTURE_WIDTH, SM_TEXTURE_WIDTH, tmpTexture.get());
    root->addChild(shadowMapCamera.get());
    shadowMapCamera->addChild(tmpGroup);

    osg::ref_ptr<osg::Camera> tmpCamera = initCamera(1000, 0, 400, 400);
    root->addChild(tmpCamera.get());
    tmpCamera->addChild(tmpGroup);

    osg::ref_ptr<osg::ShapeDrawable> shape = new osg::ShapeDrawable(new osg::Box(osg::Vec3(3, 0, 3), 2, 2, 6));
    osg::ref_ptr<osg::ShapeDrawable> shape1 = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 0), 2));
    osg::ref_ptr<osg::ShapeDrawable> shape2 = new osg::ShapeDrawable(new osg::Box(osg::Vec3(-3, 0, 3), 2, 2, 6));
    osg::ref_ptr<osg::Geode> geode = new osg::Geode;
    geode->addDrawable(shape);
    geode->addDrawable(shape1);
    geode->addDrawable(shape2);

    tmpGroup->addChild(roomNode);
    root->addChild(tmpGroup);

    osg::ref_ptr<osg::ShapeDrawable> shapeSun = new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0, 0, 2), 0.3));
    osg::ref_ptr<osg::Geode> geodeSun = new osg::Geode;
    osg::ref_ptr<osg::MatrixTransform> transformSun = new osg::MatrixTransform;
    geodeSun->addDrawable(shapeSun.get());
    transformSun->addChild(geodeSun.get());
    root->addChild(transformSun);

    osg::ref_ptr<osg::Camera> tmpShowShadowMapCamera = createTestHUD(1000, 400, 300, 300, tmpTexture);
    root->addChild(tmpShowShadowMapCamera.get());

    viewer->setSceneData(root);
    viewer->setUpViewInWindow(100, 100, 1400, 768);
    viewer->addEventHandler(new osgViewer::StatsHandler);

    osgGA::TrackballManipulator *tmpManipulator = new osgGA::TrackballManipulator;
    viewer->setCameraManipulator(tmpManipulator);   
    viewer->getCamera()->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);

    osg::StateSet *shaderStateSet = tmpCamera->getOrCreateStateSet();

    shaderStateSet->setTextureAttributeAndModes(1,tmpTexture, osg::StateAttribute::ON);

    loadShaders(shaderStateSet, "ShadowMapShader");

    shaderStateSet->getOrCreateUniform("u_Texture0",osg::Uniform::Type::SAMPLER_2D)->set(0);
    shaderStateSet->getOrCreateUniform("shadowMap",osg::Uniform::Type::SAMPLER_2D)->set(1);

    float tmpAg = 0.0;
    float tmpLen = 15;

    int frameIndex = 0;
    while(!viewer->done())
    {
        tmpCamera->setViewMatrix(tmpManipulator->getInverseMatrix());

        tmpAg += 0.001;
        osg::Vec3 tmpEyeps(0, cos(tmpAg) * tmpLen, sin(tmpAg) * tmpLen);
        osg::Vec3 tmpSunPs(0, cos(tmpAg) * (tmpLen + 1), sin(tmpAg) * (tmpLen + 1));
        shadowMapCamera->setViewMatrixAsLookAt(tmpEyeps, osg::Vec3(0, 0, 0), osg::Vec3(0, 1, 0));
        osg::Matrix depthMVP;
        transformSun->setMatrix(osg::Matrix::translate(tmpSunPs));

        //updata shader
        {
            // Compute the MVP matrix from the light's point of view
            osg::Matrix modelMatrix = osg::Matrix(osg::Matrix::identity());
            osg::Matrix viewMatrix = shadowMapCamera->getViewMatrix();
            osg::Matrix projectMatrix = shadowMapCamera->getProjectionMatrix();
            osg::Matrix biasMatrix(
                0.5, 0.0, 0.0, 0.0, 
                0.0, 0.5, 0.0, 0.0,
                0.0, 0.0, 0.5, 0.0,
                0.5, 0.5, 0.5, 1.0
                );
            osg::Matrix DepthBiasMVP = modelMatrix*viewMatrix*projectMatrix*biasMatrix;
            shaderStateSet->getOrCreateUniform("DepthBiasMVP", osg::Uniform::FLOAT_MAT4)->set(DepthBiasMVP);
        }
        viewer->frame();
    }
    return;
}

下载地址

http://download.csdn.net/detail/dancing_night/9677738

猜你喜欢

转载自blog.csdn.net/dancing_night/article/details/53100983