shadow caching

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

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

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

Special notes:
dynamicRefreshFreq for all lights is set to a (script exposed) 8MS refresh timer.
StaticRefreshFreq for the lions share of lights defaults to 250 MS (1/4 of a second)
scattersky's embedded light, which is intended to operate in a mobile manner, defaults to 8
to reiterate, these are all customizable per-light via script/inspector gui in the case of alternate project needs.
This commit is contained in:
Azaezel 2015-10-13 18:12:19 -05:00
parent 2044b2691e
commit 2753f562e8
54 changed files with 1477 additions and 464 deletions

View file

@ -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 )