瀏覽代碼

Merge pull request #1442 from Azaezel/shadow_caching

This all seems to work pretty well.
Areloch 10 年之前
父節點
當前提交
92aa785bb2
共有 61 個文件被更改,包括 1416 次插入392 次删除
  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. 1 0
      Templates/Full/game/art/shapes/Cheetah/materials.cs
  46. 2 0
      Templates/Full/game/art/shapes/actors/Soldier/materials.cs
  47. 1 0
      Templates/Full/game/art/shapes/weapons/Grenade/materials.cs
  48. 1 0
      Templates/Full/game/art/shapes/weapons/Lurker/materials.cs
  49. 1 0
      Templates/Full/game/art/shapes/weapons/ProxMine/materials.cs
  50. 2 0
      Templates/Full/game/art/shapes/weapons/Ryder/materials.cs
  51. 3 0
      Templates/Full/game/art/shapes/weapons/Turret/materials.cs
  52. 14 8
      Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs
  53. 14 1
      Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl
  54. 17 2
      Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl
  55. 138 64
      Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl
  56. 19 5
      Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl
  57. 1 1
      Templates/Full/game/shaders/common/lighting/advanced/softShadow.hlsl
  58. 19 4
      Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl
  59. 140 66
      Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl
  60. 25 2
      Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  61. 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 ),
       mBrightness( 1.0f ),
       mCastShadows( false ),
+      mStaticRefreshFreq( 250 ),
+      mDynamicRefreshFreq( 8 ),
       mPriority( 1.0f ),
       mAnimationData( 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( "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( "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. "
 		  "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->writeFlag( mCastShadows );
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
 
       stream->write( mPriority );      
 
@@ -322,6 +328,8 @@ void LightBase::unpackUpdate( NetConnection *conn, BitStream *stream )
       stream->read( &mColor );
       stream->read( &mBrightness );      
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
 
       stream->read( &mPriority );      
       

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

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

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

@@ -36,6 +36,8 @@ LightDescription::LightDescription()
    brightness( 1.0f ),
    range( 5.0f ),
    castShadows( false ),
+   mStaticRefreshFreq( 250 ),
+   mDynamicRefreshFreq( 8 ),
    animationData( NULL ),
    animationDataId( 0 ),
    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( "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( "staticRefreshFreq", TypeS32, Offset( mStaticRefreshFreq, LightDescription ), "static shadow refresh rate (milliseconds)" );
+      addField( "dynamicRefreshFreq", TypeS32, Offset( mDynamicRefreshFreq, LightDescription ), "dynamic shadow refresh rate (milliseconds)" );
 
    endGroup( "Light" );
 
@@ -153,6 +157,8 @@ void LightDescription::packData( BitStream *stream )
    stream->write( brightness );
    stream->write( range );
    stream->writeFlag( castShadows );
+   stream->write(mStaticRefreshFreq);
+   stream->write(mDynamicRefreshFreq);
 
    stream->write( animationPeriod );
    stream->write( animationPhase );
@@ -181,6 +187,8 @@ void LightDescription::unpackData( BitStream *stream )
    stream->read( &brightness );     
    stream->read( &range );
    castShadows = stream->readFlag();
+   stream->read(&mStaticRefreshFreq);
+   stream->read(&mDynamicRefreshFreq);
 
    stream->read( &animationPeriod );
    stream->read( &animationPhase );
@@ -200,6 +208,8 @@ void LightDescription::submitLight( LightState *state, const MatrixF &xfm, Light
    li->setRange( range );
    li->setColor( color );
    li->setCastShadows( castShadows );
+   li->setStaticRefreshFreq(mStaticRefreshFreq);
+   li->setDynamicRefreshFreq(mDynamicRefreshFreq);
    li->setTransform( xfm );
 
    if ( animationData )

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

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

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

@@ -116,6 +116,8 @@ void PointLight::_conformLights()
 
    mLight->setBrightness( mBrightness );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
    mLight->setPriority( mPriority );
 
    // 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->setBrightness( mBrightness );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
    mLight->setPriority( mPriority );
 
    mOuterConeAngle = getMax( 0.01f, mOuterConeAngle );

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

@@ -144,6 +144,8 @@ ScatterSky::ScatterSky()
    mBrightness = 1.0f;
 
    mCastShadows = true;
+   mStaticRefreshFreq = 8;
+   mDynamicRefreshFreq = 8;
    mDirty = true;
 
    mLight = LightManager::createLightInfo();
@@ -264,6 +266,8 @@ void ScatterSky::_conformLights()
    mLight->setAmbient( mAmbientColor );
    mLight->setColor( mSunColor );
    mLight->setCastShadows( mCastShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
 
    FogData fog = getSceneManager()->getFogData();
    fog.color = mFogColor;
@@ -374,6 +378,9 @@ void ScatterSky::initPersistFields()
       addField( "castShadows", TypeBool, Offset( mCastShadows, ScatterSky ),
          "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 ),
          "The brightness of the ScatterSky's light object." );
 
@@ -480,6 +487,8 @@ U32 ScatterSky::packUpdate(NetConnection *con, U32 mask, BitStream *stream)
       stream->write( mBrightness );
 
       stream->writeFlag( mCastShadows );
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
 
       stream->write( mFlareScale );
 
@@ -581,6 +590,8 @@ void ScatterSky::unpackUpdate(NetConnection *con, BitStream *stream)
       stream->read( &mBrightness );
 
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
 
       stream->read( &mFlareScale );
 

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

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

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

@@ -66,6 +66,8 @@ Sun::Sun()
    mSunAzimuth = 0.0f;
    mSunElevation = 35.0f;
    mCastShadows = true;
+   mStaticRefreshFreq = 250;
+   mDynamicRefreshFreq = 8;
 
    mAnimateSun = false;
    mTotalTime = 0.0f;
@@ -163,7 +165,10 @@ void Sun::initPersistFields()
          "Adjust the Sun's global contrast/intensity");      
 
       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" );
 
@@ -220,7 +225,9 @@ U32 Sun::packUpdate(NetConnection *conn, U32 mask, BitStream *stream )
       stream->write( mLightColor );
       stream->write( mLightAmbient );
       stream->write( mBrightness );      
-      stream->writeFlag( mCastShadows );
+      stream->writeFlag( mCastShadows ); 
+      stream->write(mStaticRefreshFreq);
+      stream->write(mDynamicRefreshFreq);
       stream->write( mFlareScale );
 
       if ( stream->writeFlag( mFlareData ) )
@@ -254,6 +261,8 @@ void Sun::unpackUpdate( NetConnection *conn, BitStream *stream )
       stream->read( &mLightAmbient );
       stream->read( &mBrightness );      
       mCastShadows = stream->readFlag();
+      stream->read(&mStaticRefreshFreq);
+      stream->read(&mDynamicRefreshFreq);
       stream->read( &mFlareScale );
 
       if ( stream->readFlag() )
@@ -426,6 +435,8 @@ void Sun::_conformLights()
    // directional color are the same.
    bool castShadows = mLightColor != mLightAmbient && mCastShadows; 
    mLight->setCastShadows( castShadows );
+   mLight->setStaticRefreshFreq(mStaticRefreshFreq);
+   mLight->setDynamicRefreshFreq(mDynamicRefreshFreq);
 }
 
 void Sun::_initCorona()

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

@@ -65,6 +65,8 @@ protected:
    F32  mEndElevation;
 
    bool mCastShadows;
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
 
    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() ) )
          continue;
 
+      if( state->getCullingState().isOccludedWithExtraPlanesCull( mBatches[i]->getWorldBox() ) )
+         continue;
+
       mBatches[i]->render( state );
       renderedItems += mBatches[i]->getItemCount();
    }

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

@@ -197,6 +197,10 @@ void Forest::prepRenderImage( SceneRenderState *state )
          if ( smDisableImposters )
             continue;
 
+         // if cell are to far for largest item, then skip out.
+         if( TSShapeInstance::smLastPixelSize < TSShapeInstance::smSmallestVisiblePixelSize )
+            continue;
+
          PROFILE_SCOPE(Forest_RenderBatches);
 
          // 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
    ShadowMapParams *lsp = light->getExtended<ShadowMapParams>();
    LightShadowMap *lsm = lsp->getShadowMap();
+   LightShadowMap *dynamicShadowMap = lsp->getShadowMap(true);
 
    // Get the right shadow type.
    ShadowType shadowType = ShadowType_None;
-   if (  light->getCastShadows() && 
+   if (  light->getCastShadows() &&  
          lsm && lsm->hasShadowTex() &&
          !ShadowMapPass::smDisableShadows )
       shadowType = lsm->getShadowType();
@@ -203,6 +204,7 @@ void AdvancedLightBinManager::addLight( LightInfo *light )
    LightBinEntry lEntry;
    lEntry.lightInfo = light;
    lEntry.shadowMap = lsm;
+   lEntry.dynamicShadowMap = dynamicShadowMap;
    lEntry.lightMaterial = _getLightMaterial( lightType, shadowType, lsp->hasCookieTex() );
 
    if( lightType == LightInfo::Spot )
@@ -325,10 +327,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
       setupSGData( sgData, state, curLightInfo );
       curLightMat->setLightParameters( curLightInfo, state, worldToCameraXfm );
       mShadowManager->setLightShadowMap( curEntry.shadowMap );
+      mShadowManager->setLightDynamicShadowMap( curEntry.dynamicShadowMap );
 
       // Let the shadow know we're about to render from it.
       if ( curEntry.shadowMap )
          curEntry.shadowMap->preLightRender();
+      if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->preLightRender();
 
       // Set geometry
       GFX->setVertexBuffer( curEntry.vertBuffer );
@@ -351,10 +355,12 @@ void AdvancedLightBinManager::render( SceneRenderState *state )
       // Tell it we're done rendering.
       if ( curEntry.shadowMap )
          curEntry.shadowMap->postLightRender();
+      if ( curEntry.dynamicShadowMap ) curEntry.dynamicShadowMap->postLightRender();
    }
 
    // Set NULL for active shadow map (so nothing gets confused)
    mShadowManager->setLightShadowMap(NULL);
+   mShadowManager->setLightDynamicShadowMap(NULL);
    GFX->setVertexBuffer( NULL );
    GFX->setPrimitiveBuffer( NULL );
 

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

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

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

@@ -357,10 +357,13 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
    LightingShaderConstants *lsc = getLightingShaderConstants(shaderConsts);
 
    LightShadowMap *lsm = SHADOWMGR->getCurrentShadowMap();
+   LightShadowMap *dynamicShadowMap = SHADOWMGR->getCurrentDynamicShadowMap();
 
    LightInfo *light;
-   if ( lsm )
+   if (lsm)
       light = lsm->getLightInfo();
+   else if ( dynamicShadowMap )
+      light = dynamicShadowMap->getLightInfo();
    else
    {
       light = sgData.lights[0];
@@ -385,10 +388,11 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
                         lsc->mLightInvRadiusSqSC,
                         lsc->mLightSpotDirSC,
                         lsc->mLightSpotAngleSC,
-						lsc->mLightSpotFalloffSC,
+                        lsc->mLightSpotFalloffSC,
                         shaderConsts );
 
-   if ( lsm && light->getCastShadows() )
+   // Static
+   if (lsm && light->getCastShadows())
    {
       if (  lsc->mWorldToLightProjSC->isValid() )
          shaderConsts->set(   lsc->mWorldToLightProjSC, 
@@ -426,6 +430,46 @@ void AdvancedLightManager::setLightInfo(  ProcessedMaterial *pmat,
                               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)
@@ -454,22 +498,34 @@ bool AdvancedLightManager::setTextureStage(  const SceneData &sgData,
                                              ShaderConstHandles *handles )
 {
    LightShadowMap* lsm = SHADOWMGR->getCurrentShadowMap();
+   LightShadowMap* dynamicShadowMap = SHADOWMGR->getCurrentDynamicShadowMap();
 
    // Assign Shadowmap, if it exists
    LightingShaderConstants* lsc = getLightingShaderConstants(shaderConsts);
    if ( !lsc )
       return false;
 
-   if ( lsm && lsm->getLightInfo()->getCastShadows() )
-      return lsm->setTextureStage( currTexFlag, lsc );
-
-
    if ( currTexFlag == Material::DynamicLight )
    {
+      // Static
+      if ( lsm && lsm->getLightInfo()->getCastShadows() )
+         return lsm->setTextureStage( currTexFlag, lsc );
+
       S32 reg = lsc->mShadowMapSC->getSamplerRegister();
    	if ( reg != -1 )
       	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;
    }
    else if ( currTexFlag == Material::DynamicLightMask )

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

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

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

@@ -131,6 +131,9 @@ protected:
 
    bool mCastShadows;
 
+   S32 mStaticRefreshFreq;
+   S32 mDynamicRefreshFreq;
+
    ::Vector<LightInfoEx*> mExtended;
 
    /// The priority of this light used for
@@ -190,6 +193,12 @@ public:
 
    bool getCastShadows() const { return mCastShadows; }
    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; }
    F32 getPriority() const { return mPriority; }

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

@@ -92,14 +92,17 @@ LightShadowMap::LightShadowMap( LightInfo *light )
       mVizQuery( NULL ),
       mWasOccluded( false ),
       mLastScreenSize( 0.0f ),
-      mLastPriority( 0.0f )
+      mLastPriority( 0.0f ),
+      mIsDynamic( false )
 {
    GFXTextureManager::addEventDelegate( this, &LightShadowMap::_onTextureEvent );
 
    mTarget = GFX->allocRenderToTextureTarget();
    mVizQuery = GFX->createOcclusionQuery();
 
-   smShadowMaps.push_back( this );
+   smShadowMaps.push_back(this);
+   mStaticRefreshTimer = PlatformTimer::create();
+   mDynamicRefreshTimer = PlatformTimer::create();
 }
 
 LightShadowMap::~LightShadowMap()
@@ -268,11 +271,20 @@ GFXTextureObject* LightShadowMap::_getDepthTarget( U32 width, U32 height )
 
 bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants* lsc )
 {
-   if ( currTexFlag == Material::DynamicLight )
+   if ( currTexFlag == Material::DynamicLight && !isDynamic() )
    {
       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;
    }
@@ -296,8 +308,18 @@ bool LightShadowMap::setTextureStage( U32 currTexFlag, LightingShaderConstants*
 }
 
 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 );
    _render( renderPass, diffuseState );
    mDebugTarget.setTexture( mShadowMapTex );
@@ -456,25 +478,35 @@ LightingShaderConstants::LightingShaderConstants()
       mLightInvRadiusSqSC(NULL),
       mLightSpotDirSC(NULL),
       mLightSpotAngleSC(NULL),
-	  mLightSpotFalloffSC(NULL),
+      mLightSpotFalloffSC(NULL),
       mShadowMapSC(NULL), 
+      mDynamicShadowMapSC(NULL), 
       mShadowMapSizeSC(NULL), 
       mCookieMapSC(NULL),
       mRandomDirsConst(NULL),
       mShadowSoftnessConst(NULL), 
+      mAtlasXOffsetSC(NULL), 
+      mAtlasYOffsetSC(NULL),
+      mAtlasScaleSC(NULL), 
+      mFadeStartLength(NULL), 
+      mOverDarkFactorPSSM(NULL), 
+      mTapRotationTexSC(NULL),
+
       mWorldToLightProjSC(NULL), 
       mViewToLightProjSC(NULL),
       mScaleXSC(NULL), 
       mScaleYSC(NULL),
       mOffsetXSC(NULL), 
       mOffsetYSC(NULL), 
-      mAtlasXOffsetSC(NULL), 
-      mAtlasYOffsetSC(NULL),
-      mAtlasScaleSC(NULL), 
-      mFadeStartLength(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 );
 
    mShadowMapSC = shader->getShaderConstHandle("$shadowMap");
+   mDynamicShadowMapSC = shader->getShaderConstHandle("$dynamicShadowMap");
    mShadowMapSizeSC = shader->getShaderConstHandle("$shadowMapSize");
 
    mCookieMapSC = shader->getShaderConstHandle("$cookieMap");
 
    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");
    mViewToLightProjSC = shader->getShaderConstHandle("$viewToLightProj");
-
    mScaleXSC = shader->getShaderConstHandle("$scaleX");
    mScaleYSC = shader->getShaderConstHandle("$scaleY");
    mOffsetXSC = shader->getShaderConstHandle("$offsetX");
    mOffsetYSC = shader->getShaderConstHandle("$offsetY");
-   mAtlasXOffsetSC = shader->getShaderConstHandle("$atlasXOffset");
-   mAtlasYOffsetSC = shader->getShaderConstHandle("$atlasYOffset");
-   mAtlasScaleSC = shader->getShaderConstHandle("$atlasScale");
-
-   mFadeStartLength = shader->getShaderConstHandle("$fadeStartLength");
    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;
 }
@@ -558,7 +596,9 @@ LightInfoExType ShadowMapParams::Type( "" );
 
 ShadowMapParams::ShadowMapParams( LightInfo *light ) 
    :  mLight( light ),
-      mShadowMap( NULL )
+      mShadowMap( NULL ),
+      mDynamicShadowMap ( NULL ),
+      isDynamic ( true )
 {
    attenuationRatio.set( 0.0f, 1.0f, 1.0f );
    shadowType = ShadowType_Spot;
@@ -576,6 +616,7 @@ ShadowMapParams::ShadowMapParams( LightInfo *light )
 ShadowMapParams::~ShadowMapParams()
 {
    SAFE_DELETE( mShadowMap );
+   SAFE_DELETE( mDynamicShadowMap );
 }
 
 void ShadowMapParams::_validate()
@@ -632,39 +673,55 @@ void ShadowMapParams::_validate()
    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;
 
    if ( !mLight->getCastShadows() )
       return NULL;
 
+   LightShadowMap* newShadowMap = NULL;
+
    switch ( mLight->getType() )
    {
       case LightInfo::Spot:
-         mShadowMap = new SingleLightShadowMap( mLight );
+         newShadowMap = new SingleLightShadowMap( mLight );
          break;
 
       case LightInfo::Vector:
-         mShadowMap = new PSSMLightShadowMap( mLight );
+         newShadowMap = new PSSMLightShadowMap( mLight );
          break;
 
       case LightInfo::Point:
 
          if ( shadowType == ShadowType_CubeMap )
-            mShadowMap = new CubeLightShadowMap( mLight );
+            newShadowMap = new CubeLightShadowMap( mLight );
          else if ( shadowType == ShadowType_Paraboloid )
-            mShadowMap = new ParaboloidLightShadowMap( mLight );
+            newShadowMap = new ParaboloidLightShadowMap( mLight );
          else
-            mShadowMap = new DualParaboloidLightShadowMap( mLight );
+            newShadowMap = new DualParaboloidLightShadowMap( mLight );
          break;
    
       default:
          break;
    }
 
-   return mShadowMap;
+   if ( _isDynamic )
+   {
+      newShadowMap->setDynamic( true );
+      mDynamicShadowMap = newShadowMap;
+      return mDynamicShadowMap;
+   }
+   else
+   {
+      newShadowMap->setDynamic(false);
+      mShadowMap = newShadowMap;
+      return mShadowMap;
+   }
 }
 
 GFXTextureObject* ShadowMapParams::getCookieTex()
@@ -739,6 +796,7 @@ void ShadowMapParams::unpackUpdate( BitStream *stream )
       // map so it can be reallocated on the next render.
       shadowType = newType;
       SAFE_DELETE( mShadowMap );
+      SAFE_DELETE( mDynamicShadowMap );
    }
 
    mathRead( *stream, &attenuationRatio );

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

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

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

@@ -37,6 +37,7 @@
 #include "materials/shaderData.h"
 #include "ts/tsShapeInstance.h"
 #include "console/consoleTypes.h"
+#include "math/mathUtils.h"
 
 
 AFTER_MODULE_INIT( Sim )
@@ -248,6 +249,9 @@ void PSSMLightShadowMap::_render(   RenderPassManager* renderPass,
    TSShapeInstance::smDetailAdjust *= smDetailAdjustScale;
    TSShapeInstance::smSmallestVisiblePixelSize = smSmallestVisiblePixelSize;
 
+   Vector< Vector<PlaneF> > _extraCull;
+   _calcPlanesCullForShadowCasters( _extraCull, fullFrustum, mLight->getDirection() );
+
    for (U32 i = 0; i < mNumSplits; i++)
    {
       GFXTransformSaver saver;
@@ -365,12 +369,17 @@ void PSSMLightShadowMap::_render(   RenderPassManager* renderPass,
       shadowRenderState.setDiffuseCameraTransform( diffuseState->getCameraTransform() );
       shadowRenderState.setWorldToScreenScale( diffuseState->getWorldToScreenScale() );
 
+      PlaneSetF planeSet( _extraCull[i].address(), _extraCull[i].size() );
+      shadowRenderState.getCullingState().setExtraPlanesCull( planeSet );
+
       U32 objectMask = SHADOW_TYPEMASK;
       if ( i == mNumSplits-1 && params->lastSplitTerrainOnly )
          objectMask = TerrainObjectType;
 
       sceneManager->renderSceneNoLights( &shadowRenderState, objectMask );
 
+      shadowRenderState.getCullingState().clearExtraPlanesCull();
+
       _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->mAtlasYOffsetSC, aYOff);
    params->setSafe(lsc->mAtlasScaleSC, shadowMapAtlas);
 
    Point4F lightParams( mLight->getRange().x, p->overDarkFactor.x, 0.0f, 0.0f );
    params->setSafe( lsc->mLightParamsSC, lightParams );
-      
-   params->setSafe( lsc->mFarPlaneScalePSSM, mFarPlaneScalePSSM);
 
    Point2F fadeStartLength(p->fadeStartDist, 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.
    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 _calcSplitPos(const Frustum& currFrustum);
    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);
 
    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() 
 :  mShadowMapPass(NULL), 
    mCurrentShadowMap(NULL),
+   mCurrentDynamicShadowMap(NULL),
    mIsActive(false)
 {
 }
@@ -98,9 +99,15 @@ void ShadowMapManager::setLightShadowMapForLight( LightInfo *light )
 {
    ShadowMapParams *params = light->getExtended<ShadowMapParams>();
    if ( params )
+   {
       mCurrentShadowMap = params->getShadowMap();
+      mCurrentDynamicShadowMap = params->getShadowMap(true);
+   }
    else 
+   {
       mCurrentShadowMap = NULL;
+      mCurrentDynamicShadowMap = NULL;
+   }
 }
 
 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)
    void setLightShadowMap( LightShadowMap *lm ) { mCurrentShadowMap = lm; }
+   void setLightDynamicShadowMap( LightShadowMap *lm ) { mCurrentDynamicShadowMap = lm; }
    
    /// Looks up the shadow map for the light then sets it.
    void setLightShadowMapForLight( LightInfo *light );
 
    /// Return the current shadow map
    LightShadowMap* getCurrentShadowMap() const { return mCurrentShadowMap; }
+   LightShadowMap* getCurrentDynamicShadowMap() const { return mCurrentDynamicShadowMap; }
 
    ShadowMapPass* getShadowMapPass() const { return mShadowMapPass; }
 
@@ -88,6 +90,7 @@ protected:
 
    ShadowMapPass *mShadowMapPass;
    LightShadowMap *mCurrentShadowMap;
+   LightShadowMap *mCurrentDynamicShadowMap;
 
    ///
    GFXTexHandle mTapRotationTex;

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

@@ -55,6 +55,11 @@ bool ShadowMapPass::smDisableShadows = false;
 bool ShadowMapPass::smDisableShadowsEditor = 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.
 U32 ShadowMapPass::smRenderBudgetMs = 8;
 
@@ -62,18 +67,27 @@ ShadowMapPass::ShadowMapPass(LightManager* lightManager, ShadowMapManager* shado
 {
    mLightManager = lightManager;
    mShadowManager = shadowManager;
+
+   // Setup our render pass managers
+
+   // Static
    mShadowRPM = new ShadowRenderPassManager();
    mShadowRPM->assignName( "ShadowRenderPassManager" );
    mShadowRPM->registerObject();
    Sim::getRootGroup()->addObject( mShadowRPM );
-
-   // Setup our render pass manager
-
    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 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;
 
    mTimer = PlatformTimer::create();
@@ -117,6 +131,9 @@ ShadowMapPass::~ShadowMapPass()
 
    if ( mShadowRPM )
       mShadowRPM->deleteObject();
+
+   if ( mDynamicShadowRPM )
+      mDynamicShadowRPM->deleteObject();
 }
 
 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
    // info array for this pass.
    Vector<LightShadowMap*> shadowMaps;
-   shadowMaps.reserve( mActiveLights );
+   shadowMaps.reserve( mActiveLights * 2 );
    for ( U32 i = 0; i < mActiveLights; i++ )
    {
       ShadowMapParams *params = mLights[i]->getExtended<ShadowMapParams>();
@@ -155,12 +172,14 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
       // Before we do anything... skip lights without shadows.      
       if ( !mLights[i]->getCastShadows() || smDisableShadows )
          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 
       // visible skip it.
-      if ( lsm->wasOccluded() )
+     if (lsm->wasOccluded() || dlsm->wasOccluded())
          continue;
 
       // Any shadow that is visible is counted as being 
@@ -168,13 +187,25 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
       ++smActiveShadowMaps;
 
       // 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.
-   shadowMaps.sort( LightShadowMap::cmpPriority );
+   // andrewmac: tempoarily disabled until I find a better solution.
+   //shadowMaps.sort( LightShadowMap::cmpPriority );
 
    GFXDEBUGEVENT_SCOPE( ShadowMapPass_Render, ColorI::RED );
 
@@ -183,22 +214,28 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
    mTimer->getElapsedMs();
    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 );
 
-         mShadowManager->setLightShadowMap( lsm );
-         lsm->render( mShadowRPM, diffuseState );
+		 mShadowManager->setLightShadowMap(lsm);
+         mShadowManager->setLightDynamicShadowMap( dlsm );
+
+		 lsm->render(mShadowRPM, diffuseState, false);
+		 dlsm->render(mDynamicShadowRPM, diffuseState, true);
+
          ++smUpdatedShadowMaps;
       }
 
       // View dependent shadows or ones that are covering the entire
       // screen are updated every frame no matter the time left in
       // our shadow rendering budget.
-      if ( lsm->isViewDependent() || lsm->getLastScreenSize() >= 1.0f )
+      if ( dlsm->isViewDependent() || dlsm->getLastScreenSize() >= 1.0f )
       {
          ++smNearShadowMaps;
          continue;
@@ -224,6 +261,7 @@ void ShadowMapPass::render(   SceneManager *sceneManager,
    // The NULL here is importaint as having it around
    // will cause extra work in AdvancedLightManager::setLightInfo().
    mShadowManager->setLightShadowMap( NULL );
+   mShadowManager->setLightDynamicShadowMap( NULL );
 }
 
 void ShadowRenderPassManager::addInst( RenderInst *inst )
@@ -237,7 +275,29 @@ void ShadowRenderPassManager::addInst( RenderInst *inst )
          return;
 
       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
          // of calling up to Parent::addInst()

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

@@ -45,6 +45,7 @@ class RenderObjectMgr;
 class RenderTerrainMgr;
 class PlatformTimer;
 class ShadowRenderPassManager;
+class DynamicShadowRenderPassManager;
 
 /// ShadowMapPass, this is plugged into the SceneManager to generate 
 /// ShadowMaps for the scene.
@@ -83,6 +84,11 @@ public:
    static bool smDisableShadowsEditor;
    static bool smDisableShadowsPref;
 
+   /// milliseconds before static redraw
+   static S32 smStaticShadowUpdateFreq;
+   /// milliseconds before dynamic redraw
+   static S32 smDynamicShadowUpdateFreq;
+
 private:
 
    static U32 smActiveShadowMaps;
@@ -103,6 +109,7 @@ private:
    LightInfoList mLights;
    U32 mActiveLights;
    SimObjectPtr<ShadowRenderPassManager> mShadowRPM;
+   SimObjectPtr<DynamicShadowRenderPassManager> mDynamicShadowRPM;
    LightManager* mLightManager;
    ShadowMapManager* mShadowManager;
 };
@@ -117,4 +124,14 @@ public:
    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_

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

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

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

@@ -182,6 +182,7 @@ Material::Material()
    mAlphaRef = 1;
 
    mCastShadows = true;
+   mCastDynamicShadows = false;
 
    mPlanarReflection = false;
 
@@ -288,7 +289,7 @@ void Material::initPersistFields()
       
       addField( "useAnisotropic", TypeBool, Offset(mUseAnisotropic, Material), MAX_STAGES,
          "Use anisotropic filtering for the textures of this stage." );
-
+      
       addField("envMap", TypeImageFilename, Offset(mEnvMapFilename, Material), MAX_STAGES,
          "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),
       "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("translucent", TypeBool, Offset(mTranslucent, Material),

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

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

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

@@ -85,6 +85,14 @@ void ProcessedCustomMaterial::_setStageData()
          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))
       {
          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 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
 {

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

@@ -1845,4 +1845,55 @@ U32 extrudePolygonEdgesFromPoint( const Point3F* vertices, U32 numVertices, cons
    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

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

@@ -417,6 +417,9 @@ namespace MathUtils
 
    //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
 
 #endif // _MATHUTILS_H_

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

@@ -88,6 +88,8 @@ SceneCullingState::SceneCullingState( SceneManager* sceneManager, const SceneCam
       SceneCullingVolume::Includer,
       PlaneSetF( planes, 4 )
    );
+
+   clearExtraPlanesCull();
 }
 
 //-----------------------------------------------------------------------------
@@ -789,6 +791,9 @@ U32 SceneCullingState::cullObjects( SceneObject** objects, U32 numObjects, U32 c
                       result == SceneZoneCullingState::CullingTestPositiveByOcclusion );
       }
 
+      if( !isCulled )
+         isCulled = isOccludedWithExtraPlanesCull( object->getWorldBox() );
+
       if( !isCulled )
          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
       Frustum mCullingFrustum;
 
+      /// Extra planes for culling.
+      PlaneSetF mExtraPlanesCull;
+
       /// 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
       /// 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.
       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:
 
       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";
    
    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;
 };
@@ -75,7 +76,8 @@ new CustomMaterial( AL_VectorLightMaterial )
    stateBlock = AL_VectorLightState;
    
    sampler["prePassBuffer"] = "#prepass";
-   sampler["ShadowMap"] = "$dynamiclight";
+   sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["ssaoMask"] = "#ssaoMask";
    
    target = "lightinfo";
@@ -128,8 +130,9 @@ new ShaderData( AL_PointLightShader )
 
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    pixVersion = 3.0;
 };
@@ -141,6 +144,7 @@ new CustomMaterial( AL_PointLightMaterial )
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    target = "lightinfo";
@@ -159,8 +163,9 @@ new ShaderData( AL_SpotLightShader )
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";   
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    pixVersion = 3.0;
 };
@@ -172,6 +177,7 @@ new CustomMaterial( AL_SpotLightMaterial )
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    target = "lightinfo";

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

@@ -28,6 +28,7 @@
 #include "../../../gl/lighting.glsl"
 #include "../../shadowMap/shadowMapIO_GLSL.h"
 #include "softShadow.glsl"
+#include "../../../gl/torque.glsl"
 
 in vec4 wsEyeDir;
 in vec4 ssPos;
@@ -107,6 +108,7 @@ uniform sampler2D prePassBuffer;
 	uniform samplerCube shadowMap;
 #else
 	uniform sampler2D shadowMap;
+	uniform sampler2D dynamicShadowMap;
 #endif
 
 uniform vec4 rtParams0;
@@ -119,9 +121,10 @@ uniform vec2 lightAttenuation;
 uniform vec4 lightMapParams;
 uniform vec4 vsFarPlane;
 uniform mat3 viewToLightProj;
+uniform mat3 dynamicViewToLightProj;
 uniform vec4 lightParams;
 uniform float shadowSoftness;
-			   
+
 out vec4 OUT_col;
 
 void main()               
@@ -175,7 +178,7 @@ void main()
 
          vec2 shadowCoord = decodeShadowCoord( tMul( viewToLightProj, -lightVec ) ).xy;
          
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowSoftness,
@@ -183,17 +186,28 @@ void main()
                                              nDotL,
                                              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 // !NO_SHADOW
    
+   vec3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
 
       // Lookup the cookie sample.
       vec4 cookie = texture( cookieMap, tMul( viewToLightProj, -lightVec ) );
 
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
@@ -211,7 +225,7 @@ void main()
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
    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);
     
    // 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 "softShadow.glsl"
 #include "../../../gl/lighting.glsl"
+#include "../../../gl/torque.glsl"
 
 in vec4 wsEyeDir;
 in vec4 ssPos;
@@ -45,6 +46,7 @@ uniform sampler2D cookieMap;
 
 uniform sampler2D prePassBuffer;
 uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 uniform vec4 rtParams0;
 
@@ -59,6 +61,7 @@ uniform vec4 lightMapParams;
 
 uniform vec4 vsFarPlane;
 uniform mat4 viewToLightProj;
+uniform mat4 dynamicViewToLightProj;
 
 uniform vec4 lightParams;
 uniform float shadowSoftness;
@@ -70,7 +73,7 @@ void main()
    // Compute scene UV
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
@@ -102,6 +105,10 @@ void main()
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    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
    
       float shadowed = 1.0;
@@ -111,7 +118,7 @@ void main()
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowSoftness,
@@ -119,15 +126,24 @@ void main()
                                           nDotL,
                                           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
    
+   vec3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
 
       // Lookup the cookie sample.
       vec4 cookie = texture( cookieMap, shadowCoord );
 
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
@@ -145,7 +161,7 @@ void main()
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
    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);
 
    // 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 vsEyeRay;
 
-uniform sampler2D ShadowMap ;
+uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 #ifdef USE_SSAO_MASK
 uniform sampler2D ssaoMask ;
 uniform vec4 rtParams2;
 #endif
 
-uniform sampler2D prePassBuffer;             
+uniform sampler2D prePassBuffer;            
 uniform vec3 lightDirection;
 uniform vec4 lightColor;
 uniform float  lightBrightness;
 uniform vec4 lightAmbient; 
 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 atlasYOffset;
 uniform vec2 atlasScale;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 lightMapParams;
 uniform vec2 fadeStartLength;
-uniform vec4 farPlaneScalePSSM;
 uniform vec4 overDarkPSSM;
 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
-      vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos);
+      vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
-      // Distance to light, in shadowmap space
+      // Distance to light, in shadowMap space
       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.  
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       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 
       // to the light for this pixel is less than the far plane 
@@ -132,6 +129,11 @@ void main()
       else
          finalMask = vec4(0, 0, 0, 1);
          
+      vec3 debugColor = vec3(0);
+   
+      #ifdef NO_SHADOW
+         debugColor = vec3(1.0);
+      #endif
 
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
@@ -144,50 +146,122 @@ void main()
             debugColor += vec3( 1, 1, 0 );
       #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
       // shader instructions.
       vec2 finalScale;
-      finalScale.x = dot(finalMask, scaleX);
-      finalScale.y = dot(finalMask, scaleY);
+      finalScale.x = dot(finalMask, _scaleX);
+      finalScale.y = dot(finalMask, _scaleY);
 
       vec2 finalOffset;
-      finalOffset.x = dot(finalMask, offsetX);
-      finalOffset.y = dot(finalMask, offsetY);
+      finalOffset.x = dot(finalMask, _offsetX);
+      finalOffset.y = dot(finalMask, _offsetY);
 
       vec2 shadowCoord;                  
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord += finalOffset;
 
-      // Convert to texcoord space
+      // Convert to _texCoord space
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord.y = 1.0f - shadowCoord.y;
 
       // Move around inside of atlas 
       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;
               
       // Each split has a different far plane, take this into account.
-      float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
+      float farPlaneScale = dot( _farPlaneScalePSSM, finalMask );
       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.
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       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
          if ( fadeOutAmt > 1.0 )
             debugColor = vec3(1.0);
@@ -228,7 +302,7 @@ void main()
    #ifdef PSSM_DEBUG_RENDER
       lightColorOut = debugColor;
    #endif
-   
+
    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 "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 struct ConvexConnectP
 {
@@ -40,7 +40,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 
 /// The texture for cookie rendering.
-uniform samplerCUBE cookieMap : register(S2);
+uniform samplerCUBE cookieMap : register(S3);
 
 #endif
 
@@ -114,6 +114,7 @@ float4 main(   ConvexConnectP IN,
                   uniform samplerCUBE shadowMap : register(S1),
                #else
                   uniform sampler2D shadowMap : register(S1),
+                  uniform sampler2D dynamicShadowMap : register(S2),
                #endif
 
                uniform float4 rtParams0,
@@ -127,6 +128,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform float4 vsFarPlane,
                uniform float3x3 viewToLightProj,
+               uniform float3x3 dynamicViewToLightProj,
 
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
@@ -134,7 +136,7 @@ float4 main(   ConvexConnectP IN,
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+      
    // Sample/unpack the normal/z data
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float3 normal = prepassSample.rgb;
@@ -178,9 +180,9 @@ float4 main(   ConvexConnectP IN,
          
       #else
 
+         // Static
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
-         
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowSoftness,
@@ -188,17 +190,30 @@ float4 main(   ConvexConnectP IN,
                                              nDotL,
                                              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 // !NO_SHADOW
    
+   float3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
 
       // Lookup the cookie sample.
       float4 cookie = texCUBE( cookieMap, mul( viewToLightProj, -lightVec ) );
 
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
@@ -216,7 +231,7 @@ float4 main(   ConvexConnectP IN,
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   float3 lightColorOut = lightMapParams.rgb * lightcol;
    float4 addToResult = 0.0;
     
    // 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
 /// rotations of the filter taps.
-uniform sampler2D gTapRotationTex : register(S3);
+uniform sampler2D gTapRotationTex : register(S4);
 
 
 float softShadow_sampleTaps(  sampler2D shadowMap,

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

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 struct ConvexConnectP
 {
@@ -39,7 +39,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 
 /// The texture for cookie rendering.
-uniform sampler2D cookieMap : register(S2);
+uniform sampler2D cookieMap : register(S3);
 
 #endif
 
@@ -48,6 +48,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D shadowMap : register(S1),
+               uniform sampler2D dynamicShadowMap : register(S2),
 
                uniform float4 rtParams0,
 
@@ -62,6 +63,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform float4 vsFarPlane,
                uniform float4x4 viewToLightProj,
+               uniform float4x4 dynamicViewToLightProj,
 
                uniform float4 lightParams,
                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 );
    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
    
       float shadowed = 1.0;
@@ -110,23 +117,32 @@ float4 main(   ConvexConnectP IN,
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowSoftness,
                                           distToLight,
                                           nDotL,
                                           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
    
+   float3 lightcol = lightColor.rgb;
    #ifdef USE_COOKIE_TEX
 
       // Lookup the cookie sample.
       float4 cookie = tex2D( cookieMap, shadowCoord );
 
       // Multiply the light with the cookie tex.
-      lightColor.rgb *= cookie.rgb;
+      lightcol *= cookie.rgb;
 
       // Use a maximum channel luminance to attenuate 
       // the lighting else we get specular in the dark
@@ -144,7 +160,7 @@ float4 main(   ConvexConnectP IN,
                                        normalize( -eyeRay ) ) * lightBrightness * atten * shadowed;
 
    float Sat_NL_Att = saturate( nDotL * atten * shadowed ) * lightBrightness;
-   float3 lightColorOut = lightMapParams.rgb * lightColor.rgb;
+   float3 lightColorOut = lightMapParams.rgb * lightcol;
    float4 addToResult = 0.0;
 
    // 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"
 
 
-uniform sampler2D ShadowMap : register(S1);
+uniform sampler2D shadowMap : register(S1);
+uniform sampler2D dynamicShadowMap : register(S2);
 
 #ifdef USE_SSAO_MASK
-uniform sampler2D ssaoMask : register(S2);
+uniform sampler2D ssaoMask : register(S3);
 uniform float4 rtParams2;
 #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
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
@@ -132,6 +95,11 @@ float4 main( FarFrustumQuadConnectP IN,
       else
          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
          if ( finalMask.x > 0 )
@@ -174,19 +142,125 @@ float4 main( FarFrustumQuadConnectP IN,
       // Each split has a different far plane, take this into account.
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       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.
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       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
          if ( fadeOutAmt > 1.0 )

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

@@ -3309,7 +3309,7 @@
                         HorizSizing = "width";
                         VertSizing = "bottom";
                         Position = "0 0";
-                        Extent = "210 71";
+                        Extent = "210 89";
                         
                         new GuiPopUpMenuCtrl() {
                            internalName = "blendingTypePopUp";
@@ -3480,7 +3480,7 @@
                            Visible = "1";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            tooltipprofile = "ToolsGuiDefaultProfile";
-                           ToolTip = "Alows object to cast shadows.";
+                           ToolTip = "Object casts shadows.";
                            hovertime = "1000";
                            text = "Cast Shadows";
                            groupNum = "-1";
@@ -3488,6 +3488,29 @@
                            useMouseEvents = "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() {
                            canSaveDynamicFields = "0";
                            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-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
+   MaterialEditorPropertiesWindow-->castDynamicShadows.setValue((%material).castDynamicShadows);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    
    switch$((%material).translucentBlendOp)

+ 1 - 0
Templates/Full/game/art/shapes/Cheetah/materials.cs

@@ -29,6 +29,7 @@ singleton Material(Cheetah_Main)
    translucentBlendOp = "None";
    normalMap[0] = "art/shapes/Cheetah/Cheetah_N";
    specularMap[0] = "art/shapes/Cheetah/Cheetah_S";
+   castDynamicShadows = true;
 };
 
 singleton Material(Cheetah_TailLights)

+ 2 - 0
Templates/Full/game/art/shapes/actors/Soldier/materials.cs

@@ -35,6 +35,7 @@ singleton Material(Mat_Soldier_Main)
    doubleSided = false;
    translucent = false;
    showFootprints = "0";
+   castDynamicShadows = true;
    materialTag0 = "Player";
 };
 
@@ -55,6 +56,7 @@ singleton Material(Mat_Soldier_Dazzle)
    emissive[0] = "1";
    castShadows = "0";
    showFootprints = "0";
+   castDynamicShadows = true;
    materialTag0 = "Player";
 };
 

+ 1 - 0
Templates/Full/game/art/shapes/weapons/Grenade/materials.cs

@@ -38,6 +38,7 @@ singleton Material(grenade_grenade)
 	doubleSided = false;
 	translucent = false;
 	translucentBlendOp = "None";
+   castDynamicShadows = true;    
 	materialTag0 = "Weapon";
 };
 

+ 1 - 0
Templates/Full/game/art/shapes/weapons/Lurker/materials.cs

@@ -41,6 +41,7 @@ singleton Material(Lurker_Base)
    specularPower[0] = "10";
    translucentBlendOp = "None";
    useAnisotropic[0] = "1";
+   castDynamicShadows = true;    
 };
 
 singleton Material(Lurker_MuzzleFlash_Base)

+ 1 - 0
Templates/Full/game/art/shapes/weapons/ProxMine/materials.cs

@@ -31,6 +31,7 @@ singleton Material(ProxMine_Base)
    pixelSpecular[0] = "1";
    specularMap[0] = "ProxMine_S.dds";
    useAnisotropic[0] = "1";
+   castDynamicShadows = true;    
 };
 
 singleton Material(ProxMine_Glow_Base)

+ 2 - 0
Templates/Full/game/art/shapes/weapons/Ryder/materials.cs

@@ -31,6 +31,7 @@ singleton Material(FP_Ryder_Base)
    translucentBlendOp = "None";
    pixelSpecular[0] = "1";
    useAnisotropic[0] = "1";
+   castDynamicShadows = true;    
 };
 
 singleton Material(TP_Ryder_Base)
@@ -43,6 +44,7 @@ singleton Material(TP_Ryder_Base)
    specularPower[0] = "10";
    translucentBlendOp = "None";
    pixelSpecular[0] = "1";
+   castDynamicShadows = true;    
 };
 
 singleton Material(Ryder_MuzzleFlash_Base)

+ 3 - 0
Templates/Full/game/art/shapes/weapons/Turret/materials.cs

@@ -31,6 +31,7 @@ singleton Material(Turret_Base)
    pixelSpecular[0] = "1";
    specularMap[0] = "art/shapes/weapons/Turret/Turret_D.dds";
    useAnisotropic[0] = "1";
+   castDynamicShadows = true;    
    materialTag0 = "Weapon";
 };
 
@@ -53,6 +54,7 @@ singleton Material(Turret_Lazer_Base)
    waveFreq[0] = "0";
    waveAmp[0] = "0";
    castShadows = "1";
+   castDynamicShadows = true;    
    translucentZWrite = "0";
    materialTag0 = "Weapon";
    materialTag1 = "FX";
@@ -68,6 +70,7 @@ singleton Material(Turret_Lazer_Base)
    glow[0] = "1";
    emissive[0] = "1";
    translucentBlendOp = "Add";
+   castDynamicShadows = true;    
 };
 
 singleton Material(CollisionMat)

+ 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";
    
    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;
 };
@@ -75,7 +76,8 @@ new CustomMaterial( AL_VectorLightMaterial )
    stateBlock = AL_VectorLightState;
    
    sampler["prePassBuffer"] = "#prepass";
-   sampler["ShadowMap"] = "$dynamiclight";
+   sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["ssaoMask"] = "#ssaoMask";
    
    target = "lightinfo";
@@ -128,8 +130,9 @@ new ShaderData( AL_PointLightShader )
 
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    pixVersion = 3.0;
 };
@@ -141,6 +144,7 @@ new CustomMaterial( AL_PointLightMaterial )
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    target = "lightinfo";
@@ -159,8 +163,9 @@ new ShaderData( AL_SpotLightShader )
    
    samplerNames[0] = "$prePassBuffer";
    samplerNames[1] = "$shadowMap";
-   samplerNames[2] = "$cookieMap";
-   samplerNames[3] = "$gTapRotationTex";   
+   samplerNames[2] = "$dynamicShadowMap";
+   samplerNames[3] = "$cookieMap";
+   samplerNames[4] = "$gTapRotationTex";
    
    pixVersion = 3.0;
 };
@@ -172,6 +177,7 @@ new CustomMaterial( AL_SpotLightMaterial )
    
    sampler["prePassBuffer"] = "#prepass";
    sampler["shadowMap"] = "$dynamiclight";
+   sampler["dynamicShadowMap"] = "$dynamicShadowMap";
    sampler["cookieMap"] = "$dynamiclightmask";
    
    target = "lightinfo";

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

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

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

@@ -27,6 +27,7 @@
 #include "shadergen:/autogenConditioners.h"
 #include "softShadow.glsl"
 #include "../../../gl/lighting.glsl"
+#include "../../../gl/torque.glsl"
 
 in vec4 wsEyeDir;
 in vec4 ssPos;
@@ -45,6 +46,7 @@ uniform sampler2D cookieMap;
 
 uniform sampler2D prePassBuffer;
 uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 uniform vec4 rtParams0;
 
@@ -59,6 +61,7 @@ uniform vec4 lightMapParams;
 
 uniform vec4 vsFarPlane;
 uniform mat4 viewToLightProj;
+uniform mat4 dynamicViewToLightProj;
 
 uniform vec4 lightParams;
 uniform float shadowSoftness;
@@ -70,7 +73,7 @@ void main()
    // Compute scene UV
    vec3 ssPos = IN_ssPos.xyz / IN_ssPos.w;
    vec2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+
    // Sample/unpack the normal/z data
    vec4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    vec3 normal = prepassSample.rgb;
@@ -102,6 +105,10 @@ void main()
    vec2 shadowCoord = ( ( pxlPosLightProj.xy / pxlPosLightProj.w ) * 0.5 ) + vec2( 0.5, 0.5 );
    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
    
       float shadowed = 1.0;
@@ -111,7 +118,7 @@ void main()
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowSoftness,
@@ -119,6 +126,14 @@ void main()
                                           nDotL,
                                           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
    
    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 vsEyeRay;
 
-uniform sampler2D ShadowMap ;
+uniform sampler2D shadowMap;
+uniform sampler2D dynamicShadowMap;
 
 #ifdef USE_SSAO_MASK
 uniform sampler2D ssaoMask ;
 uniform vec4 rtParams2;
 #endif
 
-uniform sampler2D prePassBuffer;             
+uniform sampler2D prePassBuffer;            
 uniform vec3 lightDirection;
 uniform vec4 lightColor;
 uniform float  lightBrightness;
 uniform vec4 lightAmbient; 
 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 atlasYOffset;
 uniform vec2 atlasScale;
 uniform vec4 zNearFarInvNearFar;
 uniform vec4 lightMapParams;
 uniform vec2 fadeStartLength;
-uniform vec4 farPlaneScalePSSM;
 uniform vec4 overDarkPSSM;
 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
-      vec4 pxlPosLightProj = tMul(worldToLightProj, worldPos);
+      vec4 pxlPosLightProj = tMul(_worldToLightProj, _worldPos);
       vec2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
 
-      // Distance to light, in shadowmap space
+      // Distance to light, in shadowMap space
       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.  
       vec4 shadowCoordX = vec4( baseShadowCoord.x );
       vec4 shadowCoordY = vec4( baseShadowCoord.y );
       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 
       // to the light for this pixel is less than the far plane 
@@ -132,6 +129,11 @@ void main()
       else
          finalMask = vec4(0, 0, 0, 1);
          
+      vec3 debugColor = vec3(0);
+   
+      #ifdef NO_SHADOW
+         debugColor = vec3(1.0);
+      #endif
 
       #ifdef PSSM_DEBUG_RENDER
          if ( finalMask.x > 0 )
@@ -144,50 +146,122 @@ void main()
             debugColor += vec3( 1, 1, 0 );
       #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
       // shader instructions.
       vec2 finalScale;
-      finalScale.x = dot(finalMask, scaleX);
-      finalScale.y = dot(finalMask, scaleY);
+      finalScale.x = dot(finalMask, _scaleX);
+      finalScale.y = dot(finalMask, _scaleY);
 
       vec2 finalOffset;
-      finalOffset.x = dot(finalMask, offsetX);
-      finalOffset.y = dot(finalMask, offsetY);
+      finalOffset.x = dot(finalMask, _offsetX);
+      finalOffset.y = dot(finalMask, _offsetY);
 
       vec2 shadowCoord;                  
       shadowCoord = baseShadowCoord * finalScale;      
       shadowCoord += finalOffset;
 
-      // Convert to texcoord space
+      // Convert to _texCoord space
       shadowCoord = 0.5 * shadowCoord + vec2(0.5, 0.5);
       shadowCoord.y = 1.0f - shadowCoord.y;
 
       // Move around inside of atlas 
       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;
               
       // Each split has a different far plane, take this into account.
-      float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
+      float farPlaneScale = dot( _farPlaneScalePSSM, finalMask );
       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.
       vec4 zDist = vec4(zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       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
          if ( fadeOutAmt > 1.0 )
             debugColor = vec3(1.0);
@@ -228,7 +302,7 @@ void main()
    #ifdef PSSM_DEBUG_RENDER
       lightColorOut = debugColor;
    #endif
-   
+
    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 "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 struct ConvexConnectP
 {
@@ -40,7 +40,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 
 /// The texture for cookie rendering.
-uniform samplerCUBE cookieMap : register(S2);
+uniform samplerCUBE cookieMap : register(S3);
 
 #endif
 
@@ -114,6 +114,7 @@ float4 main(   ConvexConnectP IN,
                   uniform samplerCUBE shadowMap : register(S1),
                #else
                   uniform sampler2D shadowMap : register(S1),
+                  uniform sampler2D dynamicShadowMap : register(S2),
                #endif
 
                uniform float4 rtParams0,
@@ -127,6 +128,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform float4 vsFarPlane,
                uniform float3x3 viewToLightProj,
+               uniform float3x3 dynamicViewToLightProj,
 
                uniform float4 lightParams,
                uniform float shadowSoftness ) : COLOR0
@@ -134,7 +136,7 @@ float4 main(   ConvexConnectP IN,
    // Compute scene UV
    float3 ssPos = IN.ssPos.xyz / IN.ssPos.w;
    float2 uvScene = getUVFromSSPos( ssPos, rtParams0 );
-   
+      
    // Sample/unpack the normal/z data
    float4 prepassSample = prepassUncondition( prePassBuffer, uvScene );
    float3 normal = prepassSample.rgb;
@@ -178,9 +180,9 @@ float4 main(   ConvexConnectP IN,
          
       #else
 
+         // Static
          float2 shadowCoord = decodeShadowCoord( mul( viewToLightProj, -lightVec ) ).xy;
-         
-         float shadowed = softShadow_filter( shadowMap,
+         float static_shadowed = softShadow_filter( shadowMap,
                                              ssPos.xy,
                                              shadowCoord,
                                              shadowSoftness,
@@ -188,6 +190,18 @@ float4 main(   ConvexConnectP IN,
                                              nDotL,
                                              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 // !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
 /// rotations of the filter taps.
-uniform sampler2D gTapRotationTex : register(S3);
+uniform sampler2D gTapRotationTex : register(S4);
 
 
 float softShadow_sampleTaps(  sampler2D shadowMap,

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

@@ -27,7 +27,7 @@
 #include "../../lighting.hlsl"
 #include "../shadowMap/shadowMapIO_HLSL.h"
 #include "softShadow.hlsl"
-
+#include "../../torque.hlsl"
 
 struct ConvexConnectP
 {
@@ -39,7 +39,7 @@ struct ConvexConnectP
 #ifdef USE_COOKIE_TEX
 
 /// The texture for cookie rendering.
-uniform sampler2D cookieMap : register(S2);
+uniform sampler2D cookieMap : register(S3);
 
 #endif
 
@@ -48,6 +48,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform sampler2D prePassBuffer : register(S0),
                uniform sampler2D shadowMap : register(S1),
+               uniform sampler2D dynamicShadowMap : register(S2),
 
                uniform float4 rtParams0,
 
@@ -62,6 +63,7 @@ float4 main(   ConvexConnectP IN,
 
                uniform float4 vsFarPlane,
                uniform float4x4 viewToLightProj,
+               uniform float4x4 dynamicViewToLightProj,
 
                uniform float4 lightParams,
                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 );
    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
    
       float shadowed = 1.0;
@@ -110,14 +117,22 @@ float4 main(   ConvexConnectP IN,
       // Get a linear depth from the light source.
       float distToLight = pxlPosLightProj.z / lightRange;
 
-      float shadowed = softShadow_filter( shadowMap,
+      float static_shadowed = softShadow_filter( shadowMap,
                                           ssPos.xy,
                                           shadowCoord,
                                           shadowSoftness,
                                           distToLight,
                                           nDotL,
                                           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
    
    float3 lightcol = lightColor.rgb;

+ 140 - 66
Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl

@@ -30,68 +30,31 @@
 #include "softShadow.hlsl"
 
 
-uniform sampler2D ShadowMap : register(S1);
+uniform sampler2D shadowMap : register(S1);
+uniform sampler2D dynamicShadowMap : register(S2);
 
 #ifdef USE_SSAO_MASK
-uniform sampler2D ssaoMask : register(S2);
-uniform float4 rtParams2;
+uniform sampler2D ssaoMask : register(S3);
+uniform float4 rtParams3;
 #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
       float4 pxlPosLightProj = mul(worldToLightProj, worldPos);
       float2 baseShadowCoord = pxlPosLightProj.xy / pxlPosLightProj.w;   
@@ -132,6 +95,11 @@ float4 main( FarFrustumQuadConnectP IN,
       else
          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
          if ( finalMask.x > 0 )
@@ -174,19 +142,125 @@ float4 main( FarFrustumQuadConnectP IN,
       // Each split has a different far plane, take this into account.
       float farPlaneScale = dot( farPlaneScalePSSM, finalMask );
       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.
       float4 zDist = (zNearFarInvNearFar.x + zNearFarInvNearFar.y * depth);
       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
          if ( fadeOutAmt > 1.0 )
@@ -221,7 +295,7 @@ float4 main( FarFrustumQuadConnectP IN,
 
    // Sample the AO texture.      
    #ifdef USE_SSAO_MASK
-      float ao = 1.0 - tex2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams2 ) ).r;
+      float ao = 1.0 - tex2D( ssaoMask, viewportCoordToRenderTarget( IN.uv0.xy, rtParams3 ) ).r;
       addToResult *= ao;
    #endif
 

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

@@ -3309,7 +3309,7 @@
                         HorizSizing = "width";
                         VertSizing = "bottom";
                         Position = "0 0";
-                        Extent = "210 71";
+                        Extent = "210 89";
                         
                         new GuiPopUpMenuCtrl() {
                            internalName = "blendingTypePopUp";
@@ -3480,7 +3480,7 @@
                            Visible = "1";
                            Command = "MaterialEditorGui.updateActiveMaterial(\"castShadows\", $ThisControl.getValue());";
                            tooltipprofile = "ToolsGuiDefaultProfile";
-                           ToolTip = "Alows object to cast shadows.";
+                           ToolTip = "Object casts shadows.";
                            hovertime = "1000";
                            text = "Cast Shadows";
                            groupNum = "-1";
@@ -3488,6 +3488,29 @@
                            useMouseEvents = "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() {
                            canSaveDynamicFields = "0";
                            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-->alphaTestCheckBox.setValue((%material).alphaTest);
    MaterialEditorPropertiesWindow-->castShadows.setValue((%material).castShadows);
+   MaterialEditorPropertiesWindow-->castDynamicShadows.setValue((%material).castDynamicShadows);
    MaterialEditorPropertiesWindow-->translucentCheckbox.setValue((%material).translucent);
    
    switch$((%material).translucentBlendOp)