From Christopher Blaesius,
"Soft shadow mapping is basically the same as hard shadow mapping beside that it uses a different fragment shader. So for me it makes sense that osgShadow::SoftShadowMap is derived from osgShadow::ShadowMap, this makes it easier to maintain the two classes. Additional SoftShadowMap also provides the same Debug methods as ShadowMap."
This commit is contained in:
@@ -91,9 +91,9 @@ class OSGSHADOW_EXPORT ShadowMap : public ShadowTechnique
|
||||
virtual ~ShadowMap(void) {};
|
||||
|
||||
/** Create the managed Uniforms */
|
||||
void createUniforms();
|
||||
virtual void createUniforms();
|
||||
|
||||
void createShaders();
|
||||
virtual void createShaders();
|
||||
|
||||
osg::ref_ptr<osg::Camera> _camera;
|
||||
osg::ref_ptr<osg::TexGen> _texgen;
|
||||
|
||||
@@ -16,13 +16,15 @@
|
||||
|
||||
#include <osg/Camera>
|
||||
#include <osg/Material>
|
||||
#include <osg/MatrixTransform>
|
||||
#include <osg/LightSource>
|
||||
|
||||
#include <osgShadow/ShadowTechnique>
|
||||
#include <osgShadow/ShadowMap>
|
||||
|
||||
namespace osgShadow {
|
||||
|
||||
/** SoftShadowMap provides an implementation of soft shadows with shadow maps.*/
|
||||
class OSGSHADOW_EXPORT SoftShadowMap : public ShadowTechnique
|
||||
class OSGSHADOW_EXPORT SoftShadowMap : public ShadowMap
|
||||
{
|
||||
public :
|
||||
SoftShadowMap();
|
||||
@@ -31,85 +33,57 @@ class OSGSHADOW_EXPORT SoftShadowMap : public ShadowTechnique
|
||||
|
||||
META_Object(osgShadow, SoftShadowMap);
|
||||
|
||||
/** Set the texture unit that the shadow texture will be applied on.*/
|
||||
void setTextureUnit(unsigned int unit);
|
||||
|
||||
/** Get the texture unit that the shadow texture will be applied on.*/
|
||||
unsigned int getTextureUnit() const { return _textureUnit; }
|
||||
|
||||
/** Set the values for the ambient bias the shader will use.*/
|
||||
void setAmbientBias(const osg::Vec2& ambientBias );
|
||||
|
||||
|
||||
/** Set the resolution of the rendertarget texture used for shadow generation */
|
||||
void setTextureSize(int width, int height) { setTextureSize(osg::Vec2s(width, height)); }
|
||||
|
||||
/** Set the resolution of the rendertarget texture used for shadow generation */
|
||||
void setTextureSize(const osg::Vec2s&);
|
||||
|
||||
/** Get the resolution of the rendertarget texture used for shadow generation */
|
||||
const osg::Vec2s& getTextureSize() const { return _textureSize; }
|
||||
|
||||
|
||||
/** Add a small bias to the z-value when calculating the MVPT matrix, this can reduce
|
||||
* shadow acne problem.
|
||||
* Suitable values are 0-0.005
|
||||
* Default is 0. */
|
||||
void setBias(float bias) { _bias = bias; }
|
||||
|
||||
/** Return the bias value set used when calculating the MVPT matrix */
|
||||
float getBias() const { return _bias; }
|
||||
|
||||
|
||||
/** Set the values for width of the soft penumbra the shader will use.
|
||||
* Zero is for hard shadow (no penumbra). 0.01 is already very soft penumbra.
|
||||
* Default is 0.005.*/
|
||||
void setSoftnessWidth(const float softnesswidth );
|
||||
void setSoftnessWidth(const float softnessWidth);
|
||||
|
||||
/** Get the value used for width of the soft penumbra in the shader.*/
|
||||
float getSoftnessWidth() const { return _softnessWidth; }
|
||||
|
||||
/** Set the values for jittering scale the shader will use.
|
||||
* Zero is no jittering (i.e. see the banding in penumbra)
|
||||
* High values (>64) cause 'pixelization' of the penumbra.
|
||||
* Usually but not necessarily power of two number.
|
||||
* Default is 32. */
|
||||
void setJitteringScale(const float jitteringscale );
|
||||
|
||||
/** Get the values that are used for the ambient bias in the shader.*/
|
||||
const osg::Vec2& getAmbientBias() const { return _ambientBias; }
|
||||
|
||||
/** Get the value used for width of the soft penumbra in the shader.*/
|
||||
const float getSoftnessWidth() const { return _softnesswidth; }
|
||||
void setJitteringScale(const float jitteringScale);
|
||||
|
||||
/** Get the value used for jittering scale in the shader.*/
|
||||
const float getJitteringScale() const { return _jitteringscale; }
|
||||
float getJitteringScale() const { return _jitteringScale; }
|
||||
|
||||
/** initialize the ShadowedScene and local cached data structures.*/
|
||||
virtual void init();
|
||||
/** Set the texture unit that the jitter texture will be applied on.*/
|
||||
void setJitterTextureUnit(unsigned int jitterTextureUnit);
|
||||
|
||||
/** run the update traversal of the ShadowedScene and update any loca chached data structures.*/
|
||||
virtual void update(osg::NodeVisitor& nv);
|
||||
|
||||
/** run the cull traversal of the ShadowedScene and set up the rendering for this ShadowTechnique.*/
|
||||
virtual void cull(osgUtil::CullVisitor& cv);
|
||||
|
||||
/** Clean scene graph from any shadow technique specific nodes, state and drawables.*/
|
||||
virtual void cleanSceneGraph();
|
||||
/** Get the texture unit that the jitter texture will be applied on.*/
|
||||
unsigned int getJitterTextureUnit() const { return _jitterTextureUnit; }
|
||||
|
||||
|
||||
protected :
|
||||
/** Add a small bias to the z-value, this can reduce
|
||||
* shadow acne problem.
|
||||
* This is the same as calling setPolygonOffset(osg::Vec2(bias,0));
|
||||
* Suitable values are 0-0.005
|
||||
* Default is 0. */
|
||||
void setBias(float bias) { setPolygonOffset(osg::Vec2(bias,0)); }
|
||||
|
||||
/** Return the bias value */
|
||||
float getBias() const { return getPolygonOffset().x(); }
|
||||
|
||||
virtual ~SoftShadowMap() {}
|
||||
void initJittering(osg::StateSet *);
|
||||
|
||||
osg::ref_ptr<osg::Camera> _camera;
|
||||
osg::ref_ptr<osg::TexGen> _texgen;
|
||||
osg::ref_ptr<osg::Texture2D> _texture;
|
||||
osg::ref_ptr<osg::StateSet> _stateset;
|
||||
unsigned int _textureUnit;
|
||||
osg::Vec2 _ambientBias;
|
||||
float _softnesswidth;
|
||||
float _jitteringscale;
|
||||
float _bias;
|
||||
osg::Vec2s _textureSize;
|
||||
protected:
|
||||
virtual ~SoftShadowMap(void) {};
|
||||
|
||||
/** Create the managed Uniforms */
|
||||
void createUniforms();
|
||||
void createShaders();
|
||||
void initJittering(osg::StateSet *ss);
|
||||
|
||||
osg::ref_ptr<osg::Uniform> _softnessWidthUniform;
|
||||
osg::ref_ptr<osg::Uniform> _jitteringScaleUniform;
|
||||
float _softnessWidth;
|
||||
float _jitteringScale;
|
||||
unsigned int _jitterTextureUnit;
|
||||
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <osgShadow/ShadowMap>
|
||||
#include <osgShadow/SoftShadowMap>
|
||||
#include <osgShadow/ShadowedScene>
|
||||
#include <osg/Notify>
|
||||
@@ -21,13 +22,19 @@
|
||||
#include <osg/CullFace>
|
||||
#include <osg/io_utils>
|
||||
|
||||
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/TexGen>
|
||||
#include <iostream>
|
||||
|
||||
using namespace osgShadow;
|
||||
|
||||
#include <iostream>
|
||||
//for debug
|
||||
#include <osg/LightSource>
|
||||
#include <osg/PolygonMode>
|
||||
#include <osg/Geometry>
|
||||
#include <osgDB/ReadFile>
|
||||
#include <osgText/Text>
|
||||
#include <osg/Texture3D>
|
||||
#include <osg/TexGen>
|
||||
|
||||
#define IMPROVE_TEXGEN_PRECISION 1
|
||||
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// fragment shader
|
||||
@@ -35,58 +42,58 @@ using namespace osgShadow;
|
||||
// Implementation from Chapter 17, Efficient Soft-Edged Shadows Using Pixel Shader Branching, Yury Uralsky.
|
||||
// GPU Gems 2, Matt Pharr ed. Addison-Wesley.
|
||||
//
|
||||
static const char fShaderSource_noBaseTexture[] =
|
||||
static const char fragmentSoftShaderSource_noBaseTexture[] =
|
||||
"#define SAMPLECOUNT 64 \n"
|
||||
"#define SAMPLECOUNT_FLOAT 64.0 \n"
|
||||
"#define SAMPLECOUNT_D2 32 \n"
|
||||
"#define SAMPLECOUNT_D2_FLOAT 32.0 \n"
|
||||
"#define INV_SAMPLECOUNT (1.0 / SAMPLECOUNT_FLOAT) \n"
|
||||
|
||||
"uniform sampler2DShadow shadowTexture; \n"
|
||||
"uniform sampler3D jitterMapSampler; \n"
|
||||
"uniform sampler2DShadow osgShadow_shadowTexture; \n"
|
||||
"uniform sampler3D osgShadow_jitterTexture; \n"
|
||||
|
||||
"uniform vec2 ambientBias; \n"
|
||||
"uniform float softwidth; \n"
|
||||
"uniform float jscale; \n"
|
||||
"uniform vec2 osgShadow_ambientBias; \n"
|
||||
"uniform float osgShadow_softnessWidth; \n"
|
||||
"uniform float osgShadow_jitteringScale; \n"
|
||||
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
" vec4 sceneShadowProj = gl_TexCoord[1]; \n"
|
||||
" float softFactor = softwidth * sceneShadowProj.w; \n"
|
||||
" float softFactor = osgShadow_softnessWidth * sceneShadowProj.w; \n"
|
||||
" vec4 smCoord = sceneShadowProj; \n"
|
||||
" vec3 jitterCoord = vec3( gl_FragCoord.xy / jscale, 0.0 ); \n"
|
||||
" vec3 jitterCoord = vec3( gl_FragCoord.xy / osgShadow_jitteringScale, 0.0 ); \n"
|
||||
" vec4 shadow = vec4(0.0, 0.0, 0.0, 0.0); \n"
|
||||
// First "cheap" sample test
|
||||
" const float pass_div = 1.0 / (2.0 * 4.0); \n"
|
||||
" for ( int i = 0; i < 4; ++i ) \n"
|
||||
" { \n"
|
||||
// Get jitter values in [0,1]; adjust to have values in [-1,1]
|
||||
" vec4 offset = 2.0 * texture3D( jitterMapSampler, jitterCoord ) -1.0; \n"
|
||||
" vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) -1.0; \n"
|
||||
" jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + (offset.xy) * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * pass_div; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * pass_div; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + (offset.zw) * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) *pass_div; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) *pass_div; \n"
|
||||
" } \n"
|
||||
// skip all the expensive shadow sampling if not needed
|
||||
" if ( shadow * (shadow -1.0) != 0.0 ) \n"
|
||||
" { \n"
|
||||
" shadow *= pass_div; \n"
|
||||
" for (int i=0; i<SAMPLECOUNT_D2 - 4; ++i){ \n"
|
||||
" vec4 offset = 2.0 * texture3D( jitterMapSampler, jitterCoord ) - 1.0; \n"
|
||||
" vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) - 1.0; \n"
|
||||
" jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + offset.xy * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + offset.zw * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" } \n"
|
||||
" } \n"
|
||||
// apply shadow, modulo the ambient bias
|
||||
" gl_FragColor = gl_Color * (ambientBias.x + shadow * ambientBias.y); \n"
|
||||
" gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow * osgShadow_ambientBias.y); \n"
|
||||
"} \n";
|
||||
|
||||
|
||||
@@ -94,358 +101,147 @@ static const char fShaderSource_noBaseTexture[] =
|
||||
//////////////////////////////////////////////////////////////////
|
||||
// fragment shader
|
||||
//
|
||||
static const char fShaderSource_withBaseTexture[] =
|
||||
static const char fragmentSoftShaderSource_withBaseTexture[] =
|
||||
"#define SAMPLECOUNT 64 \n"
|
||||
"#define SAMPLECOUNT_FLOAT 64.0 \n"
|
||||
"#define SAMPLECOUNT_D2 32 \n"
|
||||
"#define SAMPLECOUNT_D2_FLOAT 32.0 \n"
|
||||
"#define INV_SAMPLECOUNT (1.0 / SAMPLECOUNT_FLOAT) \n"
|
||||
|
||||
"uniform sampler2D baseTexture; \n"
|
||||
"uniform sampler2DShadow shadowTexture; \n"
|
||||
"uniform sampler3D jitterMapSampler; \n"
|
||||
"uniform sampler2D osgShadow_baseTexture; \n"
|
||||
"uniform sampler2DShadow osgShadow_shadowTexture; \n"
|
||||
"uniform sampler3D osgShadow_jitterTexture; \n"
|
||||
|
||||
"uniform vec2 ambientBias; \n"
|
||||
"uniform float softwidth; \n"
|
||||
"uniform float jscale; \n"
|
||||
"uniform vec2 osgShadow_ambientBias; \n"
|
||||
"uniform float osgShadow_softnessWidth; \n"
|
||||
"uniform float osgShadow_jitteringScale; \n"
|
||||
|
||||
"void main(void) \n"
|
||||
"{ \n"
|
||||
" vec4 sceneShadowProj = gl_TexCoord[1]; \n"
|
||||
" float softFactor = softwidth * sceneShadowProj.w; \n"
|
||||
" float softFactor = osgShadow_softnessWidth * sceneShadowProj.w; \n"
|
||||
" vec4 smCoord = sceneShadowProj; \n"
|
||||
" vec3 jitterCoord = vec3( gl_FragCoord.xy / jscale, 0.0 ); \n"
|
||||
" vec3 jitterCoord = vec3( gl_FragCoord.xy / osgShadow_jitteringScale, 0.0 ); \n"
|
||||
" vec4 shadow = vec4(0.0, 0.0, 0.0, 0.0); \n"
|
||||
// First "cheap" sample test
|
||||
" const float pass_div = 1.0 / (2.0 * 4.0); \n"
|
||||
" for ( int i = 0; i < 4; ++i ) \n"
|
||||
" { \n"
|
||||
// Get jitter values in [0,1]; adjust to have values in [-1,1]
|
||||
" vec4 offset = 2.0 * texture3D( jitterMapSampler, jitterCoord ) -1.0; \n"
|
||||
" vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) -1.0; \n"
|
||||
" jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + (offset.xy) * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * pass_div; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * pass_div; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + (offset.zw) * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) *pass_div; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) *pass_div; \n"
|
||||
" } \n"
|
||||
// skip all the expensive shadow sampling if not needed
|
||||
" if ( shadow * (shadow -1.0) != 0.0 ) \n"
|
||||
" { \n"
|
||||
" shadow *= pass_div; \n"
|
||||
" for (int i=0; i<SAMPLECOUNT_D2 -4; ++i){ \n"
|
||||
" vec4 offset = 2.0 * texture3D( jitterMapSampler, jitterCoord ) - 1.0; \n"
|
||||
" vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) - 1.0; \n"
|
||||
" jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + offset.xy * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
|
||||
" smCoord.xy = sceneShadowProj.xy + offset.zw * softFactor; \n"
|
||||
" shadow += shadow2DProj( shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ) * INV_SAMPLECOUNT; \n"
|
||||
" } \n"
|
||||
" } \n"
|
||||
// apply color and object base texture
|
||||
" vec4 color = gl_Color * texture2D( baseTexture, gl_TexCoord[0].xy ); \n"
|
||||
" vec4 color = gl_Color * texture2D( osgShadow_baseTexture, gl_TexCoord[0].xy ); \n"
|
||||
// apply shadow, modulo the ambient bias
|
||||
" gl_FragColor = color * (ambientBias.x + shadow * ambientBias.y); \n"
|
||||
" gl_FragColor = color * (osgShadow_ambientBias.x + shadow * osgShadow_ambientBias.y); \n"
|
||||
"} \n";
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
SoftShadowMap::SoftShadowMap():
|
||||
_textureUnit(1),
|
||||
_ambientBias(0.5f,0.5f),
|
||||
_softnesswidth(0.005f),
|
||||
_jitteringscale(32.f),
|
||||
_bias(0.0f),
|
||||
_textureSize(1024, 1024)
|
||||
_softnessWidth(0.005f),
|
||||
_jitteringScale(32.f),
|
||||
_jitterTextureUnit(_shadowTextureUnit+1)
|
||||
{
|
||||
}
|
||||
|
||||
SoftShadowMap::SoftShadowMap(const SoftShadowMap& copy, const osg::CopyOp& copyop):
|
||||
ShadowTechnique(copy,copyop),
|
||||
_textureUnit(copy._textureUnit),
|
||||
_ambientBias(copy._ambientBias),
|
||||
_softnesswidth(copy._softnesswidth),
|
||||
_jitteringscale(copy._jitteringscale),
|
||||
_bias(copy._bias),
|
||||
_textureSize(copy._textureSize)
|
||||
ShadowMap(copy,copyop),
|
||||
_softnessWidth(copy._softnessWidth),
|
||||
_jitteringScale(copy._jitteringScale),
|
||||
_jitterTextureUnit(copy._shadowTextureUnit)
|
||||
{
|
||||
}
|
||||
|
||||
void SoftShadowMap::setTextureUnit(unsigned int unit)
|
||||
void SoftShadowMap::setJitteringScale(const float jitteringScale)
|
||||
{
|
||||
_textureUnit = unit;
|
||||
_jitteringScale = jitteringScale;
|
||||
if (_jitteringScaleUniform.valid()) _jitteringScaleUniform->set(_jitteringScale);
|
||||
}
|
||||
|
||||
void SoftShadowMap::setAmbientBias(const osg::Vec2& ambientBias)
|
||||
void SoftShadowMap::setSoftnessWidth(const float softnessWidth)
|
||||
{
|
||||
_ambientBias = ambientBias;
|
||||
_softnessWidth = softnessWidth;
|
||||
if (_softnessWidthUniform.valid()) _softnessWidthUniform->set(_softnessWidth);
|
||||
}
|
||||
|
||||
void SoftShadowMap::setSoftnessWidth(const float softnesswidth )
|
||||
void SoftShadowMap::setJitterTextureUnit(unsigned int jitterTextureUnit)
|
||||
{
|
||||
_softnesswidth = softnesswidth;
|
||||
_jitterTextureUnit=jitterTextureUnit;
|
||||
}
|
||||
|
||||
void SoftShadowMap::setJitteringScale(const float jitteringscale )
|
||||
void SoftShadowMap::createUniforms()
|
||||
{
|
||||
_jitteringscale = jitteringscale;
|
||||
_uniformList.clear();
|
||||
|
||||
osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit);
|
||||
_uniformList.push_back(baseTextureSampler);
|
||||
|
||||
osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit);
|
||||
_uniformList.push_back(shadowTextureSampler);
|
||||
|
||||
_ambientBiasUniform = new osg::Uniform("osgShadow_ambientBias",_ambientBias);
|
||||
_uniformList.push_back(_ambientBiasUniform.get());
|
||||
|
||||
_softnessWidthUniform = new osg::Uniform("osgShadow_softnessWidth",_softnessWidth);
|
||||
_uniformList.push_back(_softnessWidthUniform.get());
|
||||
|
||||
_jitteringScaleUniform = new osg::Uniform("osgShadow_jitteringScale",_jitteringScale);
|
||||
_uniformList.push_back(_jitteringScaleUniform.get());
|
||||
|
||||
_jitterTextureUnit=_shadowTextureUnit+1;
|
||||
initJittering(_stateset.get());
|
||||
|
||||
osg::Uniform* jitterTextureSampler = new osg::Uniform("osgShadow_jitterTexture",(int)_jitterTextureUnit);
|
||||
_uniformList.push_back(jitterTextureSampler);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void SoftShadowMap::setTextureSize(const osg::Vec2s& texsize)
|
||||
{
|
||||
_textureSize = texsize;
|
||||
|
||||
if (_texture.valid())
|
||||
void SoftShadowMap::createShaders()
|
||||
{
|
||||
// if we are not given shaders, use the default
|
||||
if( _shaderList.empty() )
|
||||
{
|
||||
_texture->setTextureSize(_textureSize[0], _textureSize[1]);
|
||||
_camera->setViewport(0,0,_textureSize[0], _textureSize[1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void SoftShadowMap::init()
|
||||
{
|
||||
if (!_shadowedScene) return;
|
||||
|
||||
_texture = new osg::Texture2D;
|
||||
_texture->setTextureSize(_textureSize[0], _textureSize[1]);
|
||||
_texture->setInternalFormat(GL_DEPTH_COMPONENT);
|
||||
_texture->setSourceType(GL_UNSIGNED_INT);
|
||||
|
||||
// Sets GL_TEXTURE_COMPARE_MODE_ARB to GL_COMPARE_R_TO_TEXTURE_ARB
|
||||
_texture->setShadowComparison(true);
|
||||
_texture->setShadowCompareFunc(osg::Texture::LEQUAL);
|
||||
|
||||
_texture->setShadowTextureMode(osg::Texture::LUMINANCE);
|
||||
_texture->setFilter(osg::Texture::MIN_FILTER,osg::Texture::LINEAR);
|
||||
_texture->setFilter(osg::Texture::MAG_FILTER,osg::Texture::LINEAR);
|
||||
_texture->setWrap(osg::Texture::WRAP_S, osg::Texture::CLAMP_TO_EDGE);
|
||||
_texture->setWrap(osg::Texture::WRAP_T, osg::Texture::CLAMP_TO_EDGE);
|
||||
|
||||
|
||||
|
||||
// set up the render to texture camera.
|
||||
{
|
||||
// create the camera
|
||||
_camera = new osg::Camera;
|
||||
|
||||
_camera->setInheritanceMask(0x0);
|
||||
_camera->setCullCallback(new CameraCullCallback(this));
|
||||
|
||||
_camera->setClearMask(GL_DEPTH_BUFFER_BIT);
|
||||
//_camera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
|
||||
_camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||
_camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR);
|
||||
|
||||
// set viewport
|
||||
_camera->setViewport(0,0,_textureSize[0],_textureSize[1]);
|
||||
|
||||
// set the camera to render before the main camera.
|
||||
_camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||
|
||||
// tell the camera to use OpenGL frame buffer object where supported.
|
||||
_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||
//_camera->setRenderTargetImplementation(osg::Camera::SEPERATE_WINDOW);
|
||||
|
||||
// attach the texture and use it as the color buffer.
|
||||
_camera->attach(osg::Camera::DEPTH_BUFFER, _texture.get());
|
||||
|
||||
osg::StateSet* stateset = _camera->getOrCreateStateSet();
|
||||
|
||||
float factor = 0.0f;
|
||||
float units = 1.0f;
|
||||
|
||||
osg::ref_ptr<osg::PolygonOffset> polygon_offset = new osg::PolygonOffset;
|
||||
polygon_offset->setFactor(factor);
|
||||
polygon_offset->setUnits(units);
|
||||
stateset->setAttribute(polygon_offset.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
stateset->setMode(GL_POLYGON_OFFSET_FILL, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
|
||||
osg::ref_ptr<osg::CullFace> cull_face = new osg::CullFace;
|
||||
|
||||
// set culling to BACK facing (cf message from Wojtek Lewandowski in osg Mailing list)
|
||||
cull_face->setMode(osg::CullFace::FRONT);
|
||||
stateset->setAttribute(cull_face.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
stateset->setMode(GL_CULL_FACE, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
_stateset = new osg::StateSet;
|
||||
_stateset->setTextureAttributeAndModes(_textureUnit,_texture.get(),osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
_stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
_stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
_stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
_stateset->setTextureMode(_textureUnit,GL_TEXTURE_GEN_Q,osg::StateAttribute::ON);
|
||||
|
||||
_texgen = new osg::TexGen;
|
||||
|
||||
|
||||
osg::Program* program = new osg::Program;
|
||||
_stateset->setAttribute(program);
|
||||
|
||||
if ( _textureUnit==0)
|
||||
if (_shadowTextureUnit==0)
|
||||
{
|
||||
osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fShaderSource_noBaseTexture);
|
||||
program->addShader(fragment_shader);
|
||||
osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentSoftShaderSource_noBaseTexture);
|
||||
_shaderList.push_back(fragment_shader);
|
||||
}
|
||||
else
|
||||
{
|
||||
osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fShaderSource_withBaseTexture);
|
||||
program->addShader(fragment_shader);
|
||||
|
||||
osg::Uniform* baseTextureSampler = new osg::Uniform("baseTexture",0);
|
||||
_stateset->addUniform(baseTextureSampler);
|
||||
osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentSoftShaderSource_withBaseTexture);
|
||||
_shaderList.push_back(fragment_shader);
|
||||
|
||||
}
|
||||
|
||||
osg::Uniform* shadowTextureSampler = new osg::Uniform("shadowTexture",(int)_textureUnit);
|
||||
_stateset->addUniform(shadowTextureSampler);
|
||||
|
||||
osg::Uniform* ambientBias = new osg::Uniform("ambientBias",_ambientBias);
|
||||
_stateset->addUniform(ambientBias);
|
||||
|
||||
// bhbn
|
||||
// Initialisation of jittering texture
|
||||
initJittering(_stateset.get());
|
||||
|
||||
osg::Uniform* jitterMapSampler = new osg::Uniform("jitterMapSampler",(int)_textureUnit + 1);
|
||||
_stateset->addUniform(jitterMapSampler);
|
||||
|
||||
osg::Uniform* softwidth = new osg::Uniform("softwidth",_softnesswidth);
|
||||
_stateset->addUniform(softwidth);
|
||||
|
||||
osg::Uniform* jscale = new osg::Uniform("jscale",_jitteringscale);
|
||||
_stateset->addUniform(jscale);
|
||||
|
||||
}
|
||||
|
||||
_dirty = false;
|
||||
}
|
||||
|
||||
|
||||
void SoftShadowMap::update(osg::NodeVisitor& nv)
|
||||
{
|
||||
_shadowedScene->osg::Group::traverse(nv);
|
||||
}
|
||||
|
||||
void SoftShadowMap::cull(osgUtil::CullVisitor& cv)
|
||||
{
|
||||
// record the traversal mask on entry so we can reapply it later.
|
||||
unsigned int traversalMask = cv.getTraversalMask();
|
||||
|
||||
osgUtil::RenderStage* orig_rs = cv.getRenderStage();
|
||||
|
||||
// do traversal of shadow receiving scene which does need to be decorated by the shadow map
|
||||
{
|
||||
cv.pushStateSet(_stateset.get());
|
||||
|
||||
_shadowedScene->osg::Group::traverse(cv);
|
||||
|
||||
cv.popStateSet();
|
||||
|
||||
}
|
||||
|
||||
// need to compute view frustum for RTT camera.
|
||||
// 1) get the light position
|
||||
// 2) get the center and extents of the view frustum
|
||||
|
||||
const osg::Light* selectLight = 0;
|
||||
osg::Vec4 lightpos;
|
||||
|
||||
osgUtil::PositionalStateContainer::AttrMatrixList& aml = orig_rs->getPositionalStateContainer()->getAttrMatrixList();
|
||||
for(osgUtil::PositionalStateContainer::AttrMatrixList::iterator itr = aml.begin();
|
||||
itr != aml.end();
|
||||
++itr)
|
||||
{
|
||||
const osg::Light* light = dynamic_cast<const osg::Light*>(itr->first.get());
|
||||
if (light)
|
||||
{
|
||||
osg::RefMatrix* matrix = itr->second.get();
|
||||
if (matrix) lightpos = light->getPosition() * (*matrix);
|
||||
else lightpos = light->getPosition();
|
||||
|
||||
selectLight = light;
|
||||
}
|
||||
}
|
||||
|
||||
osg::Matrix eyeToWorld;
|
||||
eyeToWorld.invert(*cv.getModelViewMatrix());
|
||||
|
||||
lightpos = lightpos * eyeToWorld;
|
||||
|
||||
if (selectLight)
|
||||
{
|
||||
// get the bounds of the model.
|
||||
osg::ComputeBoundsVisitor cbbv(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
|
||||
cbbv.setTraversalMask(getShadowedScene()->getCastsShadowTraversalMask());
|
||||
|
||||
_shadowedScene->osg::Group::traverse(cbbv);
|
||||
|
||||
osg::BoundingBox bb = cbbv.getBoundingBox();
|
||||
|
||||
|
||||
osg::Vec3 position;
|
||||
|
||||
if (lightpos[3]!=0.0)
|
||||
{
|
||||
position.set(lightpos.x(), lightpos.y(), lightpos.z());
|
||||
}
|
||||
else
|
||||
{
|
||||
// make an orthographic projection
|
||||
osg::Vec3 lightDir(lightpos.x(), lightpos.y(), lightpos.z());
|
||||
lightDir.normalize();
|
||||
|
||||
// set the position far away along the light direction
|
||||
position = lightDir * bb.radius() * 20;
|
||||
}
|
||||
|
||||
float centerDistance = (position-bb.center()).length();
|
||||
|
||||
float znear = centerDistance-bb.radius();
|
||||
float zfar = centerDistance+bb.radius();
|
||||
float zNearRatio = 0.001f;
|
||||
if (znear<zfar*zNearRatio) znear = zfar*zNearRatio;
|
||||
|
||||
float top = bb.radius();
|
||||
float right = top;
|
||||
|
||||
_camera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
|
||||
_camera->setProjectionMatrixAsOrtho(-right, right, -top, top, znear, zfar);
|
||||
_camera->setViewMatrixAsLookAt(position, bb.center(), osg::Vec3(0.0f,1.0f,0.0f));
|
||||
|
||||
// compute the matrix which takes a vertex from local coords into tex coords
|
||||
// will use this later to specify osg::TexGen..
|
||||
osg::Matrix MVPT = _camera->getViewMatrix() *
|
||||
_camera->getProjectionMatrix() *
|
||||
osg::Matrix::translate(1.0,1.0,1.0) *
|
||||
osg::Matrix::scale(0.5,0.5,0.5+_bias);
|
||||
|
||||
_texgen->setMode(osg::TexGen::EYE_LINEAR);
|
||||
_texgen->setPlanesFromMatrix(MVPT);
|
||||
|
||||
cv.setTraversalMask( traversalMask &
|
||||
getShadowedScene()->getCastsShadowTraversalMask() );
|
||||
|
||||
// do RTT camera traversal
|
||||
_camera->accept(cv);
|
||||
|
||||
orig_rs->getPositionalStateContainer()->addPositionedTextureAttribute(_textureUnit, cv.getModelViewMatrix(), _texgen.get());
|
||||
}
|
||||
|
||||
|
||||
// reapply the original traversal mask
|
||||
cv.setTraversalMask( traversalMask );
|
||||
}
|
||||
|
||||
void SoftShadowMap::cleanSceneGraph()
|
||||
{
|
||||
}
|
||||
|
||||
// Implementation from Chapter 17, Efficient Soft-Edged Shadows Using Pixel Shader Branching, Yury Uralsky.
|
||||
// GPU Gems 2, Matt Pharr ed. Addison-Wesley.
|
||||
//
|
||||
@@ -519,10 +315,10 @@ void SoftShadowMap::initJittering(osg::StateSet *ss)
|
||||
image3D->setImage(size, size, R, GL_RGBA4, GL_RGBA, GL_UNSIGNED_BYTE, data3D, osg::Image::USE_NEW_DELETE);
|
||||
texture3D->setImage(image3D);
|
||||
|
||||
ss->setTextureAttributeAndModes((int)_textureUnit + 1, texture3D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
ss->setTextureMode((int)_textureUnit + 1,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
ss->setTextureMode((int)_textureUnit + 1,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
ss->setTextureMode((int)_textureUnit + 1,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
ss->setTextureAttributeAndModes(_jitterTextureUnit, texture3D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
|
||||
ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON);
|
||||
ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON);
|
||||
ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user