From 55a9ea19d7446fa6fccafcdfdf26fb83d544eaf0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 20 Sep 2007 10:12:58 +0000 Subject: [PATCH] From Anders Backman, added bias and texture size methods. From Robert Osfield, tweaks to the above for method parameters and indenting. --- include/osgShadow/SoftShadowMap | 24 +++++++++ src/osgShadow/SoftShadowMap.cpp | 92 +++++++++++++++++++-------------- 2 files changed, 76 insertions(+), 40 deletions(-) diff --git a/include/osgShadow/SoftShadowMap b/include/osgShadow/SoftShadowMap index 62999c690..1556f7e52 100644 --- a/include/osgShadow/SoftShadowMap +++ b/include/osgShadow/SoftShadowMap @@ -40,6 +40,27 @@ class OSGSHADOW_EXPORT SoftShadowMap : public ShadowTechnique /** 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.*/ @@ -87,6 +108,9 @@ class OSGSHADOW_EXPORT SoftShadowMap : public ShadowTechnique osg::Vec2 _ambientBias; float _softnesswidth; float _jitteringscale; + float _bias; + osg::Vec2s _textureSize; + }; } diff --git a/src/osgShadow/SoftShadowMap.cpp b/src/osgShadow/SoftShadowMap.cpp index 6ce041978..4f252f267 100755 --- a/src/osgShadow/SoftShadowMap.cpp +++ b/src/osgShadow/SoftShadowMap.cpp @@ -157,7 +157,9 @@ SoftShadowMap::SoftShadowMap(): _textureUnit(1), _ambientBias(0.5f,0.5f), _softnesswidth(0.005f), - _jitteringscale(32.f) + _jitteringscale(32.f), + _bias(0.0f), + _textureSize(1024, 1024) { } @@ -166,7 +168,9 @@ SoftShadowMap::SoftShadowMap(const SoftShadowMap& copy, const osg::CopyOp& copyo _textureUnit(copy._textureUnit), _ambientBias(copy._ambientBias), _softnesswidth(copy._softnesswidth), - _jitteringscale(copy._jitteringscale) + _jitteringscale(copy._jitteringscale), + _bias(copy._bias), + _textureSize(copy._textureSize) { } @@ -190,16 +194,24 @@ void SoftShadowMap::setJitteringScale(const float jitteringscale ) _jitteringscale = jitteringscale; } +void SoftShadowMap::setTextureSize(const osg::Vec2s& texsize) +{ + _textureSize = texsize; + + if (_texture.valid()) + { + _texture->setTextureSize(_textureSize[0], _textureSize[1]); + _camera->setViewport(0,0,_textureSize[0], _textureSize[1]); + } +} + void SoftShadowMap::init() { if (!_shadowedScene) return; - unsigned int tex_width = 1024; - unsigned int tex_height = 1024; - _texture = new osg::Texture2D; - _texture->setTextureSize(tex_width, tex_height); + _texture->setTextureSize(_textureSize[0], _textureSize[1]); _texture->setInternalFormat(GL_DEPTH_COMPONENT); _texture->setSourceType(GL_UNSIGNED_INT); @@ -228,7 +240,7 @@ void SoftShadowMap::init() _camera->setComputeNearFarMode(osg::Camera::DO_NOT_COMPUTE_NEAR_FAR); // set viewport - _camera->setViewport(0,0,tex_width,tex_height); + _camera->setViewport(0,0,_textureSize[0],_textureSize[1]); // set the camera to render before the main camera. _camera->setRenderOrder(osg::Camera::PRE_RENDER); @@ -410,7 +422,7 @@ void SoftShadowMap::cull(osgUtil::CullVisitor& cv) osg::Matrix MVPT = _camera->getViewMatrix() * _camera->getProjectionMatrix() * osg::Matrix::translate(1.0,1.0,1.0) * - osg::Matrix::scale(0.5f,0.5f,0.5f); + osg::Matrix::scale(0.5,0.5,0.5+_bias); _texgen->setMode(osg::TexGen::EYE_LINEAR); _texgen->setPlanesFromMatrix(MVPT); @@ -460,45 +472,45 @@ void SoftShadowMap::initJittering(osg::StateSet *ss) for ( unsigned int s = 0; s < size; ++s ) { - for ( unsigned int t = 0; t < size; ++t ) - { - float v[4], d[4]; - - for ( unsigned int r = 0; r < R; ++r ) + for ( unsigned int t = 0; t < size; ++t ) { - const int x = r % ( gridW / 2 ); - const int y = ( gridH - 1 ) - ( r / (gridW / 2) ); + float v[4], d[4]; - // Generate points on a regular gridW x gridH rectangular - // grid. We multiply x by 2 because, we treat 2 - // consecutive x each loop iteration. Add 0.5f to be in - // the center of the pixel. x, y belongs to [ 0.0, 1.0 ]. - v[0] = float( x * 2 + 0.5f ) / gridW; - v[1] = float( y + 0.5f ) / gridH; - v[2] = float( x * 2 + 1 + 0.5f ) / gridW; - v[3] = v[1]; + for ( unsigned int r = 0; r < R; ++r ) + { + const int x = r % ( gridW / 2 ); + const int y = ( gridH - 1 ) - ( r / (gridW / 2) ); - // Jitter positions. ( 0.5f / w ) == ( 1.0f / 2*w ) - v[0] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); - v[1] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); - v[2] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); - v[3] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); + // Generate points on a regular gridW x gridH rectangular + // grid. We multiply x by 2 because, we treat 2 + // consecutive x each loop iteration. Add 0.5f to be in + // the center of the pixel. x, y belongs to [ 0.0, 1.0 ]. + v[0] = float( x * 2 + 0.5f ) / gridW; + v[1] = float( y + 0.5f ) / gridH; + v[2] = float( x * 2 + 1 + 0.5f ) / gridW; + v[3] = v[1]; - // Warp to disk; values in [-1,1] - d[0] = sqrtf( v[1] ) * cosf( 2.f * 3.1415926f * v[0] ); - d[1] = sqrtf( v[1] ) * sinf( 2.f * 3.1415926f * v[0] ); - d[2] = sqrtf( v[3] ) * cosf( 2.f * 3.1415926f * v[2] ); - d[3] = sqrtf( v[3] ) * sinf( 2.f * 3.1415926f * v[2] ); + // Jitter positions. ( 0.5f / w ) == ( 1.0f / 2*w ) + v[0] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); + v[1] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); + v[2] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); + v[3] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); - // store d into unsigned values [0,255] - const unsigned int tmp = ( (r * size * size) + (t * size) + s ) * 4; - data3D[ tmp + 0 ] = (unsigned char)( ( 1.f + d[0] ) * 127 ); - data3D[ tmp + 1 ] = (unsigned char)( ( 1.f + d[1] ) * 127 ); - data3D[ tmp + 2 ] = (unsigned char)( ( 1.f + d[2] ) * 127 ); - data3D[ tmp + 3 ] = (unsigned char)( ( 1.f + d[3] ) * 127 ); + // Warp to disk; values in [-1,1] + d[0] = sqrtf( v[1] ) * cosf( 2.f * 3.1415926f * v[0] ); + d[1] = sqrtf( v[1] ) * sinf( 2.f * 3.1415926f * v[0] ); + d[2] = sqrtf( v[3] ) * cosf( 2.f * 3.1415926f * v[2] ); + d[3] = sqrtf( v[3] ) * sinf( 2.f * 3.1415926f * v[2] ); + // store d into unsigned values [0,255] + const unsigned int tmp = ( (r * size * size) + (t * size) + s ) * 4; + data3D[ tmp + 0 ] = (unsigned char)( ( 1.f + d[0] ) * 127 ); + data3D[ tmp + 1 ] = (unsigned char)( ( 1.f + d[1] ) * 127 ); + data3D[ tmp + 2 ] = (unsigned char)( ( 1.f + d[2] ) * 127 ); + data3D[ tmp + 3 ] = (unsigned char)( ( 1.f + d[3] ) * 127 ); + + } } - } } // the GPU Gem implementation uses a NV specific internal texture format (GL_SIGNED_RGBA_NV)