basicLightManager.cpp 14 KB

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