postEffectManager.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  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 "postFx/postEffectManager.h"
  24. #include "postFx/postEffect.h"
  25. #include "postFx/postEffectVis.h"
  26. #include "renderInstance/renderBinManager.h"
  27. #include "scene/sceneManager.h"
  28. #include "scene/sceneRenderState.h"
  29. #include "console/consoleTypes.h"
  30. #include "core/module.h"
  31. MODULE_BEGIN( PostEffectManager )
  32. MODULE_SHUTDOWN_AFTER( Sim )
  33. MODULE_INIT
  34. {
  35. ManagedSingleton< PostEffectManager >::createSingleton();
  36. }
  37. MODULE_SHUTDOWN
  38. {
  39. ManagedSingleton< PostEffectManager >::deleteSingleton();
  40. }
  41. MODULE_END;
  42. bool PostEffectManager::smRenderEffects = true;
  43. PostEffectManager::PostEffectManager() :
  44. mLastBackBufferTarget( NULL ),
  45. mFrameStateSwitch( false )
  46. {
  47. GFXDevice::getDeviceEventSignal().notify( this, &PostEffectManager::_handleDeviceEvent );
  48. RenderPassManager::getRenderBinSignal().notify( this, &PostEffectManager::_handleBinEvent );
  49. SceneManager::getPostRenderSignal().notify( this, &PostEffectManager::_onPostRenderPass );
  50. Con::addVariable("pref::enablePostEffects", TypeBool, &smRenderEffects,
  51. "@brief If true, post effects will be eanbled.\n\n"
  52. "@ingroup Game");
  53. }
  54. PostEffectManager::~PostEffectManager()
  55. {
  56. GFXDevice::getDeviceEventSignal().remove( this, &PostEffectManager::_handleDeviceEvent );
  57. RenderPassManager::getRenderBinSignal().remove( this, &PostEffectManager::_handleBinEvent );
  58. SceneManager::getPostRenderSignal().remove( this, &PostEffectManager::_onPostRenderPass );
  59. }
  60. bool PostEffectManager::_handleDeviceEvent( GFXDevice::GFXDeviceEventType evt )
  61. {
  62. switch( evt )
  63. {
  64. case GFXDevice::deStartOfFrame:
  65. PFXVIS->onStartOfFrame();
  66. // Fall through
  67. case GFXDevice::deDestroy:
  68. // Free the back buffer as the device or
  69. // its content is now invalid.
  70. releaseBackBufferTex();
  71. break;
  72. case GFXDevice::deEndOfFrame:
  73. renderEffects( NULL, PFXEndOfFrame );
  74. // Toggle frame state history switch
  75. mFrameStateSwitch = !mFrameStateSwitch;
  76. break;
  77. default:
  78. break;
  79. }
  80. return true;
  81. }
  82. void PostEffectManager::_handleBinEvent( RenderBinManager *bin,
  83. const SceneRenderState* sceneState,
  84. bool isBinStart )
  85. {
  86. if ( sceneState->isShadowPass() ||
  87. sceneState->isOtherPass() )
  88. return;
  89. // We require a bin name to process effects... without
  90. // it we can skip the bin entirely.
  91. String binName( bin->getName() );
  92. if ( binName.isEmpty() )
  93. return;
  94. renderEffects( sceneState, isBinStart ? PFXBeforeBin : PFXAfterBin, binName );
  95. }
  96. void PostEffectManager::_onPostRenderPass( SceneManager *sceneGraph, const SceneRenderState *sceneState )
  97. {
  98. if ( !sceneState->isDiffusePass() )
  99. return;
  100. renderEffects( sceneState, PFXAfterDiffuse );
  101. }
  102. GFXTextureObject* PostEffectManager::getBackBufferTex()
  103. {
  104. GFXTarget *target = GFX->getActiveRenderTarget();
  105. if ( mBackBufferCopyTex.isNull() ||
  106. target != mLastBackBufferTarget )
  107. {
  108. const Point2I &targetSize = target->getSize();
  109. GFXFormat targetFormat = target->getFormat();
  110. mBackBufferCopyTex.set( targetSize.x, targetSize.y,
  111. targetFormat,
  112. &PostFxTextureSRGBProfile, "mBackBufferCopyTex" );
  113. target->resolveTo( mBackBufferCopyTex );
  114. mLastBackBufferTarget = target;
  115. }
  116. return mBackBufferCopyTex;
  117. }
  118. void PostEffectManager::releaseBackBufferTex()
  119. {
  120. mBackBufferCopyTex = NULL;
  121. mLastBackBufferTarget = NULL;
  122. }
  123. bool PostEffectManager::_addEffect( PostEffect *effect )
  124. {
  125. EffectVector *effects = NULL;
  126. const String &binName = effect->getRenderBin();
  127. switch( effect->getRenderTime() )
  128. {
  129. case PFXAfterDiffuse:
  130. effects = &mAfterDiffuseList;
  131. break;
  132. case PFXEndOfFrame:
  133. effects = &mEndOfFrameList;
  134. break;
  135. case PFXBeforeBin:
  136. effects = &mBeforeBinMap[binName];
  137. break;
  138. case PFXAfterBin:
  139. effects = &mAfterBinMap[binName];
  140. break;
  141. case PFXTexGenOnDemand:
  142. break;
  143. }
  144. if ( effects == NULL )
  145. return false;
  146. effects->push_back( effect );
  147. // Resort the effects by priority.
  148. effects->sort( &_effectPrioritySort );
  149. return true;
  150. }
  151. bool PostEffectManager::_removeEffect( PostEffect *effect )
  152. {
  153. // Check the end of frame list.
  154. EffectVector::iterator iter = T3D::find( mEndOfFrameList.begin(), mEndOfFrameList.end(), effect );
  155. if ( iter != mEndOfFrameList.end() )
  156. {
  157. mEndOfFrameList.erase( iter );
  158. return true;
  159. }
  160. // Check the diffuse list.
  161. iter = T3D::find( mAfterDiffuseList.begin(), mAfterDiffuseList.end(), effect );
  162. if ( iter != mAfterDiffuseList.end() )
  163. {
  164. mAfterDiffuseList.erase( iter );
  165. return true;
  166. }
  167. // Now check the bin maps.
  168. EffectMap::Iterator mapIter = mAfterBinMap.begin();
  169. for( ; mapIter != mAfterBinMap.end(); mapIter++ )
  170. {
  171. EffectVector &effects = mapIter->value;
  172. iter = T3D::find( effects.begin(), effects.end(), effect );
  173. if ( iter != effects.end() )
  174. {
  175. effects.erase( iter );
  176. return true;
  177. }
  178. }
  179. mapIter = mBeforeBinMap.begin();
  180. for( ; mapIter != mBeforeBinMap.end(); mapIter++ )
  181. {
  182. EffectVector &effects = mapIter->value;
  183. iter = T3D::find( effects.begin(), effects.end(), effect );
  184. if ( iter != effects.end() )
  185. {
  186. effects.erase( iter );
  187. return true;
  188. }
  189. }
  190. return false;
  191. }
  192. void PostEffectManager::renderEffects( const SceneRenderState *state,
  193. const PFXRenderTime effectTiming,
  194. const String &binName )
  195. {
  196. // Check the global render effect state as
  197. // well as the
  198. if ( !smRenderEffects ||
  199. ( state && !state->usePostEffects() ))
  200. return;
  201. EffectVector *effects = NULL;
  202. switch( effectTiming )
  203. {
  204. case PFXBeforeBin:
  205. effects = &mBeforeBinMap[binName];
  206. break;
  207. case PFXAfterBin:
  208. effects = &mAfterBinMap[binName];
  209. break;
  210. case PFXAfterDiffuse:
  211. effects = &mAfterDiffuseList;
  212. break;
  213. case PFXEndOfFrame:
  214. effects = &mEndOfFrameList;
  215. break;
  216. case PFXTexGenOnDemand:
  217. break;
  218. }
  219. AssertFatal( effects != NULL, "Bad effect time" );
  220. // Skip out if we don't have any effects.
  221. if ( effects->empty() )
  222. return;
  223. // This is used to pass the output texture
  224. // of one effect into the next effect.
  225. GFXTexHandle chainTex;
  226. // Process the effects.
  227. for ( U32 i = 0; i < effects->size(); i++ )
  228. {
  229. PostEffect *effect = (*effects)[i];
  230. AssertFatal( effect != NULL, "Somehow this happened" );
  231. effect->process( state, chainTex );
  232. }
  233. }
  234. void PostEffectManager::setFrameMatrices( const MatrixF &worldToCamera, const MatrixF &cameraToScreen )
  235. {
  236. PFXFrameState &thisFrame = mFrameState[mFrameStateSwitch];
  237. thisFrame.worldToCamera = worldToCamera;
  238. thisFrame.cameraToScreen = cameraToScreen;
  239. }
  240. S32 PostEffectManager::_effectPrioritySort( PostEffect* const *e1, PostEffect* const *e2 )
  241. {
  242. F32 p1 = (*e1)->getPriority();
  243. F32 p2 = (*e2)->getPriority();
  244. if( p1 > p2 )
  245. return -1;
  246. else if( p1 < p2 )
  247. return 1;
  248. return 0;
  249. }
  250. void PostEffectManager::dumpActivePostFX()
  251. {
  252. EffectVector effects;
  253. for (U32 i = 0; i < mEndOfFrameList.size(); i++)
  254. {
  255. PostEffect* effect = mEndOfFrameList[i];
  256. if(effect->isEnabled())
  257. effects.push_back(effect);
  258. }
  259. for (U32 i = 0; i < mAfterDiffuseList.size(); i++)
  260. {
  261. PostEffect* effect = mAfterDiffuseList[i];
  262. if (effect->isEnabled())
  263. effects.push_back(effect);
  264. }
  265. // Now check the bin maps.
  266. EffectMap::Iterator mapIter = mAfterBinMap.begin();
  267. for (; mapIter != mAfterBinMap.end(); mapIter++)
  268. {
  269. EffectVector& ef = mapIter->value;
  270. for (U32 i = 0; i < ef.size(); i++)
  271. {
  272. PostEffect* effect = ef[i];
  273. if (effect->isEnabled())
  274. effects.push_back(effect);
  275. }
  276. }
  277. mapIter = mBeforeBinMap.begin();
  278. for (; mapIter != mBeforeBinMap.end(); mapIter++)
  279. {
  280. EffectVector& ef = mapIter->value;
  281. for (U32 i = 0; i < ef.size(); i++)
  282. {
  283. PostEffect* effect = ef[i];
  284. if (effect->isEnabled())
  285. effects.push_back(effect);
  286. }
  287. }
  288. // Resort the effects by priority.
  289. effects.sort(&_effectPrioritySort);
  290. Con::printf("PostEffectManager::dumpActivePostFX() - Beginning Dump");
  291. for (U32 i = 0; i < effects.size(); i++)
  292. {
  293. PostEffect* effect = effects[i];
  294. if (effect->isEnabled())
  295. {
  296. Con::printf("%s", effect->getName());
  297. }
  298. }
  299. Con::printf("PostEffectManager::dumpActivePostFX() - Ending Dump");
  300. }
  301. DefineEngineFunction(dumpActivePostFX, void, (),, "")
  302. {
  303. PFXMGR->dumpActivePostFX();
  304. }