Torque3D Documentation / _generateds / postEffectManager.cpp

postEffectManager.cpp

Engine/source/postFx/postEffectManager.cpp

More...

Public Functions

DefineEngineFunction(dumpActivePostFX , void , () , "" )

Detailed Description

Public Variables

 MODULE_END 
 MODULE_INIT 
 MODULE_SHUTDOWN 

Public Functions

DefineEngineFunction(dumpActivePostFX , void , () , "" )

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