请各位大神帮忙:使用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/ 补充问题图片 该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16-shadow-mapping/ buaalb 发表于 2014-6-10 21:20
该方法主要是参考了opengl的一个教程http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-16- ...
求帮助啊 谁有想法,说一说,大家交流一下 代码提交的完整么 我这儿下载下来编译运行,怎么一点阴影也不显示,也正在整阴影这一块,osg自带的阴影不能满足要求,也要自己写一个阴影。。。楼主再上传一份,学习了~ casthc 发表于 2014-6-13 16:24
代码提交的完整么 我这儿下载下来编译运行,怎么一点阴影也不显示,也正在整阴影这一块,osg自带的阴影不能 ...
是完整的,你看一下眼点位置对不对 恩 但是关于pssm你有做过么 下载代码后 生成的阴影图 并贴到四边形上跟你的贴图一模一样,但是不知道为什么room.ive就是出不来阴影:L,也挺郁闷 请问下楼主,原因找出来了吗?我运行你的代码也碰到了一样的问题 请问楼上的,有谁做出来了吗,是不是深度比较的时候出问题了 我这地方也遇到问题了 话说opengl里的矩阵跟osg里的是有区别的,不能直接用吧... 是时候表演真正的技术了
页:
[1]