|
各位:
用osg::Camera渲染了一个深度图,想把它用到阴影里面,但是,发现整个深度图里面的像素值都是0.可能是代码错误或是Shader错误.这个是模仿一个OpenGL例子来做的,实在找不到问题了.
大家有时间帮我看一下,是哪里有问题,我好改正过来.谢谢了.
代码如下:- #include <osg/Group>
- #include <osg/MatrixTransform>
- #include <osgDB/ReadFile>
- #include <osgViewer/Viewer>
- #include <osg/Texture>
- #include <osg/Texture2D>
- #include <osg/Image>
- #include <osg/StateSet>
- #include <osg/StateAttribute>
- #include <osg/Geode>
- #include <osg/Array>
- #include <osg/Light>
- #include <osg/Shape>
- #include <osg/ShapeDrawable>
- #include <osg/Matrix>
- #include <osg/Camera>
- #include <osgGA/GUIEventHandler>
- #include <osgViewer/View>
- #include <osg/Timer>
- #include <osg/Program>
- #include <osg/Uniform>
- #include <osg/Shader>
- #include <osg/ColorMask>
- class CameraProjectUpdate : public osgGA::GUIEventHandler
- {
- public:
- CameraProjectUpdate( osg::Camera *camera, osg::Light *light, osg::Node *shadowRoot )
- {
- _shadowCamera = camera;
- _light = light;
- _shadowRoot = shadowRoot;
- _maxtrixUniform = NULL;
- }
- bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
- {
- osgViewer::View *view = dynamic_cast<osgViewer::View*>(&aa);
- if ( !view )
- {
- return false;
- }
- osg::Camera *camera = view->getCamera();
- if ( !camera )
- {
- return false;
- }
- osg::BoundingSphere bs = _shadowRoot->getBound();
- if (!bs.valid())
- {
- return false;
- }
- float znear = 1.0f*bs.radius();
- float zfar = 3.0f*bs.radius();
- // 2:1 aspect ratio as per flag geometry below.
- float proj_top = 0.25f*znear;
- float proj_right = 0.5f*znear;
- znear *= 0.9f;
- zfar *= 1.1f;
- _shadowCamera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
- osg::Vec4 lightPos = _light->getPosition();
- _shadowCamera->setViewMatrixAsLookAt( osg::Vec3( lightPos.x(), lightPos.y(), lightPos.z() ), bs.center(), _light->getDirection() );
-
- // 视图变换矩阵
- osg::Matrix lightViewMatrix = _shadowCamera->getViewMatrix();
- // 投影矩阵
- osg::Matrix lightProjectMatrix = _shadowCamera->getProjectionMatrix();
- osg::Matrix cameraInverseViewMatrix = camera->getInverseViewMatrix();
- osg::Matrix lightResultMatrix;
- if ( ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT )
- {
- lightResultMatrix = cameraInverseViewMatrix * lightViewMatrix * lightProjectMatrix/* * biasMt*/;
- }else
- {
- lightResultMatrix = /*biasMt * */lightProjectMatrix * lightViewMatrix * cameraInverseViewMatrix;
- }
- if ( !_maxtrixUniform )
- {
- return false;
- }
- _maxtrixUniform->set( lightResultMatrix );
- return false;
- }
- osg::Camera *_shadowCamera;
- osg::Light *_light;
- osg::Node *_shadowRoot;
- osg::Uniform *_maxtrixUniform;
- };
- osg::Texture* createRenderTexture(int tex_width, int tex_height, bool nearest = false)
- {
- // create simple 2D texture
- osg::Texture2D* texture2D = new osg::Texture2D;
- texture2D->setTextureSize(tex_width, tex_height);
- texture2D->setFilter(osg::Texture2D::MIN_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
- texture2D->setFilter(osg::Texture2D::MAG_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
- texture2D->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
- texture2D->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
- texture2D->setBorderColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));
- texture2D->setResizeNonPowerOfTwoHint(false);
- texture2D->setInternalFormat(GL_RGBA32F_ARB);
- texture2D->setSourceFormat(GL_RGBA);
- texture2D->setSourceType(GL_FLOAT);
- return texture2D;
- }
- osg::Drawable* createTexturedQuadDrawable(const osg::Vec3& center,const osg::Vec3& widthVec,const osg::Vec3& heightVec, osg::Texture *tex )
- {
- //osg::Geometry* geom = osg::createTexturedQuadGeometry(corner, widthVec, heightVec, l,b,r,t);
- osg::Geometry* geom = new osg::Geometry;
- osg::Vec4Array* colors = new osg::Vec4Array;
- colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
- geom->setColorArray(colors);
- geom->setColorBinding(osg::Geometry::BIND_OVERALL);
- // Vertex coordinates
- osg::Vec3Array* coords = new osg::Vec3Array(4);
- (*coords)[0] = center + heightVec / 2 - widthVec / 2;
- (*coords)[1] = center - heightVec / 2 - widthVec / 2;
- (*coords)[2] = center - heightVec / 2 + widthVec / 2;
- (*coords)[3] = center + heightVec / 2 + widthVec / 2;
- geom->setVertexArray(coords);
- // Add texture coordinates for every input texture
-
- int unit = 0;
- // start with default normalised
- float l = 0.0;
- float b = 0.0;
- float r = 1.0;
- float t = 1.0;
- osg::Vec2Array* tcoords = new osg::Vec2Array(4);
- (*tcoords)[3].set(l,t);
- (*tcoords)[2].set(l,b);
- (*tcoords)[1].set(r,b);
- (*tcoords)[0].set(r,t);
- geom->setTexCoordArray(unit, tcoords);
-
- osg::Vec3Array* normals = new osg::Vec3Array(1);
- (*normals)[0] = widthVec^heightVec;
- (*normals)[0].normalize();
- geom->setNormalArray(normals);
- geom->setNormalBinding(osg::Geometry::BIND_OVERALL);
- geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
- // setup default state set
- geom->setStateSet(new osg::StateSet());
- if ( tex )
- {
- geom->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex );
- }
- geom->setUseDisplayList(false);
- return geom;
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- osgViewer::Viewer v;
- osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
- osg::ref_ptr<osg::Group> root = new osg::Group;
- osg::ref_ptr<osg::Group> modelRoot = new osg::Group;
- osg::ref_ptr<osg::Group> shadowRoot = new osg::Group;
- osg::ref_ptr<osg::Group> modelsGroup = new osg::Group;
- modelsGroup->addChild( cessna );
- shadowRoot->addChild( modelsGroup );
- modelRoot->addChild( modelsGroup );
- root->addChild( modelRoot );
- // add a sphere to modelsGroup
- {
- osg::ref_ptr<osg::Geode> shadowGeode = new osg::Geode;
- osg::ref_ptr<osg::Sphere> shadowSphere = new osg::Sphere;
- shadowSphere->setRadius( 5.0 );
- shadowSphere->setCenter( osg::Vec3 ( 0.0, 0.0, 0.0 ) );
- osg::ref_ptr<osg::ShapeDrawable> shadowShape = new osg::ShapeDrawable;
- shadowShape->setColor( osg::Vec4 ( 1.0, 1.0, 0.0, 1.0 ) );
- shadowShape->setShape( shadowSphere );
- shadowGeode->addDrawable( shadowShape );
- modelsGroup->addChild( shadowGeode );
- }
- osg::ref_ptr<osg::Light> light = new osg::Light;
- osg::Vec3 lightPos = osg::Vec3 ( 0, 0, 100 );
- osg::Vec3 lightDir = osg::Vec3 ( 0.0, 0.0, -1.0 );
- light->setPosition( osg::Vec4 ( lightPos.x(), lightPos.y(), lightPos.z(), 1.0 ) );
- light->setDirection( lightDir );
- int windowWidth = 2048;
- int windowHeight = 2048;
- osg::Texture* textureDepthView = createRenderTexture(windowWidth, windowHeight, true);
- // 添加一个平面,表示地面
- {
- osg::Geode *geode = new osg::Geode;
- modelsGroup->addChild( geode );
- osg::ref_ptr<osg::Drawable> depthNode = createTexturedQuadDrawable( osg::Vec3 ( 0.0, 0.0, -10.0 )
- , osg::Vec3 ( 60.0, 0.0, 0.0 )
- , osg::Vec3( 0.0, 60.0, 0.0 )
- , NULL );
- geode->addDrawable( depthNode );
- }
- osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::PIXEL_BUFFER_RTT;/*osg::Camera::FRAME_BUFFER_OBJECT*/;
- osg::ref_ptr<osg::Camera> shadowCamera = new osg::Camera;
- root->addChild( shadowCamera );
- // 在这里,需要设置相机的变换矩阵,从模型到光源空间的变换
- // 通过回调这种方式,得到相机的变换矩阵,并设置到uniform里面
- CameraProjectUpdate *cpu = new CameraProjectUpdate( shadowCamera, light, shadowRoot );
- {
- shadowCamera->setEventCallback( cpu );
- shadowCamera->setViewport(new osg::Viewport(0,0,windowWidth,windowHeight));
- shadowCamera->setClearColor( osg::Vec4 ( 0.0, 0.0, 0.0, 0.0 ) );
-
- textureDepthView->setShadowComparison( true );
- textureDepthView->setShadowCompareFunc( osg::Texture::LEQUAL );
- shadowCamera->setClearDepth( 1.0 );
- shadowCamera->attach(osg::Camera::DEPTH_BUFFER, textureDepthView);
- shadowCamera->setRenderTargetImplementation(renderImplementation);
- // set view
- shadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- // set the camera to render before the main camera.
- shadowCamera->setRenderOrder(osg::Camera::PRE_RENDER);
- shadowCamera->addChild( shadowRoot );
- }
- // setup shadow shader to modelRoot
- {
- osg::Shader *vertShader = osgDB::readShaderFile( osg::Shader::VERTEX, "ShadowMappingPCF.vert");
- osg::Shader *fragShader = osgDB::readShaderFile( osg::Shader::FRAGMENT, "ShadowMappingPCF.frag" );
- if ( vertShader && fragShader )
- {
- osg::Program *progam = new osg::Program;
- progam->addShader( vertShader );
- progam->addShader( fragShader );
- modelRoot->getOrCreateStateSet()->setAttributeAndModes( progam );
- modelRoot->getOrCreateStateSet()->setTextureAttributeAndModes( 2, textureDepthView );
- modelRoot->getOrCreateStateSet()->addUniform( new osg::Uniform( "shadowMap", 2 ) );
- osg::Matrix m;
- osg::Uniform *viewMatrixUniform = new osg::Uniform("changeMatrix", m);
- modelRoot->getOrCreateStateSet()->addUniform( viewMatrixUniform );
- cpu->_maxtrixUniform = viewMatrixUniform;
- }
- }
- // 添加一个小球,表示灯光所有位置
- osg::ref_ptr<osg::Geode> geode = new osg::Geode;
- root->addChild( geode );
- osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere;
- sphere->setCenter( lightPos );
- sphere->setRadius( 2.0 );
- osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable;
- sd->setShape( sphere );
- sd->setColor( osg::Vec4 ( 1.0, 1.0, 1.0, 1.0 ) );
- geode->addDrawable( sd );
- v.setLight( light );
- v.setSceneData( root );
- return v.run();
- return 0;
- }
复制代码 其中用到了两个Shader,如下:
ShadowMappingPCF.vert- uniform mat4 changeMatrix;
- varying vec4 projCoord;
- void main()
- {
- vec4 texcoord = changeMatrix * gl_ModelViewMatrix * gl_Vertex;
- texcoord = texcoord / texcoord.w;
- projCoord = 0.5 * projCoord + 0.5;
- gl_FrontColor = gl_Color;
- gl_Position = ftransform();
- }
复制代码 ShadowMappingPCF.frag- uniform sampler2DShadow shadowMap;
- varying vec4 projCoord;
- void main ()
- {
-
- vec4 color = gl_Color;
- vec3 shadowUV = projCoord.xyz / projCoord.q;
- float mapScale = 1.0 / 512.0;
- vec4 shadowColor = shadow2D(shadowMap, shadowUV);
- shadowColor = clamp(shadowColor, 0.0, 1.0);
- if(shadowUV.x >= 0.0 && shadowUV.y >= 0.0
- && shadowUV.x <= 1.0 && shadowUV.y <= 1.0 )
- {
- gl_FragColor = color * shadowColor;
- }
- else
- {
- gl_FragColor = color;
- }
- }
复制代码 |
|