basicLightManager.cpp
Engine/source/lighting/basic/basicLightManager.cpp
Public Variables
Public Functions
comparePluginScores(const void * a, const void * b)
Detailed Description
Public Variables
MODULE_END
MODULE_INIT
MODULE_SHUTDOWN
Public Functions
comparePluginScores(const void * a, const void * b)
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "lighting/basic/basicLightManager.h" 26 27#include "platform/platformTimer.h" 28#include "console/simSet.h" 29#include "console/consoleTypes.h" 30#include "core/module.h" 31#include "core/util/safeDelete.h" 32#include "materials/processedMaterial.h" 33#include "shaderGen/shaderFeature.h" 34#include "lighting/basic/basicSceneObjectLightingPlugin.h" 35#include "shaderGen/shaderGenVars.h" 36#include "gfx/gfxShader.h" 37#include "materials/sceneData.h" 38#include "materials/materialParameters.h" 39#include "materials/materialManager.h" 40#include "materials/materialFeatureTypes.h" 41#include "math/util/frustum.h" 42#include "scene/sceneObject.h" 43#include "renderInstance/renderDeferredMgr.h" 44#include "shaderGen/featureMgr.h" 45#include "shaderGen/HLSL/shaderFeatureHLSL.h" 46#include "shaderGen/HLSL/bumpHLSL.h" 47#include "lighting/basic/blTerrainSystem.h" 48#include "lighting/common/projectedShadow.h" 49 50#if defined( TORQUE_OPENGL ) 51#include "shaderGen/GLSL/shaderFeatureGLSL.h" 52#include "shaderGen/GLSL/bumpGLSL.h" 53#endif 54 55 56MODULE_BEGIN( BasicLightManager ) 57 58 MODULE_SHUTDOWN_AFTER( Scene ) 59 60 MODULE_INIT 61 { 62 ManagedSingleton< BasicLightManager >::createSingleton(); 63 } 64 65 MODULE_SHUTDOWN 66 { 67 ManagedSingleton< BasicLightManager >::deleteSingleton(); 68 } 69 70MODULE_END; 71 72 73U32 BasicLightManager::smActiveShadowPlugins = 0; 74U32 BasicLightManager::smShadowsUpdated = 0; 75U32 BasicLightManager::smElapsedUpdateMs = 0; 76 77F32 BasicLightManager::smProjectedShadowFilterDistance = 40.0f; 78 79static S32 QSORT_CALLBACK comparePluginScores( const void *a, const void *b ) 80{ 81 const BasicSceneObjectLightingPlugin *A = *((BasicSceneObjectLightingPlugin**)a); 82 const BasicSceneObjectLightingPlugin *B = *((BasicSceneObjectLightingPlugin**)b); 83 84 F32 dif = B->getScore() - A->getScore(); 85 return (S32)mFloor( dif ); 86} 87 88BasicLightManager::BasicLightManager() 89 : LightManager( "Basic Lighting", "BLM" ), 90 mLastShader(NULL), 91 mLastConstants(NULL) 92{ 93 mTimer = PlatformTimer::create(); 94 95 mTerrainSystem = new blTerrainSystem; 96 97 getSceneLightingInterface()->registerSystem( mTerrainSystem ); 98 99 Con::addVariable( "$BasicLightManagerStats::activePlugins", 100 TypeS32, &smActiveShadowPlugins, 101 "The number of active Basic Lighting SceneObjectLightingPlugin objects this frame.\n" 102 "@ingroup BasicLighting\n" ); 103 104 Con::addVariable( "$BasicLightManagerStats::shadowsUpdated", 105 TypeS32, &smShadowsUpdated, 106 "The number of Basic Lighting shadows updated this frame.\n" 107 "@ingroup BasicLighting\n" ); 108 109 Con::addVariable( "$BasicLightManagerStats::elapsedUpdateMs", 110 TypeS32, &smElapsedUpdateMs, 111 "The number of milliseconds spent this frame updating Basic Lighting shadows.\n" 112 "@ingroup BasicLighting\n" ); 113 114 Con::addVariable( "$BasicLightManager::shadowFilterDistance", 115 TypeF32, &smProjectedShadowFilterDistance, 116 "The maximum distance in meters that projected shadows will get soft filtering.\n" 117 "@ingroup BasicLighting\n" ); 118 119 Con::addVariable( "$pref::ProjectedShadow::fadeStartPixelSize", 120 TypeF32, &ProjectedShadow::smFadeStartPixelSize, 121 "A size in pixels at which BL shadows begin to fade out. " 122 "This should be a larger value than fadeEndPixelSize.\n" 123 "@see DecalData\n" 124 "@ingroup BasicLighting\n" ); 125 126 Con::addVariable( "$pref::ProjectedShadow::fadeEndPixelSize", 127 TypeF32, &ProjectedShadow::smFadeEndPixelSize, 128 "A size in pixels at which BL shadows are fully faded out. " 129 "This should be a smaller value than fadeStartPixelSize.\n" 130 "@see DecalData\n" 131 "@ingroup BasicLighting\n" ); 132} 133 134BasicLightManager::~BasicLightManager() 135{ 136 mLastShader = NULL; 137 mLastConstants = NULL; 138 139 for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++) 140 { 141 if (i->value) 142 SAFE_DELETE(i->value); 143 } 144 mConstantLookup.clear(); 145 146 if (mTimer) 147 SAFE_DELETE( mTimer ); 148 149 SAFE_DELETE( mTerrainSystem ); 150} 151 152bool BasicLightManager::isCompatible() const 153{ 154 // As long as we have some shaders this works. 155 return GFX->getPixelShaderVersion() > 1.0; 156} 157 158void BasicLightManager::activate( SceneManager *sceneManager ) 159{ 160 Parent::activate( sceneManager ); 161 162 if( GFX->getAdapterType() == OpenGL ) 163 { 164 #if defined( TORQUE_OPENGL ) 165 FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatGLSL ); 166 FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatGLSL ); 167 FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatGLSL ); 168 FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatGLSL ); 169 FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatGLSL); 170 #endif 171 } 172 else 173 { 174 #if defined( TORQUE_OS_WIN ) 175 FEATUREMGR->registerFeature( MFT_LightMap, new LightmapFeatHLSL ); 176 FEATUREMGR->registerFeature( MFT_ToneMap, new TonemapFeatHLSL ); 177 FEATUREMGR->registerFeature( MFT_NormalMap, new BumpFeatHLSL ); 178 FEATUREMGR->registerFeature( MFT_RTLighting, new RTLightingFeatHLSL ); 179 FEATUREMGR->registerFeature(MFT_ReflectionProbes, new ReflectionProbeFeatHLSL); 180 #endif 181 } 182 183 FEATUREMGR->unregisterFeature( MFT_MinnaertShading ); 184 FEATUREMGR->unregisterFeature( MFT_SubSurface ); 185 186 // First look for the deferred bin... 187 RenderDeferredMgr *deferredBin = _findDeferredRenderBin(); 188 189 /* 190 // If you would like to use forward shading, and have a linear depth pre-pass 191 // than un-comment this code block. 192 if ( !deferredBin ) 193 { 194 Vector<GFXFormat> formats; 195 formats.push_back( GFXFormatR32F ); 196 formats.push_back( GFXFormatR16F ); 197 formats.push_back( GFXFormatR8G8B8A8 ); 198 GFXFormat linearDepthFormat = GFX->selectSupportedFormat( &GFXDefaultRenderTargetProfile, 199 formats, 200 true, 201 false ); 202 203 // Uncomment this for a no-color-write z-fill pass. 204 //linearDepthFormat = GFXFormat_COUNT; 205 206 deferredBin = new RenderDeferredMgr( linearDepthFormat != GFXFormat_COUNT, linearDepthFormat ); 207 deferredBin->registerObject(); 208 rpm->addManager( deferredBin ); 209 } 210 */ 211 mDeferredRenderBin = deferredBin; 212 213 // If there is a deferred bin 214 MATMGR->setDeferredEnabled( mDeferredRenderBin.isValid() ); 215 sceneManager->setPostEffectFog( mDeferredRenderBin.isValid() && mDeferredRenderBin->getTargetChainLength() > 0 ); 216 217 // Tell the material manager that we don't use deferred. 218 MATMGR->setDeferredEnabled( false ); 219 220 GFXShader::addGlobalMacro( "TORQUE_BASIC_LIGHTING" ); 221 222 // Hook into the SceneManager prerender signal. 223 sceneManager->getPreRenderSignal().notify( this, &BasicLightManager::_onPreRender ); 224 225 // Last thing... let everyone know we're active. 226 smActivateSignal.trigger( getId(), true ); 227} 228 229void BasicLightManager::deactivate() 230{ 231 Parent::deactivate(); 232 233 mLastShader = NULL; 234 mLastConstants = NULL; 235 236 for (LightConstantMap::Iterator i = mConstantLookup.begin(); i != mConstantLookup.end(); i++) 237 { 238 if (i->value) 239 SAFE_DELETE(i->value); 240 } 241 mConstantLookup.clear(); 242 243 if ( mDeferredRenderBin ) 244 mDeferredRenderBin->deleteObject(); 245 mDeferredRenderBin = NULL; 246 247 GFXShader::removeGlobalMacro( "TORQUE_BASIC_LIGHTING" ); 248 249 // Remove us from the prerender signal. 250 getSceneManager()->getPreRenderSignal().remove( this, &BasicLightManager::_onPreRender ); 251 252 // Now let everyone know we've deactivated. 253 smActivateSignal.trigger( getId(), false ); 254} 255 256void BasicLightManager::_onPreRender( SceneManager *sceneManger, const SceneRenderState *state ) 257{ 258 // Update all our shadow plugins here! 259 Vector<BasicSceneObjectLightingPlugin*> *pluginInsts = BasicSceneObjectLightingPlugin::getPluginInstances(); 260 261 Vector<BasicSceneObjectLightingPlugin*>::const_iterator pluginIter = (*pluginInsts).begin(); 262 for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ ) 263 { 264 BasicSceneObjectLightingPlugin *plugin = *pluginIter; 265 plugin->updateShadow( (SceneRenderState*)state ); 266 } 267 268 U32 pluginCount = (*pluginInsts).size(); 269 270 // Sort them by the score. 271 dQsort( (*pluginInsts).address(), pluginCount, sizeof(BasicSceneObjectLightingPlugin*), comparePluginScores ); 272 273 mTimer->getElapsedMs(); 274 mTimer->reset(); 275 U32 numUpdated = 0; 276 U32 targetMs = 5; 277 278 S32 updateMs = 0; 279 280 pluginIter = (*pluginInsts).begin(); 281 for ( ; pluginIter != (*pluginInsts).end(); pluginIter++ ) 282 { 283 BasicSceneObjectLightingPlugin *plugin = *pluginIter; 284 285 // If we run out of update time then stop. 286 updateMs = mTimer->getElapsedMs(); 287 if ( updateMs >= targetMs ) 288 break; 289 290 // NOTE! Fix this all up to past const SceneRenderState! 291 plugin->renderShadow( (SceneRenderState*)state ); 292 numUpdated++; 293 } 294 295 smShadowsUpdated = numUpdated; 296 smActiveShadowPlugins = pluginCount; 297 smElapsedUpdateMs = updateMs; 298} 299 300BasicLightManager::LightingShaderConstants::LightingShaderConstants() 301 : mInit( false ), 302 mShader( NULL ), 303 mLightPosition( NULL ), 304 mLightDiffuse( NULL ), 305 mLightAmbient( NULL ), 306 mLightConfigDataSC( NULL ), 307 mLightSpotDir( NULL ), 308 mLightSpotParamsSC( NULL ), 309 mHasVectorLightSC(NULL), 310 mVectorLightDirectionSC(NULL), 311 mVectorLightColorSC(NULL), 312 mVectorLightBrightnessSC(NULL) 313{ 314} 315 316BasicLightManager::LightingShaderConstants::~LightingShaderConstants() 317{ 318 if (mShader.isValid()) 319 { 320 mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload ); 321 mShader = NULL; 322 } 323} 324 325void BasicLightManager::LightingShaderConstants::init(GFXShader* shader) 326{ 327 if (mShader.getPointer() != shader) 328 { 329 if (mShader.isValid()) 330 mShader->getReloadSignal().remove( this, &LightingShaderConstants::_onShaderReload ); 331 332 mShader = shader; 333 mShader->getReloadSignal().notify( this, &LightingShaderConstants::_onShaderReload ); 334 } 335 336 mLightPosition = shader->getShaderConstHandle( ShaderGenVars::lightPosition ); 337 mLightDiffuse = shader->getShaderConstHandle( ShaderGenVars::lightDiffuse); 338 mLightConfigDataSC = shader->getShaderConstHandle( ShaderGenVars::lightConfigData ); 339 mLightAmbient = shader->getShaderConstHandle( ShaderGenVars::lightAmbient ); 340 mLightSpotDir = shader->getShaderConstHandle( ShaderGenVars::lightSpotDir ); 341 mLightSpotParamsSC = shader->getShaderConstHandle( ShaderGenVars::lightSpotParams ); 342 343 mHasVectorLightSC = shader->getShaderConstHandle(ShaderGenVars::hasVectorLight); 344 mVectorLightDirectionSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightDirection); 345 mVectorLightColorSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightColor); 346 mVectorLightBrightnessSC = shader->getShaderConstHandle(ShaderGenVars::vectorLightBrightness); 347 348 mInit = true; 349} 350 351void BasicLightManager::LightingShaderConstants::_onShaderReload() 352{ 353 if (mShader.isValid()) 354 init( mShader ); 355} 356 357void BasicLightManager::setLightInfo( ProcessedMaterial* pmat, 358 const Material* mat, 359 const SceneData& sgData, 360 const SceneRenderState *state, 361 U32 pass, 362 GFXShaderConstBuffer* shaderConsts ) 363{ 364 PROFILE_SCOPE( BasicLightManager_SetLightInfo ); 365 366 GFXShader *shader = shaderConsts->getShader(); 367 368 // Check to see if this is the same shader. Since we 369 // sort by material we should get hit repeatedly by the 370 // same one. This optimization should save us many 371 // hash table lookups. 372 if ( mLastShader.getPointer() != shader ) 373 { 374 LightConstantMap::Iterator iter = mConstantLookup.find(shader); 375 if ( iter != mConstantLookup.end() ) 376 { 377 mLastConstants = iter->value; 378 } 379 else 380 { 381 LightingShaderConstants* lsc = new LightingShaderConstants(); 382 mConstantLookup[shader] = lsc; 383 384 mLastConstants = lsc; 385 } 386 387 // Set our new shader 388 mLastShader = shader; 389 } 390 391 // Make sure that our current lighting constants are initialized 392 if (!mLastConstants->mInit) 393 mLastConstants->init(shader); 394 395 // NOTE: If you encounter a crash from this point forward 396 // while setting a shader constant its probably because the 397 // mConstantLookup has bad shaders/constants in it. 398 // 399 // This is a known crash bug that can occur if materials/shaders 400 // are reloaded and the light manager is not reset. 401 // 402 // We should look to fix this by clearing the table. 403 404 _update4LightConsts( sgData, 405 mLastConstants->mLightPosition, 406 mLastConstants->mLightDiffuse, 407 mLastConstants->mLightAmbient, 408 mLastConstants->mLightConfigDataSC, 409 mLastConstants->mLightSpotDir, 410 mLastConstants->mLightSpotParamsSC, 411 mLastConstants->mHasVectorLightSC, 412 mLastConstants->mVectorLightDirectionSC, 413 mLastConstants->mVectorLightColorSC, 414 mLastConstants->mVectorLightBrightnessSC, 415 shaderConsts ); 416} 417