ParallelSplitShadowMap 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
  2. *
  3. * This library is open source and may be redistributed and/or modified under
  4. * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
  5. * (at your option) any later version. The full license is in LICENSE file
  6. * included with this distribution, and on the openscenegraph.org website.
  7. *
  8. * This library is distributed in the hope that it will be useful,
  9. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. * OpenSceneGraph Public License for more details.
  12. */
  13. /* ParallelSplitShadowMap written by Adrian Egli
  14. *
  15. * this version has still a bug in mutli-thread application (flickering problem)
  16. * to avoid the flickering problem try osgShadow --pssm --SingleThreaded your_scene.ive
  17. *
  18. * The Parallel Split Shadow Map only supports directional light for simulating the shadow.
  19. * It's one of the most robust algorithm for huge terrain sun light's shadow simulation, if
  20. * you need to shadow a terrain, or another huge scene, you should use Parallel Split Shadow Map
  21. * or at least test it against your scene. Have fun.
  22. *
  23. */
  24. #ifndef OSGSHADOW_ParallelSplitShadowMap
  25. #define OSGSHADOW_ParallelSplitShadowMap 1
  26. #include <osg/Camera>
  27. #include <osg/Material>
  28. #include <osg/Depth>
  29. #include <osg/ClipPlane>
  30. #include <osgShadow/ShadowTechnique>
  31. namespace osgShadow {
  32. class OSGSHADOW_EXPORT ParallelSplitShadowMap : public ShadowTechnique
  33. {
  34. public:
  35. ParallelSplitShadowMap(osg::Geode** debugGroup=NULL, int icountplanes=3);
  36. ParallelSplitShadowMap(const ParallelSplitShadowMap& es, const osg::CopyOp& copyop=osg::CopyOp::SHALLOW_COPY);
  37. META_Object(osgShadow, ParallelSplitShadowMap);
  38. /** Initialize the ShadowedScene and local cached data structures.*/
  39. virtual void init();
  40. /** Run the update traversal of the ShadowedScene and update any loca chached data structures.*/
  41. virtual void update(osg::NodeVisitor& nv);
  42. /** Run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/
  43. virtual void cull(osgUtil::CullVisitor& cv);
  44. /** Clean scene graph from any shadow technique specific nodes, state and drawables.*/
  45. virtual void cleanSceneGraph();
  46. /** Switch on the debug coloring in GLSL (only the first 3 texture/splits showed for visualisation */
  47. inline void setDebugColorOn() { _debug_color_in_GLSL = true; }
  48. /** Set the polygon offset osg::Vec2f(factor,unit) */
  49. inline void setPolygonOffset(const osg::Vec2f& p) { _polgyonOffset = p;_user_polgyonOffset_set=true;}
  50. /** Get the polygon offset osg::Vec2f(factor,unit) */
  51. inline const osg::Vec2f& getPolygonOffset() const { return _polgyonOffset;}
  52. /** Set the texture resolution */
  53. inline void setTextureResolution(unsigned int resolution) { _resolution = resolution; }
  54. /** Get the texture resolution */
  55. inline unsigned int getTextureResolution() const { return _resolution; }
  56. /** Set the max far distance */
  57. inline void setMaxFarDistance(double farDist) { _setMaxFarDistance = farDist; _isSetMaxFarDistance = true; }
  58. /** Get the max far distance */
  59. inline double getMaxFarDistance() const { return _setMaxFarDistance; }
  60. /** Set the factor for moving the virtual camera behind the real camera*/
  61. inline void setMoveVCamBehindRCamFactor(double distFactor ) { _move_vcam_behind_rcam_factor = distFactor; }
  62. /** Get the factor for moving the virtual camera behind the real camera*/
  63. inline double getMoveVCamBehindRCamFactor() const { return _move_vcam_behind_rcam_factor; }
  64. /** Set min near distance for splits */
  65. inline void setMinNearDistanceForSplits(double nd){ _split_min_near_dist=nd; }
  66. /** Get min near distance for splits */
  67. inline double getMinNearDistanceForSplits() const { return _split_min_near_dist; }
  68. /** set a user defined light for shadow simulation (sun light, ... )
  69. * when this light get passed to pssm, the scene's light are no longer collected
  70. * and simulated. just this user passed light, it needs to be a directional light.
  71. */
  72. inline void setUserLight(osg::Light* light) { _userLight = light; }
  73. /** get the user defined light for shadow simulation */
  74. inline const osg::Light* getUserLight() const { return _userLight.get(); }
  75. /** Set the values for the ambient bias the shader will use.*/
  76. void setAmbientBias(const osg::Vec2& ambientBias );
  77. /** Get the values for the ambient bias the shader will use.*/
  78. const osg::Vec2& getAmbientBias() const { return _ambientBias; }
  79. /**
  80. * you can overwrite the fragment shader if you like to modify it yourself, own fragment shader can be used
  81. */
  82. class OSGSHADOW_EXPORT FragmentShaderGenerator : public osg::Referenced {
  83. public:
  84. /**
  85. * generate the GLSL fragment shader
  86. */
  87. virtual std::string generateGLSL_FragmentShader_BaseTex(bool debug, unsigned int splitCount,double textureRes, bool filtered, unsigned int nbrSplits,unsigned int textureOffset);
  88. };
  89. /** set fragment shader generator */
  90. inline void setFragmentShaderGenerator(FragmentShaderGenerator* fsw) { _FragmentShaderGenerator = fsw;}
  91. /** enable / disable shadow filtering */
  92. inline void enableShadowGLSLFiltering(bool filtering = true) { _GLSL_shadow_filtered = filtering; }
  93. enum SplitCalcMode {
  94. SPLIT_LINEAR,
  95. SPLIT_EXP
  96. };
  97. /** set split calculation mode */
  98. inline void setSplitCalculationMode(SplitCalcMode scm=SPLIT_EXP) { _SplitCalcMode = scm; }
  99. /** get split calculation mode */
  100. inline SplitCalcMode getSplitCalculationMode() const { return _SplitCalcMode; }
  101. /** Resize any per context GLObject buffers to specified size. */
  102. virtual void resizeGLObjectBuffers(unsigned int maxSize);
  103. /** If State is non-zero, this function releases any associated OpenGL objects for
  104. * the specified graphics context. Otherwise, releases OpenGL objects
  105. * for all graphics contexts. */
  106. virtual void releaseGLObjects(osg::State* = 0) const;
  107. protected :
  108. virtual ~ParallelSplitShadowMap() {}
  109. struct PSSMShadowSplitTexture {
  110. // RTT
  111. osg::ref_ptr<osg::Camera> _camera;
  112. osg::ref_ptr<osg::TexGen> _texgen;
  113. osg::ref_ptr<osg::Texture2D> _texture;
  114. osg::ref_ptr<osg::StateSet> _stateset;
  115. unsigned int _textureUnit;
  116. double _split_far;
  117. osg::ref_ptr<osg::Camera> _debug_camera;
  118. osg::ref_ptr<osg::Texture2D> _debug_texture;
  119. osg::ref_ptr<osg::StateSet> _debug_stateset;
  120. unsigned int _debug_textureUnit;
  121. // Light (SUN)
  122. osg::Vec3d _lightCameraSource;
  123. osg::Vec3d _lightCameraTarget;
  124. osg::Vec3d _frustumSplitCenter;
  125. osg::Vec3d _lightDirection;
  126. double _lightNear;
  127. double _lightFar;
  128. osg::Matrix _cameraView;
  129. osg::Matrix _cameraProj;
  130. unsigned int _splitID;
  131. unsigned int _resolution;
  132. osg::ref_ptr<osg::Uniform> _farDistanceSplit;
  133. void resizeGLObjectBuffers(unsigned int maxSize);
  134. void releaseGLObjects(osg::State* = 0) const;
  135. };
  136. typedef std::map<unsigned int,PSSMShadowSplitTexture> PSSMShadowSplitTextureMap;
  137. PSSMShadowSplitTextureMap _PSSMShadowSplitTextureMap;
  138. private:
  139. void calculateFrustumCorners(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
  140. void calculateLightInitialPosition(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
  141. void calculateLightNearFarFormFrustum(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
  142. void calculateLightViewProjectionFormFrustum(PSSMShadowSplitTexture &pssmShadowSplitTexture,osg::Vec3d *frustumCorners);
  143. osg::Geode** _displayTexturesGroupingNode;
  144. unsigned int _textureUnitOffset;
  145. unsigned int _number_of_splits;
  146. bool _debug_color_in_GLSL;
  147. osg::Vec2 _polgyonOffset;
  148. bool _user_polgyonOffset_set;
  149. unsigned int _resolution;
  150. double _setMaxFarDistance;
  151. bool _isSetMaxFarDistance;
  152. double _split_min_near_dist;
  153. double _move_vcam_behind_rcam_factor;
  154. osg::ref_ptr<osg::Light> _userLight;
  155. osg::ref_ptr<FragmentShaderGenerator> _FragmentShaderGenerator;
  156. bool _GLSL_shadow_filtered;
  157. SplitCalcMode _SplitCalcMode;
  158. osg::Uniform* _ambientBiasUniform;
  159. osg::Vec2 _ambientBias;
  160. };
  161. }
  162. #endif