diff --git a/Engine/source/gfx/gfxDevice.cpp b/Engine/source/gfx/gfxDevice.cpp index 9e57bcc81..f4ac1902b 100644 --- a/Engine/source/gfx/gfxDevice.cpp +++ b/Engine/source/gfx/gfxDevice.cpp @@ -849,7 +849,7 @@ void GFXDevice::popActiveRenderTarget() mRTStack.pop_back(); } -void GFXDevice::setActiveRenderTarget( GFXTarget *target ) +void GFXDevice::setActiveRenderTarget( GFXTarget *target, bool updateViewport ) { AssertFatal( target, "GFXDevice::setActiveRenderTarget - must specify a render target!" ); @@ -878,7 +878,10 @@ void GFXDevice::setActiveRenderTarget( GFXTarget *target ) // We should consider removing this and making it the // responsibility of the caller to set a proper viewport // when the target is changed. - setViewport( RectI( Point2I::Zero, mCurrentRT->getSize() ) ); + if ( updateViewport ) + { + setViewport( RectI( Point2I::Zero, mCurrentRT->getSize() ) ); + } } /// Helper class for GFXDevice::describeResources. diff --git a/Engine/source/gfx/gfxDevice.h b/Engine/source/gfx/gfxDevice.h index e153d02c5..874466665 100644 --- a/Engine/source/gfx/gfxDevice.h +++ b/Engine/source/gfx/gfxDevice.h @@ -695,7 +695,7 @@ public: void popActiveRenderTarget(); /// Assign a new active render target. - void setActiveRenderTarget( GFXTarget *target ); + void setActiveRenderTarget( GFXTarget *target, bool updateViewport=true ); /// Returns the current active render target. inline GFXTarget* getActiveRenderTarget() { return mCurrentRT; } diff --git a/Engine/source/postFx/postEffect.cpp b/Engine/source/postFx/postEffect.cpp index ff83997eb..04089338e 100644 --- a/Engine/source/postFx/postEffect.cpp +++ b/Engine/source/postFx/postEffect.cpp @@ -118,6 +118,7 @@ ImplementEnumType( PFXTargetViewport, "@ingroup Rendering\n\n") { PFXTargetViewport_TargetSize, "PFXTargetViewport_TargetSize", "Set viewport to match target size (default).\n" }, { PFXTargetViewport_GFXViewport, "PFXTargetViewport_GFXViewport", "Use the current GFX viewport (scaled to match target size).\n" }, + { PFXTargetViewport_NamedInTexture0, "PFXTargetViewport_NamedInTexture0", "Use the input texture 0 if it is named (scaled to match target size), otherwise revert to PFXTargetViewport_TargetSize if there is none.\n" }, EndImplementEnumType; @@ -947,7 +948,17 @@ void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarg const Point2I &oldTargetSize = oldTarget->getSize(); Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); - const RectI viewport = GFX->getViewport(); + const RectI &viewport = GFX->getViewport(); + + mNamedTarget.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); + } + else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) + { + // Scale the named input texture's viewport to match our target + const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); + Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); + + const RectI &viewport = mActiveNamedTarget[0]->getViewport(); mNamedTarget.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); } @@ -1009,7 +1020,17 @@ void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarg const Point2I &oldTargetSize = oldTarget->getSize(); Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); - const RectI viewport = GFX->getViewport(); + const RectI &viewport = GFX->getViewport(); + + mNamedTargetDepthStencil.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); + } + else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) + { + // Scale the named input texture's viewport to match our target + const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); + Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); + + const RectI &viewport = mActiveNamedTarget[0]->getViewport(); mNamedTargetDepthStencil.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); } @@ -1093,8 +1114,6 @@ void PostEffect::process( const SceneRenderState *state, bool clearTarget = false; _setupTarget( state, &clearTarget ); - RectI oldViewport = GFX->getViewport(); - if ( mTargetTex || mTargetDepthStencil ) { @@ -1110,6 +1129,7 @@ void PostEffect::process( const SceneRenderState *state, GFX->getActiveRenderTarget()->preserve(); #endif + const RectI &oldViewport = GFX->getViewport(); GFXTarget *oldTarget = GFX->getActiveRenderTarget(); GFX->pushActiveRenderTarget(); @@ -1121,21 +1141,38 @@ void PostEffect::process( const SceneRenderState *state, else mTarget->attachTexture( GFXTextureTarget::DepthStencil, mTargetDepthStencil ); - GFX->setActiveRenderTarget( mTarget ); + // Set the render target but not its viewport. We'll do that below. + GFX->setActiveRenderTarget( mTarget, false ); - // The setActiveRenderTarget() called above will change the viewport to cover the - // entire target area. Restore the viewport as necessary. if(mNamedTarget.isRegistered()) { + // Always use the name target's viewport, if available. It was set up in _setupTarget(). GFX->setViewport(mNamedTarget.getViewport()); } else if(mTargetViewport == PFXTargetViewport_GFXViewport) { + // Go with the current viewport as scaled against our render target. const Point2I &oldTargetSize = oldTarget->getSize(); const Point2I &targetSize = mTarget->getSize(); Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); GFX->setViewport( RectI( oldViewport.point.x*scale.x, oldViewport.point.y*scale.y, oldViewport.extent.x*scale.x, oldViewport.extent.y*scale.y ) ); } + else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) + { + // Go with the first input texture, if it is named. Scale the named input texture's viewport to match our target + const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); + const Point2I &targetSize = mTarget->getSize(); + Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); + + const RectI &viewport = mActiveNamedTarget[0]->getViewport(); + + GFX->setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); + } + else + { + // Default to using the whole target as the viewport + GFX->setViewport( RectI( Point2I::Zero, mTarget->getSize() ) ); + } } if ( clearTarget ) diff --git a/Engine/source/postFx/postEffectCommon.h b/Engine/source/postFx/postEffectCommon.h index fecef5a52..00bd2d4d4 100644 --- a/Engine/source/postFx/postEffectCommon.h +++ b/Engine/source/postFx/postEffectCommon.h @@ -77,6 +77,10 @@ enum PFXTargetViewport /// Use the current GFX viewport PFXTargetViewport_GFXViewport, + + /// Use the input texture 0 if it is named, otherwise + /// revert to PFXTargetViewport_TargetSize if there is none + PFXTargetViewport_NamedInTexture0, }; DefineEnumType( PFXTargetViewport ); diff --git a/Templates/Empty/game/core/scripts/client/postFx/ssao.cs b/Templates/Empty/game/core/scripts/client/postFx/ssao.cs index 8b54ce870..cd5bfc598 100644 --- a/Templates/Empty/game/core/scripts/client/postFx/ssao.cs +++ b/Templates/Empty/game/core/scripts/client/postFx/ssao.cs @@ -190,7 +190,7 @@ singleton PostEffect( SSAOPostFx ) target = "$outTex"; targetScale = "0.5 0.5"; - targetViewport = "PFXTargetViewport_GFXViewport"; + targetViewport = "PFXTargetViewport_NamedInTexture0"; singleton PostEffect() { diff --git a/Templates/Full/game/core/scripts/client/postFx/ssao.cs b/Templates/Full/game/core/scripts/client/postFx/ssao.cs index 8b54ce870..cd5bfc598 100644 --- a/Templates/Full/game/core/scripts/client/postFx/ssao.cs +++ b/Templates/Full/game/core/scripts/client/postFx/ssao.cs @@ -190,7 +190,7 @@ singleton PostEffect( SSAOPostFx ) target = "$outTex"; targetScale = "0.5 0.5"; - targetViewport = "PFXTargetViewport_GFXViewport"; + targetViewport = "PFXTargetViewport_NamedInTexture0"; singleton PostEffect() {