postEffectManager.cpp
Engine/source/postFx/postEffectManager.cpp
Public Variables
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