lightManager.cpp 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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/lightManager.h"
  24. #include "console/console.h"
  25. #include "console/consoleTypes.h"
  26. #include "core/util/safeDelete.h"
  27. #include "console/sim.h"
  28. #include "console/simSet.h"
  29. #include "scene/sceneManager.h"
  30. #include "materials/materialManager.h"
  31. #include "materials/sceneData.h"
  32. #include "lighting/lightInfo.h"
  33. #include "lighting/lightingInterfaces.h"
  34. #include "T3D/gameBase/gameConnection.h"
  35. #include "gfx/gfxStringEnumTranslate.h"
  36. #include "console/engineAPI.h"
  37. #include "renderInstance/renderDeferredMgr.h"
  38. Signal<void(const char*,bool)> LightManager::smActivateSignal;
  39. LightManager *LightManager::smActiveLM = NULL;
  40. LightManager::LightManager( const char *name, const char *id )
  41. : mName( name ),
  42. mId( id ),
  43. mIsActive( false ),
  44. mDefaultLight( NULL ),
  45. mSceneManager( NULL ),
  46. mCullPos( Point3F::Zero ),
  47. mAvailableSLInterfaces( NULL )
  48. {
  49. _getLightManagers().insert( mName, this );
  50. dMemset( &mSpecialLights, 0, sizeof( mSpecialLights ) );
  51. }
  52. LightManager::~LightManager()
  53. {
  54. _getLightManagers().erase( mName );
  55. SAFE_DELETE( mAvailableSLInterfaces );
  56. SAFE_DELETE( mDefaultLight );
  57. }
  58. LightManagerMap& LightManager::_getLightManagers()
  59. {
  60. static LightManagerMap lightManagerMap;
  61. return lightManagerMap;
  62. }
  63. LightManager* LightManager::findByName( const char *name )
  64. {
  65. LightManagerMap &lightManagers = _getLightManagers();
  66. LightManagerMap::Iterator iter = lightManagers.find( name );
  67. if ( iter != lightManagers.end() )
  68. return iter->value;
  69. return NULL;
  70. }
  71. void LightManager::getLightManagerNames( String *outString )
  72. {
  73. LightManagerMap &lightManagers = _getLightManagers();
  74. LightManagerMap::Iterator iter = lightManagers.begin();
  75. for ( ; iter != lightManagers.end(); iter++ )
  76. *outString += iter->key + "\t";
  77. // TODO!
  78. //outString->rtrim();
  79. }
  80. LightInfo* LightManager::createLightInfo(LightInfo* light /* = NULL */)
  81. {
  82. LightInfo *outLight = (light != NULL) ? light : new LightInfo;
  83. LightManagerMap &lightManagers = _getLightManagers();
  84. LightManagerMap::Iterator iter = lightManagers.begin();
  85. for ( ; iter != lightManagers.end(); iter++ )
  86. {
  87. LightManager *lm = iter->value;
  88. lm->_addLightInfoEx( outLight );
  89. }
  90. return outLight;
  91. }
  92. void LightManager::initLightFields()
  93. {
  94. LightManagerMap &lightManagers = _getLightManagers();
  95. LightManagerMap::Iterator iter = lightManagers.begin();
  96. for ( ; iter != lightManagers.end(); iter++ )
  97. {
  98. LightManager *lm = iter->value;
  99. lm->_initLightFields();
  100. }
  101. }
  102. IMPLEMENT_GLOBAL_CALLBACK( onLightManagerActivate, void, ( const char *name ), ( name ),
  103. "A callback called by the engine when a light manager is activated.\n"
  104. "@param name The name of the light manager being activated.\n"
  105. "@ingroup Lighting\n" );
  106. void LightManager::activate( SceneManager *sceneManager )
  107. {
  108. AssertFatal( sceneManager, "LightManager::activate() - Got null scene manager!" );
  109. AssertFatal( mIsActive == false, "LightManager::activate() - Already activated!" );
  110. AssertFatal( smActiveLM == NULL, "LightManager::activate() - A previous LM is still active!" );
  111. mIsActive = true;
  112. mSceneManager = sceneManager;
  113. smActiveLM = this;
  114. onLightManagerActivate_callback( getName() );
  115. }
  116. IMPLEMENT_GLOBAL_CALLBACK( onLightManagerDeactivate, void, ( const char *name ), ( name ),
  117. "A callback called by the engine when a light manager is deactivated.\n"
  118. "@param name The name of the light manager being deactivated.\n"
  119. "@ingroup Lighting\n" );
  120. void LightManager::deactivate()
  121. {
  122. AssertFatal( mIsActive == true, "LightManager::deactivate() - Already deactivated!" );
  123. AssertFatal( smActiveLM == this, "LightManager::activate() - This isn't the active light manager!" );
  124. if( Sim::getRootGroup() ) // To protect against shutdown.
  125. onLightManagerDeactivate_callback( getName() );
  126. mIsActive = false;
  127. mSceneManager = NULL;
  128. smActiveLM = NULL;
  129. // Just in case... make sure we're all clear.
  130. unregisterAllLights();
  131. }
  132. LightInfo* LightManager::getDefaultLight()
  133. {
  134. // The sun is always our default light when
  135. // when its registered.
  136. if ( mSpecialLights[ LightManager::slSunLightType ] )
  137. return mSpecialLights[ LightManager::slSunLightType ];
  138. // Else return a dummy special light.
  139. if ( !mDefaultLight )
  140. mDefaultLight = createLightInfo();
  141. return mDefaultLight;
  142. }
  143. LightInfo* LightManager::getSpecialLight( LightManager::SpecialLightTypesEnum type, bool useDefault )
  144. {
  145. if ( mSpecialLights[type] )
  146. return mSpecialLights[type];
  147. if ( useDefault )
  148. return getDefaultLight();
  149. return NULL;
  150. }
  151. void LightManager::setSpecialLight( LightManager::SpecialLightTypesEnum type, LightInfo *light )
  152. {
  153. if ( light && type == slSunLightType )
  154. {
  155. // The sun must be specially positioned and ranged
  156. // so that it can be processed like a point light
  157. // in the stock light shader used by Basic Lighting.
  158. light->setPosition( mCullPos - ( light->getDirection() * 10000.0f ) );
  159. light->setRange( 2000000.0f );
  160. }
  161. mSpecialLights[type] = light;
  162. registerGlobalLight( light, NULL );
  163. }
  164. void LightManager::registerGlobalLights( const Frustum *frustum, bool staticLighting, bool enableZoneLightCulling)
  165. {
  166. PROFILE_SCOPE( LightManager_RegisterGlobalLights );
  167. // TODO: We need to work this out...
  168. //
  169. // 1. Why do we register and unregister lights on every
  170. // render when they don't often change... shouldn't we
  171. // just register once and keep them?
  172. //
  173. // 2. If we do culling of lights should this happen as part
  174. // of registration or somewhere else?
  175. //
  176. // Grab the lights to process.
  177. Vector<SceneObject*> activeLights;
  178. const U32 lightMask = LightObjectType;
  179. if ( staticLighting || !frustum )
  180. {
  181. // We're processing static lighting or want all the lights
  182. // in the container registerd... so no culling.
  183. getSceneManager()->getContainer()->findObjectList( lightMask, &activeLights );
  184. }
  185. else
  186. {
  187. // Cull the lights using the frustum.
  188. getSceneManager()->getContainer()->findObjectList(*frustum, lightMask, &activeLights);
  189. if (enableZoneLightCulling)
  190. {
  191. for (U32 i = 0; i < activeLights.size(); ++i)
  192. {
  193. if (!getSceneManager()->mRenderedObjectsList.contains(activeLights[i]))
  194. {
  195. activeLights.erase(i);
  196. --i;
  197. }
  198. }
  199. }
  200. // Store the culling position for sun placement
  201. // later... see setSpecialLight.
  202. mCullPos = frustum->getPosition();
  203. // HACK: Make sure the control object always gets
  204. // processed as lights mounted to it don't change
  205. // the shape bounds and can often get culled.
  206. GameConnection *conn = GameConnection::getConnectionToServer();
  207. if (conn->getControlObject())
  208. {
  209. GameBase *conObject = conn->getControlObject();
  210. activeLights.push_back_unique(conObject);
  211. }
  212. }
  213. // Let the lights register themselves.
  214. for ( U32 i = 0; i < activeLights.size(); i++ )
  215. {
  216. ISceneLight *lightInterface = dynamic_cast<ISceneLight*>( activeLights[i] );
  217. if ( lightInterface )
  218. lightInterface->submitLights( this, staticLighting );
  219. }
  220. }
  221. void LightManager::registerGlobalLight( LightInfo *light, SimObject *obj )
  222. {
  223. AssertFatal( !mRegisteredLights.contains( light ),
  224. "LightManager::registerGlobalLight - This light is already registered!" );
  225. mRegisteredLights.push_back( light );
  226. }
  227. void LightManager::unregisterGlobalLight( LightInfo *light )
  228. {
  229. mRegisteredLights.unregisterLight( light );
  230. // If this is the sun... clear the special light too.
  231. if ( light == mSpecialLights[slSunLightType] )
  232. dMemset( mSpecialLights, 0, sizeof( mSpecialLights ) );
  233. }
  234. void LightManager::registerLocalLight( LightInfo *light )
  235. {
  236. // TODO: What should we do here?
  237. }
  238. void LightManager::unregisterLocalLight( LightInfo *light )
  239. {
  240. // TODO: What should we do here?
  241. }
  242. void LightManager::unregisterAllLights()
  243. {
  244. dMemset( mSpecialLights, 0, sizeof( mSpecialLights ) );
  245. mRegisteredLights.clear();
  246. }
  247. void LightManager::getAllUnsortedLights( Vector<LightInfo*> *list ) const
  248. {
  249. list->merge( mRegisteredLights );
  250. }
  251. void LightManager::_update4LightConsts( const SceneData &sgData,
  252. GFXShaderConstHandle *lightPositionSC,
  253. GFXShaderConstHandle *lightDiffuseSC,
  254. GFXShaderConstHandle *lightAmbientSC,
  255. GFXShaderConstHandle *lightInvRadiusSqSC,
  256. GFXShaderConstHandle *lightSpotDirSC,
  257. GFXShaderConstHandle *lightSpotAngleSC,
  258. GFXShaderConstHandle *lightSpotFalloffSC,
  259. GFXShaderConstBuffer *shaderConsts )
  260. {
  261. PROFILE_SCOPE( LightManager_Update4LightConsts );
  262. // Skip over gathering lights if we don't have to!
  263. if ( lightPositionSC->isValid() ||
  264. lightDiffuseSC->isValid() ||
  265. lightInvRadiusSqSC->isValid() ||
  266. lightSpotDirSC->isValid() ||
  267. lightSpotAngleSC->isValid() ||
  268. lightSpotFalloffSC->isValid() )
  269. {
  270. PROFILE_SCOPE( LightManager_Update4LightConsts_setLights );
  271. static AlignedArray<Point4F> lightPositions( 3, sizeof( Point4F ) );
  272. static AlignedArray<Point4F> lightSpotDirs( 3, sizeof( Point4F ) );
  273. static AlignedArray<Point4F> lightColors( 4, sizeof( Point4F ) );
  274. static Point4F lightInvRadiusSq;
  275. static Point4F lightSpotAngle;
  276. static Point4F lightSpotFalloff;
  277. F32 range;
  278. // Need to clear the buffers so that we don't leak
  279. // lights from previous passes or have NaNs.
  280. dMemset( lightPositions.getBuffer(), 0, lightPositions.getBufferSize() );
  281. dMemset( lightSpotDirs.getBuffer(), 0, lightSpotDirs.getBufferSize() );
  282. dMemset( lightColors.getBuffer(), 0, lightColors.getBufferSize() );
  283. lightInvRadiusSq = Point4F::Zero;
  284. lightSpotAngle.set( -1.0f, -1.0f, -1.0f, -1.0f );
  285. lightSpotFalloff.set( F32_MAX, F32_MAX, F32_MAX, F32_MAX );
  286. // Gather the data for the first 4 lights.
  287. const LightInfo *light;
  288. for ( U32 i=0; i < 4; i++ )
  289. {
  290. light = sgData.lights[i];
  291. if ( !light )
  292. break;
  293. // The light positions and spot directions are
  294. // in SoA order to make optimal use of the GPU.
  295. const Point3F &lightPos = light->getPosition();
  296. lightPositions[0][i] = lightPos.x;
  297. lightPositions[1][i] = lightPos.y;
  298. lightPositions[2][i] = lightPos.z;
  299. const VectorF &lightDir = light->getDirection();
  300. lightSpotDirs[0][i] = lightDir.x;
  301. lightSpotDirs[1][i] = lightDir.y;
  302. lightSpotDirs[2][i] = lightDir.z;
  303. if ( light->getType() == LightInfo::Spot )
  304. {
  305. lightSpotAngle[i] = mCos( mDegToRad( light->getOuterConeAngle() / 2.0f ) );
  306. lightSpotFalloff[i] = 1.0f / getMax( F32_MIN, mCos( mDegToRad( light->getInnerConeAngle() / 2.0f ) ) - lightSpotAngle[i] );
  307. }
  308. // Prescale the light color by the brightness to
  309. // avoid doing this in the shader.
  310. lightColors[i] = Point4F(light->getColor()) * light->getBrightness();
  311. // We need 1 over range^2 here.
  312. range = light->getRange().x;
  313. lightInvRadiusSq[i] = 1.0f / ( range * range );
  314. }
  315. shaderConsts->setSafe( lightPositionSC, lightPositions );
  316. shaderConsts->setSafe( lightDiffuseSC, lightColors );
  317. shaderConsts->setSafe( lightInvRadiusSqSC, lightInvRadiusSq );
  318. shaderConsts->setSafe( lightSpotDirSC, lightSpotDirs );
  319. shaderConsts->setSafe( lightSpotAngleSC, lightSpotAngle );
  320. shaderConsts->setSafe( lightSpotFalloffSC, lightSpotFalloff );
  321. }
  322. // Setup the ambient lighting from the first
  323. // light which is the directional light if
  324. // one exists at all in the scene.
  325. if ( lightAmbientSC->isValid() )
  326. shaderConsts->set( lightAmbientSC, sgData.ambientLightColor );
  327. }
  328. AvailableSLInterfaces* LightManager::getSceneLightingInterface()
  329. {
  330. if ( !mAvailableSLInterfaces )
  331. mAvailableSLInterfaces = new AvailableSLInterfaces();
  332. return mAvailableSLInterfaces;
  333. }
  334. bool LightManager::lightScene( const char* callback, const char* param )
  335. {
  336. BitSet32 flags = 0;
  337. if ( param )
  338. {
  339. if ( !dStricmp( param, "forceAlways" ) )
  340. flags.set( SceneLighting::ForceAlways );
  341. else if ( !dStricmp(param, "forceWritable" ) )
  342. flags.set( SceneLighting::ForceWritable );
  343. else if ( !dStricmp(param, "loadOnly" ) )
  344. flags.set( SceneLighting::LoadOnly );
  345. }
  346. // The SceneLighting object will delete itself
  347. // once the lighting process is complete.
  348. SceneLighting* sl = new SceneLighting( getSceneLightingInterface() );
  349. return sl->lightScene( callback, flags );
  350. }
  351. RenderDeferredMgr* LightManager::_findDeferredRenderBin()
  352. {
  353. RenderPassManager* rpm = getSceneManager()->getDefaultRenderPass();
  354. for( U32 i = 0; i < rpm->getManagerCount(); i++ )
  355. {
  356. RenderBinManager *bin = rpm->getManager( i );
  357. if( bin->getRenderInstType() == RenderDeferredMgr::RIT_Deferred )
  358. {
  359. return ( RenderDeferredMgr* ) bin;
  360. }
  361. }
  362. return NULL;
  363. }
  364. DefineEngineFunction( setLightManager, bool, ( const char *name ),,
  365. "Finds and activates the named light manager.\n"
  366. "@return Returns true if the light manager is found and activated.\n"
  367. "@ingroup Lighting\n" )
  368. {
  369. return gClientSceneGraph->setLightManager( name );
  370. }
  371. DefineEngineFunction( lightScene, bool, ( const char *completeCallbackFn, const char *mode ), ( nullAsType<const char*>(), nullAsType<const char*>() ),
  372. "Will generate static lighting for the scene if supported by the active light manager.\n\n"
  373. "If mode is \"forceAlways\", the lightmaps will be regenerated regardless of whether "
  374. "lighting cache files can be written to. If mode is \"forceWritable\", then the lightmaps "
  375. "will be regenerated only if the lighting cache files can be written.\n"
  376. "@param completeCallbackFn The name of the function to execute when the lighting is complete.\n"
  377. "@param mode One of \"forceAlways\", \"forceWritable\" or \"loadOnly\".\n"
  378. "@return Returns true if the scene lighting process was started.\n"
  379. "@ingroup Lighting\n" )
  380. {
  381. if ( !LIGHTMGR )
  382. return false;
  383. return LIGHTMGR->lightScene( completeCallbackFn, mode );
  384. }
  385. DefineEngineFunction( getLightManagerNames, String, (),,
  386. "Returns a tab seperated list of light manager names.\n"
  387. "@ingroup Lighting\n" )
  388. {
  389. String names;
  390. LightManager::getLightManagerNames( &names );
  391. return names;
  392. }
  393. DefineEngineFunction( getActiveLightManager, const char*, (),,
  394. "Returns the active light manager name.\n"
  395. "@ingroup Lighting\n" )
  396. {
  397. if ( !LIGHTMGR )
  398. return NULL;
  399. return LIGHTMGR->getName();
  400. }
  401. DefineEngineFunction( resetLightManager, void, (),,
  402. "@brief Deactivates and then activates the currently active light manager."
  403. "This causes most shaders to be regenerated and is often used when global "
  404. "rendering changes have occured.\n"
  405. "@ingroup Lighting\n" )
  406. {
  407. LightManager *lm = LIGHTMGR;
  408. if ( !lm )
  409. return;
  410. SceneManager *sm = lm->getSceneManager();
  411. lm->deactivate();
  412. lm->activate( sm );
  413. }