|
本帖最后由 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, 2.0), osg::Vec3(0.0, 0.0, 0.0), osg::Vec3(0. ...
-
-
ShadowTest.rar
13.54 KB, 下载次数: 101, 下载积分: 威望 1
代码以及需要的文件
|