查看: 5214|回复: 4

osg做阴影时,得不到深度图的问题

[复制链接]

该用户从未签到

发表于 2011-12-11 17:41:31 | 显示全部楼层 |阅读模式
各位:
      用osg::Camera渲染了一个深度图,想把它用到阴影里面,但是,发现整个深度图里面的像素值都是0.可能是代码错误或是Shader错误.这个是模仿一个OpenGL例子来做的,实在找不到问题了.
      大家有时间帮我看一下,是哪里有问题,我好改正过来.谢谢了.
      代码如下:
  1. #include <osg/Group>
  2. #include <osg/MatrixTransform>
  3. #include <osgDB/ReadFile>
  4. #include <osgViewer/Viewer>

  5. #include <osg/Texture>
  6. #include <osg/Texture2D>
  7. #include <osg/Image>
  8. #include <osg/StateSet>
  9. #include <osg/StateAttribute>
  10. #include <osg/Geode>
  11. #include <osg/Array>
  12. #include <osg/Light>
  13. #include <osg/Shape>
  14. #include <osg/ShapeDrawable>

  15. #include <osg/Matrix>
  16. #include <osg/Camera>
  17. #include <osgGA/GUIEventHandler>

  18. #include <osgViewer/View>
  19. #include <osg/Timer>

  20. #include <osg/Program>
  21. #include <osg/Uniform>
  22. #include <osg/Shader>

  23. #include <osg/ColorMask>

  24. class CameraProjectUpdate : public osgGA::GUIEventHandler
  25. {
  26. public:
  27.         CameraProjectUpdate( osg::Camera *camera, osg::Light *light, osg::Node *shadowRoot )
  28.         {
  29.                 _shadowCamera = camera;
  30.                 _light = light;
  31.                 _shadowRoot = shadowRoot;
  32.                 _maxtrixUniform = NULL;
  33.         }
  34.         bool handle( const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& aa )
  35.         {

  36.                 osgViewer::View *view = dynamic_cast<osgViewer::View*>(&aa);
  37.                 if ( !view )
  38.                 {
  39.                         return false;
  40.                 }

  41.                 osg::Camera *camera = view->getCamera();
  42.                 if ( !camera )
  43.                 {
  44.                         return false;
  45.                 }

  46.                 osg::BoundingSphere bs = _shadowRoot->getBound();

  47.                 if (!bs.valid())
  48.                 {
  49.                         return false;
  50.                 }

  51.                 float znear = 1.0f*bs.radius();
  52.                 float zfar  = 3.0f*bs.radius();

  53.                 // 2:1 aspect ratio as per flag geometry below.
  54.                 float proj_top   = 0.25f*znear;
  55.                 float proj_right = 0.5f*znear;

  56.                 znear *= 0.9f;
  57.                 zfar *= 1.1f;

  58.                 _shadowCamera->setProjectionMatrixAsFrustum(-proj_right,proj_right,-proj_top,proj_top,znear,zfar);
  59.                 osg::Vec4 lightPos = _light->getPosition();

  60.                 _shadowCamera->setViewMatrixAsLookAt( osg::Vec3( lightPos.x(), lightPos.y(), lightPos.z() ), bs.center(), _light->getDirection() );

  61.                
  62.                 // 视图变换矩阵
  63.                 osg::Matrix lightViewMatrix = _shadowCamera->getViewMatrix();
  64.                 // 投影矩阵
  65.                 osg::Matrix lightProjectMatrix = _shadowCamera->getProjectionMatrix();

  66.                 osg::Matrix cameraInverseViewMatrix = camera->getInverseViewMatrix();
  67.                 osg::Matrix lightResultMatrix;

  68.                 if ( ea.getModKeyMask() & osgGA::GUIEventAdapter::MODKEY_SHIFT )
  69.                 {
  70.                         lightResultMatrix =   cameraInverseViewMatrix * lightViewMatrix * lightProjectMatrix/* * biasMt*/;
  71.                 }else
  72.                 {
  73.                         lightResultMatrix =   /*biasMt * */lightProjectMatrix * lightViewMatrix * cameraInverseViewMatrix;
  74.                 }

  75.                 if ( !_maxtrixUniform )
  76.                 {
  77.                         return false;
  78.                 }
  79.                 _maxtrixUniform->set( lightResultMatrix );


  80.                 return false;
  81.         }

  82.         osg::Camera *_shadowCamera;
  83.         osg::Light *_light;
  84.         osg::Node *_shadowRoot;
  85.         osg::Uniform *_maxtrixUniform;

  86. };




  87. osg::Texture* createRenderTexture(int tex_width, int tex_height, bool nearest = false)
  88. {
  89.         // create simple 2D texture
  90.         osg::Texture2D* texture2D = new osg::Texture2D;
  91.         texture2D->setTextureSize(tex_width, tex_height);
  92.         texture2D->setFilter(osg::Texture2D::MIN_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
  93.         texture2D->setFilter(osg::Texture2D::MAG_FILTER, nearest ? osg::Texture2D::NEAREST : osg::Texture2D::LINEAR);
  94.         texture2D->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
  95.         texture2D->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
  96.         texture2D->setBorderColor(osg::Vec4(0.0f,0.0f,0.0f,0.0f));
  97.         texture2D->setResizeNonPowerOfTwoHint(false);

  98.         texture2D->setInternalFormat(GL_RGBA32F_ARB);
  99.         texture2D->setSourceFormat(GL_RGBA);
  100.         texture2D->setSourceType(GL_FLOAT);

  101.         return texture2D;
  102. }
  103. osg::Drawable* createTexturedQuadDrawable(const osg::Vec3& center,const osg::Vec3& widthVec,const osg::Vec3& heightVec, osg::Texture *tex )
  104. {
  105.         //osg::Geometry* geom = osg::createTexturedQuadGeometry(corner, widthVec, heightVec, l,b,r,t);

  106.         osg::Geometry* geom = new osg::Geometry;

  107.         osg::Vec4Array* colors = new osg::Vec4Array;
  108.         colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
  109.         geom->setColorArray(colors);
  110.         geom->setColorBinding(osg::Geometry::BIND_OVERALL);

  111.         // Vertex coordinates
  112.         osg::Vec3Array* coords = new osg::Vec3Array(4);
  113.         (*coords)[0] = center + heightVec / 2 - widthVec / 2;
  114.         (*coords)[1] = center - heightVec / 2 - widthVec / 2;
  115.         (*coords)[2] = center - heightVec / 2 + widthVec / 2;
  116.         (*coords)[3] = center + heightVec / 2 + widthVec / 2;
  117.         geom->setVertexArray(coords);

  118.         // Add texture coordinates for every input texture
  119.        
  120.         int unit = 0;

  121.         // start with default normalised
  122.         float l = 0.0;
  123.         float b = 0.0;
  124.         float r = 1.0;
  125.         float t = 1.0;

  126.         osg::Vec2Array* tcoords = new osg::Vec2Array(4);
  127.         (*tcoords)[3].set(l,t);
  128.         (*tcoords)[2].set(l,b);
  129.         (*tcoords)[1].set(r,b);
  130.         (*tcoords)[0].set(r,t);
  131.         geom->setTexCoordArray(unit, tcoords);
  132.                

  133.         osg::Vec3Array* normals = new osg::Vec3Array(1);
  134.         (*normals)[0] = widthVec^heightVec;
  135.         (*normals)[0].normalize();
  136.         geom->setNormalArray(normals);
  137.         geom->setNormalBinding(osg::Geometry::BIND_OVERALL);

  138.         geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));

  139.         // setup default state set
  140.         geom->setStateSet(new osg::StateSet());
  141.         if ( tex )
  142.         {
  143.                 geom->getOrCreateStateSet()->setTextureAttributeAndModes(0, tex );
  144.         }

  145.         geom->setUseDisplayList(false);

  146.         return geom;
  147. }



  148. int _tmain(int argc, _TCHAR* argv[])
  149. {
  150.         osgViewer::Viewer v;

  151.         osg::ref_ptr<osg::Node> cow = osgDB::readNodeFile("cow.osg");
  152.         osg::ref_ptr<osg::Group> root = new osg::Group;
  153.         osg::ref_ptr<osg::Group> modelRoot = new osg::Group;
  154.         osg::ref_ptr<osg::Group> shadowRoot = new osg::Group;
  155.         osg::ref_ptr<osg::Group> modelsGroup = new osg::Group;

  156.         modelsGroup->addChild( cessna );
  157.         shadowRoot->addChild( modelsGroup );
  158.         modelRoot->addChild( modelsGroup );

  159.         root->addChild( modelRoot );

  160.         // add a sphere to modelsGroup
  161.         {
  162.                 osg::ref_ptr<osg::Geode> shadowGeode = new osg::Geode;
  163.                 osg::ref_ptr<osg::Sphere> shadowSphere = new osg::Sphere;
  164.                 shadowSphere->setRadius( 5.0 );
  165.                 shadowSphere->setCenter( osg::Vec3 ( 0.0, 0.0, 0.0 ) );
  166.                 osg::ref_ptr<osg::ShapeDrawable> shadowShape = new osg::ShapeDrawable;
  167.                 shadowShape->setColor( osg::Vec4 ( 1.0, 1.0, 0.0, 1.0 ) );
  168.                 shadowShape->setShape( shadowSphere );
  169.                 shadowGeode->addDrawable( shadowShape );
  170.                 modelsGroup->addChild( shadowGeode );
  171.         }

  172.         osg::ref_ptr<osg::Light> light = new osg::Light;
  173.         osg::Vec3 lightPos = osg::Vec3 ( 0, 0, 100 );
  174.         osg::Vec3 lightDir = osg::Vec3 ( 0.0, 0.0, -1.0 );
  175.         light->setPosition( osg::Vec4 ( lightPos.x(), lightPos.y(), lightPos.z(), 1.0 ) );
  176.         light->setDirection( lightDir );

  177.         int windowWidth = 2048;
  178.         int windowHeight = 2048;
  179.         osg::Texture* textureDepthView = createRenderTexture(windowWidth, windowHeight, true);


  180.         // 添加一个平面,表示地面
  181.         {
  182.                 osg::Geode *geode = new osg::Geode;
  183.                 modelsGroup->addChild( geode );
  184.                 osg::ref_ptr<osg::Drawable> depthNode = createTexturedQuadDrawable( osg::Vec3 ( 0.0, 0.0, -10.0 )
  185.                         , osg::Vec3 ( 60.0, 0.0, 0.0 )
  186.                         , osg::Vec3( 0.0, 60.0, 0.0 )
  187.                         , NULL );
  188.                 geode->addDrawable( depthNode );
  189.         }

  190.         osg::Camera::RenderTargetImplementation renderImplementation = osg::Camera::PIXEL_BUFFER_RTT;/*osg::Camera::FRAME_BUFFER_OBJECT*/;
  191.         osg::ref_ptr<osg::Camera> shadowCamera = new osg::Camera;
  192.         root->addChild( shadowCamera );

  193.         // 在这里,需要设置相机的变换矩阵,从模型到光源空间的变换
  194.         // 通过回调这种方式,得到相机的变换矩阵,并设置到uniform里面
  195.         CameraProjectUpdate *cpu = new CameraProjectUpdate( shadowCamera, light, shadowRoot );
  196.         {       
  197.                 shadowCamera->setEventCallback( cpu );
  198.                 shadowCamera->setViewport(new osg::Viewport(0,0,windowWidth,windowHeight));
  199.                 shadowCamera->setClearColor( osg::Vec4 ( 0.0, 0.0, 0.0, 0.0 ) );

  200.                
  201.                 textureDepthView->setShadowComparison( true );
  202.                 textureDepthView->setShadowCompareFunc( osg::Texture::LEQUAL );
  203.                 shadowCamera->setClearDepth( 1.0 );

  204.                 shadowCamera->attach(osg::Camera::DEPTH_BUFFER, textureDepthView);



  205.                 shadowCamera->setRenderTargetImplementation(renderImplementation);
  206.                 // set view
  207.                 shadowCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);

  208.                 // set the camera to render before the main camera.
  209.                 shadowCamera->setRenderOrder(osg::Camera::PRE_RENDER);

  210.                 shadowCamera->addChild( shadowRoot );

  211.         }
  212.         // setup shadow shader to modelRoot
  213.         {
  214.                 osg::Shader *vertShader = osgDB::readShaderFile( osg::Shader::VERTEX, "ShadowMappingPCF.vert");
  215.                 osg::Shader *fragShader = osgDB::readShaderFile( osg::Shader::FRAGMENT, "ShadowMappingPCF.frag" );
  216.                 if ( vertShader && fragShader )
  217.                 {
  218.                         osg::Program *progam = new osg::Program;
  219.                         progam->addShader( vertShader );
  220.                         progam->addShader( fragShader );
  221.                         modelRoot->getOrCreateStateSet()->setAttributeAndModes( progam );
  222.                         modelRoot->getOrCreateStateSet()->setTextureAttributeAndModes( 2, textureDepthView );
  223.                         modelRoot->getOrCreateStateSet()->addUniform( new osg::Uniform( "shadowMap", 2 ) );

  224.                         osg::Matrix m;
  225.                         osg::Uniform *viewMatrixUniform = new osg::Uniform("changeMatrix", m);
  226.                         modelRoot->getOrCreateStateSet()->addUniform( viewMatrixUniform );
  227.                         cpu->_maxtrixUniform = viewMatrixUniform;
  228.                 }
  229.         }


  230.         // 添加一个小球,表示灯光所有位置
  231.         osg::ref_ptr<osg::Geode> geode = new osg::Geode;
  232.         root->addChild( geode );
  233.         osg::ref_ptr<osg::Sphere> sphere = new osg::Sphere;
  234.         sphere->setCenter( lightPos );
  235.         sphere->setRadius( 2.0 );
  236.         osg::ref_ptr<osg::ShapeDrawable> sd = new osg::ShapeDrawable;
  237.         sd->setShape( sphere );
  238.         sd->setColor( osg::Vec4 ( 1.0, 1.0, 1.0, 1.0 ) );
  239.         geode->addDrawable( sd );


  240.         v.setLight( light );
  241.         v.setSceneData( root );


  242.         return v.run();


  243.         return 0;
  244. }

复制代码
其中用到了两个Shader,如下:
ShadowMappingPCF.vert
  1. uniform mat4 changeMatrix;

  2. varying vec4 projCoord;

  3. void main()
  4. {
  5.   vec4 texcoord = changeMatrix * gl_ModelViewMatrix * gl_Vertex;
  6.   texcoord = texcoord / texcoord.w;
  7.   projCoord = 0.5 * projCoord + 0.5;
  8.   gl_FrontColor = gl_Color;
  9.   gl_Position = ftransform();
  10. }
复制代码
ShadowMappingPCF.frag
  1. uniform sampler2DShadow shadowMap;

  2. varying vec4 projCoord;

  3. void main ()
  4. {
  5.   
  6.   vec4 color = gl_Color;

  7.   vec3 shadowUV = projCoord.xyz / projCoord.q;
  8.   float mapScale = 1.0 / 512.0;

  9.   vec4 shadowColor = shadow2D(shadowMap, shadowUV);
  10.   shadowColor = clamp(shadowColor, 0.0, 1.0);

  11.   if(shadowUV.x >= 0.0 && shadowUV.y >= 0.0
  12.       && shadowUV.x <= 1.0 && shadowUV.y <= 1.0 )
  13.   {
  14.           gl_FragColor = color * shadowColor;
  15.   }
  16.   else
  17.   {
  18.           gl_FragColor = color;
  19.   }
  20. }
复制代码

该用户从未签到

 楼主| 发表于 2011-12-11 21:10:08 | 显示全部楼层
Shader里面有一个错误,修改如下
ShadowMappingPCF.vert
  1. uniform mat4 changeMatrix;

  2. varying vec4 projCoord;

  3. void main()
  4. {
  5.   vec4 texcoord = changeMatrix * gl_ModelViewMatrix * gl_Vertex;
  6.   texcoord = texcoord / texcoord.w;
  7.   projCoord = 0.5 * texcoord + 0.5;
  8.   gl_FrontColor = gl_Color;
  9.   gl_Position = ftransform();
  10. }
复制代码
此时,还是不出阴影

该用户从未签到

发表于 2011-12-22 14:03:59 | 显示全部楼层
楼主怎么保存深度图像的?

该用户从未签到

发表于 2012-2-28 19:26:53 | 显示全部楼层
ding

该用户从未签到

发表于 2012-3-7 14:18:42 | 显示全部楼层
保存深度纹理应该是setInternalFormat(GL_DEPTH_COMPONENT);吧
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

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

联系我们

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