Permalink
Browse files

shadow caching.

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

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

Special notes:
dynamicRefreshFreq for all lights is set to a (script exposed) 8MS refresh timer.
StaticRefreshFreq for the lions share of lights defaults to 250 MS (1/4 of a second)
scattersky's embedded light, which is intended to operate in a mobile manner, defaults to 8
to reiterate, these are all customizable per-light via script/inspector gui in the case of alternate project needs.
  • Loading branch information...
Azaezel committed Oct 7, 2015
1 parent 2044b26 commit cff46be3c4eb15bf3f779dfe69589f5716b54cbc
Showing with 1,349 additions and 386 deletions.
  1. +8 −0 Engine/source/T3D/lightBase.cpp
  2. +2 −1 Engine/source/T3D/lightBase.h
  3. +10 −0 Engine/source/T3D/lightDescription.cpp
  4. +2 −0 Engine/source/T3D/lightDescription.h
  5. +2 −0 Engine/source/T3D/pointLight.cpp
  6. +2 −0 Engine/source/T3D/spotLight.cpp
  7. +11 −0 Engine/source/environment/scatterSky.cpp
  8. +2 −0 Engine/source/environment/scatterSky.h
  9. +13 −2 Engine/source/environment/sun.cpp
  10. +2 −0 Engine/source/environment/sun.h
  11. +3 −0 Engine/source/forest/forestCell.cpp
  12. +4 −0 Engine/source/forest/forestRender.cpp
  13. +7 −1 Engine/source/lighting/advanced/advancedLightBinManager.cpp
  14. +1 −0 Engine/source/lighting/advanced/advancedLightBinManager.h
  15. +63 −7 Engine/source/lighting/advanced/advancedLightManager.cpp
  16. +4 −0 Engine/source/lighting/lightInfo.cpp
  17. +9 −0 Engine/source/lighting/lightInfo.h
  18. +89 −31 Engine/source/lighting/shadowMap/lightShadowMap.cpp
  19. +37 −12 Engine/source/lighting/shadowMap/lightShadowMap.h
  20. +139 −6 Engine/source/lighting/shadowMap/pssmLightShadowMap.cpp
  21. +1 −0 Engine/source/lighting/shadowMap/pssmLightShadowMap.h
  22. +7 −0 Engine/source/lighting/shadowMap/shadowMapManager.cpp
  23. +3 −0 Engine/source/lighting/shadowMap/shadowMapManager.h
  24. +77 −17 Engine/source/lighting/shadowMap/shadowMapPass.cpp
  25. +17 −0 Engine/source/lighting/shadowMap/shadowMapPass.h
  26. +1 −0 Engine/source/materials/baseMaterialDefinition.h
  27. +5 −1 Engine/source/materials/materialDefinition.cpp
  28. +4 −1 Engine/source/materials/materialDefinition.h
  29. +8 −0 Engine/source/materials/processedCustomMaterial.cpp
  30. +8 −0 Engine/source/math/mPoint2.h
  31. +51 −0 Engine/source/math/mathUtils.cpp
  32. +3 −0 Engine/source/math/mathUtils.h
  33. +5 −0 Engine/source/scene/culling/sceneCullingState.cpp
  34. +18 −0 Engine/source/scene/culling/sceneCullingState.h
  35. +12 −6 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. +125 −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. +126 −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. +12 −6 Templates/Full/game/core/scripts/client/lighting/advanced/shaders.cs
  46. +14 −1 Templates/Full/game/shaders/common/lighting/advanced/gl/pointLightP.glsl
  47. +17 −2 Templates/Full/game/shaders/common/lighting/advanced/gl/spotLightP.glsl
  48. +125 −64 Templates/Full/game/shaders/common/lighting/advanced/gl/vectorLightP.glsl
  49. +19 −5 Templates/Full/game/shaders/common/lighting/advanced/pointLightP.hlsl
  50. +1 −1 Templates/Full/game/shaders/common/lighting/advanced/softShadow.hlsl
  51. +19 −4 Templates/Full/game/shaders/common/lighting/advanced/spotLightP.hlsl
  52. +126 −64 Templates/Full/game/shaders/common/lighting/advanced/vectorLightP.hlsl
  53. +25 −2 Templates/Full/game/tools/materialEditor/gui/guiMaterialPropertiesWindow.ed.gui
  54. +1 −0 Templates/Full/game/tools/materialEditor/scripts/materialEditor.ed.cs
@@ -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 );
@@ -56,7 +56,8 @@ class LightBase : public SceneObject, public ISceneLight, public virtual ITickab
F32 mBrightness;
bool mCastShadows;
S32 mStaticRefreshFreq;
S32 mDynamicRefreshFreq;
F32 mPriority;
LightInfo *mLight;
@@ -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 )
@@ -101,6 +101,8 @@ class LightDescription : public SimDataBlock
F32 brightness;
F32 range;
bool castShadows;
S32 mStaticRefreshFreq;
S32 mDynamicRefreshFreq;
LightAnimData *animationData;
S32 animationDataId;
@@ -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.
@@ -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 );
@@ -151,6 +151,8 @@ ScatterSky::ScatterSky()
mBrightness = 1.0f;
mCastShadows = true;
mStaticRefreshFreq = 8;
mDynamicRefreshFreq = 8;
mDirty = true;
mLight = LightManager::createLightInfo();
@@ -271,6 +273,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;
@@ -381,6 +385,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." );
@@ -487,6 +494,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 );
@@ -588,6 +597,8 @@ void ScatterSky::unpackUpdate(NetConnection *con, BitStream *stream)
stream->read( &mBrightness );
mCastShadows = stream->readFlag();
stream->read(&mStaticRefreshFreq);
stream->read(&mDynamicRefreshFreq);
stream->read( &mFlareScale );
@@ -207,6 +207,8 @@ class ScatterSky : public SceneObject, public ISceneLight
LightInfo *mLight;
bool mCastShadows;
S32 mStaticRefreshFreq;
S32 mDynamicRefreshFreq;
bool mDirty;
LightFlareData *mFlareData;
@@ -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()
@@ -65,6 +65,8 @@ class Sun : public SceneObject, public ISceneLight
F32 mEndElevation;
bool mCastShadows;
S32 mStaticRefreshFreq;
S32 mDynamicRefreshFreq;
LightInfo *mLight;
@@ -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();
}
@@ -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.
@@ -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 );
@@ -185,6 +185,7 @@ class AdvancedLightBinManager : public RenderTexTargetBinManager
{
LightInfo* lightInfo;
LightShadowMap* shadowMap;
LightShadowMap* dynamicShadowMap;
LightMaterialInfo* lightMaterial;
GFXPrimitiveBuffer* primBuffer;
GFXVertexBuffer* vertBuffer;
Oops, something went wrong.

0 comments on commit cff46be

Please sign in to comment.