| 1 | |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | |
|---|
| 5 | |
|---|
| 6 | |
|---|
| 7 | |
|---|
| 8 | |
|---|
| 9 | |
|---|
| 10 | |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | |
|---|
| 14 | #include <stdlib.h> |
|---|
| 15 | |
|---|
| 16 | #include <osgShadow/ShadowMap> |
|---|
| 17 | #include <osgShadow/SoftShadowMap> |
|---|
| 18 | #include <osgShadow/ShadowedScene> |
|---|
| 19 | #include <osg/Notify> |
|---|
| 20 | #include <osg/ComputeBoundsVisitor> |
|---|
| 21 | #include <osg/PolygonOffset> |
|---|
| 22 | #include <osg/CullFace> |
|---|
| 23 | #include <osg/io_utils> |
|---|
| 24 | |
|---|
| 25 | using namespace osgShadow; |
|---|
| 26 | |
|---|
| 27 | #include <iostream> |
|---|
| 28 | |
|---|
| 29 | #include <osg/LightSource> |
|---|
| 30 | #include <osg/PolygonMode> |
|---|
| 31 | #include <osg/Geometry> |
|---|
| 32 | #include <osgDB/ReadFile> |
|---|
| 33 | #include <osgText/Text> |
|---|
| 34 | #include <osg/Texture3D> |
|---|
| 35 | #include <osg/TexGen> |
|---|
| 36 | |
|---|
| 37 | #define IMPROVE_TEXGEN_PRECISION 1 |
|---|
| 38 | |
|---|
| 39 | |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | |
|---|
| 45 | static const char fragmentSoftShaderSource_noBaseTexture[] = |
|---|
| 46 | "#define SAMPLECOUNT 64 \n" |
|---|
| 47 | "#define SAMPLECOUNT_FLOAT 64.0 \n" |
|---|
| 48 | "#define SAMPLECOUNT_D2 32 \n" |
|---|
| 49 | "#define SAMPLECOUNT_D2_FLOAT 32.0 \n" |
|---|
| 50 | "#define INV_SAMPLECOUNT (1.0 / SAMPLECOUNT_FLOAT) \n" |
|---|
| 51 | |
|---|
| 52 | "uniform sampler2DShadow osgShadow_shadowTexture; \n" |
|---|
| 53 | "uniform sampler3D osgShadow_jitterTexture; \n" |
|---|
| 54 | |
|---|
| 55 | "uniform vec2 osgShadow_ambientBias; \n" |
|---|
| 56 | "uniform float osgShadow_softnessWidth; \n" |
|---|
| 57 | "uniform float osgShadow_jitteringScale; \n" |
|---|
| 58 | |
|---|
| 59 | "void main(void) \n" |
|---|
| 60 | "{ \n" |
|---|
| 61 | " vec4 sceneShadowProj = gl_TexCoord[1]; \n" |
|---|
| 62 | " float softFactor = osgShadow_softnessWidth * sceneShadowProj.w; \n" |
|---|
| 63 | " vec4 smCoord = sceneShadowProj; \n" |
|---|
| 64 | " vec3 jitterCoord = vec3( gl_FragCoord.xy / osgShadow_jitteringScale, 0.0 ); \n" |
|---|
| 65 | " float shadow = 0.0; \n" |
|---|
| 66 | |
|---|
| 67 | " const float pass_div = 1.0 / (2.0 * 4.0); \n" |
|---|
| 68 | " for ( int i = 0; i < 4; ++i ) \n" |
|---|
| 69 | " { \n" |
|---|
| 70 | |
|---|
| 71 | " vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) -1.0; \n" |
|---|
| 72 | " jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n" |
|---|
| 73 | |
|---|
| 74 | " smCoord.xy = sceneShadowProj.xy + (offset.xy) * softFactor; \n" |
|---|
| 75 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * pass_div; \n" |
|---|
| 76 | |
|---|
| 77 | " smCoord.xy = sceneShadowProj.xy + (offset.zw) * softFactor; \n" |
|---|
| 78 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x *pass_div; \n" |
|---|
| 79 | " } \n" |
|---|
| 80 | |
|---|
| 81 | " if ( shadow * (shadow -1.0) != 0.0 ) \n" |
|---|
| 82 | " { \n" |
|---|
| 83 | " shadow *= pass_div; \n" |
|---|
| 84 | " for (int i=0; i<SAMPLECOUNT_D2 - 4; ++i){ \n" |
|---|
| 85 | " vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) - 1.0; \n" |
|---|
| 86 | " jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n" |
|---|
| 87 | |
|---|
| 88 | " smCoord.xy = sceneShadowProj.xy + offset.xy * softFactor; \n" |
|---|
| 89 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * INV_SAMPLECOUNT; \n" |
|---|
| 90 | |
|---|
| 91 | " smCoord.xy = sceneShadowProj.xy + offset.zw * softFactor; \n" |
|---|
| 92 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * INV_SAMPLECOUNT; \n" |
|---|
| 93 | " } \n" |
|---|
| 94 | " } \n" |
|---|
| 95 | |
|---|
| 96 | " gl_FragColor = gl_Color * (osgShadow_ambientBias.x + shadow * osgShadow_ambientBias.y); \n" |
|---|
| 97 | "} \n"; |
|---|
| 98 | |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | |
|---|
| 102 | |
|---|
| 103 | |
|---|
| 104 | static const char fragmentSoftShaderSource_withBaseTexture[] = |
|---|
| 105 | "#define SAMPLECOUNT 64 \n" |
|---|
| 106 | "#define SAMPLECOUNT_FLOAT 64.0 \n" |
|---|
| 107 | "#define SAMPLECOUNT_D2 32 \n" |
|---|
| 108 | "#define SAMPLECOUNT_D2_FLOAT 32.0 \n" |
|---|
| 109 | "#define INV_SAMPLECOUNT (1.0 / SAMPLECOUNT_FLOAT) \n" |
|---|
| 110 | |
|---|
| 111 | "uniform sampler2D osgShadow_baseTexture; \n" |
|---|
| 112 | "uniform sampler2DShadow osgShadow_shadowTexture; \n" |
|---|
| 113 | "uniform sampler3D osgShadow_jitterTexture; \n" |
|---|
| 114 | |
|---|
| 115 | "uniform vec2 osgShadow_ambientBias; \n" |
|---|
| 116 | "uniform float osgShadow_softnessWidth; \n" |
|---|
| 117 | "uniform float osgShadow_jitteringScale; \n" |
|---|
| 118 | |
|---|
| 119 | "void main(void) \n" |
|---|
| 120 | "{ \n" |
|---|
| 121 | " vec4 sceneShadowProj = gl_TexCoord[1]; \n" |
|---|
| 122 | " float softFactor = osgShadow_softnessWidth * sceneShadowProj.w; \n" |
|---|
| 123 | " vec4 smCoord = sceneShadowProj; \n" |
|---|
| 124 | " vec3 jitterCoord = vec3( gl_FragCoord.xy / osgShadow_jitteringScale, 0.0 ); \n" |
|---|
| 125 | " float shadow = 0.0; \n" |
|---|
| 126 | |
|---|
| 127 | " const float pass_div = 1.0 / (2.0 * 4.0); \n" |
|---|
| 128 | " for ( int i = 0; i < 4; ++i ) \n" |
|---|
| 129 | " { \n" |
|---|
| 130 | |
|---|
| 131 | " vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) -1.0; \n" |
|---|
| 132 | " jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n" |
|---|
| 133 | |
|---|
| 134 | " smCoord.xy = sceneShadowProj.xy + (offset.xy) * softFactor; \n" |
|---|
| 135 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * pass_div; \n" |
|---|
| 136 | |
|---|
| 137 | " smCoord.xy = sceneShadowProj.xy + (offset.zw) * softFactor; \n" |
|---|
| 138 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x *pass_div; \n" |
|---|
| 139 | " } \n" |
|---|
| 140 | |
|---|
| 141 | " if ( shadow * (shadow -1.0) != 0.0 ) \n" |
|---|
| 142 | " { \n" |
|---|
| 143 | " shadow *= pass_div; \n" |
|---|
| 144 | " for (int i=0; i<SAMPLECOUNT_D2 -4; ++i){ \n" |
|---|
| 145 | " vec4 offset = 2.0 * texture3D( osgShadow_jitterTexture, jitterCoord ) - 1.0; \n" |
|---|
| 146 | " jitterCoord.z += 1.0 / SAMPLECOUNT_D2_FLOAT; \n" |
|---|
| 147 | |
|---|
| 148 | " smCoord.xy = sceneShadowProj.xy + offset.xy * softFactor; \n" |
|---|
| 149 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * INV_SAMPLECOUNT; \n" |
|---|
| 150 | |
|---|
| 151 | " smCoord.xy = sceneShadowProj.xy + offset.zw * softFactor; \n" |
|---|
| 152 | " shadow += shadow2DProj( osgShadow_shadowTexture, smCoord ).x * INV_SAMPLECOUNT; \n" |
|---|
| 153 | " } \n" |
|---|
| 154 | " } \n" |
|---|
| 155 | |
|---|
| 156 | " vec4 color = gl_Color * texture2D( osgShadow_baseTexture, gl_TexCoord[0].xy ); \n" |
|---|
| 157 | |
|---|
| 158 | " gl_FragColor = color * (osgShadow_ambientBias.x + shadow * osgShadow_ambientBias.y); \n" |
|---|
| 159 | "} \n"; |
|---|
| 160 | |
|---|
| 161 | |
|---|
| 162 | |
|---|
| 163 | |
|---|
| 164 | |
|---|
| 165 | SoftShadowMap::SoftShadowMap(): |
|---|
| 166 | _softnessWidth(0.005f), |
|---|
| 167 | _jitteringScale(32.f), |
|---|
| 168 | _jitterTextureUnit(_shadowTextureUnit+1) |
|---|
| 169 | { |
|---|
| 170 | } |
|---|
| 171 | |
|---|
| 172 | SoftShadowMap::SoftShadowMap(const SoftShadowMap& copy, const osg::CopyOp& copyop): |
|---|
| 173 | ShadowMap(copy,copyop), |
|---|
| 174 | _softnessWidth(copy._softnessWidth), |
|---|
| 175 | _jitteringScale(copy._jitteringScale), |
|---|
| 176 | _jitterTextureUnit(copy._shadowTextureUnit) |
|---|
| 177 | { |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | void SoftShadowMap::setJitteringScale(const float jitteringScale) |
|---|
| 181 | { |
|---|
| 182 | _jitteringScale = jitteringScale; |
|---|
| 183 | if (_jitteringScaleUniform.valid()) _jitteringScaleUniform->set(_jitteringScale); |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | void SoftShadowMap::setSoftnessWidth(const float softnessWidth) |
|---|
| 187 | { |
|---|
| 188 | _softnessWidth = softnessWidth; |
|---|
| 189 | if (_softnessWidthUniform.valid()) _softnessWidthUniform->set(_softnessWidth); |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | void SoftShadowMap::setJitterTextureUnit(unsigned int jitterTextureUnit) |
|---|
| 193 | { |
|---|
| 194 | _jitterTextureUnit=jitterTextureUnit; |
|---|
| 195 | } |
|---|
| 196 | |
|---|
| 197 | void SoftShadowMap::createUniforms() |
|---|
| 198 | { |
|---|
| 199 | _uniformList.clear(); |
|---|
| 200 | |
|---|
| 201 | osg::Uniform* baseTextureSampler = new osg::Uniform("osgShadow_baseTexture",(int)_baseTextureUnit); |
|---|
| 202 | _uniformList.push_back(baseTextureSampler); |
|---|
| 203 | |
|---|
| 204 | osg::Uniform* shadowTextureSampler = new osg::Uniform("osgShadow_shadowTexture",(int)_shadowTextureUnit); |
|---|
| 205 | _uniformList.push_back(shadowTextureSampler); |
|---|
| 206 | |
|---|
| 207 | _ambientBiasUniform = new osg::Uniform("osgShadow_ambientBias",_ambientBias); |
|---|
| 208 | _uniformList.push_back(_ambientBiasUniform.get()); |
|---|
| 209 | |
|---|
| 210 | _softnessWidthUniform = new osg::Uniform("osgShadow_softnessWidth",_softnessWidth); |
|---|
| 211 | _uniformList.push_back(_softnessWidthUniform.get()); |
|---|
| 212 | |
|---|
| 213 | _jitteringScaleUniform = new osg::Uniform("osgShadow_jitteringScale",_jitteringScale); |
|---|
| 214 | _uniformList.push_back(_jitteringScaleUniform.get()); |
|---|
| 215 | |
|---|
| 216 | _jitterTextureUnit=_shadowTextureUnit+1; |
|---|
| 217 | initJittering(_stateset.get()); |
|---|
| 218 | |
|---|
| 219 | osg::Uniform* jitterTextureSampler = new osg::Uniform("osgShadow_jitterTexture",(int)_jitterTextureUnit); |
|---|
| 220 | _uniformList.push_back(jitterTextureSampler); |
|---|
| 221 | |
|---|
| 222 | |
|---|
| 223 | } |
|---|
| 224 | |
|---|
| 225 | void SoftShadowMap::createShaders() |
|---|
| 226 | { |
|---|
| 227 | |
|---|
| 228 | if( _shaderList.empty() ) |
|---|
| 229 | { |
|---|
| 230 | if (_shadowTextureUnit==0) |
|---|
| 231 | { |
|---|
| 232 | osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentSoftShaderSource_noBaseTexture); |
|---|
| 233 | _shaderList.push_back(fragment_shader); |
|---|
| 234 | } |
|---|
| 235 | else |
|---|
| 236 | { |
|---|
| 237 | osg::Shader* fragment_shader = new osg::Shader(osg::Shader::FRAGMENT, fragmentSoftShaderSource_withBaseTexture); |
|---|
| 238 | _shaderList.push_back(fragment_shader); |
|---|
| 239 | |
|---|
| 240 | } |
|---|
| 241 | } |
|---|
| 242 | } |
|---|
| 243 | |
|---|
| 244 | |
|---|
| 245 | |
|---|
| 246 | |
|---|
| 247 | |
|---|
| 248 | |
|---|
| 249 | void SoftShadowMap::initJittering(osg::StateSet *ss) |
|---|
| 250 | { |
|---|
| 251 | |
|---|
| 252 | osg::Texture3D* texture3D = new osg::Texture3D; |
|---|
| 253 | texture3D->setFilter(osg::Texture3D::MIN_FILTER,osg::Texture3D::NEAREST); |
|---|
| 254 | texture3D->setFilter(osg::Texture3D::MAG_FILTER,osg::Texture3D::NEAREST); |
|---|
| 255 | texture3D->setWrap(osg::Texture3D::WRAP_S,osg::Texture3D::REPEAT); |
|---|
| 256 | texture3D->setWrap(osg::Texture3D::WRAP_T,osg::Texture3D::REPEAT); |
|---|
| 257 | texture3D->setWrap(osg::Texture3D::WRAP_R,osg::Texture3D::REPEAT); |
|---|
| 258 | texture3D->setUseHardwareMipMapGeneration(true); |
|---|
| 259 | |
|---|
| 260 | const unsigned int size = 16; |
|---|
| 261 | const unsigned int gridW = 8; |
|---|
| 262 | const unsigned int gridH = 8; |
|---|
| 263 | unsigned int R = (gridW * gridH / 2); |
|---|
| 264 | texture3D->setTextureSize(size, size, R); |
|---|
| 265 | |
|---|
| 266 | |
|---|
| 267 | osg::Image* image3D = new osg::Image; |
|---|
| 268 | unsigned char *data3D = new unsigned char[size * size * R * 4]; |
|---|
| 269 | |
|---|
| 270 | for ( unsigned int s = 0; s < size; ++s ) |
|---|
| 271 | { |
|---|
| 272 | for ( unsigned int t = 0; t < size; ++t ) |
|---|
| 273 | { |
|---|
| 274 | float v[4], d[4]; |
|---|
| 275 | |
|---|
| 276 | for ( unsigned int r = 0; r < R; ++r ) |
|---|
| 277 | { |
|---|
| 278 | const int x = r % ( gridW / 2 ); |
|---|
| 279 | const int y = ( gridH - 1 ) - ( r / (gridW / 2) ); |
|---|
| 280 | |
|---|
| 281 | |
|---|
| 282 | |
|---|
| 283 | |
|---|
| 284 | |
|---|
| 285 | v[0] = float( x * 2 + 0.5f ) / gridW; |
|---|
| 286 | v[1] = float( y + 0.5f ) / gridH; |
|---|
| 287 | v[2] = float( x * 2 + 1 + 0.5f ) / gridW; |
|---|
| 288 | v[3] = v[1]; |
|---|
| 289 | |
|---|
| 290 | |
|---|
| 291 | v[0] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); |
|---|
| 292 | v[1] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); |
|---|
| 293 | v[2] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridW ); |
|---|
| 294 | v[3] += ((float)rand() * 2.f / RAND_MAX - 1.f) * ( 0.5f / gridH ); |
|---|
| 295 | |
|---|
| 296 | |
|---|
| 297 | d[0] = sqrtf( v[1] ) * cosf( 2.f * 3.1415926f * v[0] ); |
|---|
| 298 | d[1] = sqrtf( v[1] ) * sinf( 2.f * 3.1415926f * v[0] ); |
|---|
| 299 | d[2] = sqrtf( v[3] ) * cosf( 2.f * 3.1415926f * v[2] ); |
|---|
| 300 | d[3] = sqrtf( v[3] ) * sinf( 2.f * 3.1415926f * v[2] ); |
|---|
| 301 | |
|---|
| 302 | |
|---|
| 303 | const unsigned int tmp = ( (r * size * size) + (t * size) + s ) * 4; |
|---|
| 304 | data3D[ tmp + 0 ] = (unsigned char)( ( 1.f + d[0] ) * 127 ); |
|---|
| 305 | data3D[ tmp + 1 ] = (unsigned char)( ( 1.f + d[1] ) * 127 ); |
|---|
| 306 | data3D[ tmp + 2 ] = (unsigned char)( ( 1.f + d[2] ) * 127 ); |
|---|
| 307 | data3D[ tmp + 3 ] = (unsigned char)( ( 1.f + d[3] ) * 127 ); |
|---|
| 308 | |
|---|
| 309 | } |
|---|
| 310 | } |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | |
|---|
| 314 | |
|---|
| 315 | #ifdef GL_RGBA4 |
|---|
| 316 | GLenum internalTextureFormat = GL_RGBA4; |
|---|
| 317 | #else |
|---|
| 318 | |
|---|
| 319 | GLenum internalTextureFormat = GL_RGBA; |
|---|
| 320 | #endif |
|---|
| 321 | image3D->setImage(size, size, R, internalTextureFormat, GL_RGBA, GL_UNSIGNED_BYTE, data3D, osg::Image::USE_NEW_DELETE); |
|---|
| 322 | |
|---|
| 323 | texture3D->setImage(image3D); |
|---|
| 324 | |
|---|
| 325 | ss->setTextureAttributeAndModes(_jitterTextureUnit, texture3D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE); |
|---|
| 326 | ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_S,osg::StateAttribute::ON); |
|---|
| 327 | ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_T,osg::StateAttribute::ON); |
|---|
| 328 | ss->setTextureMode(_jitterTextureUnit,GL_TEXTURE_GEN_R,osg::StateAttribute::ON); |
|---|
| 329 | |
|---|
| 330 | } |
|---|