查看: 4891|回复: 13

请各位大神帮忙:使用RTT生成shadow map,然后在shader中实现阴影效果

[复制链接]

该用户从未签到

发表于 2014-6-10 21:13:29 | 显示全部楼层 |阅读模式
本帖最后由 buaalb 于 2014-6-10 21:23 编辑

我的目的是想使用预处理好的shadow map来生成实体的阴影,但是实现过程中出现了一些不理想的效果,且看下文.
第一步:生成shadow map

osg::ref_ptr<osg::Group> root;
osg::ref_ptr<osg::Node> roomNode;
osg::ref_ptr<osgViewer::Viewer> mViewer;
osg::ref_ptr<osg::Camera> rttCamera;
osg::ref_ptr<osg::Geode> quad;
//创建一个多边形,用于显示深度缓冲区中图像
osg::Geode* createQuad()
{
        osg::ref_ptr<osg::Geode> gnode ;
        osg::ref_ptr<osg::Geometry> gm ;

        gnode = new osg::Geode;
        gm = new osg::Geometry;

        gnode->addDrawable(gm);
        osg::ref_ptr<osg::Vec3Array> vertex = new osg::Vec3Array;
        vertex->push_back(osg::Vec3(-10, 10, -10));
        vertex->push_back(osg::Vec3(10, 10, -10));
        vertex->push_back(osg::Vec3(10, 10, 10));
        vertex->push_back(osg::Vec3(-10, 10, 10));
        gm->setVertexArray(vertex);
        osg::ref_ptr<osg::Vec3Array> norm = new osg::Vec3Array;
        norm->push_back(osg::Vec3(0, -1.0, 0));
        gm->setNormalArray(norm);
        gm->setNormalBinding(osg::Geometry::BIND_OVERALL);
        osg::ref_ptr<osg::Vec2Array> coord = new osg::Vec2Array;
        coord->push_back(osg::Vec2(0.0, 0.0));
        coord->push_back(osg::Vec2(1.0, 0.0));
        coord->push_back(osg::Vec2(1.0, 1.0));
        coord->push_back(osg::Vec2(0.0, 1.0));
        gm->setTexCoordArray(0, coord);
        gm->addPrimitiveSet(new osg:rawArrays(osg:rimitiveSet:UADS, 0, 4));
        gm->getOrCreateStateSet()->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
        return gnode.release();
}
//创建一个rtt相机,用来从深度缓冲区中读取深度数据
void createRtt()
{
        rttCamera = new osg::Camera;
        rttCamera->setRenderOrder(osg::Camera::POST_RENDER);
        rttCamera->setAllowEventFocus(false);
        rttCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
        rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
        rttCamera->setViewport(0.0, 0.0, 1024,        1024);
        rttCamera->setProjectionMatrix(osg::Matrix:rtho(-10, 10, -10, 10, -10, 20));
        rttCamera->setViewMatrixAsLookAt(osg::Vec3(0.5, -2.0, 4.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0.0, 1.0, 0.0));
}
int main()
{
        mViewer = new osgViewer::Viewer;
        root = new osg::Group;
        /////////////场景中的观察的实体///////////////////////////////////////////////
        roomNode = osgDB::readNodeFile("room.ive");
        root->addChild(roomNode);
        osg::ref_ptr<osg::Image> imge = osgDB::readImageFile("uvmap.DDS");
        osg::ref_ptr<osg::Texture2D> roomTex = new osg::Texture2D;
        roomTex->setImage(imge);
        roomNode->getOrCreateStateSet()->setTextureAttributeAndModes(0, roomTex, osg::StateAttribute::ON);
        /////////////为观察深度图像建立多边形/////////////////////////////////////////////////////////////
        quad = createQuad();
        createRtt();
        //从深度缓冲区中读取数据
        rttCamera->addChild(roomNode);
        osg::ref_ptr<osg::Texture2D> tex = new osg::Texture2D;
        tex->setTextureSize(1024, 1024);
        tex->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
        tex->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
        tex->setFilter(osg::Texture::MAG_FILTER, osg::Texture:INEAR);
        tex->setFilter(osg::Texture::MIN_FILTER, osg::Texture::LINEAR);
        tex->setInternalFormat(GL_DEPTH_COMPONENT);
        tex->setSourceFormat(GL_DEPTH_COMPONENT);
        tex->setSourceType(GL_FLOAT);
        //tex->setShadowComparison(true);
        tex->setShadowTextureMode(osg::Texture2D::LUMINANCE);
        rttCamera->attach(osg::Camera::DEPTH_BUFFER, tex);
        //将深度缓冲区的图像绘制在多边形上
        quad->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex, osg::StateAttribute::ON);
        root->addChild(quad);
        root->addChild(rttCamera);
        //////////////////////////////////////////////////////////////////////////
        //store the tex for shadow calc
        //将获取到的深度图像保存起来
        roomNode->getOrCreateStateSet()->setTextureAttributeAndModes(1, tex, osg::StateAttribute::ON);
        ////////////////在着色器中处理这些深度图像//////////////////////////////////////////////////////////
        osg::ref_ptr<osg::Program> program = new osg::Program;
        {
                osg::ref_ptr<osg::Shader> vertexShader = new osg::Shader(osg::Shader::VERTEX);
                vertexShader->loadShaderSourceFromFile("shadow_vs.glsl");
                program->addShader(vertexShader.get());
                osg::ref_ptr<osg::Shader> fragmentShader = new osg::Shader(osg::Shader::FRAGMENT);
                fragmentShader->loadShaderSourceFromFile("shadow_fs.glsl");
                program->addShader(fragmentShader);
        }
        osg::StateSet* stateset = roomNode->getOrCreateStateSet();
        stateset->setAttributeAndModes(program.get(), osg::StateAttribute::ON);
        //calculate the depth mvp
        osg::Matrix modelMatrix = osg::Matrix();
        osg::Matrix viewMatrix = rttCamera->getViewMatrix();
        osg::Matrix projectMatrix = rttCamera->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 m =modelMatrix*viewMatrix*projectMatrix *biasMatrix;
        osg::ref_ptr<osg::Uniform> depthBiasMVP = new osg::Uniform("DepthBiasMVP", m);
        stateset->addUniform(depthBiasMVP.get());
        stateset->addUniform(new osg::Uniform("defaultTex", 0));
        stateset->addUniform(new osg::Uniform("shadowMap", 1));
        mViewer->setSceneData(root.get());
        mViewer->setCameraManipulator(NULL);
        return mViewer->run();
}
着色中算法:对于任意的顶点,计算该顶点离观察点的距离D1和该顶点在shadow map中深度值D2,若D2<D1则说明该顶点在阴影中。
顶点着色器:
varying vec3 vNormal;
varying vec2 UV;
varying vec4 ShadowCoord;
uniform mat4 DepthBiasMVP;
uniform mat4 osg_ViewMatrixInverse;
void main()
{
        ShadowCoord = DepthBiasMVP *gl_Vertex;
        UV = gl_MultiTexCoord0.st;
        vNormal = normalize(gl_NormalMatrix * gl_Normal);
        gl_Position = ftransform();
}
片段着色器:
uniform sampler2D defaultTex;
uniform sampler2DShadow shadowMap;
varying vec3 vNormal;
varying vec2 UV;
varying vec4 ShadowCoord;
void main()
{
        vec4 LightColor = vec4(1,1,1, 1);
        vec3 MaterialDiffuseColor = texture2D( defaultTex, UV ).rgb;
        float visibility =1.0;
        float bias = 0.005;
        if ( texture( shadowMap, vec3(ShadowCoord.xy, (ShadowCoord.z)/ShadowCoord.w) )  <  (ShadowCoord.z-bias)){
                visibility = 0.5;
        }
        gl_FragColor = vec4(visibility *MaterialDiffuseColor*LightColor, 1.0);
}

问题:
仔细观察其中的阴影,不处在阴影位置的区域变暗了,或者处在阴影区域变亮了
该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/i ... -16-shadow-mapping/

rttCamera->setViewMatrixAsLookAt(osg::Vec3(0.5, -2.0, 4.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0. ...

rttCamera->setViewMatrixAsLookAt(osg::Vec3(0.5, -2.0, 4.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0. ...

rttCamera->setViewMatrixAsLookAt(osg::Vec3(0.5, -2.0, 2.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0. ...

rttCamera->setViewMatrixAsLookAt(osg::Vec3(0.5, -2.0, 2.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0. ...

ShadowTest.rar

13.54 KB, 下载次数: 101, 下载积分: 威望 1

代码以及需要的文件

该用户从未签到

 楼主| 发表于 2014-6-10 21:18:28 | 显示全部楼层
补充问题图片

画线区域为问题区域

画线区域为问题区域
height4.0.jpg

该用户从未签到

 楼主| 发表于 2014-6-10 21:20:49 | 显示全部楼层
该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/i ... -16-shadow-mapping/

该用户从未签到

 楼主| 发表于 2014-6-11 12:03:24 | 显示全部楼层
buaalb 发表于 2014-6-10 21:20
该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16- ...

求帮助啊

该用户从未签到

 楼主| 发表于 2014-6-13 14:52:09 | 显示全部楼层
谁有想法,说一说,大家交流一下

该用户从未签到

发表于 2014-6-13 16:24:27 | 显示全部楼层
代码提交的完整么 我这儿下载下来编译运行,怎么一点阴影也不显示,也正在整阴影这一块,osg自带的阴影不能满足要求,也要自己写一个阴影。。。楼主再上传一份,学习了~

该用户从未签到

 楼主| 发表于 2014-6-19 08:52:02 | 显示全部楼层
casthc 发表于 2014-6-13 16:24
代码提交的完整么 我这儿下载下来编译运行,怎么一点阴影也不显示,也正在整阴影这一块,osg自带的阴影不能 ...

是完整的,你看一下眼点位置对不对

该用户从未签到

发表于 2014-6-20 15:49:35 | 显示全部楼层
恩 但是关于pssm你有做过么

该用户从未签到

发表于 2014-6-20 15:51:23 | 显示全部楼层
下载代码后 生成的阴影图 并贴到四边形上跟你的贴图一模一样,但是不知道为什么room.ive就是出不来阴影,也挺郁闷

该用户从未签到

发表于 2016-5-3 17:10:51 | 显示全部楼层
请问下楼主,原因找出来了吗?我运行你的代码也碰到了一样的问题

该用户从未签到

发表于 2016-8-27 15:00:33 | 显示全部楼层
请问楼上的,有谁做出来了吗,是不是深度比较的时候出问题了

该用户从未签到

发表于 2019-6-4 10:13:48 | 显示全部楼层
我这地方也遇到问题了   

该用户从未签到

发表于 2020-4-16 19:08:15 | 显示全部楼层
话说opengl里的矩阵跟osg里的是有区别的,不能直接用吧...

该用户从未签到

发表于 2020-4-23 15:08:14 | 显示全部楼层
是时候表演真正的技术了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

OSG中国官方论坛-有您OSG在中国才更好

网站简介:osgChina是国内首个三维相关技术开源社区,旨在为国内更多的技术开发人员提供最前沿的技术资讯,为更多的三维从业者提供一个学习、交流的技术平台。

联系我们

  • 工作时间:09:00--18:00
  • 反馈邮箱:1315785073@qq.com
快速回复 返回顶部 返回列表