123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #include "platform/platform.h"
- #include "lighting/basic/basicLightManager.h"
- #include "platform/platformTimer.h"
- #include "console/simSet.h"
- #include "console/consoleTypes.h"
- #include "core/module.h"
- #include "core/util/safeDelete.h"
- #include "materials/processedMaterial.h"
- #include "shaderGen/shaderFeature.h"
- #include "lighting/basic/basicSceneObjectLightingPlugin.h"
- #include "shaderGen/shaderGenVars.h"
- #include "gfx/gfxShader.h"
- #include "materials/sceneData.h"
- #include "materials/materialParameters.h"
- #include "materials/materialManager.h"
- #include "materials/materialFeatureTypes.h"
- #include "math/util/frustum.h"
- #include "scene/sceneObject.h"
- #include "renderInstance/renderDeferredMgr.h"
- #include "shaderGen/featureMgr.h"
- #include "shaderGen/HLSL/shaderFeatureHLSL.h"
- #include "shaderGen/HLSL/bumpHLSL.h"
- #include "lighting/basic/blTerrainSystem.h"
- #include "lighting/common/projectedShadow.h"
- #if defined( TORQUE_OPENGL )
- #include "shaderGen/GLSL/shaderFeatureGLSL.h"
- #include "shaderGen/GLSL/bumpGLSL.h"
- #endif
- MODULE_BEGIN( BasicLightManager )
- MODULE_SHUTDOWN_AFTER( Scene )
- MODULE_INIT
- {
- ManagedSingleton< BasicLightManager >::createSingleton();
- }
-
- MODULE_SHUTDOWN
- {
- ManagedSingleton< BasicLightManager >::deleteSingleton();
- }
- MODULE_END;
- U32 BasicLightManager::smActiveShadowPlugins = 0;
- U32 BasicLightManager::smShadowsUpdated = 0;
- U32 BasicLightManager::smElapsedUpdateMs = 0;
- F32 BasicLightManager::smProjectedShadowFilterDistance = 40.0f;
- static S32 QSORT_CALLBACK comparePluginScores( const void *a, const void *b )
- {
- const BasicSceneObjectLightingPlugin *A = *((BasicSceneObjectLightingPlugin**)a);
- const BasicSceneObjectLightingPlugin *B = *((BasicSceneObjectLightingPlugin**)b);
-
- F32 dif = B->getScore() - A->getScore();
- return (S32)mFloor( dif );
- }
- BasicLightManager::BasicLightManager()
- : LightManager( "Basic Lighting", "BLM" ),
- mLastShader(NULL),
- mLastConstants(NULL)
- {
- mTimer = PlatformTimer::create();
-
- mTerrainSystem = new blTerrainSystem;
-
- getSceneLightingInterface()->registerSystem( mTerrainSystem );
- Con::addVariable( "$BasicLightManagerStats::activePlugins",
- TypeS32, &smActiveShadowPlugins,
- "The number of active Basic Lighting SceneObjectLightingPlugin objects this frame.\n"
- "@ingroup BasicLighting\n" );
- Con::addVariable( "$BasicLightManagerStats::shadowsUpdated",
- TypeS32, &smShadowsUpdated,
- "The number of Basic Lighting shadows updated this frame.\n"
- "@ingroup BasicLighting\n" );
- Con::addVariable( "$BasicLightManagerStats::elapsedUpdateMs",
- TypeS32, &smElapsedUpdateMs,
- "The number of milliseconds spent this frame updating Basic Lighting shadows.\n"
- "@ingroup BasicLighting\n" );
- Con::addVariable( "$BasicLightManager::shadowFilterDistance",
- TypeF32, &smProjectedShadowFilterDistance,
- "The maximum distance in meters that projected shadows will get soft filtering.\n"
- "@ingroup BasicLighting\n" );
- Con::addVariable( "$pref::ProjectedShadow::fadeStartPixelSize",
- TypeF32, &ProjectedShadow::smFadeStartPixelSize,
- "A size in pixels at which BL shadows begin to fade out. "
- "This should be a larger value than fadeEndPixelSize.\n"
- "@see DecalData\n"
- "@ingroup BasicLighting\n" );
- Con::addVariable( "$pref::ProjectedShadow::fadeEndPixelSize",
- TypeF32, &ProjectedShadow::smFadeEndPixelSize,
- "A size in pixels at which BL shadows are fully faded out. "
- "This should be a smaller value than fadeStartPixelSize.\n"
- "@see DecalData\n"
- "@ingroup BasicLighting\n" );
- }
- BasicLightManager::~BasicLightManager()
- {
- mLastShader = NULL;
- mLastConstants = NULL;
- for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
- {
- if (i->value)
- SAFE_DELETE(i->value);
- }
- mConstantLookup.clear();
- if (mTimer)
- SAFE_DELETE( mTimer );
- SAFE_DELETE( mTerrainSystem );
- }
- bool BasicLightManager::isCompatible() const
- {
- // As long as we have some shaders this works.
- return GFX->getPixelShaderVersion() > 1.0;
- }
- void BasicLightManager::activate( SceneManager *sceneManager )
- {
- Parent::activate( sceneManager );
- if( GFX->getAdapterType() == OpenGL )
- {
- #if defined( TORQUE_OPENGL )
- FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatGLSL );
- FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatGLSL );
- FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL );
- FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL );
- FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL);
- #endif
- }
- else
- {
- #if defined( TORQUE_OS_WIN )
- FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatHLSL );
- FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatHLSL );
- FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL );
- FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL );
- FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL);
- #endif
- }
- FEATUREMGR->unregisterFeature( MFT_MinnaertShading );
- FEATUREMGR->unregisterFeature( MFT_SubSurface );
- // First look for the deferred bin...
- RenderDeferredMgr *deferredBin = _findDeferredRenderBin();
- /*
- // If you would like to use forward shading, and have a linear depth pre-pass
- // than un-comment this code block.
- if ( !deferredBin )
- {
- Vector<GFXFormat> formats;
- formats.push_back( GFXFormatR32F );
- formats.push_back( GFXFormatR16F );
- formats.push_back( GFXFormatR8G8B8A8 );
- GFXFormat linearDepthFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile,
- formats,
- true,
- false );
- // Uncomment this for a no-color-write z-fill pass.
- //linearDepthFormat = GFXFormat_COUNT;
- deferredBin = new RenderDeferredMgr( linearDepthFormat != GFXFormat_COUNT, linearDepthFormat );
- deferredBin->registerObject();
- rpm->addManager( deferredBin );
- }
- */
- mDeferredRenderBin = deferredBin;
- // If there is a deferred bin
- MATMGR->setDeferredEnabled( mDeferredRenderBin.isValid() );
- sceneManager->setPostEffectFog( mDeferredRenderBin.isValid() && mDeferredRenderBin->getTargetChainLength() > 0 );
- // Tell the material manager that we don't use deferred.
- MATMGR->setDeferredEnabled( false );
- GFXShader::addGlobalMacro( "TORQUE_BASIC_LIGHTING" );
- // Hook into the SceneManager prerender signal.
- sceneManager->getPreRenderSignal().notify( this, &BasicLightManager::_onPreRender );
- // Last thing... let everyone know we're active.
- smActivateSignal.trigger( getId(), true );
- }
- void BasicLightManager::deactivate()
- {
- Parent::deactivate();
- mLastShader = NULL;
- mLastConstants = NULL;
- for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++)
- {
- if (i->value)
- SAFE_DELETE(i->value);
- }
- mConstantLookup.clear();
- if ( mDeferredRenderBin )
- mDeferredRenderBin->deleteObject();
- mDeferredRenderBin = NULL;
- GFXShader::removeGlobalMacro( "TORQUE_BASIC_LIGHTING" );
- // Remove us from the prerender signal.
- getSceneManager()->getPreRenderSignal().remove( this, &BasicLightManager::_onPreRender );
- // Now let everyone know we've deactivated.
- smActivateSignal.trigger( getId(), false );
- }
- void BasicLightManager::_onPreRender( SceneManager *sceneManger, const SceneRenderState *state )
- {
- // Update all our shadow plugins here!
- Vector<BasicSceneObjectLightingPlugin*> *pluginInsts = BasicSceneObjectLightingPlugin::getPluginInstances();
- Vector<BasicSceneObjectLightingPlugin*>::const_iterator pluginIter = (*pluginInsts).begin();
- for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ )
- {
- BasicSceneObjectLightingPlugin *plugin = *pluginIter;
- plugin->updateShadow( (SceneRenderState*)state );
- }
- U32 pluginCount = (*pluginInsts).size();
- // Sort them by the score.
- dQsort( (*pluginInsts).address(), pluginCount, sizeof(BasicSceneObjectLightingPlugin*), comparePluginScores );
- mTimer->getElapsedMs();
- mTimer->reset();
- U32 numUpdated = 0;
- U32 targetMs = 5;
- S32 updateMs = 0;
- pluginIter = (*pluginInsts).begin();
- for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ )
- {
- BasicSceneObjectLightingPlugin *plugin = *pluginIter;
- // If we run out of update time then stop.
- updateMs = mTimer->getElapsedMs();
- if ( updateMs >= targetMs )
- break;
- // NOTE! Fix this all up to past const SceneRenderState!
- plugin->renderShadow( (SceneRenderState*)state );
- numUpdated++;
- }
- smShadowsUpdated = numUpdated;
- smActiveShadowPlugins = pluginCount;
- smElapsedUpdateMs = updateMs;
- }
- BasicLightManager::LightingShaderConstants::LightingShaderConstants()
- : mInit( false ),
- mShader( NULL ),
- mLightPosition( NULL ),
- mLightDiffuse( NULL ),
- mLightAmbient( NULL ),
- mLightConfigDataSC( NULL ),
- mLightSpotDir( NULL ),
- mLightSpotParamsSC( NULL ),
- mHasVectorLightSC(NULL),
- mVectorLightDirectionSC(NULL),
- mVectorLightColorSC(NULL),
- mVectorLightBrightnessSC(NULL)
- {
- }
- BasicLightManager::LightingShaderConstants::~LightingShaderConstants()
- {
- if (mShader.isValid())
- {
- mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
- mShader = NULL;
- }
- }
- void BasicLightManager::LightingShaderConstants::init(GFXShader* shader)
- {
- if (mShader.getPointer() != shader)
- {
- if (mShader.isValid())
- mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload );
- mShader = shader;
- mShader->getReloadSignal().notify( this, &LightingShaderConstants::_onShaderReload );
- }
- mLightPosition = shader->getShaderConstHandle( ShaderGenVars::lightPosition );
- mLightDiffuse = shader->getShaderConstHandle( ShaderGenVars::lightDiffuse);
- mLightConfigDataSC = shader->getShaderConstHandle( ShaderGenVars::lightConfigData );
- mLightAmbient = shader->getShaderConstHandle( ShaderGenVars::lightAmbient );
- mLightSpotDir = shader->getShaderConstHandle( ShaderGenVars::lightSpotDir );
- mLightSpotParamsSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotParams );
- mHasVectorLightSC = shader->getShaderConstHandle(ShaderGenVars::hasVectorLight);
- mVectorLightDirectionSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightDirection);
- mVectorLightColorSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightColor);
- mVectorLightBrightnessSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightBrightness);
- mInit = true;
- }
- void BasicLightManager::LightingShaderConstants::_onShaderReload()
- {
- if (mShader.isValid())
- init( mShader );
- }
- void BasicLightManager::setLightInfo( ProcessedMaterial* pmat,
- const Material* mat,
- const SceneData& sgData,
- const SceneRenderState *state,
- U32 pass,
- GFXShaderConstBuffer* shaderConsts )
- {
- PROFILE_SCOPE( BasicLightManager_SetLightInfo );
- GFXShader *shader = shaderConsts->getShader();
- // Check to see if this is the same shader. Since we
- // sort by material we should get hit repeatedly by the
- // same one. This optimization should save us many
- // hash table lookups.
- if ( mLastShader.getPointer() != shader )
- {
- LightConstantMap::Iterator iter = mConstantLookup.find(shader);
- if ( iter != mConstantLookup.end() )
- {
- mLastConstants = iter->value;
- }
- else
- {
- LightingShaderConstants* lsc = new LightingShaderConstants();
- mConstantLookup[shader] = lsc;
- mLastConstants = lsc;
- }
- // Set our new shader
- mLastShader = shader;
- }
- // Make sure that our current lighting constants are initialized
- if (!mLastConstants->mInit)
- mLastConstants->init(shader);
- // NOTE: If you encounter a crash from this point forward
- // while setting a shader constant its probably because the
- // mConstantLookup has bad shaders/constants in it.
- //
- // This is a known crash bug that can occur if materials/shaders
- // are reloaded and the light manager is not reset.
- //
- // We should look to fix this by clearing the table.
- _update4LightConsts( sgData,
- mLastConstants->mLightPosition,
- mLastConstants->mLightDiffuse,
- mLastConstants->mLightAmbient,
- mLastConstants->mLightConfigDataSC,
- mLastConstants->mLightSpotDir,
- mLastConstants->mLightSpotParamsSC,
- mLastConstants->mHasVectorLightSC,
- mLastConstants->mVectorLightDirectionSC,
- mLastConstants->mVectorLightColorSC,
- mLastConstants->mVectorLightBrightnessSC,
- shaderConsts );
- }
|