浏览代码

Viewport fix for PostFX and SSAO

- General fix for PostFX render targets to properly support the GFX
viewport setting.  This is an opt-in change through the use of the new
mTargetViewport property as most PostFX run fine with their assumption
of the viewport being the whole rendering target.
- The SSAO PostFX has been modified to use the new mTargetViewport
property.  This allows correct rendering in a side-by-side view such as
with the Oculus Rift, or any other constrained viewport rendering.
DavidWyand-GG 12 年之前
父节点
当前提交
88f2a4d903

+ 64 - 2
Engine/source/postFx/postEffect.cpp

@@ -112,6 +112,14 @@ ImplementEnumType( PFXTargetClear,
    { PFXTargetClear_OnDraw, "PFXTargetClear_OnDraw", "Clear before every draw.\n" },
 EndImplementEnumType;
 
+ImplementEnumType( PFXTargetViewport,
+   "Specifies how the viewport should be set up for a PostEffect's target.\n"
+   "@note Applies to both the diffuse target and the depth target (if defined).\n"
+   "@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" },
+EndImplementEnumType;
+
 
 GFXImplementVertexFormat( PFXVertex )
 {
@@ -235,6 +243,7 @@ PostEffect::PostEffect()
       mStateBlockData( NULL ),
       mAllowReflectPass( false ),
       mTargetClear( PFXTargetClear_None ),
+      mTargetViewport( PFXTargetViewport_TargetSize ),
       mTargetScale( Point2F::One ),
       mTargetSize( Point2I::Zero ),
       mTargetFormat( GFXFormatR8G8B8A8 ),
@@ -312,6 +321,9 @@ void PostEffect::initPersistFields()
    addField( "targetClear", TYPEID< PFXTargetClear >(), Offset( mTargetClear, PostEffect ),
       "Describes when the target texture should be cleared." );
 
+   addField( "targetViewport", TYPEID< PFXTargetViewport >(), Offset( mTargetViewport, PostEffect ),
+      "Specifies how the viewport should be set up for a target texture." );
+
    addField( "texture", TypeImageFilename, Offset( mTexFilename, PostEffect ), NumTextures,
       "Input textures to this effect ( samplers ).\n"
       "@see PFXTextureIdentifiers" );
@@ -927,7 +939,23 @@ void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarg
          if ( mTargetClear == PFXTargetClear_OnCreate )
             *outClearTarget = true;
 
-         mNamedTarget.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) );
+         if(mTargetViewport == PFXTargetViewport_GFXViewport)
+         {
+            // We may need to scale the GFX viewport to fit within
+            // our target texture size
+            GFXTarget *oldTarget = GFX->getActiveRenderTarget();
+            const Point2I &oldTargetSize = oldTarget->getSize();
+            Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y));
+
+            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
+         {
+            // PFXTargetViewport_TargetSize
+            mNamedTarget.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) );
+         }
       }
    }
    else
@@ -973,7 +1001,23 @@ void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarg
          if ( mTargetClear == PFXTargetClear_OnCreate )
             *outClearTarget = true;
 
-         mNamedTargetDepthStencil.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) );
+         if(mTargetViewport == PFXTargetViewport_GFXViewport)
+         {
+            // We may need to scale the GFX viewport to fit within
+            // our target texture size
+            GFXTarget *oldTarget = GFX->getActiveRenderTarget();
+            const Point2I &oldTargetSize = oldTarget->getSize();
+            Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y));
+
+            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
+         {
+            // PFXTargetViewport_TargetSize
+            mNamedTargetDepthStencil.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) );
+         }
       }
    }
    else
@@ -1049,6 +1093,8 @@ void PostEffect::process(  const SceneRenderState *state,
    bool clearTarget = false;
    _setupTarget( state, &clearTarget );
 
+   RectI oldViewport = GFX->getViewport();
+
    if ( mTargetTex || mTargetDepthStencil )
    {
 
@@ -1064,6 +1110,8 @@ void PostEffect::process(  const SceneRenderState *state,
          GFX->getActiveRenderTarget()->preserve();
 #endif
 
+      GFXTarget *oldTarget = GFX->getActiveRenderTarget();
+
       GFX->pushActiveRenderTarget();
       mTarget->attachTexture( GFXTextureTarget::Color0, mTargetTex );
 
@@ -1074,6 +1122,20 @@ void PostEffect::process(  const SceneRenderState *state,
          mTarget->attachTexture( GFXTextureTarget::DepthStencil, mTargetDepthStencil );
 
       GFX->setActiveRenderTarget( mTarget );
+
+      // The setActiveRenderTarget() called above will change the viewport to cover the
+      // entire target area.  Restore the viewport as necessary.
+      if(mNamedTarget.isRegistered())
+      {
+         GFX->setViewport(mNamedTarget.getViewport());
+      }
+      else if(mTargetViewport == PFXTargetViewport_GFXViewport)
+      {
+         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 ) );
+      }
    }
 
    if ( clearTarget )

+ 1 - 0
Engine/source/postFx/postEffect.h

@@ -170,6 +170,7 @@ protected:
 
    PFXRenderTime mRenderTime;
    PFXTargetClear mTargetClear;
+   PFXTargetViewport mTargetViewport;
 
    String mRenderBin;
 

+ 14 - 0
Engine/source/postFx/postEffectCommon.h

@@ -67,6 +67,20 @@ enum PFXTargetClear
 
 DefineEnumType( PFXTargetClear );
 
+
+/// PFXTargetViewport specifies how the viewport should be
+/// set up for a PostEffect's target.
+enum PFXTargetViewport
+{
+   /// The default viewport set up to match the target size
+   PFXTargetViewport_TargetSize,
+
+   /// Use the current GFX viewport
+   PFXTargetViewport_GFXViewport,
+};
+
+DefineEnumType( PFXTargetViewport );
+
 ///
 struct PFXFrameState
 {

+ 1 - 0
Templates/Empty/game/core/scripts/client/postFx/ssao.cs

@@ -190,6 +190,7 @@ singleton PostEffect( SSAOPostFx )
    
    target = "$outTex";
    targetScale = "0.5 0.5";
+   targetViewport = "PFXTargetViewport_GFXViewport";
    
    singleton PostEffect()
    {

+ 1 - 0
Templates/Full/game/core/scripts/client/postFx/ssao.cs

@@ -190,6 +190,7 @@ singleton PostEffect( SSAOPostFx )
    
    target = "$outTex";
    targetScale = "0.5 0.5";
+   targetViewport = "PFXTargetViewport_GFXViewport";
    
    singleton PostEffect()
    {