diff --git a/Engine/source/lighting/common/projectedShadow.cpp b/Engine/source/lighting/common/projectedShadow.cpp index 030c37fd7..867f5c1b8 100644 --- a/Engine/source/lighting/common/projectedShadow.cpp +++ b/Engine/source/lighting/common/projectedShadow.cpp @@ -551,7 +551,7 @@ void ProjectedShadow::_renderToTexture( F32 camDist, const TSRenderState &rdata } if ( smShadowFilter ) - smShadowFilter->process( NULL, mShadowTexture ); + smShadowFilter->process( NULL, &mShadowTexture ); } // Restore frustum diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index e17509b02..7a4ec3353 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -1169,7 +1169,10 @@ void PostEffect::_setupConstants( const SceneRenderState *state ) } } -void PostEffect::_setupTexture( U32 stage, GFXTexHandle &inputTex, const RectI *inTexViewport ) +void PostEffect::_setupTexture(U32 stage, + GFXTexHandle* inputTex, + U32 inputTexCount, + const RectI* inTexViewport) { const String &texFilename = mTextureAsset[stage].notNull() ? mTextureAsset[stage]->getImageFile() : ""; @@ -1178,17 +1181,17 @@ void PostEffect::_setupTexture( U32 stage, GFXTexHandle &inputTex, const RectI * RectI viewport = GFX->getViewport(); - if ( _inTexSlotFromName(texFilename) >= 0 ) + S32 inSlot = _inTexSlotFromName(texFilename); + if (inSlot >= 0) { - theTex = inputTex; + if ((U32)inSlot < inputTexCount) + { + theTex = inputTex[inSlot]; - if ( inTexViewport ) - { - viewport = *inTexViewport; - } - else if ( theTex ) - { - viewport.set( 0, 0, theTex->getWidth(), theTex->getHeight() ); + if (inSlot == 0 && inTexViewport) + viewport = *inTexViewport; + else if (theTex) + viewport.set(0, 0, theTex->getWidth(), theTex->getHeight()); } } else if ( texFilename.compare( "$backBuffer", 0, String::NoCase ) == 0 ) @@ -1432,9 +1435,10 @@ void PostEffect::_cleanTargets( bool recurse ) } } -void PostEffect::process( const SceneRenderState *state, - GFXTexHandle& inOutTex, - const RectI *inTexViewport ) +void PostEffect::process( const SceneRenderState* state, + GFXTexHandle* inOutTex, + U32 inOutTexCount, + const RectI* inTexViewport) { // If the shader is forced to be skipped... then skip. if ( mSkip ) @@ -1470,11 +1474,16 @@ void PostEffect::process( const SceneRenderState *state, } GFXTransformSaver saver; + GFXTexHandle chain[NumMRTTargets]; + U32 texCount = getMin(inOutTexCount, (U32)NumMRTTargets); + for (U32 c = 0; c < texCount; c++) + chain[c] = inOutTex[c]; + // Set the textures. for (U32 i = 0; i < NumTextures; i++) { if (mTextureType[i] == NormalTextureType) - _setupTexture(i, inOutTex, inTexViewport); + _setupTexture(i, chain, texCount, inTexViewport); else if (mTextureType[i] == CubemapType) _setupCubemapTexture(i, mCubemapTextures[i]); else if (mTextureType[i] == CubemapArrayType) @@ -1490,12 +1499,13 @@ void PostEffect::process( const SceneRenderState *state, const bool hasDepth = mTargetDepthStencil.isValid(); bool hasColorTarget = false; + U32 curTargetCount = 0; for (U32 c = 0; c < NumMRTTargets; c++) { if (mTargetTex[c].isValid()) { hasColorTarget = true; - break; + curTargetCount++; } } @@ -1621,9 +1631,11 @@ void PostEffect::process( const SceneRenderState *state, PFXMGR->releaseBackBufferTex(); } - inOutTex = mTargetTex[0]; for (U32 c = 0; c < NumMRTTargets; c++) { + if (c < texCount) + chain[c] = mTargetTex[c]; + if (!mNamedTarget[c].isRegistered()) mTargetTex[c] = NULL; } @@ -1632,12 +1644,13 @@ void PostEffect::process( const SceneRenderState *state, // are processed as it screws up the viewport. saver.restore(); + const U32 nextTexCount = getMax(getMax(texCount, curTargetCount), 1u); // Now process my children. iterator i = begin(); for ( ; i != end(); i++ ) { PostEffect *effect = static_cast(*i); - effect->process( state, inOutTex ); + effect->process( state, chain, nextTexCount); } if ( mOneFrameOnly ) @@ -2048,19 +2061,13 @@ void PostEffect::clearShaderMacros() mUpdateShader = true; } -GFXTextureObject* PostEffect::_getTargetTexture( U32 index) +GFXTextureObject* PostEffect::_getTargetTexture(U32 index) { - // A TexGen PostEffect will generate its texture now if it - // has not already. - if ( mRenderTime == PFXTexGenOnDemand && - ( !mTargetTex[index] || mUpdateShader ) ) + if (mRenderTime == PFXTexGenOnDemand + && (!mTargetTex[index] || mUpdateShader)) { - GFXTexHandle chainTex; - process( NULL, chainTex ); - - // TODO: We should add a conditional copy - // to a non-RT texture here to reduce the - // amount of non-swappable RTs in use. + GFXTexHandle chainTex[NumMRTTargets]; // zero-initialised by GFXTexHandle ctor + process(NULL, chainTex, NumMRTTargets); } return mTargetTex[index].getPointer(); diff --git a/Engine/source/postFx/postEffect.h b/Engine/source/postFx/postEffect.h index 801db33c4..7d7914f22 100644 --- a/Engine/source/postFx/postEffect.h +++ b/Engine/source/postFx/postEffect.h @@ -280,7 +280,7 @@ protected: virtual void _setupConstants(const SceneRenderState* state); virtual void _setupTransforms(); virtual void _setupTarget(const SceneRenderState* state, bool* outClearTarget); - virtual void _setupTexture(U32 slot, GFXTexHandle& inputTex, const RectI* inTexViewport); + virtual void _setupTexture(U32 stage, GFXTexHandle* inputTex, U32 inputTexCount, const RectI* inTexViewport); virtual void _setupCubemapTexture(U32 stage, GFXCubemapHandle& inputTex); virtual void _setupCubemapArrayTexture(U32 slot, GFXCubemapArrayHandle& inputTex); @@ -345,7 +345,8 @@ public: DECLARE_CALLBACK(void, onDisabled, ()); virtual void process(const SceneRenderState* state, - GFXTexHandle& inOutTex, + GFXTexHandle* inOutTex, + U32 inOutTexCount = 1, const RectI* inTexViewport = NULL); void reload(); diff --git a/Engine/source/postFx/postEffectManager.cpp b/Engine/source/postFx/postEffectManager.cpp index d65e25e25..ec30732de 100644 --- a/Engine/source/postFx/postEffectManager.cpp +++ b/Engine/source/postFx/postEffectManager.cpp @@ -284,14 +284,14 @@ void PostEffectManager::renderEffects( const SceneRenderState *state, // This is used to pass the output texture // of one effect into the next effect. - GFXTexHandle chainTex; + GFXTexHandle chainTex[PostEffect::NumMRTTargets]; // Process the effects. for ( U32 i = 0; i < effects->size(); i++ ) { PostEffect *effect = (*effects)[i]; AssertFatal( effect != NULL, "Somehow this happened" ); - effect->process( state, chainTex ); + effect->process(state, chainTex, PostEffect::NumMRTTargets); } } diff --git a/Engine/source/renderInstance/renderFormatChanger.cpp b/Engine/source/renderInstance/renderFormatChanger.cpp index 893ef2cf6..374de6de4 100644 --- a/Engine/source/renderInstance/renderFormatChanger.cpp +++ b/Engine/source/renderInstance/renderFormatChanger.cpp @@ -144,7 +144,7 @@ void RenderFormatToken::process(SceneRenderState *state, RenderPassStateBin *cal // Run the PostEffect which copies data into the new target. if ( mCopyPostEffect.isValid() ) - mCopyPostEffect->process( state, curBackBuffer, &mTarget.getViewport() ); + mCopyPostEffect->process( state, &curBackBuffer,1, &mTarget.getViewport() ); } break; @@ -174,7 +174,7 @@ void RenderFormatToken::process(SceneRenderState *state, RenderPassStateBin *cal { // Need to create a texhandle here, since inOutTex gets assigned during process() GFXTexHandle inOutTex = mTargetColorTexture[mTargetChainIdx]; - mResolvePostEffect->process( state, inOutTex, &mTarget.getViewport() ); + mResolvePostEffect->process( state, &inOutTex, 1, &mTarget.getViewport() ); } } break;