buaalb 发表于 2014-6-10 21:13:29

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

本帖最后由 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::DrawArrays(osg::PrimitiveSet::QUADS, 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::ortho(-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::LINEAR);
        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/

buaalb 发表于 2014-6-10 21:18:28

补充问题图片

buaalb 发表于 2014-6-10 21:20:49

该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/

buaalb 发表于 2014-6-11 12:03:24

buaalb 发表于 2014-6-10 21:20
该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16- ...

求帮助啊

buaalb 发表于 2014-6-13 14:52:09

谁有想法,说一说,大家交流一下

casthc 发表于 2014-6-13 16:24:27

代码提交的完整么 我这儿下载下来编译运行,怎么一点阴影也不显示,也正在整阴影这一块,osg自带的阴影不能满足要求,也要自己写一个阴影。。。楼主再上传一份,学习了~

buaalb 发表于 2014-6-19 08:52:02

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

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

casthc 发表于 2014-6-20 15:49:35

恩 但是关于pssm你有做过么

casthc 发表于 2014-6-20 15:51:23

下载代码后 生成的阴影图 并贴到四边形上跟你的贴图一模一样,但是不知道为什么room.ive就是出不来阴影:L,也挺郁闷

ziwei20 发表于 2016-5-3 17:10:51

请问下楼主,原因找出来了吗?我运行你的代码也碰到了一样的问题

fjlinguanyu 发表于 2016-8-27 15:00:33

请问楼上的,有谁做出来了吗,是不是深度比较的时候出问题了

abc-osg 发表于 2019-6-4 10:13:48

我这地方也遇到问题了   

ttyuy 发表于 2020-4-16 19:08:15

话说opengl里的矩阵跟osg里的是有区别的,不能直接用吧...

dawei9989 发表于 2020-4-23 15:08:14

是时候表演真正的技术了
页: [1]
查看完整版本: 请各位大神帮忙:使用RTT生成shadow map,然后在shader中实现阴影效果