Browse Source

shadow caching

SPECIAL NOTE: highly suggest https://github.com/GarageGames/Torque3D/pull/1441 or a variation thereof to prevent debug spew and false-postives for occlusion results.

With significant research, development and prototyping assistance from both @andr3wmac (shaders and partial hook work), and @LuisAntonRebollo (additional culling)

System operates as follows:
1) materials are given an additional castDynamicShadows boolean entry. (Default at time of writing is true by request. Personal usage at time of writing defaults to false. value is default-initialized in materialDefinition.cpp. script/gui exposed)
2) lights are given a staticRefreshFreq and dynamicRefreshFreq (in milliseconds). script/gui exposed
3) materials are (effectively) sorted into dynamic and static shadowmap render lists based on flag. (see shadowMapPass.cpp)
4) initial shadowmaps are generated for each light and 'list'.
5) as each refreshFreq times out, the relevant shadowmap for a given light is refreshed.

Special notes:
dynamicRefreshFreq for all lights is set to a (script exposed) 8MS refresh timer.
StaticRefreshFreq for the lions share of lights defaults to 250 MS (1/4 of a second)
scattersky's embedded light, which is intended to operate in a mobile manner, defaults to 8
to reiterate, these are all customizable per-light via script/inspector gui in the case of alternate project needs.
Azaezel 10 years ago
parent
commit
2753f562e8
54 changed files with 1403 additions and 390 deletions
  1. 8 0
      Engine/source/T3D/lightBase.cpp
  2. 2 1
      Engine/source/T3D/lightBase.h
  3. 10 0
      Engine/source/T3D/lightDescription.cpp
  4. 2 0
      Engine/source/T3D/lightDescription.h
  5. 2 0
      Engine/source/T3D/pointLight.cpp
  6. 2 0
      Engine/source/T3D/spotLight.cpp
  7. 11 0
      Engine/source/environment/scatterSky.cpp
  8. 2 0
      Engine/source/environment/scatterSky.h
  9. 13 2
      Engine/source/environment/sun.cpp
  10. 2 0
      Engine/source/environment/sun.h
  11. 3 0
      Engine/source/forest/forestCell.cpp
  12. 4 0
      Engine/source/forest/forestRender.cpp
  13. 7 1
      Engine/source/lighting/advanced/advancedLightBinManager.cpp
  14. 1 0
      Engine/source/lighting/advanced/advancedLightBinManager.h
  15. 63 7
      Engine/source/lighting/advanced/advancedLightManager.cpp
  16. 4 0
      Engine/source/lighting/lightInfo.cpp
  17. 9 0
      Engine/source/lighting/lightInfo.h
  18. 89 31
      Engine/source/lighting/shadowMap/lightShadowMap.cpp
  19. 37 12
      Engine/source/lighting/shadowMap/lightShadowMap.h
  20. 139 6
      Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp
  21. 1 0
      Engine/source/lighting/shadowMap/pssmLightShadowMap.h
  22. 7 0
      Engine/source/lighting/shadowMap/shadowMapManager.cpp
  23. 3 0
      Engine/source/lighting/shadowMap/shadowMapManager.h
  24. 77 17
      Engine/source/lighting/shadowMap/shadowMapPass.cpp
  25. 17 0
      Engine/source/lighting/shadowMap/shadowMapPass.h
  26. 1 0
      Engine/source/materials/baseMaterialDefinition.h
  27. 5 1
      Engine/source/materials/materialDefinition.cpp
  28. 4 1
      Engine/source/materials/materialDefinition.h
  29. 8 0
      Engine/source/materials/processedCustomMaterial.cpp
  30. 8 0
      Engine/source/math/mPoint2.h
  31. 51 0
      Engine/source/math/mathUtils.cpp
  32. 3 0
      Engine/source/math/mathUtils.h
  33. 5 0
      Engine/source/scene/culling/sceneCullingState.cpp
  34. 18 0
      Engine/source/scene/culling/sceneCullingState.h
  35. 14 8
      Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs
  36. 18 4
      Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl
  37. 20 4
      Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl
  38. 138 64
      Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl
  39. 22 7
      Templates/Empty/game/shaders/common/lighting/advanced/pointLightP.hlsl
  40. 1 1
      Templates/Empty/game/shaders/common/lighting/advanced/softShadow.hlsl
  41. 22 6
      Templates/Empty/game/shaders/common/lighting/advanced/spotLightP.hlsl
  42. 138 64
      Templates/Empty/game/shaders/common/lighting/advanced/vectorLightP.hlsl
  43. 25 2
      Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  44. 1 0
      Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs
  45. 14 8
      Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs
  46. 14 1
      Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl
  47. 17 2
      Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl
  48. 138 64
      Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl
  49. 19 5
      Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl
  50. 1 1
      Templates/Full/game/shaders/common/lighting/advanced/softShadow.hlsl
  51. 19 4
      Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl
  52. 138 64
      Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl
  53. 25 2
      Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  54. 1 0
      Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs

+ 8 - 0
Engine/source/T3D/lightBase.cpp

@@ -60,6 +60,8 @@ LightBase::LightBase()
       mColor( ColorF::WHITE ),
       mColor( ColorF::WHITE ),
       mBrightness( 1.0f ),
       mBrightness( 1.0f ),
       mCastShadows( false ),
       mCastShadows( false ),
+      mStaticRefreshFreq( 250 ),
+      mDynamicRefreshFreq( 8 ),
       mPriority( 1.0f ),
       mPriority( 1.0f ),
       mAnimationData( NULL ),      
       mAnimationData( NULL ),      
       mFlareData( NULL ),
       mFlareData( NULL ),
@@ -90,6 +92,8 @@ void LightBase::initPersistFields()
       addField( "color", TypeColorF, Offset( mColor, LightBase ), "Changes the base color hue of the light." );
       addField( "color", TypeColorF, Offset( mColor, LightBase ), "Changes the base color hue of the light." );
       addField( "brightness", TypeF32, Offset( mBrightness, LightBase ), "Adjusts the lights power, 0 being off completely." );      
       addField( "brightness", TypeF32, Offset( mBrightness, LightBase ), "Adjusts the lights power, 0 being off completely." );      
       addField( "castShadows", TypeBool, Offset( mCastShadows, LightBase ), "Enables/disabled shadow casts by this light." );
       addField( "castShadows", TypeBool, Offset( mCastShadows, LightBase ), "Enables/disabled shadow casts by this light." );
+      addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightBase ), "static shadow refresh rate (milliseconds)" );
+      addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightBase ), "dynamic shadow refresh rate (milliseconds)" );
       addField( "priority", TypeF32, Offset( mPriority, LightBase ), "Used for sorting of lights by the light manager. "
       addField( "priority", TypeF32, Offset( mPriority, LightBase ), "Used for sorting of lights by the light manager. "
 		  "Priority determines if a light has a stronger effect than, those with a lower value" );
 		  "Priority determines if a light has a stronger effect than, those with a lower value" );
 
 
@@ -277,6 +281,8 @@ U32 LightBase::packUpdate( NetConnection *conn, U32 mask, BitStream *stream )
       stream->write( mBrightness );
       stream->write( mBrightness );
 
 
       stream->writeFlag( mCastShadows );
       stream->writeFlag( mCastShadows );
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
 
 
       stream->write( mPriority );      
       stream->write( mPriority );      
 
 
@@ -322,6 +328,8 @@ void LightBase::unpackUpdate( NetConnection *conn, BitStream *stream )
       stream->read( &mColor );
       stream->read( &mColor );
       stream->read( &mBrightness );      
       stream->read( &mBrightness );      
       mCastShadows = stream->readFlag();
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
 
 
       stream->read( &mPriority );      
       stream->read( &mPriority );      
       
       

+ 2 - 1
Engine/source/T3D/lightBase.h

@@ -56,7 +56,8 @@ protected:
    F32 mBrightness;
    F32 mBrightness;
 
 
    bool mCastShadows;
    bool mCastShadows;
-
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
    F32 mPriority;
    F32 mPriority;
 
 
    LightInfo *mLight;
    LightInfo *mLight;

+ 10 - 0
Engine/source/T3D/lightDescription.cpp

@@ -36,6 +36,8 @@ LightDescription::LightDescription()
    brightness( 1.0f ),
    brightness( 1.0f ),
    range( 5.0f ),
    range( 5.0f ),
    castShadows( false ),
    castShadows( false ),
+   mStaticRefreshFreq( 250 ),
+   mDynamicRefreshFreq( 8 ),
    animationData( NULL ),
    animationData( NULL ),
    animationDataId( 0 ),
    animationDataId( 0 ),
    animationPeriod( 1.0f ),
    animationPeriod( 1.0f ),
@@ -94,6 +96,8 @@ void LightDescription::initPersistFields()
       addField( "brightness", TypeF32, Offset( brightness, LightDescription ), "Adjusts the lights power, 0 being off completely." );      
       addField( "brightness", TypeF32, Offset( brightness, LightDescription ), "Adjusts the lights power, 0 being off completely." );      
       addField( "range", TypeF32, Offset( range, LightDescription ), "Controls the size (radius) of the light" );
       addField( "range", TypeF32, Offset( range, LightDescription ), "Controls the size (radius) of the light" );
       addField( "castShadows", TypeBool, Offset( castShadows, LightDescription ), "Enables/disabled shadow casts by this light." );
       addField( "castShadows", TypeBool, Offset( castShadows, LightDescription ), "Enables/disabled shadow casts by this light." );
+      addField( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightDescription ), "static shadow refresh rate (milliseconds)" );
+      addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightDescription ), "dynamic shadow refresh rate (milliseconds)" );
 
 
    endGroup( "Light" );
    endGroup( "Light" );
 
 
@@ -153,6 +157,8 @@ void LightDescription::packData( BitStream *stream )
    stream->write( brightness );
    stream->write( brightness );
    stream->write( range );
    stream->write( range );
    stream->writeFlag( castShadows );
    stream->writeFlag( castShadows );
+   stream->write(mStaticRefreshFreq);
+   stream->write(mDynamicRefreshFreq);
 
 
    stream->write( animationPeriod );
    stream->write( animationPeriod );
    stream->write( animationPhase );
    stream->write( animationPhase );
@@ -181,6 +187,8 @@ void LightDescription::unpackData( BitStream *stream )
    stream->read( &brightness );     
    stream->read( &brightness );     
    stream->read( &range );
    stream->read( &range );
    castShadows = stream->readFlag();
    castShadows = stream->readFlag();
+   stream->read(&mStaticRefreshFreq);
+   stream->read(&mDynamicRefreshFreq);
 
 
    stream->read( &animationPeriod );
    stream->read( &animationPeriod );
    stream->read( &animationPhase );
    stream->read( &animationPhase );
@@ -200,6 +208,8 @@ void LightDescription::submitLight( LightState *state, const MatrixF &xfm, Light
    li->setRange( range );
    li->setRange( range );
    li->setColor( color );
    li->setColor( color );
    li->setCastShadows( castShadows );
    li->setCastShadows( castShadows );
+   li->setStaticRefreshFreq(mStaticRefreshFreq);
+   li->setDynamicRefreshFreq(mDynamicRefreshFreq);
    li->setTransform( xfm );
    li->setTransform( xfm );
 
 
    if ( animationData )
    if ( animationData )

+ 2 - 0
Engine/source/T3D/lightDescription.h

@@ -101,6 +101,8 @@ public:
    F32 brightness;
    F32 brightness;
    F32 range;
    F32 range;
    bool castShadows;
    bool castShadows;
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
 
 
    LightAnimData *animationData;   
    LightAnimData *animationData;   
    S32 animationDataId;
    S32 animationDataId;

+ 2 - 0
Engine/source/T3D/pointLight.cpp

@@ -116,6 +116,8 @@ void PointLight::_conformLights()
 
 
    mLight->setBrightness( mBrightness );
    mLight->setBrightness( mBrightness );
    mLight->setCastShadows( mCastShadows );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
    mLight->setPriority( mPriority );
    mLight->setPriority( mPriority );
 
 
    // Update the bounds and scale to fit our light.
    // Update the bounds and scale to fit our light.

+ 2 - 0
Engine/source/T3D/spotLight.cpp

@@ -122,6 +122,8 @@ void SpotLight::_conformLights()
    mLight->setColor( mColor );
    mLight->setColor( mColor );
    mLight->setBrightness( mBrightness );
    mLight->setBrightness( mBrightness );
    mLight->setCastShadows( mCastShadows );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
    mLight->setPriority( mPriority );
    mLight->setPriority( mPriority );
 
 
    mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );
    mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );

+ 11 - 0
Engine/source/environment/scatterSky.cpp

@@ -151,6 +151,8 @@ ScatterSky::ScatterSky()
    mBrightness = 1.0f;
    mBrightness = 1.0f;
 
 
    mCastShadows = true;
    mCastShadows = true;
+   mStaticRefreshFreq = 8;
+   mDynamicRefreshFreq = 8;
    mDirty = true;
    mDirty = true;
 
 
    mLight = LightManager::createLightInfo();
    mLight = LightManager::createLightInfo();
@@ -271,6 +273,8 @@ void ScatterSky::_conformLights()
    mLight->setAmbient( mAmbientColor );
    mLight->setAmbient( mAmbientColor );
    mLight->setColor( mSunColor );
    mLight->setColor( mSunColor );
    mLight->setCastShadows( mCastShadows );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
 
 
    FogData fog = getSceneManager()->getFogData();
    FogData fog = getSceneManager()->getFogData();
    fog.color = mFogColor;
    fog.color = mFogColor;
@@ -381,6 +385,9 @@ void ScatterSky::initPersistFields()
       addField( "castShadows", TypeBool, Offset( mCastShadows, ScatterSky ),
       addField( "castShadows", TypeBool, Offset( mCastShadows, ScatterSky ),
          "Enables/disables shadows cast by objects due to ScatterSky light." );
          "Enables/disables shadows cast by objects due to ScatterSky light." );
 
 
+      addField("staticRefreshFreq", TypeS32, Offset(mStaticRefreshFreq, ScatterSky), "static shadow refresh rate (milliseconds)");
+      addField("dynamicRefreshFreq", TypeS32, Offset(mDynamicRefreshFreq, ScatterSky), "dynamic shadow refresh rate (milliseconds)");
+
       addField( "brightness", TypeF32, Offset( mBrightness, ScatterSky ),
       addField( "brightness", TypeF32, Offset( mBrightness, ScatterSky ),
          "The brightness of the ScatterSky's light object." );
          "The brightness of the ScatterSky's light object." );
 
 
@@ -487,6 +494,8 @@ U32 ScatterSky::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
       stream->write( mBrightness );
       stream->write( mBrightness );
 
 
       stream->writeFlag( mCastShadows );
       stream->writeFlag( mCastShadows );
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
 
 
       stream->write( mFlareScale );
       stream->write( mFlareScale );
 
 
@@ -588,6 +597,8 @@ void ScatterSky::unpackUpdate(NetConnection *con, BitStream *stream)
       stream->read( &mBrightness );
       stream->read( &mBrightness );
 
 
       mCastShadows = stream->readFlag();
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
 
 
       stream->read( &mFlareScale );
       stream->read( &mFlareScale );
 
 

+ 2 - 0
Engine/source/environment/scatterSky.h

@@ -207,6 +207,8 @@ protected:
    LightInfo *mLight;
    LightInfo *mLight;
 
 
    bool mCastShadows;
    bool mCastShadows;
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
    bool mDirty;
    bool mDirty;
 
 
    LightFlareData *mFlareData;
    LightFlareData *mFlareData;

+ 13 - 2
Engine/source/environment/sun.cpp

@@ -66,6 +66,8 @@ Sun::Sun()
    mSunAzimuth = 0.0f;
    mSunAzimuth = 0.0f;
    mSunElevation = 35.0f;
    mSunElevation = 35.0f;
    mCastShadows = true;
    mCastShadows = true;
+   mStaticRefreshFreq = 250;
+   mDynamicRefreshFreq = 8;
 
 
    mAnimateSun = false;
    mAnimateSun = false;
    mTotalTime = 0.0f;
    mTotalTime = 0.0f;
@@ -163,7 +165,10 @@ void Sun::initPersistFields()
          "Adjust the Sun's global contrast/intensity");      
          "Adjust the Sun's global contrast/intensity");      
 
 
       addField( "castShadows", TypeBool, Offset( mCastShadows, Sun ), 
       addField( "castShadows", TypeBool, Offset( mCastShadows, Sun ), 
-         "Enables/disables shadows cast by objects due to Sun light");      
+         "Enables/disables shadows cast by objects due to Sun light");    
+
+      addField("staticRefreshFreq", TypeS32, Offset(mStaticRefreshFreq, Sun), "static shadow refresh rate (milliseconds)");
+      addField("dynamicRefreshFreq", TypeS32, Offset(mDynamicRefreshFreq, Sun), "dynamic shadow refresh rate (milliseconds)");
 
 
    endGroup( "Lighting" );
    endGroup( "Lighting" );
 
 
@@ -220,7 +225,9 @@ U32 Sun::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
       stream->write( mLightColor );
       stream->write( mLightColor );
       stream->write( mLightAmbient );
       stream->write( mLightAmbient );
       stream->write( mBrightness );      
       stream->write( mBrightness );      
-      stream->writeFlag( mCastShadows );
+      stream->writeFlag( mCastShadows ); 
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
       stream->write( mFlareScale );
       stream->write( mFlareScale );
 
 
       if ( stream->writeFlag( mFlareData ) )
       if ( stream->writeFlag( mFlareData ) )
@@ -254,6 +261,8 @@ void Sun::unpackUpdate( NetConnection *conn, BitStream *stream )
       stream->read( &mLightAmbient );
       stream->read( &mLightAmbient );
       stream->read( &mBrightness );      
       stream->read( &mBrightness );      
       mCastShadows = stream->readFlag();
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
       stream->read( &mFlareScale );
       stream->read( &mFlareScale );
 
 
       if ( stream->readFlag() )
       if ( stream->readFlag() )
@@ -426,6 +435,8 @@ void Sun::_conformLights()
    // directional color are the same.
    // directional color are the same.
    bool castShadows = mLightColor != mLightAmbient && mCastShadows; 
    bool castShadows = mLightColor != mLightAmbient && mCastShadows; 
    mLight->setCastShadows( castShadows );
    mLight->setCastShadows( castShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
 }
 }
 
 
 void Sun::_initCorona()
 void Sun::_initCorona()

+ 2 - 0
Engine/source/environment/sun.h

@@ -65,6 +65,8 @@ protected:
    F32  mEndElevation;
    F32  mEndElevation;
 
 
    bool mCastShadows;
    bool mCastShadows;
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
 
 
    LightInfo *mLight;
    LightInfo *mLight;
 
 

+ 3 - 0
Engine/source/forest/forestCell.cpp

@@ -118,6 +118,9 @@ S32 ForestCell::renderBatches( SceneRenderState *state, Frustum *culler )
       if ( culler && culler->isCulled( mBatches[i]->getWorldBox() ) )
       if ( culler && culler->isCulled( mBatches[i]->getWorldBox() ) )
          continue;
          continue;
 
 
+      if( state->getCullingState().isOccludedWithExtraPlanesCull( mBatches[i]->getWorldBox() ) )
+         continue;
+
       mBatches[i]->render( state );
       mBatches[i]->render( state );
       renderedItems += mBatches[i]->getItemCount();
       renderedItems += mBatches[i]->getItemCount();
    }
    }

+ 4 - 0
Engine/source/forest/forestRender.cpp

@@ -197,6 +197,10 @@ void Forest::prepRenderImage( SceneRenderState *state )
          if ( smDisableImposters )
          if ( smDisableImposters )
             continue;
             continue;
 
 
+         // if cell are to far for largest item, then skip out.
+         if( TSShapeInstance::smLastPixelSize < TSShapeInstance::smSmallestVisiblePixelSize )
+            continue;
+
          PROFILE_SCOPE(Forest_RenderBatches);
          PROFILE_SCOPE(Forest_RenderBatches);
 
 
          // Keep track of how many cells were batched.
          // Keep track of how many cells were batched.

+ 7 - 1
Engine/source/lighting/advanced/advancedLightBinManager.cpp

@@ -191,10 +191,11 @@ void AdvancedLightBinManager::addLight( LightInfo *light )
    // Find a shadow map for this light, if it has one
    // Find a shadow map for this light, if it has one
    ShadowMapParams *lsp = light->getExtended<ShadowMapParams>();
    ShadowMapParams *lsp = light->getExtended<ShadowMapParams>();
    LightShadowMap *lsm = lsp->getShadowMap();
    LightShadowMap *lsm = lsp->getShadowMap();
+   LightShadowMap *dynamicShadowMap = lsp->getShadowMap(true);
 
 
    // Get the right shadow type.
    // Get the right shadow type.
    ShadowType shadowType = ShadowType_None;
    ShadowType shadowType = ShadowType_None;
-   if (  light->getCastShadows() && 
+   if (  light->getCastShadows() &&  
          lsm && lsm->hasShadowTex() &&
          lsm && lsm->hasShadowTex() &&
          !ShadowMapPass::smDisableShadows )
          !ShadowMapPass::smDisableShadows )
       shadowType = lsm->getShadowType();
       shadowType = lsm->getShadowType();
@@ -203,6 +204,7 @@ void AdvancedLightBinManager::addLight( LightInfo *light )
    LightBinEntry lEntry;
    LightBinEntry lEntry;
    lEntry.lightInfo = light;
    lEntry.lightInfo = light;
    lEntry.shadowMap = lsm;
    lEntry.shadowMap = lsm;
+   lEntry.dynamicShadowMap = dynamicShadowMap;
    lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex() );
    lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex() );
 
 
    if( lightType == LightInfo::Spot )
    if( lightType == LightInfo::Spot )
@@ -325,10 +327,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
       setupSGData( sgData, state, curLightInfo );
       setupSGData( sgData, state, curLightInfo );
       curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
       curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
       mShadowManager->setLightShadowMap( curEntry.shadowMap );
       mShadowManager->setLightShadowMap( curEntry.shadowMap );
+      mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap );
 
 
       // Let the shadow know we're about to render from it.
       // Let the shadow know we're about to render from it.
       if ( curEntry.shadowMap )
       if ( curEntry.shadowMap )
          curEntry.shadowMap->preLightRender();
          curEntry.shadowMap->preLightRender();
+      if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->preLightRender();
 
 
       // Set geometry
       // Set geometry
       GFX->setVertexBuffer( curEntry.vertBuffer );
       GFX->setVertexBuffer( curEntry.vertBuffer );
@@ -351,10 +355,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
       // Tell it we're done rendering.
       // Tell it we're done rendering.
       if ( curEntry.shadowMap )
       if ( curEntry.shadowMap )
          curEntry.shadowMap->postLightRender();
          curEntry.shadowMap->postLightRender();
+      if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->postLightRender();
    }
    }
 
 
    // Set NULL for active shadow map (so nothing gets confused)
    // Set NULL for active shadow map (so nothing gets confused)
    mShadowManager->setLightShadowMap(NULL);
    mShadowManager->setLightShadowMap(NULL);
+   mShadowManager->setLightDynamicShadowMap(NULL);
    GFX->setVertexBuffer( NULL );
    GFX->setVertexBuffer( NULL );
    GFX->setPrimitiveBuffer( NULL );
    GFX->setPrimitiveBuffer( NULL );
 
 

+ 1 - 0
Engine/source/lighting/advanced/advancedLightBinManager.h

@@ -185,6 +185,7 @@ protected:
    {
    {
       LightInfo* lightInfo;
       LightInfo* lightInfo;
       LightShadowMap* shadowMap;
       LightShadowMap* shadowMap;
+      LightShadowMap* dynamicShadowMap;
       LightMaterialInfo* lightMaterial;
       LightMaterialInfo* lightMaterial;
       GFXPrimitiveBuffer* primBuffer;
       GFXPrimitiveBuffer* primBuffer;
       GFXVertexBuffer* vertBuffer;
       GFXVertexBuffer* vertBuffer;

+ 63 - 7
Engine/source/lighting/advanced/advancedLightManager.cpp

@@ -357,10 +357,13 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
    LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);
    LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);
 
 
    LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();
    LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();
+   LightShadowMap *dynamicShadowMap = SHADOWMGR->getCurrentDynamicShadowMap();
 
 
    LightInfo *light;
    LightInfo *light;
-   if ( lsm )
+   if (lsm)
       light = lsm->getLightInfo();
       light = lsm->getLightInfo();
+   else if ( dynamicShadowMap )
+      light = dynamicShadowMap->getLightInfo();
    else
    else
    {
    {
       light = sgData.lights[0];
       light = sgData.lights[0];
@@ -385,10 +388,11 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
                         lsc->mLightInvRadiusSqSC,
                         lsc->mLightInvRadiusSqSC,
                         lsc->mLightSpotDirSC,
                         lsc->mLightSpotDirSC,
                         lsc->mLightSpotAngleSC,
                         lsc->mLightSpotAngleSC,
-						lsc->mLightSpotFalloffSC,
+                        lsc->mLightSpotFalloffSC,
                         shaderConsts );
                         shaderConsts );
 
 
-   if ( lsm && light->getCastShadows() )
+   // Static
+   if (lsm && light->getCastShadows())
    {
    {
       if (  lsc->mWorldToLightProjSC->isValid() )
       if (  lsc->mWorldToLightProjSC->isValid() )
          shaderConsts->set(   lsc->mWorldToLightProjSC, 
          shaderConsts->set(   lsc->mWorldToLightProjSC, 
@@ -426,6 +430,46 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
                               lsc->mViewToLightProjSC->getType() );
                               lsc->mViewToLightProjSC->getType() );
       }
       }
    }
    }
+
+   // Dynamic
+   if ( dynamicShadowMap )
+   {
+      if (  lsc->mDynamicWorldToLightProjSC->isValid() )
+         shaderConsts->set(   lsc->mDynamicWorldToLightProjSC, 
+                              dynamicShadowMap->getWorldToLightProj(), 
+                              lsc->mDynamicWorldToLightProjSC->getType() );
+
+      if (  lsc->mDynamicViewToLightProjSC->isValid() )
+      {
+         // TODO: Should probably cache these results and 
+         // not do this mul here on every material that needs
+         // this transform.
+
+         shaderConsts->set(   lsc->mDynamicViewToLightProjSC, 
+                              dynamicShadowMap->getWorldToLightProj() * state->getCameraTransform(), 
+                              lsc->mDynamicViewToLightProjSC->getType() );
+      }
+
+      shaderConsts->setSafe( lsc->mShadowMapSizeSC, 1.0f / (F32)dynamicShadowMap->getTexSize() );
+
+      // Do this last so that overrides can properly override parameters previously set
+      dynamicShadowMap->setShaderParameters(shaderConsts, lsc);
+   }   
+   else
+   {
+      if ( lsc->mDynamicViewToLightProjSC->isValid() )
+      {
+         // TODO: Should probably cache these results and 
+         // not do this mul here on every material that needs
+         // this transform.
+         MatrixF proj;
+         light->getWorldToLightProj( &proj );
+
+         shaderConsts->set(   lsc->mDynamicViewToLightProjSC, 
+                              proj * state->getCameraTransform(), 
+                              lsc->mDynamicViewToLightProjSC->getType() );
+      }
+   }
 }
 }
 
 
 void AdvancedLightManager::registerGlobalLight(LightInfo *light, SimObject *obj)
 void AdvancedLightManager::registerGlobalLight(LightInfo *light, SimObject *obj)
@@ -454,22 +498,34 @@ bool AdvancedLightManager::setTextureStage(  const SceneData &sgData,
                                              ShaderConstHandles *handles )
                                              ShaderConstHandles *handles )
 {
 {
    LightShadowMap* lsm = SHADOWMGR->getCurrentShadowMap();
    LightShadowMap* lsm = SHADOWMGR->getCurrentShadowMap();
+   LightShadowMap* dynamicShadowMap = SHADOWMGR->getCurrentDynamicShadowMap();
 
 
    // Assign Shadowmap, if it exists
    // Assign Shadowmap, if it exists
    LightingShaderConstants* lsc = getLightingShaderConstants(shaderConsts);
    LightingShaderConstants* lsc = getLightingShaderConstants(shaderConsts);
    if ( !lsc )
    if ( !lsc )
       return false;
       return false;
 
 
-   if ( lsm && lsm->getLightInfo()->getCastShadows() )
-      return lsm->setTextureStage( currTexFlag, lsc );
-
-
    if ( currTexFlag == Material::DynamicLight )
    if ( currTexFlag == Material::DynamicLight )
    {
    {
+      // Static
+      if ( lsm && lsm->getLightInfo()->getCastShadows() )
+         return lsm->setTextureStage( currTexFlag, lsc );
+
       S32 reg = lsc->mShadowMapSC->getSamplerRegister();
       S32 reg = lsc->mShadowMapSC->getSamplerRegister();
    	if ( reg != -1 )
    	if ( reg != -1 )
       	GFX->setTexture( reg, GFXTexHandle::ONE );
       	GFX->setTexture( reg, GFXTexHandle::ONE );
 
 
+      return true;
+   } else if ( currTexFlag == Material::DynamicShadowMap )
+   {
+      // Dynamic
+      if ( dynamicShadowMap )
+         return dynamicShadowMap->setTextureStage( currTexFlag, lsc );
+
+      S32 reg = lsc->mDynamicShadowMapSC->getSamplerRegister();
+   	if ( reg != -1 )
+      	GFX->setTexture( reg, GFXTexHandle::ONE );
+
       return true;
       return true;
    }
    }
    else if ( currTexFlag == Material::DynamicLightMask )
    else if ( currTexFlag == Material::DynamicLightMask )

+ 4 - 0
Engine/source/lighting/lightInfo.cpp

@@ -50,6 +50,8 @@ LightInfo::LightInfo()
       mOuterConeAngle( 90.0f ),
       mOuterConeAngle( 90.0f ),
       mType( Vector ),
       mType( Vector ),
       mCastShadows( false ),
       mCastShadows( false ),
+      mStaticRefreshFreq( 250 ),
+      mDynamicRefreshFreq( 8 ),
       mPriority( 1.0f ),
       mPriority( 1.0f ),
       mScore( 0.0f ),
       mScore( 0.0f ),
       mDebugRender( false )
       mDebugRender( false )
@@ -72,6 +74,8 @@ void LightInfo::set( const LightInfo *light )
    mOuterConeAngle = light->mOuterConeAngle;
    mOuterConeAngle = light->mOuterConeAngle;
    mType = light->mType;
    mType = light->mType;
    mCastShadows = light->mCastShadows;
    mCastShadows = light->mCastShadows;
+   mStaticRefreshFreq = light->mStaticRefreshFreq;
+   mDynamicRefreshFreq = light->mDynamicRefreshFreq;
 
 
    for ( U32 i=0; i < mExtended.size(); i++ )
    for ( U32 i=0; i < mExtended.size(); i++ )
    {
    {

+ 9 - 0
Engine/source/lighting/lightInfo.h

@@ -131,6 +131,9 @@ protected:
 
 
    bool mCastShadows;
    bool mCastShadows;
 
 
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
+
    ::Vector<LightInfoEx*> mExtended;
    ::Vector<LightInfoEx*> mExtended;
 
 
    /// The priority of this light used for
    /// The priority of this light used for
@@ -190,6 +193,12 @@ public:
 
 
    bool getCastShadows() const { return mCastShadows; }
    bool getCastShadows() const { return mCastShadows; }
    void setCastShadows( bool castShadows ) { mCastShadows = castShadows; }
    void setCastShadows( bool castShadows ) { mCastShadows = castShadows; }
+   
+   S32 getStaticRefreshFreq() const { return mStaticRefreshFreq; }
+   void setStaticRefreshFreq(S32 _staticRefreshFreq) { mStaticRefreshFreq = _staticRefreshFreq; }
+
+   S32 getDynamicRefreshFreq() const { return mDynamicRefreshFreq; }
+   void setDynamicRefreshFreq(S32 _dynamicRefreshFreq) { mDynamicRefreshFreq = _dynamicRefreshFreq; }
 
 
    void setPriority( F32 priority ) { mPriority = priority; }
    void setPriority( F32 priority ) { mPriority = priority; }
    F32 getPriority() const { return mPriority; }
    F32 getPriority() const { return mPriority; }

+ 89 - 31
Engine/source/lighting/shadowMap/lightShadowMap.cpp

@@ -92,14 +92,17 @@ LightShadowMap::LightShadowMap( LightInfo *light )
       mVizQuery( NULL ),
       mVizQuery( NULL ),
       mWasOccluded( false ),
       mWasOccluded( false ),
       mLastScreenSize( 0.0f ),
       mLastScreenSize( 0.0f ),
-      mLastPriority( 0.0f )
+      mLastPriority( 0.0f ),
+      mIsDynamic( false )
 {
 {
    GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent );
    GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent );
 
 
    mTarget = GFX->allocRenderToTextureTarget();
    mTarget = GFX->allocRenderToTextureTarget();
    mVizQuery = GFX->createOcclusionQuery();
    mVizQuery = GFX->createOcclusionQuery();
 
 
-   smShadowMaps.push_back( this );
+   smShadowMaps.push_back(this);
+   mStaticRefreshTimer = PlatformTimer::create();
+   mDynamicRefreshTimer = PlatformTimer::create();
 }
 }
 
 
 LightShadowMap::~LightShadowMap()
 LightShadowMap::~LightShadowMap()
@@ -268,11 +271,20 @@ GFXTextureObject* LightShadowMap::_getDepthTarget( U32 width, U32 height )
 
 
 bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants* lsc )
 bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants* lsc )
 {
 {
-   if ( currTexFlag == Material::DynamicLight )
+   if ( currTexFlag == Material::DynamicLight && !isDynamic() )
    {
    {
       S32 reg = lsc->mShadowMapSC->getSamplerRegister();
       S32 reg = lsc->mShadowMapSC->getSamplerRegister();
-   	if ( reg != -1 )
-      	GFX->setTexture( reg, mShadowMapTex);
+
+      if ( reg != -1 )
+         GFX->setTexture( reg, mShadowMapTex);
+
+      return true;
+   } else if ( currTexFlag == Material::DynamicShadowMap && isDynamic() )
+   {
+      S32 reg = lsc->mDynamicShadowMapSC->getSamplerRegister();
+
+      if ( reg != -1 )
+         GFX->setTexture( reg, mShadowMapTex);
 
 
       return true;
       return true;
    }
    }
@@ -296,8 +308,18 @@ bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants*
 }
 }
 
 
 void LightShadowMap::render(  RenderPassManager* renderPass,
 void LightShadowMap::render(  RenderPassManager* renderPass,
-                              const SceneRenderState *diffuseState )
+                              const SceneRenderState *diffuseState,
+                              bool _dynamic)
 {
 {
+    //  control how often shadow maps are refreshed
+    if (!_dynamic && (mStaticRefreshTimer->getElapsedMs() < getLightInfo()->getStaticRefreshFreq()))
+        return;
+    mStaticRefreshTimer->reset();
+
+    if (_dynamic && (mDynamicRefreshTimer->getElapsedMs() < getLightInfo()->getDynamicRefreshFreq()))
+        return;
+    mDynamicRefreshTimer->reset();
+
    mDebugTarget.setTexture( NULL );
    mDebugTarget.setTexture( NULL );
    _render( renderPass, diffuseState );
    _render( renderPass, diffuseState );
    mDebugTarget.setTexture( mShadowMapTex );
    mDebugTarget.setTexture( mShadowMapTex );
@@ -456,25 +478,35 @@ LightingShaderConstants::LightingShaderConstants()
       mLightInvRadiusSqSC(NULL),
       mLightInvRadiusSqSC(NULL),
       mLightSpotDirSC(NULL),
       mLightSpotDirSC(NULL),
       mLightSpotAngleSC(NULL),
       mLightSpotAngleSC(NULL),
-	  mLightSpotFalloffSC(NULL),
+      mLightSpotFalloffSC(NULL),
       mShadowMapSC(NULL), 
       mShadowMapSC(NULL), 
+      mDynamicShadowMapSC(NULL), 
       mShadowMapSizeSC(NULL), 
       mShadowMapSizeSC(NULL), 
       mCookieMapSC(NULL),
       mCookieMapSC(NULL),
       mRandomDirsConst(NULL),
       mRandomDirsConst(NULL),
       mShadowSoftnessConst(NULL), 
       mShadowSoftnessConst(NULL), 
+      mAtlasXOffsetSC(NULL), 
+      mAtlasYOffsetSC(NULL),
+      mAtlasScaleSC(NULL), 
+      mFadeStartLength(NULL), 
+      mOverDarkFactorPSSM(NULL), 
+      mTapRotationTexSC(NULL),
+
       mWorldToLightProjSC(NULL), 
       mWorldToLightProjSC(NULL), 
       mViewToLightProjSC(NULL),
       mViewToLightProjSC(NULL),
       mScaleXSC(NULL), 
       mScaleXSC(NULL), 
       mScaleYSC(NULL),
       mScaleYSC(NULL),
       mOffsetXSC(NULL), 
       mOffsetXSC(NULL), 
       mOffsetYSC(NULL), 
       mOffsetYSC(NULL), 
-      mAtlasXOffsetSC(NULL), 
-      mAtlasYOffsetSC(NULL),
-      mAtlasScaleSC(NULL), 
-      mFadeStartLength(NULL), 
       mFarPlaneScalePSSM(NULL),
       mFarPlaneScalePSSM(NULL),
-      mOverDarkFactorPSSM(NULL), 
-      mTapRotationTexSC(NULL)
+
+      mDynamicWorldToLightProjSC(NULL),
+      mDynamicViewToLightProjSC(NULL),
+      mDynamicScaleXSC(NULL),
+      mDynamicScaleYSC(NULL),
+      mDynamicOffsetXSC(NULL),
+      mDynamicOffsetYSC(NULL),
+      mDynamicFarPlaneScalePSSM(NULL)
 {
 {
 }
 }
 
 
@@ -513,29 +545,35 @@ void LightingShaderConstants::init(GFXShader* shader)
    mLightSpotFalloffSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotFalloff );
    mLightSpotFalloffSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotFalloff );
 
 
    mShadowMapSC = shader->getShaderConstHandle("$shadowMap");
    mShadowMapSC = shader->getShaderConstHandle("$shadowMap");
+   mDynamicShadowMapSC = shader->getShaderConstHandle("$dynamicShadowMap");
    mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize");
    mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize");
 
 
    mCookieMapSC = shader->getShaderConstHandle("$cookieMap");
    mCookieMapSC = shader->getShaderConstHandle("$cookieMap");
 
 
    mShadowSoftnessConst = shader->getShaderConstHandle("$shadowSoftness");
    mShadowSoftnessConst = shader->getShaderConstHandle("$shadowSoftness");
+   mAtlasXOffsetSC = shader->getShaderConstHandle("$atlasXOffset");
+   mAtlasYOffsetSC = shader->getShaderConstHandle("$atlasYOffset");
+   mAtlasScaleSC = shader->getShaderConstHandle("$atlasScale");
+
+   mFadeStartLength = shader->getShaderConstHandle("$fadeStartLength");
+   mOverDarkFactorPSSM = shader->getShaderConstHandle("$overDarkPSSM");
+   mTapRotationTexSC = shader->getShaderConstHandle( "$gTapRotationTex" );
 
 
    mWorldToLightProjSC = shader->getShaderConstHandle("$worldToLightProj");
    mWorldToLightProjSC = shader->getShaderConstHandle("$worldToLightProj");
    mViewToLightProjSC = shader->getShaderConstHandle("$viewToLightProj");
    mViewToLightProjSC = shader->getShaderConstHandle("$viewToLightProj");
-
    mScaleXSC = shader->getShaderConstHandle("$scaleX");
    mScaleXSC = shader->getShaderConstHandle("$scaleX");
    mScaleYSC = shader->getShaderConstHandle("$scaleY");
    mScaleYSC = shader->getShaderConstHandle("$scaleY");
    mOffsetXSC = shader->getShaderConstHandle("$offsetX");
    mOffsetXSC = shader->getShaderConstHandle("$offsetX");
    mOffsetYSC = shader->getShaderConstHandle("$offsetY");
    mOffsetYSC = shader->getShaderConstHandle("$offsetY");
-   mAtlasXOffsetSC = shader->getShaderConstHandle("$atlasXOffset");
-   mAtlasYOffsetSC = shader->getShaderConstHandle("$atlasYOffset");
-   mAtlasScaleSC = shader->getShaderConstHandle("$atlasScale");
-
-   mFadeStartLength = shader->getShaderConstHandle("$fadeStartLength");
    mFarPlaneScalePSSM = shader->getShaderConstHandle("$farPlaneScalePSSM");
    mFarPlaneScalePSSM = shader->getShaderConstHandle("$farPlaneScalePSSM");
 
 
-   mOverDarkFactorPSSM = shader->getShaderConstHandle("$overDarkPSSM");
-
-   mTapRotationTexSC = shader->getShaderConstHandle( "$gTapRotationTex" );
+   mDynamicWorldToLightProjSC = shader->getShaderConstHandle("$dynamicWorldToLightProj");
+   mDynamicViewToLightProjSC = shader->getShaderConstHandle("$dynamicViewToLightProj");
+   mDynamicScaleXSC = shader->getShaderConstHandle("$dynamicScaleX");
+   mDynamicScaleYSC = shader->getShaderConstHandle("$dynamicScaleY");
+   mDynamicOffsetXSC = shader->getShaderConstHandle("$dynamicOffsetX");
+   mDynamicOffsetYSC = shader->getShaderConstHandle("$dynamicOffsetY");
+   mDynamicFarPlaneScalePSSM = shader->getShaderConstHandle("$dynamicFarPlaneScalePSSM");
 
 
    mInit = true;
    mInit = true;
 }
 }
@@ -558,7 +596,9 @@ LightInfoExType ShadowMapParams::Type( "" );
 
 
 ShadowMapParams::ShadowMapParams( LightInfo *light ) 
 ShadowMapParams::ShadowMapParams( LightInfo *light ) 
    :  mLight( light ),
    :  mLight( light ),
-      mShadowMap( NULL )
+      mShadowMap( NULL ),
+      mDynamicShadowMap ( NULL ),
+      isDynamic ( true )
 {
 {
    attenuationRatio.set( 0.0f, 1.0f, 1.0f );
    attenuationRatio.set( 0.0f, 1.0f, 1.0f );
    shadowType = ShadowType_Spot;
    shadowType = ShadowType_Spot;
@@ -576,6 +616,7 @@ ShadowMapParams::ShadowMapParams( LightInfo *light )
 ShadowMapParams::~ShadowMapParams()
 ShadowMapParams::~ShadowMapParams()
 {
 {
    SAFE_DELETE( mShadowMap );
    SAFE_DELETE( mShadowMap );
+   SAFE_DELETE( mDynamicShadowMap );
 }
 }
 
 
 void ShadowMapParams::_validate()
 void ShadowMapParams::_validate()
@@ -632,39 +673,55 @@ void ShadowMapParams::_validate()
    texSize = mClamp( texSize, 32, maxTexSize );
    texSize = mClamp( texSize, 32, maxTexSize );
 }
 }
 
 
-LightShadowMap* ShadowMapParams::getOrCreateShadowMap()
+LightShadowMap* ShadowMapParams::getOrCreateShadowMap(bool _isDynamic)
 {
 {
-   if ( mShadowMap )
+	if (_isDynamic && mDynamicShadowMap)
+		return mDynamicShadowMap;
+
+	if (!_isDynamic && mShadowMap)
       return mShadowMap;
       return mShadowMap;
 
 
    if ( !mLight->getCastShadows() )
    if ( !mLight->getCastShadows() )
       return NULL;
       return NULL;
 
 
+   LightShadowMap* newShadowMap = NULL;
+
    switch ( mLight->getType() )
    switch ( mLight->getType() )
    {
    {
       case LightInfo::Spot:
       case LightInfo::Spot:
-         mShadowMap = new SingleLightShadowMap( mLight );
+         newShadowMap = new SingleLightShadowMap( mLight );
          break;
          break;
 
 
       case LightInfo::Vector:
       case LightInfo::Vector:
-         mShadowMap = new PSSMLightShadowMap( mLight );
+         newShadowMap = new PSSMLightShadowMap( mLight );
          break;
          break;
 
 
       case LightInfo::Point:
       case LightInfo::Point:
 
 
          if ( shadowType == ShadowType_CubeMap )
          if ( shadowType == ShadowType_CubeMap )
-            mShadowMap = new CubeLightShadowMap( mLight );
+            newShadowMap = new CubeLightShadowMap( mLight );
          else if ( shadowType == ShadowType_Paraboloid )
          else if ( shadowType == ShadowType_Paraboloid )
-            mShadowMap = new ParaboloidLightShadowMap( mLight );
+            newShadowMap = new ParaboloidLightShadowMap( mLight );
          else
          else
-            mShadowMap = new DualParaboloidLightShadowMap( mLight );
+            newShadowMap = new DualParaboloidLightShadowMap( mLight );
          break;
          break;
    
    
       default:
       default:
          break;
          break;
    }
    }
 
 
-   return mShadowMap;
+   if ( _isDynamic )
+   {
+      newShadowMap->setDynamic( true );
+      mDynamicShadowMap = newShadowMap;
+      return mDynamicShadowMap;
+   }
+   else
+   {
+      newShadowMap->setDynamic(false);
+      mShadowMap = newShadowMap;
+      return mShadowMap;
+   }
 }
 }
 
 
 GFXTextureObject* ShadowMapParams::getCookieTex()
 GFXTextureObject* ShadowMapParams::getCookieTex()
@@ -739,6 +796,7 @@ void ShadowMapParams::unpackUpdate( BitStream *stream )
       // map so it can be reallocated on the next render.
       // map so it can be reallocated on the next render.
       shadowType = newType;
       shadowType = newType;
       SAFE_DELETE( mShadowMap );
       SAFE_DELETE( mShadowMap );
+      SAFE_DELETE( mDynamicShadowMap );
    }
    }
 
 
    mathRead( *stream, &attenuationRatio );
    mathRead( *stream, &attenuationRatio );

+ 37 - 12
Engine/source/lighting/shadowMap/lightShadowMap.h

@@ -47,6 +47,9 @@
 #ifndef _GFXSHADER_H_
 #ifndef _GFXSHADER_H_
 #include "gfx/gfxShader.h"
 #include "gfx/gfxShader.h"
 #endif
 #endif
+#ifndef _PLATFORM_PLATFORMTIMER_H_
+#include "platform/platformTimer.h"
+#endif
 
 
 class ShadowMapManager;
 class ShadowMapManager;
 class SceneManager;
 class SceneManager;
@@ -88,20 +91,13 @@ struct LightingShaderConstants
    GFXShaderConstHandle *mLightSpotFalloffSC;
    GFXShaderConstHandle *mLightSpotFalloffSC;
 
 
    GFXShaderConstHandle* mShadowMapSC;
    GFXShaderConstHandle* mShadowMapSC;
+   GFXShaderConstHandle* mDynamicShadowMapSC;
    GFXShaderConstHandle* mShadowMapSizeSC;
    GFXShaderConstHandle* mShadowMapSizeSC;
 
 
    GFXShaderConstHandle* mCookieMapSC;
    GFXShaderConstHandle* mCookieMapSC;
 
 
    GFXShaderConstHandle* mRandomDirsConst;
    GFXShaderConstHandle* mRandomDirsConst;
    GFXShaderConstHandle* mShadowSoftnessConst;
    GFXShaderConstHandle* mShadowSoftnessConst;
-
-   GFXShaderConstHandle* mWorldToLightProjSC;
-   GFXShaderConstHandle* mViewToLightProjSC;
-
-   GFXShaderConstHandle* mScaleXSC;
-   GFXShaderConstHandle* mScaleYSC;
-   GFXShaderConstHandle* mOffsetXSC;
-   GFXShaderConstHandle* mOffsetYSC;
    GFXShaderConstHandle* mAtlasXOffsetSC;
    GFXShaderConstHandle* mAtlasXOffsetSC;
    GFXShaderConstHandle* mAtlasYOffsetSC;
    GFXShaderConstHandle* mAtlasYOffsetSC;
    GFXShaderConstHandle* mAtlasScaleSC;
    GFXShaderConstHandle* mAtlasScaleSC;
@@ -109,11 +105,28 @@ struct LightingShaderConstants
    // fadeStartLength.x = Distance in eye space to start fading shadows
    // fadeStartLength.x = Distance in eye space to start fading shadows
    // fadeStartLength.y = 1 / Length of fade
    // fadeStartLength.y = 1 / Length of fade
    GFXShaderConstHandle* mFadeStartLength;
    GFXShaderConstHandle* mFadeStartLength;
-   GFXShaderConstHandle* mFarPlaneScalePSSM;
    GFXShaderConstHandle* mOverDarkFactorPSSM;
    GFXShaderConstHandle* mOverDarkFactorPSSM;
 
 
    GFXShaderConstHandle* mTapRotationTexSC;
    GFXShaderConstHandle* mTapRotationTexSC;
 
 
+   // Static Specific:   
+   GFXShaderConstHandle* mWorldToLightProjSC;
+   GFXShaderConstHandle* mViewToLightProjSC;
+   GFXShaderConstHandle* mScaleXSC;
+   GFXShaderConstHandle* mScaleYSC;
+   GFXShaderConstHandle* mOffsetXSC;
+   GFXShaderConstHandle* mOffsetYSC;
+   GFXShaderConstHandle* mFarPlaneScalePSSM;
+
+   // Dynamic Specific:   
+   GFXShaderConstHandle* mDynamicWorldToLightProjSC;
+   GFXShaderConstHandle* mDynamicViewToLightProjSC;
+   GFXShaderConstHandle* mDynamicScaleXSC;
+   GFXShaderConstHandle* mDynamicScaleYSC;
+   GFXShaderConstHandle* mDynamicOffsetXSC;
+   GFXShaderConstHandle* mDynamicOffsetYSC;
+   GFXShaderConstHandle* mDynamicFarPlaneScalePSSM;
+
    LightingShaderConstants();
    LightingShaderConstants();
    ~LightingShaderConstants();
    ~LightingShaderConstants();
 
 
@@ -147,7 +160,8 @@ public:
    virtual ~LightShadowMap();
    virtual ~LightShadowMap();
 
 
    void render(   RenderPassManager* renderPass,
    void render(   RenderPassManager* renderPass,
-                  const SceneRenderState *diffuseState );
+                  const SceneRenderState *diffuseState,
+                  bool _dynamic);
 
 
    U32 getLastUpdate() const { return mLastUpdate; }
    U32 getLastUpdate() const { return mLastUpdate; }
 
 
@@ -237,6 +251,8 @@ protected:
 
 
    /// The time this shadow was last updated.
    /// The time this shadow was last updated.
    U32 mLastUpdate;
    U32 mLastUpdate;
+   PlatformTimer *mStaticRefreshTimer;
+   PlatformTimer *mDynamicRefreshTimer;
 
 
    /// The time this shadow was last culled and prioritized.
    /// The time this shadow was last culled and prioritized.
    U32 mLastCull;
    U32 mLastCull;
@@ -274,6 +290,13 @@ protected:
    /// The callback used to get texture events.
    /// The callback used to get texture events.
    /// @see GFXTextureManager::addEventDelegate
    /// @see GFXTextureManager::addEventDelegate
    void _onTextureEvent( GFXTexCallbackCode code );  
    void _onTextureEvent( GFXTexCallbackCode code );  
+
+   bool mIsDynamic;
+public:
+
+   bool isDynamic() { return mIsDynamic; }
+   void setDynamic(bool value) { mIsDynamic = value; }
+
 };
 };
 
 
 GFX_DeclareTextureProfile( ShadowMapProfile );
 GFX_DeclareTextureProfile( ShadowMapProfile );
@@ -296,9 +319,9 @@ public:
    virtual void packUpdate( BitStream *stream ) const;
    virtual void packUpdate( BitStream *stream ) const;
    virtual void unpackUpdate( BitStream *stream );
    virtual void unpackUpdate( BitStream *stream );
 
 
-   LightShadowMap* getShadowMap() const { return mShadowMap; }
+   LightShadowMap* getShadowMap(bool _isDynamic = false) const { return _isDynamic ? mDynamicShadowMap : mShadowMap; }
 
 
-   LightShadowMap* getOrCreateShadowMap();
+   LightShadowMap* getOrCreateShadowMap(bool _isDynamic = false);
 
 
    bool hasCookieTex() const { return cookie.isNotEmpty(); }
    bool hasCookieTex() const { return cookie.isNotEmpty(); }
 
 
@@ -315,6 +338,7 @@ protected:
 
 
    ///
    ///
    LightShadowMap *mShadowMap;
    LightShadowMap *mShadowMap;
+   LightShadowMap *mDynamicShadowMap;
 
 
    LightInfo *mLight;
    LightInfo *mLight;
 
 
@@ -376,6 +400,7 @@ public:
    bool lastSplitTerrainOnly;
    bool lastSplitTerrainOnly;
 
 
    /// @}
    /// @}
+   bool isDynamic;
 };
 };
 
 
 #endif // _LIGHTSHADOWMAP_H_
 #endif // _LIGHTSHADOWMAP_H_

+ 139 - 6
Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp

@@ -37,6 +37,7 @@
 #include "materials/shaderData.h"
 #include "materials/shaderData.h"
 #include "ts/tsShapeInstance.h"
 #include "ts/tsShapeInstance.h"
 #include "console/consoleTypes.h"
 #include "console/consoleTypes.h"
+#include "math/mathUtils.h"
 
 
 
 
 AFTER_MODULE_INIT( Sim )
 AFTER_MODULE_INIT( Sim )
@@ -248,6 +249,9 @@ void PSSMLightShadowMap::_render(   RenderPassManager* renderPass,
    TSShapeInstance::smDetailAdjust *= smDetailAdjustScale;
    TSShapeInstance::smDetailAdjust *= smDetailAdjustScale;
    TSShapeInstance::smSmallestVisiblePixelSize = smSmallestVisiblePixelSize;
    TSShapeInstance::smSmallestVisiblePixelSize = smSmallestVisiblePixelSize;
 
 
+   Vector< Vector<PlaneF> > _extraCull;
+   _calcPlanesCullForShadowCasters( _extraCull, fullFrustum, mLight->getDirection() );
+
    for (U32 i = 0; i < mNumSplits; i++)
    for (U32 i = 0; i < mNumSplits; i++)
    {
    {
       GFXTransformSaver saver;
       GFXTransformSaver saver;
@@ -365,12 +369,17 @@ void PSSMLightShadowMap::_render(   RenderPassManager* renderPass,
       shadowRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() );
       shadowRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() );
       shadowRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() );
       shadowRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() );
 
 
+      PlaneSetF planeSet( _extraCull[i].address(), _extraCull[i].size() );
+      shadowRenderState.getCullingState().setExtraPlanesCull( planeSet );
+
       U32 objectMask = SHADOW_TYPEMASK;
       U32 objectMask = SHADOW_TYPEMASK;
       if ( i == mNumSplits-1 && params->lastSplitTerrainOnly )
       if ( i == mNumSplits-1 && params->lastSplitTerrainOnly )
          objectMask = TerrainObjectType;
          objectMask = TerrainObjectType;
 
 
       sceneManager->renderSceneNoLights( &shadowRenderState, objectMask );
       sceneManager->renderSceneNoLights( &shadowRenderState, objectMask );
 
 
+      shadowRenderState.getCullingState().clearExtraPlanesCull();
+
       _debugRender( &shadowRenderState );
       _debugRender( &shadowRenderState );
    }
    }
 
 
@@ -435,18 +444,28 @@ void PSSMLightShadowMap::setShaderParameters(GFXShaderConstBuffer* params, Light
       }
       }
    }
    }
 
 
-   params->setSafe(lsc->mScaleXSC, sx);
-   params->setSafe(lsc->mScaleYSC, sy);
-   params->setSafe(lsc->mOffsetXSC, ox);
-   params->setSafe(lsc->mOffsetYSC, oy);
+   // These values change based on static/dynamic.
+   if ( mIsDynamic )
+   {
+      params->setSafe(lsc->mDynamicScaleXSC, sx);
+      params->setSafe(lsc->mDynamicScaleYSC, sy);
+      params->setSafe(lsc->mDynamicOffsetXSC, ox);
+      params->setSafe(lsc->mDynamicOffsetYSC, oy);
+      params->setSafe( lsc->mDynamicFarPlaneScalePSSM, mFarPlaneScalePSSM);
+   } else {
+      params->setSafe(lsc->mScaleXSC, sx);
+      params->setSafe(lsc->mScaleYSC, sy);
+      params->setSafe(lsc->mOffsetXSC, ox);
+      params->setSafe(lsc->mOffsetYSC, oy);
+      params->setSafe( lsc->mFarPlaneScalePSSM, mFarPlaneScalePSSM);
+   }
+
    params->setSafe(lsc->mAtlasXOffsetSC, aXOff);
    params->setSafe(lsc->mAtlasXOffsetSC, aXOff);
    params->setSafe(lsc->mAtlasYOffsetSC, aYOff);
    params->setSafe(lsc->mAtlasYOffsetSC, aYOff);
    params->setSafe(lsc->mAtlasScaleSC, shadowMapAtlas);
    params->setSafe(lsc->mAtlasScaleSC, shadowMapAtlas);
 
 
    Point4F lightParams( mLight->getRange().x, p->overDarkFactor.x, 0.0f, 0.0f );
    Point4F lightParams( mLight->getRange().x, p->overDarkFactor.x, 0.0f, 0.0f );
    params->setSafe( lsc->mLightParamsSC, lightParams );
    params->setSafe( lsc->mLightParamsSC, lightParams );
-      
-   params->setSafe( lsc->mFarPlaneScalePSSM, mFarPlaneScalePSSM);
 
 
    Point2F fadeStartLength(p->fadeStartDist, 0.0f);
    Point2F fadeStartLength(p->fadeStartDist, 0.0f);
    if (fadeStartLength.x == 0.0f)
    if (fadeStartLength.x == 0.0f)
@@ -462,3 +481,117 @@ void PSSMLightShadowMap::setShaderParameters(GFXShaderConstBuffer* params, Light
    // The softness is a factor of the texel size.
    // The softness is a factor of the texel size.
    params->setSafe( lsc->mShadowSoftnessConst, p->shadowSoftness * ( 1.0f / mTexSize ) );
    params->setSafe( lsc->mShadowSoftnessConst, p->shadowSoftness * ( 1.0f / mTexSize ) );
 }
 }
+
+void PSSMLightShadowMap::_calcPlanesCullForShadowCasters(Vector< Vector<PlaneF> > &out, const Frustum &viewFrustum, const Point3F &_ligthDir)
+{
+
+#define ENABLE_CULL_ASSERT
+
+   PROFILE_SCOPE(PSSMLightShadowMap_render_getCullFrustrum);
+
+   Point3F ligthDir = _ligthDir;
+   PlaneF lightFarPlane, lightNearPlane;
+   MatrixF lightFarPlaneMat(true);
+   MatrixF invLightFarPlaneMat(true);
+
+   // init data
+   {
+      ligthDir.normalize();
+      Point3F viewDir = viewFrustum.getTransform().getForwardVector();
+      viewDir.normalize();
+      const Point3F viewPosition = viewFrustum.getPosition();
+      const F32 viewDistance = viewFrustum.getBounds().len();
+      lightNearPlane = PlaneF(viewPosition + (viewDistance * -ligthDir), ligthDir);
+
+      const Point3F lightFarPlanePos = viewPosition + (viewDistance * ligthDir);
+      lightFarPlane = PlaneF(lightFarPlanePos, -ligthDir);
+
+      lightFarPlaneMat = MathUtils::createOrientFromDir(-ligthDir);
+      lightFarPlaneMat.setPosition(lightFarPlanePos);
+      lightFarPlaneMat.invertTo(&invLightFarPlaneMat);
+   }
+
+   Vector<Point2F> projVertices;
+
+   //project all frustum vertices into plane
+   // all vertices are 2d and local to far plane
+   projVertices.setSize(8);
+   for (int i = 0; i < 8; ++i) //
+   {
+      const Point3F &point = viewFrustum.getPoints()[i];
+#ifdef ENABLE_CULL_ASSERT
+      AssertFatal( PlaneF::Front == lightNearPlane.whichSide(point), "" );
+      AssertFatal( PlaneF::Front == lightFarPlane.whichSide(point), "" );
+#endif
+
+      Point3F localPoint(lightFarPlane.project(point));
+      invLightFarPlaneMat.mulP(localPoint);
+      projVertices[i] = Point2F(localPoint.x, localPoint.z);
+   }
+
+   //create hull arround projected proints
+   Vector<Point2F> hullVerts;
+   MathUtils::mBuildHull2D(projVertices, hullVerts);
+
+   Vector<PlaneF> planes;
+   planes.push_back(lightNearPlane);
+   planes.push_back(lightFarPlane);
+
+   //build planes
+   for (int i = 0; i < (hullVerts.size() - 1); ++i)
+   {
+      Point2F pos2D = (hullVerts[i] + hullVerts[i + 1]) / 2;
+      Point3F pos3D(pos2D.x, 0, pos2D.y);
+
+      Point3F pos3DA(hullVerts[i].x, 0, hullVerts[i].y);
+      Point3F pos3DB(hullVerts[i + 1].x, 0, hullVerts[i + 1].y);
+
+      // move hull points to 3d space
+      lightFarPlaneMat.mulP(pos3D);
+      lightFarPlaneMat.mulP(pos3DA);
+      lightFarPlaneMat.mulP(pos3DB);
+
+      PlaneF plane(pos3D, MathUtils::mTriangleNormal(pos3DB, pos3DA, (pos3DA - ligthDir)));
+      planes.push_back(plane);
+   }
+
+   //recalculate planes for each splits
+   for (int split = 0; split < mNumSplits; ++split)
+   {
+      Frustum subFrustum(viewFrustum);
+      subFrustum.cropNearFar(mSplitDist[split], mSplitDist[split + 1]);
+      subFrustum.setFarDist(getMin(subFrustum.getFarDist()*2.5f, viewFrustum.getFarDist()));
+      subFrustum.update();
+
+      Vector<PlaneF> subPlanes = planes;
+
+      for (int planeIdx = 0; planeIdx < subPlanes.size(); ++planeIdx)
+      {
+         PlaneF &plane = subPlanes[planeIdx];
+         F32 minDist = 0;
+
+         //calculate near vertex distance
+         for (int vertexIdx = 0; vertexIdx < 8; ++vertexIdx)
+         {
+            Point3F point = subFrustum.getPoints()[vertexIdx];
+            minDist = getMin(plane.distToPlane(point), minDist);
+         }
+
+         // move plane to near vertex
+         Point3F newPos = plane.getPosition() + (plane.getNormal() * minDist);
+         plane = PlaneF(newPos, plane.getNormal());
+
+#ifdef ENABLE_CULL_ASSERT
+         for(int x = 0; x < 8; ++x)
+         {
+            AssertFatal( PlaneF::Back != plane.whichSide( subFrustum.getPoints()[x] ), "");
+         }
+#endif
+      }
+
+      out.push_back(subPlanes);
+   }
+
+#undef ENABLE_CULL_ASSERT
+
+}

+ 1 - 0
Engine/source/lighting/shadowMap/pssmLightShadowMap.h

@@ -56,6 +56,7 @@ protected:
    void _setNumSplits( U32 numSplits, U32 texSize );
    void _setNumSplits( U32 numSplits, U32 texSize );
    void _calcSplitPos(const Frustum& currFrustum);
    void _calcSplitPos(const Frustum& currFrustum);
    Box3F _calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist);
    Box3F _calcClipSpaceAABB(const Frustum& f, const MatrixF& transform, F32 farDist);
+   void _calcPlanesCullForShadowCasters(Vector< Vector<PlaneF> > &out, const Frustum &viewFrustum, const Point3F &_ligthDir);
    void _roundProjection(const MatrixF& lightMat, const MatrixF& cropMatrix, Point3F &offset, U32 splitNum);
    void _roundProjection(const MatrixF& lightMat, const MatrixF& cropMatrix, Point3F &offset, U32 splitNum);
 
 
    static const S32 MAX_SPLITS = 4;
    static const S32 MAX_SPLITS = 4;

+ 7 - 0
Engine/source/lighting/shadowMap/shadowMapManager.cpp

@@ -86,6 +86,7 @@ Signal<void(void)> ShadowMapManager::smShadowDeactivateSignal;
 ShadowMapManager::ShadowMapManager() 
 ShadowMapManager::ShadowMapManager() 
 :  mShadowMapPass(NULL), 
 :  mShadowMapPass(NULL), 
    mCurrentShadowMap(NULL),
    mCurrentShadowMap(NULL),
+   mCurrentDynamicShadowMap(NULL),
    mIsActive(false)
    mIsActive(false)
 {
 {
 }
 }
@@ -98,9 +99,15 @@ void ShadowMapManager::setLightShadowMapForLight( LightInfo *light )
 {
 {
    ShadowMapParams *params = light->getExtended<ShadowMapParams>();
    ShadowMapParams *params = light->getExtended<ShadowMapParams>();
    if ( params )
    if ( params )
+   {
       mCurrentShadowMap = params->getShadowMap();
       mCurrentShadowMap = params->getShadowMap();
+      mCurrentDynamicShadowMap = params->getShadowMap(true);
+   }
    else 
    else 
+   {
       mCurrentShadowMap = NULL;
       mCurrentShadowMap = NULL;
+      mCurrentDynamicShadowMap = NULL;
+   }
 }
 }
 
 
 void ShadowMapManager::activate()
 void ShadowMapManager::activate()

+ 3 - 0
Engine/source/lighting/shadowMap/shadowMapManager.h

@@ -60,12 +60,14 @@ public:
 
 
    /// Sets the current shadowmap (used in setLightInfo/setTextureStage calls)
    /// Sets the current shadowmap (used in setLightInfo/setTextureStage calls)
    void setLightShadowMap( LightShadowMap *lm ) { mCurrentShadowMap = lm; }
    void setLightShadowMap( LightShadowMap *lm ) { mCurrentShadowMap = lm; }
+   void setLightDynamicShadowMap( LightShadowMap *lm ) { mCurrentDynamicShadowMap = lm; }
    
    
    /// Looks up the shadow map for the light then sets it.
    /// Looks up the shadow map for the light then sets it.
    void setLightShadowMapForLight( LightInfo *light );
    void setLightShadowMapForLight( LightInfo *light );
 
 
    /// Return the current shadow map
    /// Return the current shadow map
    LightShadowMap* getCurrentShadowMap() const { return mCurrentShadowMap; }
    LightShadowMap* getCurrentShadowMap() const { return mCurrentShadowMap; }
+   LightShadowMap* getCurrentDynamicShadowMap() const { return mCurrentDynamicShadowMap; }
 
 
    ShadowMapPass* getShadowMapPass() const { return mShadowMapPass; }
    ShadowMapPass* getShadowMapPass() const { return mShadowMapPass; }
 
 
@@ -88,6 +90,7 @@ protected:
 
 
    ShadowMapPass *mShadowMapPass;
    ShadowMapPass *mShadowMapPass;
    LightShadowMap *mCurrentShadowMap;
    LightShadowMap *mCurrentShadowMap;
+   LightShadowMap *mCurrentDynamicShadowMap;
 
 
    ///
    ///
    GFXTexHandle mTapRotationTex;
    GFXTexHandle mTapRotationTex;

+ 77 - 17
Engine/source/lighting/shadowMap/shadowMapPass.cpp

@@ -55,6 +55,11 @@ bool ShadowMapPass::smDisableShadows = false;
 bool ShadowMapPass::smDisableShadowsEditor = false;
 bool ShadowMapPass::smDisableShadowsEditor = false;
 bool ShadowMapPass::smDisableShadowsPref = false;
 bool ShadowMapPass::smDisableShadowsPref = false;
 
 
+/// milliseconds before static redraw
+S32 ShadowMapPass::smStaticShadowUpdateFreq = 32;
+/// milliseconds before dynamic redraw
+S32 ShadowMapPass::smDynamicShadowUpdateFreq = 16;
+
 /// We have a default 8ms render budget for shadow rendering.
 /// We have a default 8ms render budget for shadow rendering.
 U32 ShadowMapPass::smRenderBudgetMs = 8;
 U32 ShadowMapPass::smRenderBudgetMs = 8;
 
 
@@ -62,18 +67,27 @@ ShadowMapPass::ShadowMapPass(LightManager* lightManager, ShadowMapManager* shado
 {
 {
    mLightManager = lightManager;
    mLightManager = lightManager;
    mShadowManager = shadowManager;
    mShadowManager = shadowManager;
+
+   // Setup our render pass managers
+
+   // Static
    mShadowRPM = new ShadowRenderPassManager();
    mShadowRPM = new ShadowRenderPassManager();
    mShadowRPM->assignName( "ShadowRenderPassManager" );
    mShadowRPM->assignName( "ShadowRenderPassManager" );
    mShadowRPM->registerObject();
    mShadowRPM->registerObject();
    Sim::getRootGroup()->addObject( mShadowRPM );
    Sim::getRootGroup()->addObject( mShadowRPM );
-
-   // Setup our render pass manager
-
    mShadowRPM->addManager( new RenderMeshMgr(RenderPassManager::RIT_Mesh, 0.3f, 0.3f) );
    mShadowRPM->addManager( new RenderMeshMgr(RenderPassManager::RIT_Mesh, 0.3f, 0.3f) );
-   //mShadowRPM->addManager( new RenderObjectMgr() );
    mShadowRPM->addManager( new RenderTerrainMgr( 0.5f, 0.5f )  );
    mShadowRPM->addManager( new RenderTerrainMgr( 0.5f, 0.5f )  );
    mShadowRPM->addManager( new RenderImposterMgr( 0.6f, 0.6f )  );
    mShadowRPM->addManager( new RenderImposterMgr( 0.6f, 0.6f )  );
 
 
+   // Dynamic
+   mDynamicShadowRPM = new DynamicShadowRenderPassManager();
+   mDynamicShadowRPM->assignName( "DynamicShadowRenderPassManager" );
+   mDynamicShadowRPM->registerObject();
+   Sim::getRootGroup()->addObject( mDynamicShadowRPM );
+   mDynamicShadowRPM->addManager( new RenderMeshMgr(RenderPassManager::RIT_Mesh, 0.3f, 0.3f) );
+   mDynamicShadowRPM->addManager( new RenderTerrainMgr( 0.5f, 0.5f )  );
+   mDynamicShadowRPM->addManager( new RenderImposterMgr( 0.6f, 0.6f )  );
+
    mActiveLights = 0;
    mActiveLights = 0;
 
 
    mTimer = PlatformTimer::create();
    mTimer = PlatformTimer::create();
@@ -117,6 +131,9 @@ ShadowMapPass::~ShadowMapPass()
 
 
    if ( mShadowRPM )
    if ( mShadowRPM )
       mShadowRPM->deleteObject();
       mShadowRPM->deleteObject();
+
+   if ( mDynamicShadowRPM )
+      mDynamicShadowRPM->deleteObject();
 }
 }
 
 
 void ShadowMapPass::render(   SceneManager *sceneManager, 
 void ShadowMapPass::render(   SceneManager *sceneManager, 
@@ -147,7 +164,7 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
    // First do a loop thru the lights setting up the shadow
    // First do a loop thru the lights setting up the shadow
    // info array for this pass.
    // info array for this pass.
    Vector<LightShadowMap*> shadowMaps;
    Vector<LightShadowMap*> shadowMaps;
-   shadowMaps.reserve( mActiveLights );
+   shadowMaps.reserve( mActiveLights * 2 );
    for ( U32 i = 0; i < mActiveLights; i++ )
    for ( U32 i = 0; i < mActiveLights; i++ )
    {
    {
       ShadowMapParams *params = mLights[i]->getExtended<ShadowMapParams>();
       ShadowMapParams *params = mLights[i]->getExtended<ShadowMapParams>();
@@ -155,12 +172,14 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
       // Before we do anything... skip lights without shadows.      
       // Before we do anything... skip lights without shadows.      
       if ( !mLights[i]->getCastShadows() || smDisableShadows )
       if ( !mLights[i]->getCastShadows() || smDisableShadows )
          continue;
          continue;
-
-      LightShadowMap *lsm = params->getOrCreateShadowMap();
+      
+      // --- Static Shadow Map ---
+	  LightShadowMap *lsm = params->getOrCreateShadowMap();
+     LightShadowMap *dlsm = params->getOrCreateShadowMap(true);
 
 
       // First check the visiblity query... if it wasn't 
       // First check the visiblity query... if it wasn't 
       // visible skip it.
       // visible skip it.
-      if ( lsm->wasOccluded() )
+     if (lsm->wasOccluded() || dlsm->wasOccluded())
          continue;
          continue;
 
 
       // Any shadow that is visible is counted as being 
       // Any shadow that is visible is counted as being 
@@ -168,13 +187,25 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
       ++smActiveShadowMaps;
       ++smActiveShadowMaps;
 
 
       // Do a priority update for this shadow.
       // Do a priority update for this shadow.
-      lsm->updatePriority( diffuseState, currTime );
+	  lsm->updatePriority(diffuseState, currTime);
+
+	  shadowMaps.push_back(lsm);
+
+      // --- Dynamic Shadow Map ---
 
 
-      shadowMaps.push_back( lsm );
+      // Any shadow that is visible is counted as being 
+      // active regardless if we update it or not.
+      ++smActiveShadowMaps;
+
+      // Do a priority update for this shadow.
+	  dlsm->updatePriority(diffuseState, currTime);
+
+      shadowMaps.push_back( dlsm );
    }
    }
 
 
    // Now sort the shadow info by priority.
    // Now sort the shadow info by priority.
-   shadowMaps.sort( LightShadowMap::cmpPriority );
+   // andrewmac: tempoarily disabled until I find a better solution.
+   //shadowMaps.sort( LightShadowMap::cmpPriority );
 
 
    GFXDEBUGEVENT_SCOPE( ShadowMapPass_Render, ColorI::RED );
    GFXDEBUGEVENT_SCOPE( ShadowMapPass_Render, ColorI::RED );
 
 
@@ -183,22 +214,28 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
    mTimer->getElapsedMs();
    mTimer->getElapsedMs();
    mTimer->reset();
    mTimer->reset();
 
 
-   for ( U32 i = 0; i < shadowMaps.size(); i++ )
+   // 2 Shadow Maps per Light. This may fail.
+   for ( U32 i = 0; i < shadowMaps.size(); i += 2 )
    {
    {
-      LightShadowMap *lsm = shadowMaps[i];
+	   LightShadowMap *lsm = shadowMaps[i];
+	   LightShadowMap *dlsm = shadowMaps[i + 1];
 
 
       {
       {
          GFXDEBUGEVENT_SCOPE( ShadowMapPass_Render_Shadow, ColorI::RED );
          GFXDEBUGEVENT_SCOPE( ShadowMapPass_Render_Shadow, ColorI::RED );
 
 
-         mShadowManager->setLightShadowMap( lsm );
-         lsm->render( mShadowRPM, diffuseState );
+		 mShadowManager->setLightShadowMap(lsm);
+         mShadowManager->setLightDynamicShadowMap( dlsm );
+
+		 lsm->render(mShadowRPM, diffuseState, false);
+		 dlsm->render(mDynamicShadowRPM, diffuseState, true);
+
          ++smUpdatedShadowMaps;
          ++smUpdatedShadowMaps;
       }
       }
 
 
       // View dependent shadows or ones that are covering the entire
       // View dependent shadows or ones that are covering the entire
       // screen are updated every frame no matter the time left in
       // screen are updated every frame no matter the time left in
       // our shadow rendering budget.
       // our shadow rendering budget.
-      if ( lsm->isViewDependent() || lsm->getLastScreenSize() >= 1.0f )
+      if ( dlsm->isViewDependent() || dlsm->getLastScreenSize() >= 1.0f )
       {
       {
          ++smNearShadowMaps;
          ++smNearShadowMaps;
          continue;
          continue;
@@ -224,6 +261,7 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
    // The NULL here is importaint as having it around
    // The NULL here is importaint as having it around
    // will cause extra work in AdvancedLightManager::setLightInfo().
    // will cause extra work in AdvancedLightManager::setLightInfo().
    mShadowManager->setLightShadowMap( NULL );
    mShadowManager->setLightShadowMap( NULL );
+   mShadowManager->setLightDynamicShadowMap( NULL );
 }
 }
 
 
 void ShadowRenderPassManager::addInst( RenderInst *inst )
 void ShadowRenderPassManager::addInst( RenderInst *inst )
@@ -237,7 +275,29 @@ void ShadowRenderPassManager::addInst( RenderInst *inst )
          return;
          return;
 
 
       const BaseMaterialDefinition *mat = meshRI->matInst->getMaterial();
       const BaseMaterialDefinition *mat = meshRI->matInst->getMaterial();
-      if ( !mat->castsShadows() || mat->isTranslucent() )
+      if ( !mat->castsShadows() || mat->castsDynamicShadows() || mat->isTranslucent() )
+      {
+         // Do not add this instance, return here and avoid the default behavior
+         // of calling up to Parent::addInst()
+         return;
+      }
+   }
+
+   Parent::addInst(inst);
+}
+
+void DynamicShadowRenderPassManager::addInst( RenderInst *inst )
+{
+   PROFILE_SCOPE(DynamicShadowRenderPassManager_addInst);
+
+   if ( inst->type == RIT_Mesh )
+   {
+      MeshRenderInst *meshRI = static_cast<MeshRenderInst*>( inst );
+      if ( !meshRI->matInst )
+         return;
+
+      const BaseMaterialDefinition *mat = meshRI->matInst->getMaterial();
+      if ( !mat->castsShadows() || !mat->castsDynamicShadows() || mat->isTranslucent() )
       {
       {
          // Do not add this instance, return here and avoid the default behavior
          // Do not add this instance, return here and avoid the default behavior
          // of calling up to Parent::addInst()
          // of calling up to Parent::addInst()

+ 17 - 0
Engine/source/lighting/shadowMap/shadowMapPass.h

@@ -45,6 +45,7 @@ class RenderObjectMgr;
 class RenderTerrainMgr;
 class RenderTerrainMgr;
 class PlatformTimer;
 class PlatformTimer;
 class ShadowRenderPassManager;
 class ShadowRenderPassManager;
+class DynamicShadowRenderPassManager;
 
 
 /// ShadowMapPass, this is plugged into the SceneManager to generate 
 /// ShadowMapPass, this is plugged into the SceneManager to generate 
 /// ShadowMaps for the scene.
 /// ShadowMaps for the scene.
@@ -83,6 +84,11 @@ public:
    static bool smDisableShadowsEditor;
    static bool smDisableShadowsEditor;
    static bool smDisableShadowsPref;
    static bool smDisableShadowsPref;
 
 
+   /// milliseconds before static redraw
+   static S32 smStaticShadowUpdateFreq;
+   /// milliseconds before dynamic redraw
+   static S32 smDynamicShadowUpdateFreq;
+
 private:
 private:
 
 
    static U32 smActiveShadowMaps;
    static U32 smActiveShadowMaps;
@@ -103,6 +109,7 @@ private:
    LightInfoList mLights;
    LightInfoList mLights;
    U32 mActiveLights;
    U32 mActiveLights;
    SimObjectPtr<ShadowRenderPassManager> mShadowRPM;
    SimObjectPtr<ShadowRenderPassManager> mShadowRPM;
+   SimObjectPtr<DynamicShadowRenderPassManager> mDynamicShadowRPM;
    LightManager* mLightManager;
    LightManager* mLightManager;
    ShadowMapManager* mShadowManager;
    ShadowMapManager* mShadowManager;
 };
 };
@@ -117,4 +124,14 @@ public:
    virtual void addInst( RenderInst *inst );
    virtual void addInst( RenderInst *inst );
 };
 };
 
 
+class DynamicShadowRenderPassManager : public RenderPassManager
+{
+	typedef RenderPassManager Parent;
+public:
+	DynamicShadowRenderPassManager() : Parent() {}
+
+	/// Add a RenderInstance to the list
+	virtual void addInst(RenderInst *inst);
+};
+
 #endif // _SHADOWMAPPASS_H_
 #endif // _SHADOWMAPPASS_H_

+ 1 - 0
Engine/source/materials/baseMaterialDefinition.h

@@ -37,6 +37,7 @@ public:
    virtual bool isDoubleSided() const = 0;
    virtual bool isDoubleSided() const = 0;
    virtual bool isLightmapped() const = 0;
    virtual bool isLightmapped() const = 0;
    virtual bool castsShadows() const = 0;
    virtual bool castsShadows() const = 0;
+   virtual bool castsDynamicShadows() const = 0;
 };
 };
 
 
 #endif // _BASEMATERIALDEFINITION_H_
 #endif // _BASEMATERIALDEFINITION_H_

+ 5 - 1
Engine/source/materials/materialDefinition.cpp

@@ -182,6 +182,7 @@ Material::Material()
    mAlphaRef = 1;
    mAlphaRef = 1;
 
 
    mCastShadows = true;
    mCastShadows = true;
+   mCastDynamicShadows = true;
 
 
    mPlanarReflection = false;
    mPlanarReflection = false;
 
 
@@ -288,7 +289,7 @@ void Material::initPersistFields()
       
       
       addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES,
       addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES,
          "Use anisotropic filtering for the textures of this stage." );
          "Use anisotropic filtering for the textures of this stage." );
-
+      
       addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES,
       addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES,
          "The name of an environment map cube map to apply to this material." );
          "The name of an environment map cube map to apply to this material." );
 
 
@@ -390,6 +391,9 @@ void Material::initPersistFields()
    addField( "castShadows", TypeBool, Offset(mCastShadows, Material),
    addField( "castShadows", TypeBool, Offset(mCastShadows, Material),
       "If set to false the lighting system will not cast shadows from this material." );
       "If set to false the lighting system will not cast shadows from this material." );
 
 
+   addField( "castDynamicShadows", TypeBool, Offset(mCastDynamicShadows, Material),
+      "If set to false the lighting system will not cast dynamic shadows from this material." );
+
    addField("planarReflection", TypeBool, Offset(mPlanarReflection, Material), "@internal" );
    addField("planarReflection", TypeBool, Offset(mPlanarReflection, Material), "@internal" );
 
 
    addField("translucent", TypeBool, Offset(mTranslucent, Material),
    addField("translucent", TypeBool, Offset(mTranslucent, Material),

+ 4 - 1
Engine/source/materials/materialDefinition.h

@@ -89,6 +89,7 @@ public:
       NormalizeCube,
       NormalizeCube,
       TexTarget,
       TexTarget,
       AccuMap,
       AccuMap,
+      DynamicShadowMap,
    };
    };
 
 
    enum BlendOp
    enum BlendOp
@@ -219,7 +220,7 @@ public:
 
 
    /// The strength scalar for the detail normal map.
    /// The strength scalar for the detail normal map.
    F32 mDetailNormalMapStrength[MAX_STAGES];   
    F32 mDetailNormalMapStrength[MAX_STAGES];   
-
+      
    FileName mEnvMapFilename[MAX_STAGES];
    FileName mEnvMapFilename[MAX_STAGES];
    
    
    /// This color is the diffuse color of the material
    /// This color is the diffuse color of the material
@@ -299,6 +300,7 @@ public:
    /// A generic setting which tells the system to skip 
    /// A generic setting which tells the system to skip 
    /// generation of shadows from this material.
    /// generation of shadows from this material.
    bool mCastShadows;
    bool mCastShadows;
+   bool mCastDynamicShadows;
 
 
    bool mAlphaTest;
    bool mAlphaTest;
    U32 mAlphaRef;
    U32 mAlphaRef;
@@ -355,6 +357,7 @@ public:
    virtual void setAutoGenerated(bool isAutoGenerated) { mAutoGenerated = isAutoGenerated; }
    virtual void setAutoGenerated(bool isAutoGenerated) { mAutoGenerated = isAutoGenerated; }
    virtual bool isLightmapped() const;
    virtual bool isLightmapped() const;
    virtual bool castsShadows() const { return mCastShadows; }
    virtual bool castsShadows() const { return mCastShadows; }
+   virtual bool castsDynamicShadows() const { return mCastDynamicShadows; }
    const String &getPath() const { return mPath; }
    const String &getPath() const { return mPath; }
 
 
    void flush();
    void flush();

+ 8 - 0
Engine/source/materials/processedCustomMaterial.cpp

@@ -85,6 +85,14 @@ void ProcessedCustomMaterial::_setStageData()
          continue;
          continue;
       }
       }
 
 
+      if(filename.equal(String("$dynamicShadowMap"), String::NoCase))
+      {
+         rpd->mTexType[i] = Material::DynamicShadowMap;
+         rpd->mSamplerNames[i] = mCustomMaterial->mSamplerNames[i];
+         mMaxTex = i+1;
+         continue;
+      }
+
       if(filename.equal(String("$dynamiclightmask"), String::NoCase))
       if(filename.equal(String("$dynamiclightmask"), String::NoCase))
       {
       {
          rpd->mTexType[i] = Material::DynamicLightMask;
          rpd->mTexType[i] = Material::DynamicLightMask;

+ 8 - 0
Engine/source/math/mPoint2.h

@@ -908,6 +908,14 @@ inline bool mIsNaN( const Point2F &p )
    return mIsNaN_F( p.x ) || mIsNaN_F( p.y );
    return mIsNaN_F( p.x ) || mIsNaN_F( p.y );
 }
 }
 
 
+/// Return 0 if points are colinear
+/// Return positive if p0p1p2 are counter-clockwise
+/// Return negative if p0p1p2 are clockwise 
+inline F64 mCross(const Point2F &p0, const Point2F &p1, const Point2F &pt2)
+{
+   return (p1.x - p0.x) * (pt2.y - p0.y) - (p1.y - p0.y) * (pt2.x - p0.x);
+}
+
 
 
 namespace DictHash
 namespace DictHash
 {
 {

+ 51 - 0
Engine/source/math/mathUtils.cpp

@@ -1845,4 +1845,55 @@ U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, cons
    return numPlanes;
    return numPlanes;
 }
 }
 
 
+//-----------------------------------------------------------------------------
+
+void MathUtils::mBuildHull2D(const Vector<Point2F> _inPoints, Vector<Point2F> &hullPoints)
+{
+   /// Andrew's monotone chain convex hull algorithm implementation
+
+   struct Util
+   {
+      //compare by x and then by y   
+      static int CompareLexicographic( const Point2F *a, const Point2F *b)
+      {
+         return a->x < b->x || (a->x == b->x && a->y < b->y);
+      }
+   };
+
+   hullPoints.clear();
+   hullPoints.setSize( _inPoints.size()*2 );
+
+   // sort in points by x and then by y
+   Vector<Point2F> inSortedPoints = _inPoints;
+   inSortedPoints.sort( &Util::CompareLexicographic );
+
+   Point2F* lowerHullPtr = hullPoints.address();
+   U32 lowerHullIdx = 0;
+
+   //lower part of hull
+   for( int i = 0; i < inSortedPoints.size(); ++i )
+   {      
+      while( lowerHullIdx >= 2 && mCross( lowerHullPtr[ lowerHullIdx - 2], lowerHullPtr[lowerHullIdx - 1], inSortedPoints[i] ) <= 0 )
+         --lowerHullIdx;
+
+      lowerHullPtr[lowerHullIdx++] = inSortedPoints[i];
+   }
+
+   --lowerHullIdx; // last point are the same as first in upperHullPtr
+
+   Point2F* upperHullPtr = hullPoints.address() + lowerHullIdx;
+   U32 upperHullIdx = 0;
+
+   //upper part of hull
+   for( int i = inSortedPoints.size()-1; i >= 0; --i )
+   {
+      while( upperHullIdx >= 2 && mCross( upperHullPtr[ upperHullIdx - 2], upperHullPtr[upperHullIdx - 1], inSortedPoints[i] ) <= 0 )
+         --upperHullIdx;
+
+      upperHullPtr[upperHullIdx++] = inSortedPoints[i];
+   }
+
+   hullPoints.setSize( lowerHullIdx + upperHullIdx );
+}
+
 } // namespace MathUtils
 } // namespace MathUtils

+ 3 - 0
Engine/source/math/mathUtils.h

@@ -417,6 +417,9 @@ namespace MathUtils
 
 
    //void findFarthestPoint( const Point3F* points, U32 numPoints, const Point3F& fromPoint, )
    //void findFarthestPoint( const Point3F* points, U32 numPoints, const Point3F& fromPoint, )
 
 
+   /// Build a convex hull from a cloud of 2D points, first and last hull point are the same.
+   void mBuildHull2D(const Vector<Point2F> inPoints, Vector<Point2F> &hullPoints);
+
 } // namespace MathUtils
 } // namespace MathUtils
 
 
 #endif // _MATHUTILS_H_
 #endif // _MATHUTILS_H_

+ 5 - 0
Engine/source/scene/culling/sceneCullingState.cpp

@@ -88,6 +88,8 @@ SceneCullingState::SceneCullingState( SceneManager* sceneManager, const SceneCam
       SceneCullingVolume::Includer,
       SceneCullingVolume::Includer,
       PlaneSetF( planes, 4 )
       PlaneSetF( planes, 4 )
    );
    );
+
+   clearExtraPlanesCull();
 }
 }
 
 
 //-----------------------------------------------------------------------------
 //-----------------------------------------------------------------------------
@@ -789,6 +791,9 @@ U32 SceneCullingState::cullObjects( SceneObject** objects, U32 numObjects, U32 c
                       result == SceneZoneCullingState::CullingTestPositiveByOcclusion );
                       result == SceneZoneCullingState::CullingTestPositiveByOcclusion );
       }
       }
 
 
+      if( !isCulled )
+         isCulled = isOccludedWithExtraPlanesCull( object->getWorldBox() );
+
       if( !isCulled )
       if( !isCulled )
          objects[ numRemainingObjects ++ ] = object;
          objects[ numRemainingObjects ++ ] = object;
    }
    }

+ 18 - 0
Engine/source/scene/culling/sceneCullingState.h

@@ -106,6 +106,9 @@ class SceneCullingState
       /// The root culling frustum, which may be different from the camera frustum
       /// The root culling frustum, which may be different from the camera frustum
       Frustum mCullingFrustum;
       Frustum mCullingFrustum;
 
 
+      /// Extra planes for culling.
+      PlaneSetF mExtraPlanesCull;
+
       /// Occluders that have been added to this render state.  Adding an occluder does not
       /// Occluders that have been added to this render state.  Adding an occluder does not
       /// necessarily result in an occluder volume being added.  To not repeatedly try to
       /// necessarily result in an occluder volume being added.  To not repeatedly try to
       /// process the same occluder object, all objects that are added are recorded here.
       /// process the same occluder object, all objects that are added are recorded here.
@@ -301,6 +304,21 @@ class SceneCullingState
       /// (or, if no zone is selected, all volumes in the outdoor zone) to the debug drawer.
       /// (or, if no zone is selected, all volumes in the outdoor zone) to the debug drawer.
       void debugRenderCullingVolumes() const;
       void debugRenderCullingVolumes() const;
 
 
+      /// Set planes for extra culling
+      void setExtraPlanesCull( const PlaneSetF &cull) { mExtraPlanesCull = cull; }
+
+      /// Clear planes for extra culling.
+      void clearExtraPlanesCull() { mExtraPlanesCull = PlaneSetF(NULL, 0); }
+
+      /// Check extra planes culling
+      bool isOccludedWithExtraPlanesCull(const Box3F &box) const
+      {
+         if(mExtraPlanesCull.getNumPlanes())
+            return mExtraPlanesCull.testPotentialIntersection( box ) == GeometryOutside;
+
+         return false;
+      }
+
    private:
    private:
 
 
       typedef SceneZoneCullingState::CullingTestResult CullingTestResult;
       typedef SceneZoneCullingState::CullingTestResult CullingTestResult;

+ 14 - 8
Templates/Empty/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -62,9 +62,10 @@ new ShaderData( AL_VectorLightShader )
    OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/vectorLightP.glsl";
    OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/vectorLightP.glsl";
    
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
-   samplerNames[1] = "$ShadowMap";
-   samplerNames[2] = "$ssaoMask";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[1] = "$shadowMap";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$ssaoMask";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -75,7 +76,8 @@ new CustomMaterial( AL_VectorLightMaterial )
    stateBlock = AL_VectorLightState;
    stateBlock = AL_VectorLightState;
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
-   sampler["ShadowMap"] = "$dynamiclight";
+   sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["ssaoMask"] = "#ssaoMask";
    sampler["ssaoMask"] = "#ssaoMask";
    
    
    target = "lightinfo";
    target = "lightinfo";
@@ -128,8 +130,9 @@ new ShaderData( AL_PointLightShader )
 
 
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -141,6 +144,7 @@ new CustomMaterial( AL_PointLightMaterial )
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    
    target = "lightinfo";
    target = "lightinfo";
@@ -159,8 +163,9 @@ new ShaderData( AL_SpotLightShader )
    
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";   
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -172,6 +177,7 @@ new CustomMaterial( AL_SpotLightMaterial )
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    
    target = "lightinfo";
    target = "lightinfo";

+ 18 - 4
Templates/Empty/game/shaders/common/lighting/advanced/gl/pointLightP.glsl

@@ -28,6 +28,7 @@
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
+#include "../../../gl/torque.glsl"
 
 
 in vec4 wsEyeDir;
 in vec4 wsEyeDir;
 in vec4 ssPos;
 in vec4 ssPos;
@@ -107,6 +108,7 @@ uniform sampler2D prePassBuffer;
 	uniform samplerCube shadowMap;
 	uniform samplerCube shadowMap;
 #else
 #else
 	uniform sampler2D shadowMap;
 	uniform sampler2D shadowMap;
+	uniform sampler2D dynamicShadowMap;
 #endif
 #endif
 
 
 uniform vec4 rtParams0;
 uniform vec4 rtParams0;
@@ -119,9 +121,10 @@ uniform vec2 lightAttenuation;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
 uniform mat3 viewToLightProj;
 uniform mat3 viewToLightProj;
+uniform mat3 dynamicViewToLightProj;
 uniform vec4 lightParams;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
-			   
+
 out vec4 OUT_col;
 out vec4 OUT_col;
 
 
 void main()               
 void main()               
@@ -175,7 +178,7 @@ void main()
 
 
          vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
          vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
          
          
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowCoord,
                                              shadowSoftness,
                                              shadowSoftness,
@@ -183,17 +186,28 @@ void main()
                                              nDotL,
                                              nDotL,
                                              lightParams.y );
                                              lightParams.y );
 
 
+         vec2 dynamicShadowCoord = decodeShadowCoord( tMul( dynamicViewToLightProj, -lightVec ) ).xy;
+         float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                             ssPos.xy,
+                                             dynamicShadowCoord,
+                                             shadowSoftness,
+                                             distToLight,
+                                             nDotL,
+                                             lightParams.y );
+
+         float shadowed = min(static_shadowed, dynamic_shadowed);
       #endif
       #endif
 
 
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
+   vec3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
       vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) );
       vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) );
 
 
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
 
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
@@ -211,7 +225,7 @@ void main()
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   vec3 lightColorOut = lightMapParams.rgb * lightcol;
    vec4 addToResult = vec4(0.0);
    vec4 addToResult = vec4(0.0);
     
     
    // TODO: This needs to be removed when lightmapping is disabled
    // TODO: This needs to be removed when lightmapping is disabled

+ 20 - 4
Templates/Empty/game/shaders/common/lighting/advanced/gl/spotLightP.glsl

@@ -27,6 +27,7 @@
 #include "shadergen:/autogenConditioners.h"
 #include "shadergen:/autogenConditioners.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
+#include "../../../gl/torque.glsl"
 
 
 in vec4 wsEyeDir;
 in vec4 wsEyeDir;
 in vec4 ssPos;
 in vec4 ssPos;
@@ -45,6 +46,7 @@ uniform sampler2D cookieMap;
 
 
 uniform sampler2D prePassBuffer;
 uniform sampler2D prePassBuffer;
 uniform sampler2D shadowMap;
 uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 
 uniform vec4 rtParams0;
 uniform vec4 rtParams0;
 
 
@@ -59,6 +61,7 @@ uniform vec4 lightMapParams;
 
 
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
 uniform mat4 viewToLightProj;
 uniform mat4 viewToLightProj;
+uniform mat4 dynamicViewToLightProj;
 
 
 uniform vec4 lightParams;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
@@ -70,7 +73,7 @@ void main()
    // Compute scene UV
    // Compute scene UV
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+
    // Sample/unpack the normal/z data
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
    vec3 normal = prepassSample.rgb;
@@ -102,6 +105,10 @@ void main()
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    shadowCoord.y = 1.0f - shadowCoord.y;
    shadowCoord.y = 1.0f - shadowCoord.y;
 
 
+   // Get the dynamic shadow texture coordinate
+   vec4 dynpxlPosLightProj = tMul( dynamicViewToLightProj, vec4( viewSpacePos, 1 ) );
+   vec2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
+   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
    
    
       float shadowed = 1.0;
       float shadowed = 1.0;
@@ -111,7 +118,7 @@ void main()
       // Get a linear depth from the light source.
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
       float distToLight = pxlPosLightProj.z / lightRange;
 
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowCoord,
                                           shadowSoftness,
                                           shadowSoftness,
@@ -119,15 +126,24 @@ void main()
                                           nDotL,
                                           nDotL,
                                           lightParams.y );
                                           lightParams.y );
 
 
+      float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                          ssPos.xy,
+                                          dynshadowCoord,
+                                          shadowSoftness,
+                                          distToLight,
+                                          nDotL,
+                                          lightParams.y );
+      float shadowed = min(static_shadowed, dynamic_shadowed);
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
+   vec3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
       vec4 cookie = texture( cookieMap, shadowCoord );
       vec4 cookie = texture( cookieMap, shadowCoord );
 
 
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
 
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
@@ -145,7 +161,7 @@ void main()
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   vec3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   vec3 lightColorOut = lightMapParams.rgb * lightcol;
    vec4 addToResult = vec4(0.0);
    vec4 addToResult = vec4(0.0);
 
 
    // TODO: This needs to be removed when lightmapping is disabled
    // TODO: This needs to be removed when lightmapping is disabled

+ 138 - 64
Templates/Empty/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl

@@ -34,81 +34,78 @@ in vec2 uv0;
 in vec3 wsEyeRay;
 in vec3 wsEyeRay;
 in vec3 vsEyeRay;
 in vec3 vsEyeRay;
 
 
-uniform sampler2D ShadowMap ;
+uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 
 #ifdef USE_SSAO_MASK
 #ifdef USE_SSAO_MASK
 uniform sampler2D ssaoMask ;
 uniform sampler2D ssaoMask ;
 uniform vec4 rtParams2;
 uniform vec4 rtParams2;
 #endif
 #endif
 
 
-uniform sampler2D prePassBuffer;             
+uniform sampler2D prePassBuffer;            
 uniform vec3 lightDirection;
 uniform vec3 lightDirection;
 uniform vec4 lightColor;
 uniform vec4 lightColor;
 uniform float  lightBrightness;
 uniform float  lightBrightness;
 uniform vec4 lightAmbient; 
 uniform vec4 lightAmbient; 
 uniform vec3 eyePosWorld; 
 uniform vec3 eyePosWorld; 
-uniform mat4x4 worldToLightProj;
-uniform vec4 scaleX;
-uniform vec4 scaleY;
-uniform vec4 offsetX;
-uniform vec4 offsetY;
+uniform mat4x4 eyeMat;
 uniform vec4 atlasXOffset;
 uniform vec4 atlasXOffset;
 uniform vec4 atlasYOffset;
 uniform vec4 atlasYOffset;
 uniform vec2 atlasScale;
 uniform vec2 atlasScale;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 uniform vec2 fadeStartLength;
 uniform vec2 fadeStartLength;
-uniform vec4 farPlaneScalePSSM;
 uniform vec4 overDarkPSSM;
 uniform vec4 overDarkPSSM;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
-
-out vec4 OUT_col;
-
-void main()             
-{
-   // Sample/unpack the normal/z data
-   vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
-   vec3 normal = prepassSample.rgb;
-   float depth = prepassSample.a;
-
-   // Use eye ray to get ws pos
-   vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
-   
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
-
-   #ifdef PSSM_DEBUG_RENDER
-      vec3 debugColor = vec3(0);
-   #endif
    
    
-   #ifdef NO_SHADOW
-
-      // Fully unshadowed.
-      float shadowed = 1.0;
+//static shadowMap
+uniform mat4x4 worldToLightProj;
+uniform vec4 scaleX;
+uniform vec4 scaleY;
+uniform vec4 offsetX;
+uniform vec4 offsetY;
+uniform vec4 farPlaneScalePSSM;
 
 
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = vec3(1.0);
-      #endif
+//dynamic shadowMap
+uniform mat4x4 dynamicWorldToLightProj;
+uniform vec4 dynamicScaleX;
+uniform vec4 dynamicScaleY;
+uniform vec4 dynamicOffsetX;
+uniform vec4 dynamicOffsetY;
+uniform vec4 dynamicFarPlaneScalePSSM;
 
 
-   #else
+vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
+                                vec2 _texCoord,
+                                mat4 _worldToLightProj,
+                                vec4 _worldPos,
+                                vec4 _scaleX, vec4 _scaleY,
+                                vec4 _offsetX, vec4 _offsetY,
+                                vec4 _farPlaneScalePSSM,
+                                vec4 _atlasXOffset, vec4 _atlasYOffset,
+                                vec2 _atlasScale,
+                                float _shadowSoftness, 
+                                float _dotNL ,
+                                vec4 _overDarkPSSM
+)
+{
 
 
       // Compute shadow map coordinate
       // Compute shadow map coordinate
-      vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos);
+      vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
 
-      // Distance to light, in shadowmap space
+      // Distance to light, in shadowMap space
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
          
          
-      // Figure out which split to sample from.  Basically, we compute the shadowmap sample coord
+      // Figure out which split to sample from.  Basically, we compute the shadowMap sample coord
       // for all of the splits and then check if its valid.  
       // for all of the splits and then check if its valid.  
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       vec4 farPlaneDists = vec4( distToLight );      
       vec4 farPlaneDists = vec4( distToLight );      
-      shadowCoordX *= scaleX;
-      shadowCoordY *= scaleY;
-      shadowCoordX += offsetX;
-      shadowCoordY += offsetY;
-      farPlaneDists *= farPlaneScalePSSM;
+      shadowCoordX *= _scaleX;
+      shadowCoordY *= _scaleY;
+      shadowCoordX += _offsetX;
+      shadowCoordY += _offsetY;
+      farPlaneDists *= _farPlaneScalePSSM;
       
       
       // If the shadow sample is within -1..1 and the distance 
       // If the shadow sample is within -1..1 and the distance 
       // to the light for this pixel is less than the far plane 
       // to the light for this pixel is less than the far plane 
@@ -132,6 +129,11 @@ void main()
       else
       else
          finalMask = vec4(0, 0, 0, 1);
          finalMask = vec4(0, 0, 0, 1);
          
          
+      vec3 debugColor = vec3(0);
+   
+      #ifdef NO_SHADOW
+         debugColor = vec3(1.0);
+      #endif
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
          if ( finalMask.x > 0 )
@@ -144,50 +146,122 @@ void main()
             debugColor += vec3( 1, 1, 0 );
             debugColor += vec3( 1, 1, 0 );
       #endif
       #endif
 
 
-      // Here we know what split we're sampling from, so recompute the texcoord location
+      // Here we know what split we're sampling from, so recompute the _texCoord location
       // Yes, we could just use the result from above, but doing it this way actually saves
       // Yes, we could just use the result from above, but doing it this way actually saves
       // shader instructions.
       // shader instructions.
       vec2 finalScale;
       vec2 finalScale;
-      finalScale.x = dot(finalMask, scaleX);
-      finalScale.y = dot(finalMask, scaleY);
+      finalScale.x = dot(finalMask, _scaleX);
+      finalScale.y = dot(finalMask, _scaleY);
 
 
       vec2 finalOffset;
       vec2 finalOffset;
-      finalOffset.x = dot(finalMask, offsetX);
-      finalOffset.y = dot(finalMask, offsetY);
+      finalOffset.x = dot(finalMask, _offsetX);
+      finalOffset.y = dot(finalMask, _offsetY);
 
 
       vec2 shadowCoord;                  
       vec2 shadowCoord;                  
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord += finalOffset;
       shadowCoord += finalOffset;
 
 
-      // Convert to texcoord space
+      // Convert to _texCoord space
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord.y = 1.0f - shadowCoord.y;
       shadowCoord.y = 1.0f - shadowCoord.y;
 
 
       // Move around inside of atlas 
       // Move around inside of atlas 
       vec2 aOffset;
       vec2 aOffset;
-      aOffset.x = dot(finalMask, atlasXOffset);
-      aOffset.y = dot(finalMask, atlasYOffset);
+      aOffset.x = dot(finalMask, _atlasXOffset);
+      aOffset.y = dot(finalMask, _atlasYOffset);
 
 
-      shadowCoord *= atlasScale;
+      shadowCoord *= _atlasScale;
       shadowCoord += aOffset;
       shadowCoord += aOffset;
               
               
       // Each split has a different far plane, take this into account.
       // Each split has a different far plane, take this into account.
-      float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
+      float farPlaneScale = dot( _farPlaneScalePSSM, finalMask );
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
       
       
-      float shadowed = softShadow_filter(   ShadowMap,
-                                             uv0.xy,
-                                             shadowCoord,
-                                             farPlaneScale * shadowSoftness,
-                                             distToLight,
-                                             dotNL,
-                                             dot( finalMask, overDarkPSSM ) );
-  
+      return vec4(debugColor,
+	                             softShadow_filter(  _sourceshadowMap,
+                                 _texCoord,
+                                 shadowCoord,
+                                 farPlaneScale * _shadowSoftness,
+                                 distToLight,
+                                 _dotNL,
+                                 dot( finalMask, _overDarkPSSM ) ) );
+}
+
+out vec4 OUT_col;
+void main()             
+{   
+   // Sample/unpack the normal/z data
+   vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
+   vec3 normal = prepassSample.rgb;
+   float depth = prepassSample.a;
+
+   // Use eye ray to get ws pos
+   vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
+   
+   // Get the light attenuation.
+   float dotNL = dot(-lightDirection, normal);
+
+   #ifdef PSSM_DEBUG_RENDER
+      vec3 debugColor = vec3(0);
+   #endif
+   
+   #ifdef NO_SHADOW
+
+      // Fully unshadowed.
+      float shadowed = 1.0;
+
+      #ifdef PSSM_DEBUG_RENDER
+         debugColor = vec3(1.0);
+      #endif
+
+   #else
+
+      vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
+                                                        uv0.xy,
+                                                        worldToLightProj,
+                                                        worldPos,
+                                                        scaleX, scaleY,
+                                                        offsetX, offsetY,
+                                                        farPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
+
+                                             
+      vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
+                                                        uv0.xy,
+                                                        dynamicWorldToLightProj,
+                                                        worldPos,
+                                                        dynamicScaleX, dynamicScaleY,
+                                                        dynamicOffsetX, dynamicOffsetY,
+                                                        dynamicFarPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);  
+      
+      float static_shadowed = static_shadowed_colors.a;
+      float dynamic_shadowed = dynamic_shadowed_colors.a;
+	  
+      #ifdef PSSM_DEBUG_RENDER
+	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+      #endif
+	   
       // Fade out the shadow at the end of the range.
       // Fade out the shadow at the end of the range.
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
-      shadowed = mix( shadowed, 1.0, saturate( fadeOutAmt ) );
-
+      
+      static_shadowed = mix( static_shadowed, 1.0, saturate( fadeOutAmt ) );
+      dynamic_shadowed = mix( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
+            
+      // temp for debugging. uncomment one or the other.
+      //float shadowed = static_shadowed;
+      //float shadowed = dynamic_shadowed;
+      float shadowed = min(static_shadowed, dynamic_shadowed);
+      
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )
             debugColor = vec3(1.0);
             debugColor = vec3(1.0);
@@ -228,7 +302,7 @@ void main()
    #ifdef PSSM_DEBUG_RENDER
    #ifdef PSSM_DEBUG_RENDER
       lightColorOut = debugColor;
       lightColorOut = debugColor;
    #endif
    #endif
-   
+
    OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult );  
    OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult );  
    
    
 }
 }

+ 22 - 7
Templates/Empty/game/shaders/common/lighting/advanced/pointLightP.hlsl

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 
 struct ConvexConnectP
 struct ConvexConnectP
 {
 {
@@ -40,7 +40,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
-uniform samplerCUBE cookieMap : register(S2);
+uniform samplerCUBE cookieMap : register(S3);
 
 
 #endif
 #endif
 
 
@@ -114,6 +114,7 @@ float4 main(   ConvexConnectP IN,
                   uniform samplerCUBE shadowMap : register(S1),
                   uniform samplerCUBE shadowMap : register(S1),
                #else
                #else
                   uniform sampler2D shadowMap : register(S1),
                   uniform sampler2D shadowMap : register(S1),
+                  uniform sampler2D dynamicShadowMap : register(S2),
                #endif
                #endif
 
 
                uniform float4 rtParams0,
                uniform float4 rtParams0,
@@ -127,6 +128,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform float4 vsFarPlane,
                uniform float4 vsFarPlane,
                uniform float3x3 viewToLightProj,
                uniform float3x3 viewToLightProj,
+               uniform float3x3 dynamicViewToLightProj,
 
 
                uniform float4 lightParams,
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
                uniform float shadowSoftness ) : COLOR0
@@ -134,7 +136,7 @@ float4 main(   ConvexConnectP IN,
    // Compute scene UV
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+      
    // Sample/unpack the normal/z data
    // Sample/unpack the normal/z data
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float3 normal = prepassSample.rgb;
    float3 normal = prepassSample.rgb;
@@ -178,9 +180,9 @@ float4 main(   ConvexConnectP IN,
          
          
       #else
       #else
 
 
+         // Static
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
-         
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowCoord,
                                              shadowSoftness,
                                              shadowSoftness,
@@ -188,17 +190,30 @@ float4 main(   ConvexConnectP IN,
                                              nDotL,
                                              nDotL,
                                              lightParams.y );
                                              lightParams.y );
 
 
+         // Dynamic
+         float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy;
+         float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                             ssPos.xy,
+                                             dynamicShadowCoord,
+                                             shadowSoftness,
+                                             distToLight,
+                                             nDotL,
+                                             lightParams.y );
+
+         float shadowed = min(static_shadowed, dynamic_shadowed);
+
       #endif
       #endif
 
 
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
+   float3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
       float4 cookie = texCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
       float4 cookie = texCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
 
 
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
 
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
@@ -216,7 +231,7 @@ float4 main(   ConvexConnectP IN,
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   float3 lightColorOut = lightMapParams.rgb * lightcol;
    float4 addToResult = 0.0;
    float4 addToResult = 0.0;
     
     
    // TODO: This needs to be removed when lightmapping is disabled
    // TODO: This needs to be removed when lightmapping is disabled

+ 1 - 1
Templates/Empty/game/shaders/common/lighting/advanced/softShadow.hlsl

@@ -69,7 +69,7 @@ static float2 sNonUniformTaps[NUM_PRE_TAPS] =
 
 
 /// The texture used to do per-pixel pseudorandom
 /// The texture used to do per-pixel pseudorandom
 /// rotations of the filter taps.
 /// rotations of the filter taps.
-uniform sampler2D gTapRotationTex : register(S3);
+uniform sampler2D gTapRotationTex : register(S4);
 
 
 
 
 float softShadow_sampleTaps(  sampler2D shadowMap,
 float softShadow_sampleTaps(  sampler2D shadowMap,

+ 22 - 6
Templates/Empty/game/shaders/common/lighting/advanced/spotLightP.hlsl

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 
 struct ConvexConnectP
 struct ConvexConnectP
 {
 {
@@ -39,7 +39,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
-uniform sampler2D cookieMap : register(S2);
+uniform sampler2D cookieMap : register(S3);
 
 
 #endif
 #endif
 
 
@@ -48,6 +48,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D shadowMap : register(S1),
                uniform sampler2D shadowMap : register(S1),
+               uniform sampler2D dynamicShadowMap : register(S2),
 
 
                uniform float4 rtParams0,
                uniform float4 rtParams0,
 
 
@@ -62,6 +63,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform float4 vsFarPlane,
                uniform float4 vsFarPlane,
                uniform float4x4 viewToLightProj,
                uniform float4x4 viewToLightProj,
+               uniform float4x4 dynamicViewToLightProj,
 
 
                uniform float4 lightParams,
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
                uniform float shadowSoftness ) : COLOR0
@@ -101,6 +103,11 @@ float4 main(   ConvexConnectP IN,
    float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
    float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
    shadowCoord.y = 1.0f - shadowCoord.y;
    shadowCoord.y = 1.0f - shadowCoord.y;
 
 
+   // Get the dynamic shadow texture coordinate
+   float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) );
+   float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
+   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
+   
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
    
    
       float shadowed = 1.0;
       float shadowed = 1.0;
@@ -110,23 +117,32 @@ float4 main(   ConvexConnectP IN,
       // Get a linear depth from the light source.
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
       float distToLight = pxlPosLightProj.z / lightRange;
 
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowCoord,
                                           shadowSoftness,
                                           shadowSoftness,
                                           distToLight,
                                           distToLight,
                                           nDotL,
                                           nDotL,
                                           lightParams.y );
                                           lightParams.y );
-
+                                          
+      float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                          ssPos.xy,
+                                          dynshadowCoord,
+                                          shadowSoftness,
+                                          distToLight,
+                                          nDotL,
+                                          lightParams.y );
+      float shadowed = min(static_shadowed, dynamic_shadowed);
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
+   float3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
    #ifdef USE_COOKIE_TEX
 
 
       // Lookup the cookie sample.
       // Lookup the cookie sample.
       float4 cookie = tex2D( cookieMap, shadowCoord );
       float4 cookie = tex2D( cookieMap, shadowCoord );
 
 
       // Multiply the light with the cookie tex.
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
 
       // Use a maximum channel luminance to attenuate 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
       // the lighting else we get specular in the dark
@@ -144,7 +160,7 @@ float4 main(   ConvexConnectP IN,
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   float3 lightColorOut = lightMapParams.rgb * lightcol;
    float4 addToResult = 0.0;
    float4 addToResult = 0.0;
 
 
    // TODO: This needs to be removed when lightmapping is disabled
    // TODO: This needs to be removed when lightmapping is disabled

+ 138 - 64
Templates/Empty/game/shaders/common/lighting/advanced/vectorLightP.hlsl

@@ -30,68 +30,31 @@
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
 
 
 
 
-uniform sampler2D ShadowMap : register(S1);
+uniform sampler2D shadowMap : register(S1);
+uniform sampler2D dynamicShadowMap : register(S2);
 
 
 #ifdef USE_SSAO_MASK
 #ifdef USE_SSAO_MASK
-uniform sampler2D ssaoMask : register(S2);
+uniform sampler2D ssaoMask : register(S3);
 uniform float4 rtParams2;
 uniform float4 rtParams2;
 #endif
 #endif
 
 
-
-float4 main( FarFrustumQuadConnectP IN,
-
-             uniform sampler2D prePassBuffer : register(S0),
-             
-             uniform float3 lightDirection,
-             uniform float4 lightColor,
-             uniform float  lightBrightness,
-             uniform float4 lightAmbient,
-             
-             uniform float3 eyePosWorld,
-             
-             uniform float4x4 worldToLightProj,
-
-             uniform float4 scaleX,
-             uniform float4 scaleY,
-             uniform float4 offsetX,
-             uniform float4 offsetY,
-             uniform float4 atlasXOffset,
-             uniform float4 atlasYOffset,
-             uniform float2 atlasScale,
-             uniform float4 zNearFarInvNearFar,
-             uniform float4 lightMapParams,
-
-             uniform float2 fadeStartLength,
-             uniform float4 farPlaneScalePSSM,
-             uniform float4 overDarkPSSM,
-             uniform float shadowSoftness ) : COLOR0
+float4 AL_VectorLightShadowCast( sampler2D sourceShadowMap,
+                                float2 texCoord,
+                                float4x4 worldToLightProj,
+                                float4 worldPos,
+                                float4 scaleX,
+                                float4 scaleY,
+                                float4 offsetX,
+                                float4 offsetY,
+                                float4 farPlaneScalePSSM,
+                                float4 atlasXOffset,
+                                float4 atlasYOffset,
+                                float2 atlasScale,
+                                float shadowSoftness, 
+                                float dotNL ,
+                                float4 overDarkPSSM
+)
 {
 {
-   // Sample/unpack the normal/z data
-   float4 prepassSample = prepassUncondition( prePassBuffer, IN.uv0 );
-   float3 normal = prepassSample.rgb;
-   float depth = prepassSample.a;
-
-   // Use eye ray to get ws pos
-   float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
-   
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
-
-   #ifdef PSSM_DEBUG_RENDER
-      float3 debugColor = 0;
-   #endif
-   
-   #ifdef NO_SHADOW
-
-      // Fully unshadowed.
-      float shadowed = 1.0;
-
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = 1.0;
-      #endif
-
-   #else
-
       // Compute shadow map coordinate
       // Compute shadow map coordinate
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
@@ -132,6 +95,11 @@ float4 main( FarFrustumQuadConnectP IN,
       else
       else
          finalMask = float4(0, 0, 0, 1);
          finalMask = float4(0, 0, 0, 1);
          
          
+      float3 debugColor = float3(0,0,0);
+   
+      #ifdef NO_SHADOW
+         debugColor = float3(1.0,1.0,1.0);
+      #endif
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
          if ( finalMask.x > 0 )
@@ -174,19 +142,125 @@ float4 main( FarFrustumQuadConnectP IN,
       // Each split has a different far plane, take this into account.
       // Each split has a different far plane, take this into account.
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
+
+      return float4(debugColor,
+                    softShadow_filter(  sourceShadowMap,
+                                 texCoord,
+                                 shadowCoord,
+                                 farPlaneScale * shadowSoftness,
+                                 distToLight,
+                                 dotNL,
+                                 dot( finalMask, overDarkPSSM ) ) );
+};
+
+float4 main( FarFrustumQuadConnectP IN,
+
+             uniform sampler2D prePassBuffer : register(S0),
+             
+             uniform float3 lightDirection,
+             uniform float4 lightColor,
+             uniform float  lightBrightness,
+             uniform float4 lightAmbient,
+             uniform float4x4 eyeMat,
+             
+             uniform float3 eyePosWorld,
+             uniform float4 atlasXOffset,
+             uniform float4 atlasYOffset,
+             uniform float2 atlasScale,
+             uniform float4 zNearFarInvNearFar,
+             uniform float4 lightMapParams,
+             uniform float2 fadeStartLength,
+             uniform float4 overDarkPSSM,
+             uniform float shadowSoftness,
+
+             // Static Shadows
+             uniform float4x4 worldToLightProj,
+             uniform float4 scaleX,
+             uniform float4 scaleY,
+             uniform float4 offsetX,
+             uniform float4 offsetY,
+             uniform float4 farPlaneScalePSSM,
+
+             // Dynamic Shadows
+             uniform float4x4 dynamicWorldToLightProj,
+             uniform float4 dynamicScaleX,
+             uniform float4 dynamicScaleY,
+             uniform float4 dynamicOffsetX,
+             uniform float4 dynamicOffsetY,
+             uniform float4 dynamicFarPlaneScalePSSM
+
+            ) : COLOR0
+{   
+   // Sample/unpack the normal/z data
+   float4 prepassSample = prepassUncondition( prePassBuffer, IN.uv0 );
+   float3 normal = prepassSample.rgb;
+   float depth = prepassSample.a;
+
+   // Use eye ray to get ws pos
+   float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
+   
+   // Get the light attenuation.
+   float dotNL = dot(-lightDirection, normal);
+
+   #ifdef PSSM_DEBUG_RENDER
+      float3 debugColor = float3(0,0,0);
+   #endif
+   
+   #ifdef NO_SHADOW
+
+      // Fully unshadowed.
+      float shadowed = 1.0;
+
+      #ifdef PSSM_DEBUG_RENDER
+         debugColor = float3(1.0,1.0,1.0);
+      #endif
+
+   #else
+      
+      float4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
+                                                        IN.uv0.xy,
+                                                        worldToLightProj,
+                                                        worldPos,
+                                                        scaleX, scaleY,
+                                                        offsetX, offsetY,
+                                                        farPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
+
+      float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
+                                                        IN.uv0.xy,
+                                                        dynamicWorldToLightProj,
+                                                        worldPos,
+                                                        dynamicScaleX, dynamicScaleY,
+                                                        dynamicOffsetX, dynamicOffsetY,
+                                                        dynamicFarPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
       
       
-      float shadowed = softShadow_filter(   ShadowMap,
-                                             IN.uv0.xy,
-                                             shadowCoord,
-                                             farPlaneScale * shadowSoftness,
-                                             distToLight,
-                                             dotNL,
-                                             dot( finalMask, overDarkPSSM ) );
+      float static_shadowed = static_shadowed_colors.a;
+      float dynamic_shadowed = dynamic_shadowed_colors.a;
+	  
+      #ifdef PSSM_DEBUG_RENDER
+	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+      #endif
   
   
       // Fade out the shadow at the end of the range.
       // Fade out the shadow at the end of the range.
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
-      shadowed = lerp( shadowed, 1.0, saturate( fadeOutAmt ) );
+
+      static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
+      dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
+
+      // temp for debugging. uncomment one or the other.
+      //float shadowed = static_shadowed;
+      //float shadowed = dynamic_shadowed;
+      float shadowed = min(static_shadowed, dynamic_shadowed);
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )

+ 25 - 2
Templates/Empty/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui

@@ -3309,7 +3309,7 @@
                         HorizSizing = "width";
                         HorizSizing = "width";
                         VertSizing = "bottom";
                         VertSizing = "bottom";
                         Position = "0 0";
                         Position = "0 0";
-                        Extent = "210 71";
+                        Extent = "210 89";
                         
                         
                         new GuiPopUpMenuCtrl() {
                         new GuiPopUpMenuCtrl() {
                            internalName = "blendingTypePopUp";
                            internalName = "blendingTypePopUp";
@@ -3480,7 +3480,7 @@
                            Visible = "1";
                            Visible = "1";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            tooltipprofile = "ToolsGuiDefaultProfile";
                            tooltipprofile = "ToolsGuiDefaultProfile";
-                           ToolTip = "Alows object to cast shadows.";
+                           ToolTip = "Object casts shadows.";
                            hovertime = "1000";
                            hovertime = "1000";
                            text = "Cast Shadows";
                            text = "Cast Shadows";
                            groupNum = "-1";
                            groupNum = "-1";
@@ -3488,6 +3488,29 @@
                            useMouseEvents = "0";
                            useMouseEvents = "0";
                            useInactiveState = "0";
                            useInactiveState = "0";
                         };
                         };
+                        new GuiCheckBoxCtrl() {
+                           canSaveDynamicFields = "0";
+                           internalName = "castDynamicShadows";
+                           Enabled = "1";
+                           isContainer = "0";
+                           Profile = "ToolsGuiCheckBoxProfile";
+                           HorizSizing = "right";
+                           VertSizing = "bottom";
+                           position = "3 70";
+                           Extent = "112 16";
+                           MinExtent = "8 2";
+                           canSave = "1";
+                           Visible = "1";
+                           Command = "MaterialEditorGui.updateActiveMaterial(\"castDynamicShadows\", $ThisControl.getValue());";
+                           tooltipprofile = "ToolsGuiDefaultProfile";
+                           ToolTip = "Object casts dynamic shadows.";
+                           hovertime = "1000";
+                           text = "Dynamic Shadows";
+                           groupNum = "-1";
+                           buttonType = "ToggleButton";
+                           useMouseEvents = "0";
+                           useInactiveState = "0";
+                        };
                         new GuiCheckBoxCtrl() {
                         new GuiCheckBoxCtrl() {
                            canSaveDynamicFields = "0";
                            canSaveDynamicFields = "0";
                            internalName = "doubleSidedCheckBox";
                            internalName = "doubleSidedCheckBox";

+ 1 - 0
Templates/Empty/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -754,6 +754,7 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->transZWriteCheckBox.setValue((%material).translucentZWrite);
    MaterialEditorPropertiesWindow-->transZWriteCheckBox.setValue((%material).translucentZWrite);
    MaterialEditorPropertiesWindow-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
+   MaterialEditorPropertiesWindow-->castDynamicShadows.setValue((%material).castDynamicShadows);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    
    
    switch$((%material).translucentBlendOp)
    switch$((%material).translucentBlendOp)

+ 14 - 8
Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs

@@ -62,9 +62,10 @@ new ShaderData( AL_VectorLightShader )
    OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/vectorLightP.glsl";
    OGLPixelShaderFile  = "shaders/common/lighting/advanced/gl/vectorLightP.glsl";
    
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
-   samplerNames[1] = "$ShadowMap";
-   samplerNames[2] = "$ssaoMask";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[1] = "$shadowMap";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$ssaoMask";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -75,7 +76,8 @@ new CustomMaterial( AL_VectorLightMaterial )
    stateBlock = AL_VectorLightState;
    stateBlock = AL_VectorLightState;
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
-   sampler["ShadowMap"] = "$dynamiclight";
+   sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["ssaoMask"] = "#ssaoMask";
    sampler["ssaoMask"] = "#ssaoMask";
    
    
    target = "lightinfo";
    target = "lightinfo";
@@ -128,8 +130,9 @@ new ShaderData( AL_PointLightShader )
 
 
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -141,6 +144,7 @@ new CustomMaterial( AL_PointLightMaterial )
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    
    target = "lightinfo";
    target = "lightinfo";
@@ -159,8 +163,9 @@ new ShaderData( AL_SpotLightShader )
    
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";   
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    
    pixVersion = 3.0;
    pixVersion = 3.0;
 };
 };
@@ -172,6 +177,7 @@ new CustomMaterial( AL_SpotLightMaterial )
    
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    
    target = "lightinfo";
    target = "lightinfo";

+ 14 - 1
Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl

@@ -28,6 +28,7 @@
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
+#include "../../../gl/torque.glsl"
 
 
 in vec4 wsEyeDir;
 in vec4 wsEyeDir;
 in vec4 ssPos;
 in vec4 ssPos;
@@ -107,6 +108,7 @@ uniform sampler2D prePassBuffer;
 	uniform samplerCube shadowMap;
 	uniform samplerCube shadowMap;
 #else
 #else
 	uniform sampler2D shadowMap;
 	uniform sampler2D shadowMap;
+	uniform sampler2D dynamicShadowMap;
 #endif
 #endif
 
 
 uniform vec4 rtParams0;
 uniform vec4 rtParams0;
@@ -119,6 +121,7 @@ uniform vec2 lightAttenuation;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
 uniform mat3 viewToLightProj;
 uniform mat3 viewToLightProj;
+uniform mat3 dynamicViewToLightProj;
 uniform vec4 lightParams;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
 
 
@@ -175,7 +178,7 @@ void main()
 
 
          vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
          vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
          
          
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowCoord,
                                              shadowSoftness,
                                              shadowSoftness,
@@ -183,6 +186,16 @@ void main()
                                              nDotL,
                                              nDotL,
                                              lightParams.y );
                                              lightParams.y );
 
 
+         vec2 dynamicShadowCoord = decodeShadowCoord( tMul( dynamicViewToLightProj, -lightVec ) ).xy;
+         float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                             ssPos.xy,
+                                             dynamicShadowCoord,
+                                             shadowSoftness,
+                                             distToLight,
+                                             nDotL,
+                                             lightParams.y );
+
+         float shadowed = min(static_shadowed, dynamic_shadowed);
       #endif
       #endif
 
 
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW

+ 17 - 2
Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl

@@ -27,6 +27,7 @@
 #include "shadergen:/autogenConditioners.h"
 #include "shadergen:/autogenConditioners.h"
 #include "softShadow.glsl"
 #include "softShadow.glsl"
 #include "../../../gl/lighting.glsl"
 #include "../../../gl/lighting.glsl"
+#include "../../../gl/torque.glsl"
 
 
 in vec4 wsEyeDir;
 in vec4 wsEyeDir;
 in vec4 ssPos;
 in vec4 ssPos;
@@ -45,6 +46,7 @@ uniform sampler2D cookieMap;
 
 
 uniform sampler2D prePassBuffer;
 uniform sampler2D prePassBuffer;
 uniform sampler2D shadowMap;
 uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 
 uniform vec4 rtParams0;
 uniform vec4 rtParams0;
 
 
@@ -59,6 +61,7 @@ uniform vec4 lightMapParams;
 
 
 uniform vec4 vsFarPlane;
 uniform vec4 vsFarPlane;
 uniform mat4 viewToLightProj;
 uniform mat4 viewToLightProj;
+uniform mat4 dynamicViewToLightProj;
 
 
 uniform vec4 lightParams;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
@@ -70,7 +73,7 @@ void main()
    // Compute scene UV
    // Compute scene UV
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+
    // Sample/unpack the normal/z data
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
    vec3 normal = prepassSample.rgb;
@@ -102,6 +105,10 @@ void main()
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    shadowCoord.y = 1.0f - shadowCoord.y;
    shadowCoord.y = 1.0f - shadowCoord.y;
 
 
+   // Get the dynamic shadow texture coordinate
+   vec4 dynpxlPosLightProj = tMul( dynamicViewToLightProj, vec4( viewSpacePos, 1 ) );
+   vec2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
+   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
    
    
       float shadowed = 1.0;
       float shadowed = 1.0;
@@ -111,7 +118,7 @@ void main()
       // Get a linear depth from the light source.
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
       float distToLight = pxlPosLightProj.z / lightRange;
 
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowCoord,
                                           shadowSoftness,
                                           shadowSoftness,
@@ -119,6 +126,14 @@ void main()
                                           nDotL,
                                           nDotL,
                                           lightParams.y );
                                           lightParams.y );
 
 
+      float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                          ssPos.xy,
+                                          dynshadowCoord,
+                                          shadowSoftness,
+                                          distToLight,
+                                          nDotL,
+                                          lightParams.y );
+      float shadowed = min(static_shadowed, dynamic_shadowed);
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
    vec3 lightcol = lightColor.rgb;
    vec3 lightcol = lightColor.rgb;

+ 138 - 64
Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl

@@ -34,81 +34,78 @@ in vec2 uv0;
 in vec3 wsEyeRay;
 in vec3 wsEyeRay;
 in vec3 vsEyeRay;
 in vec3 vsEyeRay;
 
 
-uniform sampler2D ShadowMap ;
+uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 
 #ifdef USE_SSAO_MASK
 #ifdef USE_SSAO_MASK
 uniform sampler2D ssaoMask ;
 uniform sampler2D ssaoMask ;
 uniform vec4 rtParams2;
 uniform vec4 rtParams2;
 #endif
 #endif
 
 
-uniform sampler2D prePassBuffer;             
+uniform sampler2D prePassBuffer;            
 uniform vec3 lightDirection;
 uniform vec3 lightDirection;
 uniform vec4 lightColor;
 uniform vec4 lightColor;
 uniform float  lightBrightness;
 uniform float  lightBrightness;
 uniform vec4 lightAmbient; 
 uniform vec4 lightAmbient; 
 uniform vec3 eyePosWorld; 
 uniform vec3 eyePosWorld; 
-uniform mat4x4 worldToLightProj;
-uniform vec4 scaleX;
-uniform vec4 scaleY;
-uniform vec4 offsetX;
-uniform vec4 offsetY;
+uniform mat4x4 eyeMat;
 uniform vec4 atlasXOffset;
 uniform vec4 atlasXOffset;
 uniform vec4 atlasYOffset;
 uniform vec4 atlasYOffset;
 uniform vec2 atlasScale;
 uniform vec2 atlasScale;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 lightMapParams;
 uniform vec4 lightMapParams;
 uniform vec2 fadeStartLength;
 uniform vec2 fadeStartLength;
-uniform vec4 farPlaneScalePSSM;
 uniform vec4 overDarkPSSM;
 uniform vec4 overDarkPSSM;
 uniform float shadowSoftness;
 uniform float shadowSoftness;
-
-out vec4 OUT_col;
-
-void main()             
-{
-   // Sample/unpack the normal/z data
-   vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
-   vec3 normal = prepassSample.rgb;
-   float depth = prepassSample.a;
-
-   // Use eye ray to get ws pos
-   vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
-   
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
-
-   #ifdef PSSM_DEBUG_RENDER
-      vec3 debugColor = vec3(0);
-   #endif
    
    
-   #ifdef NO_SHADOW
-
-      // Fully unshadowed.
-      float shadowed = 1.0;
+//static shadowMap
+uniform mat4x4 worldToLightProj;
+uniform vec4 scaleX;
+uniform vec4 scaleY;
+uniform vec4 offsetX;
+uniform vec4 offsetY;
+uniform vec4 farPlaneScalePSSM;
 
 
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = vec3(1.0);
-      #endif
+//dynamic shadowMap
+uniform mat4x4 dynamicWorldToLightProj;
+uniform vec4 dynamicScaleX;
+uniform vec4 dynamicScaleY;
+uniform vec4 dynamicOffsetX;
+uniform vec4 dynamicOffsetY;
+uniform vec4 dynamicFarPlaneScalePSSM;
 
 
-   #else
+vec4 AL_VectorLightShadowCast( sampler2D _sourceshadowMap,
+                                vec2 _texCoord,
+                                mat4 _worldToLightProj,
+                                vec4 _worldPos,
+                                vec4 _scaleX, vec4 _scaleY,
+                                vec4 _offsetX, vec4 _offsetY,
+                                vec4 _farPlaneScalePSSM,
+                                vec4 _atlasXOffset, vec4 _atlasYOffset,
+                                vec2 _atlasScale,
+                                float _shadowSoftness, 
+                                float _dotNL ,
+                                vec4 _overDarkPSSM
+)
+{
 
 
       // Compute shadow map coordinate
       // Compute shadow map coordinate
-      vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos);
+      vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
 
-      // Distance to light, in shadowmap space
+      // Distance to light, in shadowMap space
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
       float distToLight = pxlPosLightProj.z / pxlPosLightProj.w;
          
          
-      // Figure out which split to sample from.  Basically, we compute the shadowmap sample coord
+      // Figure out which split to sample from.  Basically, we compute the shadowMap sample coord
       // for all of the splits and then check if its valid.  
       // for all of the splits and then check if its valid.  
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       vec4 farPlaneDists = vec4( distToLight );      
       vec4 farPlaneDists = vec4( distToLight );      
-      shadowCoordX *= scaleX;
-      shadowCoordY *= scaleY;
-      shadowCoordX += offsetX;
-      shadowCoordY += offsetY;
-      farPlaneDists *= farPlaneScalePSSM;
+      shadowCoordX *= _scaleX;
+      shadowCoordY *= _scaleY;
+      shadowCoordX += _offsetX;
+      shadowCoordY += _offsetY;
+      farPlaneDists *= _farPlaneScalePSSM;
       
       
       // If the shadow sample is within -1..1 and the distance 
       // If the shadow sample is within -1..1 and the distance 
       // to the light for this pixel is less than the far plane 
       // to the light for this pixel is less than the far plane 
@@ -132,6 +129,11 @@ void main()
       else
       else
          finalMask = vec4(0, 0, 0, 1);
          finalMask = vec4(0, 0, 0, 1);
          
          
+      vec3 debugColor = vec3(0);
+   
+      #ifdef NO_SHADOW
+         debugColor = vec3(1.0);
+      #endif
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
          if ( finalMask.x > 0 )
@@ -144,50 +146,122 @@ void main()
             debugColor += vec3( 1, 1, 0 );
             debugColor += vec3( 1, 1, 0 );
       #endif
       #endif
 
 
-      // Here we know what split we're sampling from, so recompute the texcoord location
+      // Here we know what split we're sampling from, so recompute the _texCoord location
       // Yes, we could just use the result from above, but doing it this way actually saves
       // Yes, we could just use the result from above, but doing it this way actually saves
       // shader instructions.
       // shader instructions.
       vec2 finalScale;
       vec2 finalScale;
-      finalScale.x = dot(finalMask, scaleX);
-      finalScale.y = dot(finalMask, scaleY);
+      finalScale.x = dot(finalMask, _scaleX);
+      finalScale.y = dot(finalMask, _scaleY);
 
 
       vec2 finalOffset;
       vec2 finalOffset;
-      finalOffset.x = dot(finalMask, offsetX);
-      finalOffset.y = dot(finalMask, offsetY);
+      finalOffset.x = dot(finalMask, _offsetX);
+      finalOffset.y = dot(finalMask, _offsetY);
 
 
       vec2 shadowCoord;                  
       vec2 shadowCoord;                  
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord += finalOffset;
       shadowCoord += finalOffset;
 
 
-      // Convert to texcoord space
+      // Convert to _texCoord space
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord.y = 1.0f - shadowCoord.y;
       shadowCoord.y = 1.0f - shadowCoord.y;
 
 
       // Move around inside of atlas 
       // Move around inside of atlas 
       vec2 aOffset;
       vec2 aOffset;
-      aOffset.x = dot(finalMask, atlasXOffset);
-      aOffset.y = dot(finalMask, atlasYOffset);
+      aOffset.x = dot(finalMask, _atlasXOffset);
+      aOffset.y = dot(finalMask, _atlasYOffset);
 
 
-      shadowCoord *= atlasScale;
+      shadowCoord *= _atlasScale;
       shadowCoord += aOffset;
       shadowCoord += aOffset;
               
               
       // Each split has a different far plane, take this into account.
       // Each split has a different far plane, take this into account.
-      float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
+      float farPlaneScale = dot( _farPlaneScalePSSM, finalMask );
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
       
       
-      float shadowed = softShadow_filter(   ShadowMap,
-                                             uv0.xy,
-                                             shadowCoord,
-                                             farPlaneScale * shadowSoftness,
-                                             distToLight,
-                                             dotNL,
-                                             dot( finalMask, overDarkPSSM ) );
-  
+      return vec4(debugColor,
+	                             softShadow_filter(  _sourceshadowMap,
+                                 _texCoord,
+                                 shadowCoord,
+                                 farPlaneScale * _shadowSoftness,
+                                 distToLight,
+                                 _dotNL,
+                                 dot( finalMask, _overDarkPSSM ) ) );
+}
+
+out vec4 OUT_col;
+void main()             
+{   
+   // Sample/unpack the normal/z data
+   vec4 prepassSample = prepassUncondition( prePassBuffer, uv0 );
+   vec3 normal = prepassSample.rgb;
+   float depth = prepassSample.a;
+
+   // Use eye ray to get ws pos
+   vec4 worldPos = vec4(eyePosWorld + wsEyeRay * depth, 1.0f);
+   
+   // Get the light attenuation.
+   float dotNL = dot(-lightDirection, normal);
+
+   #ifdef PSSM_DEBUG_RENDER
+      vec3 debugColor = vec3(0);
+   #endif
+   
+   #ifdef NO_SHADOW
+
+      // Fully unshadowed.
+      float shadowed = 1.0;
+
+      #ifdef PSSM_DEBUG_RENDER
+         debugColor = vec3(1.0);
+      #endif
+
+   #else
+
+      vec4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
+                                                        uv0.xy,
+                                                        worldToLightProj,
+                                                        worldPos,
+                                                        scaleX, scaleY,
+                                                        offsetX, offsetY,
+                                                        farPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
+
+                                             
+      vec4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
+                                                        uv0.xy,
+                                                        dynamicWorldToLightProj,
+                                                        worldPos,
+                                                        dynamicScaleX, dynamicScaleY,
+                                                        dynamicOffsetX, dynamicOffsetY,
+                                                        dynamicFarPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);  
+      
+      float static_shadowed = static_shadowed_colors.a;
+      float dynamic_shadowed = dynamic_shadowed_colors.a;
+	  
+      #ifdef PSSM_DEBUG_RENDER
+	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+      #endif
+	   
       // Fade out the shadow at the end of the range.
       // Fade out the shadow at the end of the range.
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
-      shadowed = mix( shadowed, 1.0, saturate( fadeOutAmt ) );
-
+      
+      static_shadowed = mix( static_shadowed, 1.0, saturate( fadeOutAmt ) );
+      dynamic_shadowed = mix( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
+            
+      // temp for debugging. uncomment one or the other.
+      //float shadowed = static_shadowed;
+      //float shadowed = dynamic_shadowed;
+      float shadowed = min(static_shadowed, dynamic_shadowed);
+      
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )
             debugColor = vec3(1.0);
             debugColor = vec3(1.0);
@@ -228,7 +302,7 @@ void main()
    #ifdef PSSM_DEBUG_RENDER
    #ifdef PSSM_DEBUG_RENDER
       lightColorOut = debugColor;
       lightColorOut = debugColor;
    #endif
    #endif
-   
+
    OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult );  
    OUT_col = lightinfoCondition( lightColorOut, Sat_NL_Att, specular, addToResult );  
    
    
 }
 }

+ 19 - 5
Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 
 struct ConvexConnectP
 struct ConvexConnectP
 {
 {
@@ -40,7 +40,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
-uniform samplerCUBE cookieMap : register(S2);
+uniform samplerCUBE cookieMap : register(S3);
 
 
 #endif
 #endif
 
 
@@ -114,6 +114,7 @@ float4 main(   ConvexConnectP IN,
                   uniform samplerCUBE shadowMap : register(S1),
                   uniform samplerCUBE shadowMap : register(S1),
                #else
                #else
                   uniform sampler2D shadowMap : register(S1),
                   uniform sampler2D shadowMap : register(S1),
+                  uniform sampler2D dynamicShadowMap : register(S2),
                #endif
                #endif
 
 
                uniform float4 rtParams0,
                uniform float4 rtParams0,
@@ -127,6 +128,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform float4 vsFarPlane,
                uniform float4 vsFarPlane,
                uniform float3x3 viewToLightProj,
                uniform float3x3 viewToLightProj,
+               uniform float3x3 dynamicViewToLightProj,
 
 
                uniform float4 lightParams,
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
                uniform float shadowSoftness ) : COLOR0
@@ -134,7 +136,7 @@ float4 main(   ConvexConnectP IN,
    // Compute scene UV
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+      
    // Sample/unpack the normal/z data
    // Sample/unpack the normal/z data
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float3 normal = prepassSample.rgb;
    float3 normal = prepassSample.rgb;
@@ -178,9 +180,9 @@ float4 main(   ConvexConnectP IN,
          
          
       #else
       #else
 
 
+         // Static
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
-         
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowCoord,
                                              shadowSoftness,
                                              shadowSoftness,
@@ -188,6 +190,18 @@ float4 main(   ConvexConnectP IN,
                                              nDotL,
                                              nDotL,
                                              lightParams.y );
                                              lightParams.y );
 
 
+         // Dynamic
+         float2 dynamicShadowCoord = decodeShadowCoord( mul( dynamicViewToLightProj, -lightVec ) ).xy;
+         float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                             ssPos.xy,
+                                             dynamicShadowCoord,
+                                             shadowSoftness,
+                                             distToLight,
+                                             nDotL,
+                                             lightParams.y );
+
+         float shadowed = min(static_shadowed, dynamic_shadowed);
+
       #endif
       #endif
 
 
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW

+ 1 - 1
Templates/Full/game/shaders/common/lighting/advanced/softShadow.hlsl

@@ -69,7 +69,7 @@ static float2 sNonUniformTaps[NUM_PRE_TAPS] =
 
 
 /// The texture used to do per-pixel pseudorandom
 /// The texture used to do per-pixel pseudorandom
 /// rotations of the filter taps.
 /// rotations of the filter taps.
-uniform sampler2D gTapRotationTex : register(S3);
+uniform sampler2D gTapRotationTex : register(S4);
 
 
 
 
 float softShadow_sampleTaps(  sampler2D shadowMap,
 float softShadow_sampleTaps(  sampler2D shadowMap,

+ 19 - 4
Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 
 struct ConvexConnectP
 struct ConvexConnectP
 {
 {
@@ -39,7 +39,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 #ifdef USE_COOKIE_TEX
 
 
 /// The texture for cookie rendering.
 /// The texture for cookie rendering.
-uniform sampler2D cookieMap : register(S2);
+uniform sampler2D cookieMap : register(S3);
 
 
 #endif
 #endif
 
 
@@ -48,6 +48,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D shadowMap : register(S1),
                uniform sampler2D shadowMap : register(S1),
+               uniform sampler2D dynamicShadowMap : register(S2),
 
 
                uniform float4 rtParams0,
                uniform float4 rtParams0,
 
 
@@ -62,6 +63,7 @@ float4 main(   ConvexConnectP IN,
 
 
                uniform float4 vsFarPlane,
                uniform float4 vsFarPlane,
                uniform float4x4 viewToLightProj,
                uniform float4x4 viewToLightProj,
+               uniform float4x4 dynamicViewToLightProj,
 
 
                uniform float4 lightParams,
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
                uniform float shadowSoftness ) : COLOR0
@@ -101,6 +103,11 @@ float4 main(   ConvexConnectP IN,
    float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
    float2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
    shadowCoord.y = 1.0f - shadowCoord.y;
    shadowCoord.y = 1.0f - shadowCoord.y;
 
 
+   // Get the dynamic shadow texture coordinate
+   float4 dynpxlPosLightProj = mul( dynamicViewToLightProj, float4( viewSpacePos, 1 ) );
+   float2 dynshadowCoord = ( ( dynpxlPosLightProj.xy / dynpxlPosLightProj.w ) * 0.5 ) + float2( 0.5, 0.5 );
+   dynshadowCoord.y = 1.0f - dynshadowCoord.y;
+   
    #ifdef NO_SHADOW
    #ifdef NO_SHADOW
    
    
       float shadowed = 1.0;
       float shadowed = 1.0;
@@ -110,14 +117,22 @@ float4 main(   ConvexConnectP IN,
       // Get a linear depth from the light source.
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
       float distToLight = pxlPosLightProj.z / lightRange;
 
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowCoord,
                                           shadowSoftness,
                                           shadowSoftness,
                                           distToLight,
                                           distToLight,
                                           nDotL,
                                           nDotL,
                                           lightParams.y );
                                           lightParams.y );
-
+                                          
+      float dynamic_shadowed = softShadow_filter( dynamicShadowMap,
+                                          ssPos.xy,
+                                          dynshadowCoord,
+                                          shadowSoftness,
+                                          distToLight,
+                                          nDotL,
+                                          lightParams.y );
+      float shadowed = min(static_shadowed, dynamic_shadowed);
    #endif // !NO_SHADOW
    #endif // !NO_SHADOW
    
    
    float3 lightcol = lightColor.rgb;
    float3 lightcol = lightColor.rgb;

+ 138 - 64
Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl

@@ -30,68 +30,31 @@
 #include "softShadow.hlsl"
 #include "softShadow.hlsl"
 
 
 
 
-uniform sampler2D ShadowMap : register(S1);
+uniform sampler2D shadowMap : register(S1);
+uniform sampler2D dynamicShadowMap : register(S2);
 
 
 #ifdef USE_SSAO_MASK
 #ifdef USE_SSAO_MASK
-uniform sampler2D ssaoMask : register(S2);
+uniform sampler2D ssaoMask : register(S3);
 uniform float4 rtParams2;
 uniform float4 rtParams2;
 #endif
 #endif
 
 
-
-float4 main( FarFrustumQuadConnectP IN,
-
-             uniform sampler2D prePassBuffer : register(S0),
-             
-             uniform float3 lightDirection,
-             uniform float4 lightColor,
-             uniform float  lightBrightness,
-             uniform float4 lightAmbient,
-             
-             uniform float3 eyePosWorld,
-             
-             uniform float4x4 worldToLightProj,
-
-             uniform float4 scaleX,
-             uniform float4 scaleY,
-             uniform float4 offsetX,
-             uniform float4 offsetY,
-             uniform float4 atlasXOffset,
-             uniform float4 atlasYOffset,
-             uniform float2 atlasScale,
-             uniform float4 zNearFarInvNearFar,
-             uniform float4 lightMapParams,
-
-             uniform float2 fadeStartLength,
-             uniform float4 farPlaneScalePSSM,
-             uniform float4 overDarkPSSM,
-             uniform float shadowSoftness ) : COLOR0
+float4 AL_VectorLightShadowCast( sampler2D sourceShadowMap,
+                                float2 texCoord,
+                                float4x4 worldToLightProj,
+                                float4 worldPos,
+                                float4 scaleX,
+                                float4 scaleY,
+                                float4 offsetX,
+                                float4 offsetY,
+                                float4 farPlaneScalePSSM,
+                                float4 atlasXOffset,
+                                float4 atlasYOffset,
+                                float2 atlasScale,
+                                float shadowSoftness, 
+                                float dotNL ,
+                                float4 overDarkPSSM
+)
 {
 {
-   // Sample/unpack the normal/z data
-   float4 prepassSample = prepassUncondition( prePassBuffer, IN.uv0 );
-   float3 normal = prepassSample.rgb;
-   float depth = prepassSample.a;
-
-   // Use eye ray to get ws pos
-   float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
-   
-   // Get the light attenuation.
-   float dotNL = dot(-lightDirection, normal);
-
-   #ifdef PSSM_DEBUG_RENDER
-      float3 debugColor = 0;
-   #endif
-   
-   #ifdef NO_SHADOW
-
-      // Fully unshadowed.
-      float shadowed = 1.0;
-
-      #ifdef PSSM_DEBUG_RENDER
-         debugColor = 1.0;
-      #endif
-
-   #else
-
       // Compute shadow map coordinate
       // Compute shadow map coordinate
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
@@ -132,6 +95,11 @@ float4 main( FarFrustumQuadConnectP IN,
       else
       else
          finalMask = float4(0, 0, 0, 1);
          finalMask = float4(0, 0, 0, 1);
          
          
+      float3 debugColor = float3(0,0,0);
+   
+      #ifdef NO_SHADOW
+         debugColor = float3(1.0,1.0,1.0);
+      #endif
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
          if ( finalMask.x > 0 )
@@ -174,19 +142,125 @@ float4 main( FarFrustumQuadConnectP IN,
       // Each split has a different far plane, take this into account.
       // Each split has a different far plane, take this into account.
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       distToLight *= farPlaneScale;
       distToLight *= farPlaneScale;
+
+      return float4(debugColor,
+                    softShadow_filter(  sourceShadowMap,
+                                 texCoord,
+                                 shadowCoord,
+                                 farPlaneScale * shadowSoftness,
+                                 distToLight,
+                                 dotNL,
+                                 dot( finalMask, overDarkPSSM ) ) );
+};
+
+float4 main( FarFrustumQuadConnectP IN,
+
+             uniform sampler2D prePassBuffer : register(S0),
+             
+             uniform float3 lightDirection,
+             uniform float4 lightColor,
+             uniform float  lightBrightness,
+             uniform float4 lightAmbient,
+             uniform float4x4 eyeMat,
+             
+             uniform float3 eyePosWorld,
+             uniform float4 atlasXOffset,
+             uniform float4 atlasYOffset,
+             uniform float2 atlasScale,
+             uniform float4 zNearFarInvNearFar,
+             uniform float4 lightMapParams,
+             uniform float2 fadeStartLength,
+             uniform float4 overDarkPSSM,
+             uniform float shadowSoftness,
+
+             // Static Shadows
+             uniform float4x4 worldToLightProj,
+             uniform float4 scaleX,
+             uniform float4 scaleY,
+             uniform float4 offsetX,
+             uniform float4 offsetY,
+             uniform float4 farPlaneScalePSSM,
+
+             // Dynamic Shadows
+             uniform float4x4 dynamicWorldToLightProj,
+             uniform float4 dynamicScaleX,
+             uniform float4 dynamicScaleY,
+             uniform float4 dynamicOffsetX,
+             uniform float4 dynamicOffsetY,
+             uniform float4 dynamicFarPlaneScalePSSM
+
+            ) : COLOR0
+{   
+   // Sample/unpack the normal/z data
+   float4 prepassSample = prepassUncondition( prePassBuffer, IN.uv0 );
+   float3 normal = prepassSample.rgb;
+   float depth = prepassSample.a;
+
+   // Use eye ray to get ws pos
+   float4 worldPos = float4(eyePosWorld + IN.wsEyeRay * depth, 1.0f);
+   
+   // Get the light attenuation.
+   float dotNL = dot(-lightDirection, normal);
+
+   #ifdef PSSM_DEBUG_RENDER
+      float3 debugColor = float3(0,0,0);
+   #endif
+   
+   #ifdef NO_SHADOW
+
+      // Fully unshadowed.
+      float shadowed = 1.0;
+
+      #ifdef PSSM_DEBUG_RENDER
+         debugColor = float3(1.0,1.0,1.0);
+      #endif
+
+   #else
+      
+      float4 static_shadowed_colors = AL_VectorLightShadowCast( shadowMap,
+                                                        IN.uv0.xy,
+                                                        worldToLightProj,
+                                                        worldPos,
+                                                        scaleX, scaleY,
+                                                        offsetX, offsetY,
+                                                        farPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
+
+      float4 dynamic_shadowed_colors = AL_VectorLightShadowCast( dynamicShadowMap,
+                                                        IN.uv0.xy,
+                                                        dynamicWorldToLightProj,
+                                                        worldPos,
+                                                        dynamicScaleX, dynamicScaleY,
+                                                        dynamicOffsetX, dynamicOffsetY,
+                                                        dynamicFarPlaneScalePSSM,
+                                                        atlasXOffset, atlasYOffset,
+                                                        atlasScale,
+                                                        shadowSoftness, 
+                                                        dotNL,
+                                                        overDarkPSSM);
       
       
-      float shadowed = softShadow_filter(   ShadowMap,
-                                             IN.uv0.xy,
-                                             shadowCoord,
-                                             farPlaneScale * shadowSoftness,
-                                             distToLight,
-                                             dotNL,
-                                             dot( finalMask, overDarkPSSM ) );
+      float static_shadowed = static_shadowed_colors.a;
+      float dynamic_shadowed = dynamic_shadowed_colors.a;
+	  
+      #ifdef PSSM_DEBUG_RENDER
+	     debugColor = static_shadowed_colors.rgb*0.5+dynamic_shadowed_colors.rgb*0.5;
+      #endif
   
   
       // Fade out the shadow at the end of the range.
       // Fade out the shadow at the end of the range.
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
       float fadeOutAmt = ( zDist.x - fadeStartLength.x ) * fadeStartLength.y;
-      shadowed = lerp( shadowed, 1.0, saturate( fadeOutAmt ) );
+
+      static_shadowed = lerp( static_shadowed, 1.0, saturate( fadeOutAmt ) );
+      dynamic_shadowed = lerp( dynamic_shadowed, 1.0, saturate( fadeOutAmt ) );
+
+      // temp for debugging. uncomment one or the other.
+      //float shadowed = static_shadowed;
+      //float shadowed = dynamic_shadowed;
+      float shadowed = min(static_shadowed, dynamic_shadowed);
 
 
       #ifdef PSSM_DEBUG_RENDER
       #ifdef PSSM_DEBUG_RENDER
          if ( fadeOutAmt > 1.0 )
          if ( fadeOutAmt > 1.0 )

+ 25 - 2
Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui

@@ -3309,7 +3309,7 @@
                         HorizSizing = "width";
                         HorizSizing = "width";
                         VertSizing = "bottom";
                         VertSizing = "bottom";
                         Position = "0 0";
                         Position = "0 0";
-                        Extent = "210 71";
+                        Extent = "210 89";
                         
                         
                         new GuiPopUpMenuCtrl() {
                         new GuiPopUpMenuCtrl() {
                            internalName = "blendingTypePopUp";
                            internalName = "blendingTypePopUp";
@@ -3480,7 +3480,7 @@
                            Visible = "1";
                            Visible = "1";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            tooltipprofile = "ToolsGuiDefaultProfile";
                            tooltipprofile = "ToolsGuiDefaultProfile";
-                           ToolTip = "Alows object to cast shadows.";
+                           ToolTip = "Object casts shadows.";
                            hovertime = "1000";
                            hovertime = "1000";
                            text = "Cast Shadows";
                            text = "Cast Shadows";
                            groupNum = "-1";
                            groupNum = "-1";
@@ -3488,6 +3488,29 @@
                            useMouseEvents = "0";
                            useMouseEvents = "0";
                            useInactiveState = "0";
                            useInactiveState = "0";
                         };
                         };
+                        new GuiCheckBoxCtrl() {
+                           canSaveDynamicFields = "0";
+                           internalName = "castDynamicShadows";
+                           Enabled = "1";
+                           isContainer = "0";
+                           Profile = "ToolsGuiCheckBoxProfile";
+                           HorizSizing = "right";
+                           VertSizing = "bottom";
+                           position = "3 70";
+                           Extent = "112 16";
+                           MinExtent = "8 2";
+                           canSave = "1";
+                           Visible = "1";
+                           Command = "MaterialEditorGui.updateActiveMaterial(\"castDynamicShadows\", $ThisControl.getValue());";
+                           tooltipprofile = "ToolsGuiDefaultProfile";
+                           ToolTip = "Object casts dynamic shadows.";
+                           hovertime = "1000";
+                           text = "Dynamic Shadows";
+                           groupNum = "-1";
+                           buttonType = "ToggleButton";
+                           useMouseEvents = "0";
+                           useInactiveState = "0";
+                        };
                         new GuiCheckBoxCtrl() {
                         new GuiCheckBoxCtrl() {
                            canSaveDynamicFields = "0";
                            canSaveDynamicFields = "0";
                            internalName = "doubleSidedCheckBox";
                            internalName = "doubleSidedCheckBox";

+ 1 - 0
Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs

@@ -754,6 +754,7 @@ function MaterialEditorGui::guiSync( %this, %material )
    MaterialEditorPropertiesWindow-->transZWriteCheckBox.setValue((%material).translucentZWrite);
    MaterialEditorPropertiesWindow-->transZWriteCheckBox.setValue((%material).translucentZWrite);
    MaterialEditorPropertiesWindow-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
+   MaterialEditorPropertiesWindow-->castDynamicShadows.setValue((%material).castDynamicShadows);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    
    
    switch$((%material).translucentBlendOp)
    switch$((%material).translucentBlendOp)