adds multiple targets to the posteffect class

These changes allows for multiple color targets from a post effect pass.

This is not 100% complete yet as the api still expects 1 target out from a posteffect and will not pass those on to other stages in a posteffect chain but will be adding that soon. This is a working state and everything renders correctly here.
This commit is contained in:
marauder2k7 2026-04-19 15:47:48 +01:00
parent 10cff00c23
commit 60e659aedc
4 changed files with 494 additions and 508 deletions

View file

@ -137,9 +137,6 @@ GFX_ImplementTextureProfile( PostFxTargetProfile,
GFXTextureProfile::Pooled,
GFXTextureProfile::NONE );
IMPLEMENT_CONOBJECT(PostEffect);
GFX_ImplementTextureProfile( PostFxTextureProfile,
GFXTextureProfile::DiffuseMap,
GFXTextureProfile::Static | GFXTextureProfile::PreserveSize,
@ -162,6 +159,12 @@ GFX_ImplementTextureProfile( VRDepthProfile,
GFXTextureProfile::ZTarget,
GFXTextureProfile::NONE );
IMPLEMENT_CONOBJECT(PostEffect);
//---------------------------------------------------------------------
// EffectConst
//---------------------------------------------------------------------
void PostEffect::EffectConst::set( const String &newVal )
{
if ( mStringVal == newVal )
@ -445,69 +448,77 @@ void PostEffect::EffectConst::setToBuffer( GFXShaderConstBufferRef buff )
}
}
//---------------------------------------------------------------------
// EffectConst END
//---------------------------------------------------------------------
//-------------------------------------------------------------------------
// PostEffect
//-------------------------------------------------------------------------
PostEffect::PostEffect()
: mRenderTime( PFXAfterDiffuse ),
mRenderPriority( 1.0 ),
mEnabled( false ),
mStateBlockData( NULL ),
mUpdateShader( true ),
mSkip( false ),
mPreProcessed(false),
mAllowReflectPass( false ),
mTargetClear( PFXTargetClear_None ),
mTargetScale( Point2F::One ),
mTargetViewport( PFXTargetViewport_TargetSize ),
mTargetSize( Point2I::Zero ),
mTargetFormat( GFXFormatR8G8B8A8 ),
mTargetClearColor( LinearColorF::BLACK ),
mOneFrameOnly( false ),
mOnThisFrame( true ),
mRTSizeSC( NULL ),
mIsValid( false ),
mShaderReloadKey( 0 ),
mOneOverRTSizeSC( NULL ),
mViewportOffsetSC( NULL ),
mTargetViewportSC( NULL ),
mFogDataSC( NULL ),
mFogColorSC( NULL ),
mEyePosSC( NULL ),
mMatWorldToScreenSC( NULL ),
mMatScreenToWorldSC( NULL ),
mMatPrevScreenToWorldSC( NULL ),
mNearFarSC( NULL ),
mInvNearFarSC( NULL ),
mWorldToScreenScaleSC( NULL ),
mProjectionOffsetSC( NULL ),
mWaterColorSC( NULL ),
mWaterFogDataSC( NULL ),
mAmbientColorSC( NULL ),
mWaterFogPlaneSC( NULL ),
mWaterDepthGradMaxSC( NULL ),
mScreenSunPosSC( NULL ),
mLightDirectionSC( NULL ),
mCameraForwardSC( NULL ),
mAccumTimeSC( NULL ),
mDampnessSC(NULL),
mDeltaTimeSC( NULL ),
mInvCameraMatSC( NULL ),
mMatCameraToWorldSC( NULL),
mInvCameraTransSC(NULL),
mMatCameraToScreenSC(NULL),
mMatScreenToCameraSC(NULL),
mIsCapturingSC(NULL),
mMipCap(1)
: mRenderTime(PFXAfterDiffuse),
mRenderPriority(1.0),
mEnabled(false),
mStateBlockData(NULL),
mUpdateShader(true),
mSkip(false),
mPreProcessed(false),
mAllowReflectPass(false),
mTargetScale(Point2F::One),
mTargetSize(Point2I::Zero),
mTargetViewport(PFXTargetViewport_TargetSize),
mMipCap(1),
mOneFrameOnly(false),
mOnThisFrame(true),
mRTSizeSC(NULL),
mIsValid(false),
mShaderReloadKey(0),
mOneOverRTSizeSC(NULL),
mViewportOffsetSC(NULL),
mTargetViewportSC(NULL),
mFogDataSC(NULL),
mFogColorSC(NULL),
mEyePosSC(NULL),
mMatWorldToScreenSC(NULL),
mMatScreenToWorldSC(NULL),
mMatPrevScreenToWorldSC(NULL),
mNearFarSC(NULL),
mInvNearFarSC(NULL),
mWorldToScreenScaleSC(NULL),
mProjectionOffsetSC(NULL),
mWaterColorSC(NULL),
mWaterFogDataSC(NULL),
mAmbientColorSC(NULL),
mWaterFogPlaneSC(NULL),
mWaterDepthGradMaxSC(NULL),
mScreenSunPosSC(NULL),
mLightDirectionSC(NULL),
mCameraForwardSC(NULL),
mAccumTimeSC(NULL),
mDampnessSC(NULL),
mDeltaTimeSC(NULL),
mInvCameraMatSC(NULL),
mMatCameraToWorldSC(NULL),
mInvCameraTransSC(NULL),
mMatCameraToScreenSC(NULL),
mMatScreenToCameraSC(NULL),
mIsCapturingSC(NULL)
{
dMemset( mTexSRGB, 0, sizeof(bool) * NumTextures);
dMemset( mActiveTextures, 0, sizeof( GFXTextureObject* ) * NumTextures );
dMemset( mActiveNamedTarget, 0, sizeof( NamedTexTarget* ) * NumTextures );
dMemset( mActiveTextureViewport, 0, sizeof( RectI ) * NumTextures );
dMemset( mTexSizeSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures );
dMemset( mRenderTargetParamsSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures );
// MRT arrays — slot 0 gets primary defaults, 1-3 are inactive.
for (U32 c = 0; c < NumMRTTargets; c++)
{
mTargetFormat[c] = GFXFormatR8G8B8A8;
mTargetClearColor[c] = LinearColorF::BLACK;
mTargetClear[c] = PFXTargetClear_None;
}
dMemset(mTexSRGB, 0, sizeof(bool) * NumTextures);
dMemset(mActiveTextures, 0, sizeof(GFXTextureObject*) * NumTextures);
dMemset(mActiveNamedTarget, 0, sizeof(NamedTexTarget*) * NumTextures);
dMemset(mActiveTextureViewport, 0, sizeof(RectI) * NumTextures);
dMemset(mTexSizeSC, 0, sizeof(GFXShaderConstHandle*) * NumTextures);
dMemset(mRenderTargetParamsSC, 0, sizeof(GFXShaderConstHandle*) * NumTextures);
dMemset(mMipCountSC, 0, sizeof(GFXShaderConstHandle*) * NumTextures);
}
@ -527,9 +538,18 @@ void PostEffect::initPersistFields()
addField( "stateBlock", TYPEID<GFXStateBlockData>(), Offset( mStateBlockData, PostEffect ),
"Name of a GFXStateBlockData for this effect." );
addField( "target", TypeRealString, Offset( mTargetName, PostEffect ),
addField( "target", TypeRealString, Offset( mTargetName, PostEffect ), NumMRTTargets,
"String identifier of this effect's target texture.\n"
"@see PFXTextureIdentifiers" );
addField("targetFormat", TypeGFXFormat, Offset(mTargetFormat, PostEffect), NumMRTTargets,
"Format of the target texture, not applicable if writing to the backbuffer.");
addField("targetClearColor", TypeColorF, Offset(mTargetClearColor, PostEffect), NumMRTTargets,
"Color to which the target texture is cleared before rendering.");
addField("targetClear", TYPEID< PFXTargetClear >(), Offset(mTargetClear, PostEffect), NumMRTTargets,
"Describes when the target texture should be cleared.");
addField( "targetDepthStencil", TypeRealString, Offset( mTargetDepthStencilName, PostEffect ),
"Optional string identifier for this effect's target depth/stencil texture.\n"
@ -543,15 +563,6 @@ void PostEffect::initPersistFields()
addField( "targetSize", TypePoint2I, Offset( mTargetSize, PostEffect ),
"If non-zero this is used as the absolute target size." );
addField( "targetFormat", TypeGFXFormat, Offset( mTargetFormat, PostEffect ),
"Format of the target texture, not applicable if writing to the backbuffer." );
addField( "targetClearColor", TypeColorF, Offset( mTargetClearColor, PostEffect ),
"Color to which the target texture is cleared before rendering." );
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." );
@ -624,15 +635,21 @@ bool PostEffect::onAdd()
}
// Is the target a named target?
if ( mTargetName.isNotEmpty() && mTargetName[0] == '#' )
bool anyNamed = false;
for (U32 c = 0; c < NumMRTTargets; c++)
{
mNamedTarget.registerWithName(mTargetName.substr(1));
mNamedTarget.getTextureDelegate().bind( this, &PostEffect::_getTargetTexture );
if (mTargetName[c].isNotEmpty() && mTargetName[c][0] == '#')
{
mNamedTarget[c].registerWithName(mTargetName[c].substr(1));
mNamedTarget[c].getTextureDelegate().bind(this, &PostEffect::_getTargetTexture);
anyNamed = true;
}
}
if ( mTargetDepthStencilName.isNotEmpty() && mTargetDepthStencilName[0] == '#' )
mNamedTargetDepthStencil.registerWithName( mTargetDepthStencilName.substr( 1 ) );
if (mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered())
if (anyNamed || mNamedTargetDepthStencil.isRegistered())
GFXTextureManager::addEventDelegate( this, &PostEffect::_onTextureEvent );
// Call onAdd in script
@ -661,15 +678,20 @@ void PostEffect::onRemove()
mShader = NULL;
_cleanTargets();
if ( mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered() )
GFXTextureManager::removeEventDelegate( this, &PostEffect::_onTextureEvent );
if ( mNamedTarget.isRegistered() )
bool anyNamed = false;
for (U32 c = 0; c < NumMRTTargets; c++)
{
mNamedTarget.unregister();
mNamedTarget.getTextureDelegate().clear();
if (mNamedTarget[c].isRegistered())
{
mNamedTarget[c].unregister();
mNamedTarget[c].getTextureDelegate().clear();
anyNamed = true;
}
}
if (anyNamed || mNamedTargetDepthStencil.isRegistered() )
GFXTextureManager::removeEventDelegate( this, &PostEffect::_onTextureEvent );
if ( mNamedTargetDepthStencil.isRegistered() )
mNamedTargetDepthStencil.unregister();
}
@ -1156,7 +1178,7 @@ void PostEffect::_setupTexture( U32 stage, GFXTexHandle &inputTex, const RectI *
RectI viewport = GFX->getViewport();
if ( texFilename.compare( "$inTex", 0, String::NoCase ) == 0 )
if ( _inTexSlotFromName(texFilename) >= 0 )
{
theTex = inputTex;
@ -1236,162 +1258,166 @@ void PostEffect::_setupTransforms()
void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarget )
{
if ( mNamedTarget.isRegistered() ||
mTargetName.compare( "$outTex", 0, String::NoCase ) == 0 )
for (U32 c = 0; c < NumMRTTargets; c++)
{
// Size it relative to the texture of the first stage or
// if NULL then use the current target.
Point2I targetSize;
// If we have an absolute target size then use that.
if ( !mTargetSize.isZero() )
targetSize = mTargetSize;
// Else generate a relative size using the target scale.
else if ( mActiveTextures[ 0 ] )
if (mNamedTarget[c].isRegistered() || _outTexSlotFromName(mTargetName[c]) >= 0)
{
const Point3I &texSize = mActiveTextures[ 0 ]->getSize();
// Size it relative to the texture of the first stage or
// if NULL then use the current target.
targetSize.set( texSize.x * mTargetScale.x,
texSize.y * mTargetScale.y );
}
else
{
GFXTarget *oldTarget = GFX->getActiveRenderTarget();
const Point2I &oldTargetSize = oldTarget->getSize();
Point2I targetSize;
targetSize.set( oldTargetSize.x * mTargetScale.x,
oldTargetSize.y * mTargetScale.y );
}
// If we have an absolute target size then use that.
if (!mTargetSize.isZero())
targetSize = mTargetSize;
// Make sure its at least 1x1.
targetSize.setMax( Point2I::One );
if ( mNamedTarget.isRegistered() ||
!mTargetTex ||
mTargetTex.getWidthHeight() != targetSize )
{
mTargetTex.set( targetSize.x, targetSize.y, mTargetFormat,
&PostFxTargetProfile, "PostEffect::_setupTarget", mMipCap);
if ( mTargetClear == PFXTargetClear_OnCreate )
*outClearTarget = true;
if(mTargetViewport == PFXTargetViewport_GFXViewport)
// Else generate a relative size using the target scale.
else if (mActiveTextures[0])
{
// 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 Point3I& texSize = mActiveTextures[0]->getSize();
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 ) );
targetSize.set(texSize.x * mTargetScale.x,
texSize.y * mTargetScale.y);
}
else
{
// PFXTargetViewport_TargetSize
mNamedTarget.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) );
GFXTarget* oldTarget = GFX->getActiveRenderTarget();
const Point2I& oldTargetSize = oldTarget->getSize();
targetSize.set(oldTargetSize.x * mTargetScale.x,
oldTargetSize.y * mTargetScale.y);
}
// Make sure its at least 1x1.
targetSize.setMax(Point2I::One);
if (mNamedTarget[c].isRegistered() ||
!mTargetTex[c] ||
mTargetTex[c].getWidthHeight() != targetSize)
{
mTargetTex[c].set(targetSize.x, targetSize.y, mTargetFormat[c],
&PostFxTargetProfile, "PostEffect::_setupTarget", mMipCap);
if (mTargetClear[c] == PFXTargetClear_OnCreate)
*outClearTarget = true;
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[c].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[c].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[c].setViewport(RectI(0, 0, targetSize.x, targetSize.y));
}
}
}
else
mTargetTex[c] = NULL;
}
else
mTargetTex = NULL;
// Do we have a named depthStencil target?
if ( mNamedTargetDepthStencil.isRegistered() )
if (mNamedTargetDepthStencil.isRegistered())
{
// Size it relative to the texture of the first stage or
// if NULL then use the current target.
Point2I targetSize;
// If we have an absolute target size then use that.
if ( !mTargetSize.isZero() )
if (!mTargetSize.isZero())
targetSize = mTargetSize;
// Else generate a relative size using the target scale.
else if ( mActiveTextures[ 0 ] )
else if (mActiveTextures[0])
{
const Point3I &texSize = mActiveTextures[ 0 ]->getSize();
const Point3I& texSize = mActiveTextures[0]->getSize();
targetSize.set( texSize.x * mTargetScale.x,
texSize.y * mTargetScale.y );
targetSize.set(texSize.x * mTargetScale.x,
texSize.y * mTargetScale.y);
}
else
{
GFXTarget *oldTarget = GFX->getActiveRenderTarget();
const Point2I &oldTargetSize = oldTarget->getSize();
GFXTarget* oldTarget = GFX->getActiveRenderTarget();
const Point2I& oldTargetSize = oldTarget->getSize();
targetSize.set( oldTargetSize.x * mTargetScale.x,
oldTargetSize.y * mTargetScale.y );
targetSize.set(oldTargetSize.x * mTargetScale.x,
oldTargetSize.y * mTargetScale.y);
}
// Make sure its at least 1x1.
targetSize.setMax( Point2I::One );
if ( mNamedTargetDepthStencil.isRegistered() &&
mTargetDepthStencil.getWidthHeight() != targetSize )
{
mTargetDepthStencil.set( targetSize.x, targetSize.y, GFXFormatD24S8,
&GFXZTargetProfile, "PostEffect::_setupTarget" );
targetSize.setMax(Point2I::One);
if ( mTargetClear == PFXTargetClear_OnCreate )
if (mNamedTargetDepthStencil.isRegistered() &&
mTargetDepthStencil.getWidthHeight() != targetSize)
{
mTargetDepthStencil.set(targetSize.x, targetSize.y, GFXFormatD24S8,
&GFXZTargetProfile, "PostEffect::_setupTarget");
if (mTargetClear[0] == PFXTargetClear_OnCreate)
*outClearTarget = true;
if(mTargetViewport == PFXTargetViewport_GFXViewport)
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();
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();
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 ) );
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())
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();
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();
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 ) );
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 ) );
mNamedTargetDepthStencil.setViewport(RectI(0, 0, targetSize.x, targetSize.y));
}
}
}
else
mTargetDepthStencil = NULL;
if ( mTargetClear == PFXTargetClear_OnDraw )
if (mTargetClear[0] == PFXTargetClear_OnDraw)
*outClearTarget = true;
if ( !mTarget && (mTargetTex || mTargetDepthStencil) )
if (!mTarget && (mTargetTex || mTargetDepthStencil))
mTarget = GFX->allocRenderToTextureTarget();
}
void PostEffect::_cleanTargets( bool recurse )
{
mTargetTex = NULL;
for (U32 c = 0; c < NumMRTTargets; c++)
mTargetTex[c] = NULL;
mTargetDepthStencil = NULL;
mTarget = NULL;
@ -1407,7 +1433,7 @@ void PostEffect::_cleanTargets( bool recurse )
}
void PostEffect::process( const SceneRenderState *state,
GFXTexHandle &inOutTex,
GFXTexHandle& inOutTex,
const RectI *inTexViewport )
{
// If the shader is forced to be skipped... then skip.
@ -1461,27 +1487,56 @@ void PostEffect::process( const SceneRenderState *state,
bool clearTarget = false;
_setupTarget( state, &clearTarget );
if ( mTargetTex || mTargetDepthStencil )
const bool hasDepth = mTargetDepthStencil.isValid();
bool hasColorTarget = false;
for (U32 c = 0; c < NumMRTTargets; c++)
{
if (mTargetTex[c].isValid())
{
hasColorTarget = true;
break;
}
}
// Attach each color slot. NULL explicitly detaches unused slots,
// preventing stale attachments from a previous frame.
static const GFXTextureTarget::RenderSlot kSlots[NumMRTTargets] =
{
GFXTextureTarget::Color0,
GFXTextureTarget::Color1,
GFXTextureTarget::Color2,
GFXTextureTarget::Color3,
};
if (hasColorTarget || hasDepth)
{
const RectI &oldViewport = GFX->getViewport();
GFXTarget *oldTarget = GFX->getActiveRenderTarget();
GFX->pushActiveRenderTarget();
mTarget->attachTexture( GFXTextureTarget::Color0, mTargetTex );
for (U32 c = 0; c < NumMRTTargets; c++)
{
mTarget->attachTexture(kSlots[c], mTargetTex[c].isValid() ? mTargetTex[c] : NULL);
}
// Set the right depth stencil target.
if ( !mTargetDepthStencil && mTargetTex.getWidthHeight() == GFX->getActiveRenderTarget()->getSize() )
mTarget->attachTexture( GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil );
if (!hasDepth && mTargetTex[0].isValid() && mTargetTex[0].getWidthHeight() == oldTarget->getSize())
mTarget->attachTexture(GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil);
else
mTarget->attachTexture( GFXTextureTarget::DepthStencil, mTargetDepthStencil );
mTarget->attachTexture(GFXTextureTarget::DepthStencil, mTargetDepthStencil);
// Set the render target but not its viewport. We'll do that below.
GFX->setActiveRenderTarget( mTarget, false );
if(mNamedTarget.isRegistered())
if (mNamedTarget[0].isRegistered())
{
// Always use the name target's viewport, if available. It was set up in _setupTarget().
GFX->setViewport(mNamedTarget.getViewport());
GFX->setViewport(mNamedTarget[0].getViewport());
}
else if (mTargetTex[0].isValid())
{
GFX->setViewport(RectI(Point2I::Zero, mTargetTex[0].getWidthHeight()));
}
else if(mTargetViewport == PFXTargetViewport_GFXViewport)
{
@ -1509,8 +1564,19 @@ void PostEffect::process( const SceneRenderState *state,
}
}
if ( clearTarget )
GFX->clear( GFXClearTarget, mTargetClearColor, 1.f, 0 );
if (clearTarget)
{
LinearColorF clearColor = LinearColorF::BLACK;
for (U32 c = 0; c < NumMRTTargets; c++)
{
if (mTargetTex[c].isValid() && mTargetClear[c] != PFXTargetClear_None)
{
clearColor = mTargetClearColor[c];
break;
}
}
GFX->clear(GFXClearTarget, clearColor, 1.f, 0);
}
// Setup the shader and constants.
if ( mShader )
@ -1545,24 +1611,22 @@ void PostEffect::process( const SceneRenderState *state,
// Allow PostEffecVis to hook in.
PFXVIS->onPFXProcessed( this );
if ( mTargetTex || mTargetDepthStencil )
if (hasColorTarget || hasDepth)
{
mTarget->resolve();
GFX->popActiveRenderTarget();
}
else
{
// We wrote to the active back buffer, so release
// the current texture copy held by the manager.
//
// This ensures a new copy is made.
PFXMGR->releaseBackBufferTex();
}
// Return and release our target texture.
inOutTex = mTargetTex;
if ( !mNamedTarget.isRegistered() )
mTargetTex = NULL;
inOutTex = mTargetTex[0];
for (U32 c = 0; c < NumMRTTargets; c++)
{
if (!mNamedTarget[c].isRegistered())
mTargetTex[c] = NULL;
}
// Restore the transforms before the children
// are processed as it screws up the viewport.
@ -1842,19 +1906,22 @@ void PostEffect::_checkRequirements()
}
// First make sure the target format is supported.
if ( mNamedTarget.isRegistered() )
for (U32 c = 0; c < NumMRTTargets; c++)
{
Vector<GFXFormat> formats;
formats.push_back( mTargetFormat );
GFXFormat format = GFX->selectSupportedFormat( &PostFxTargetProfile,
formats,
true,
false,
false );
// If we didn't get our format out then its unsupported!
if ( format != mTargetFormat )
return;
if (mNamedTarget[c].isRegistered())
{
Vector<GFXFormat> formats;
formats.push_back(mTargetFormat[c]);
GFXFormat format = GFX->selectSupportedFormat(&PostFxTargetProfile,
formats,
true,
false,
false);
// If we didn't get our format out then its unsupported!
if (format != mTargetFormat[c])
return;
}
}
// Gather macros specified on this PostEffect.
@ -1981,12 +2048,12 @@ void PostEffect::clearShaderMacros()
mUpdateShader = true;
}
GFXTextureObject* PostEffect::_getTargetTexture( U32 )
GFXTextureObject* PostEffect::_getTargetTexture( U32 index)
{
// A TexGen PostEffect will generate its texture now if it
// has not already.
if ( mRenderTime == PFXTexGenOnDemand &&
( !mTargetTex || mUpdateShader ) )
( !mTargetTex[index] || mUpdateShader ) )
{
GFXTexHandle chainTex;
process( NULL, chainTex );
@ -1996,7 +2063,7 @@ GFXTextureObject* PostEffect::_getTargetTexture( U32 )
// amount of non-swappable RTs in use.
}
return mTargetTex.getPointer();
return mTargetTex[index].getPointer();
}
DefineEngineMethod( PostEffect, reload, void, (),,

View file

@ -67,14 +67,6 @@ class Frustum;
class SceneRenderState;
class ConditionerFeature;
///
GFX_DeclareTextureProfile( PostFxTargetProfile );
///
class PostEffect : public SimGroup
{
typedef SimGroup Parent;
@ -86,389 +78,317 @@ public:
enum
{
NumTextures = 16,
/// Maximum simultaneous color render target outputs (MRT)
NumMRTTargets = 4,
};
protected:
//--------------------------------------------------------------------------
// Input textures
//--------------------------------------------------------------------------
DECLARE_IMAGEASSET_ARRAY(PostEffect, Texture, GFXStaticTextureSRGBProfile, NumTextures);
GFXTextureProfile* mTextureProfile[NumTextures];
GFXTexHandle mTexture[NumTextures];
GFXTextureProfile* mTextureProfile[NumTextures];
GFXTexHandle mTexture[NumTextures];
bool mTexSRGB[NumTextures];
bool mTexSRGB[NumTextures];
enum { NormalTextureType = 0, CubemapType, CubemapArrayType } mTextureType[NumTextures];
enum
{
NormalTextureType = 0,
CubemapType,
CubemapArrayType,
} mTextureType[NumTextures];
GFXCubemapHandle mCubemapTextures[NumTextures];
GFXCubemapHandle mCubemapTextures[NumTextures];
GFXCubemapArrayHandle mCubemapArrayTextures[NumTextures];
NamedTexTarget mNamedTarget;
NamedTexTarget mNamedTargetDepthStencil;
GFXTextureObject* mActiveTextures[NumTextures];
NamedTexTarget* mActiveNamedTarget[NumTextures];
RectI mActiveTextureViewport[NumTextures];
GFXTextureObject *mActiveTextures[NumTextures];
//--------------------------------------------------------------------------
// MRT color output targets
//
// Replaces the original single: mNamedTarget, mTargetName, mTargetTex,
// mTargetFormat, mTargetClearColor, mTargetClear
//--------------------------------------------------------------------------
NamedTexTarget *mActiveNamedTarget[NumTextures];
String mTargetName[NumMRTTargets]; ///< Per-slot output name.
GFXFormat mTargetFormat[NumMRTTargets]; ///< Per-slot texture format.
LinearColorF mTargetClearColor[NumMRTTargets]; ///< Per-slot clear colour.
PFXTargetClear mTargetClear[NumMRTTargets]; ///< Per-slot clear policy.
RectI mActiveTextureViewport[NumTextures];
GFXTexHandle mTargetTex[NumMRTTargets]; ///< Runtime texture per slot.
NamedTexTarget mNamedTarget[NumMRTTargets]; ///< Named target per slot.
GFXStateBlockData *mStateBlockData;
GFXStateBlockRef mStateBlock;
String mShaderName;
GFXShaderRef mShader;
Vector<GFXShaderMacro> mShaderMacros;
GFXShaderConstBufferRef mShaderConsts;
GFXShaderConstHandle *mRTSizeSC;
GFXShaderConstHandle *mOneOverRTSizeSC;
GFXShaderConstHandle* mRTRatioSC;
GFXShaderConstHandle *mTexSizeSC[NumTextures];
GFXShaderConstHandle *mRenderTargetParamsSC[NumTextures];
GFXShaderConstHandle* mMipCountSC[NumTextures];
GFXShaderConstHandle *mViewportOffsetSC;
GFXShaderConstHandle *mTargetViewportSC;
GFXShaderConstHandle *mFogDataSC;
GFXShaderConstHandle *mFogColorSC;
GFXShaderConstHandle *mEyePosSC;
GFXShaderConstHandle *mMatWorldToScreenSC;
GFXShaderConstHandle *mMatScreenToWorldSC;
GFXShaderConstHandle *mMatPrevScreenToWorldSC;
GFXShaderConstHandle *mNearFarSC;
GFXShaderConstHandle *mInvNearFarSC;
GFXShaderConstHandle *mWorldToScreenScaleSC;
GFXShaderConstHandle *mProjectionOffsetSC;
GFXShaderConstHandle *mWaterColorSC;
GFXShaderConstHandle *mWaterFogDataSC;
GFXShaderConstHandle *mAmbientColorSC;
GFXShaderConstHandle *mWaterFogPlaneSC;
GFXShaderConstHandle *mWaterDepthGradMaxSC;
GFXShaderConstHandle *mScreenSunPosSC;
GFXShaderConstHandle *mLightDirectionSC;
GFXShaderConstHandle *mCameraForwardSC;
GFXShaderConstHandle *mAccumTimeSC;
GFXShaderConstHandle* mDampnessSC;
GFXShaderConstHandle *mDeltaTimeSC;
GFXShaderConstHandle *mInvCameraMatSC;
GFXShaderConstHandle *mMatCameraToWorldSC;
GFXShaderConstHandle *mInvCameraTransSC;
GFXShaderConstHandle *mMatCameraToScreenSC;
GFXShaderConstHandle *mMatScreenToCameraSC;
GFXShaderConstHandle* mIsCapturingSC;
bool mAllowReflectPass;
/// If true update the shader.
bool mUpdateShader;
// These remain single values — shared across ALL active MRT slots.
Point2F mTargetScale; ///< Relative size vs current GFX render target.
Point2I mTargetSize; ///< Absolute size override; (0,0) = use mTargetScale.
PFXTargetViewport mTargetViewport; ///< How the viewport rect is derived.
/// Single GFXTextureTarget — ALL active MRT slots attach to this one object.
GFXTextureTargetRef mTarget;
String mTargetName;
GFXTexHandle mTargetTex;
S32 mMipCap;
String mTargetDepthStencilName;
GFXTexHandle mTargetDepthStencil;
//--------------------------------------------------------------------------
// Depth stencil
//--------------------------------------------------------------------------
/// If mTargetSize is zero then this scale is
/// used to make a relative texture size to the
/// active render target.
Point2F mTargetScale;
String mTargetDepthStencilName;
GFXTexHandle mTargetDepthStencil;
NamedTexTarget mNamedTargetDepthStencil;
/// If non-zero this is used as the absolute
/// texture target size.
/// @see mTargetScale
Point2I mTargetSize;
//--------------------------------------------------------------------------
// State block / shader
//--------------------------------------------------------------------------
GFXFormat mTargetFormat;
GFXStateBlockData* mStateBlockData;
GFXStateBlockRef mStateBlock;
String mShaderName;
GFXShaderRef mShader;
Vector<GFXShaderMacro> mShaderMacros;
GFXShaderConstBufferRef mShaderConsts;
/// The color to prefill the named target when
/// first created by the effect.
LinearColorF mTargetClearColor;
//--------------------------------------------------------------------------
// Auto shader constant handles
//--------------------------------------------------------------------------
GFXShaderConstHandle* mRTSizeSC;
GFXShaderConstHandle* mOneOverRTSizeSC;
GFXShaderConstHandle* mRTRatioSC;
GFXShaderConstHandle* mTexSizeSC[NumTextures];
GFXShaderConstHandle* mRenderTargetParamsSC[NumTextures];
GFXShaderConstHandle* mMipCountSC[NumTextures];
GFXShaderConstHandle* mViewportOffsetSC;
GFXShaderConstHandle* mTargetViewportSC;
GFXShaderConstHandle* mFogDataSC;
GFXShaderConstHandle* mFogColorSC;
GFXShaderConstHandle* mEyePosSC;
GFXShaderConstHandle* mMatWorldToScreenSC;
GFXShaderConstHandle* mMatScreenToWorldSC;
GFXShaderConstHandle* mMatPrevScreenToWorldSC;
GFXShaderConstHandle* mNearFarSC;
GFXShaderConstHandle* mInvNearFarSC;
GFXShaderConstHandle* mWorldToScreenScaleSC;
GFXShaderConstHandle* mProjectionOffsetSC;
GFXShaderConstHandle* mWaterColorSC;
GFXShaderConstHandle* mWaterFogDataSC;
GFXShaderConstHandle* mAmbientColorSC;
GFXShaderConstHandle* mWaterFogPlaneSC;
GFXShaderConstHandle* mWaterDepthGradMaxSC;
GFXShaderConstHandle* mScreenSunPosSC;
GFXShaderConstHandle* mLightDirectionSC;
GFXShaderConstHandle* mCameraForwardSC;
GFXShaderConstHandle* mAccumTimeSC;
GFXShaderConstHandle* mDampnessSC;
GFXShaderConstHandle* mDeltaTimeSC;
GFXShaderConstHandle* mInvCameraMatSC;
GFXShaderConstHandle* mMatCameraToWorldSC;
GFXShaderConstHandle* mInvCameraTransSC;
GFXShaderConstHandle* mMatCameraToScreenSC;
GFXShaderConstHandle* mMatScreenToCameraSC;
GFXShaderConstHandle* mIsCapturingSC;
//--------------------------------------------------------------------------
// Render scheduling
//--------------------------------------------------------------------------
bool mAllowReflectPass;
bool mUpdateShader;
PFXRenderTime mRenderTime;
PFXTargetClear mTargetClear;
PFXTargetViewport mTargetViewport;
PFXTargetClear mTargetClear_unused; // kept for binary compat if needed — see arrays above
String mRenderBin;
S16 mRenderPriority;
bool mIsValid;
bool mEnabled;
bool mSkip;
bool mPreProcessed;
bool mOneFrameOnly;
bool mOnThisFrame;
U32 mShaderReloadKey;
String mRenderBin;
S16 mRenderPriority;
/// This is true if the effect has been succesfully
/// initialized and all requirements are met for use.
bool mIsValid;
/// True if the effect has been enabled by the manager.
bool mEnabled;
/// Skip processing of this PostEffect and its children even if its parent is enabled.
/// Parent and sibling PostEffects in the chain are still processed.
/// This is intended for debugging purposes.
bool mSkip;
bool mPreProcessed;
bool mOneFrameOnly;
bool mOnThisFrame;
U32 mShaderReloadKey;
//--------------------------------------------------------------------------
// EffectConst
//--------------------------------------------------------------------------
class EffectConst
{
public:
EffectConst( const String &name, const String &val )
: mName( name ),
mHandle( NULL ),
mDirty( true )
{
set( val );
}
EffectConst(const String &name, const F32 &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
EffectConst(const String& name, const String& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const F32& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const int& val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const Point4F& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const MatrixF& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const Vector<Point4F>& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String& name, const Vector<MatrixF>& val)
: mName(name), mHandle(NULL), mDirty(true) {
set(val);
}
EffectConst(const String &name, const Point4F &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
set(val);
}
EffectConst(const String &name, const MatrixF &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
set(val);
}
EffectConst(const String &name, const Vector<Point4F> &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
set(val);
}
EffectConst(const String &name, const Vector<MatrixF> &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
set(val);
}
void set( const String &newVal );
void set(const F32 &newVal);
void set(const String& newVal);
void set(const F32& newVal);
void set(const int& newVal);
void set(const Point4F &newVal);
void set(const MatrixF &newVal);
void set(const Vector<Point4F> &newVal);
void set(const Vector<MatrixF> &newVal);
void setToBuffer( GFXShaderConstBufferRef buff );
String mName;
GFXShaderConstHandle *mHandle;
String mStringVal;
S32 mIntVal;
F32 mFloatVal;
Point4F mPointVal;
MatrixF mMatrixVal;
void set(const Point4F& newVal);
void set(const MatrixF& newVal);
void set(const Vector<Point4F>& newVal);
void set(const Vector<MatrixF>& newVal);
void setToBuffer(GFXShaderConstBufferRef buff);
String mName;
GFXShaderConstHandle* mHandle;
String mStringVal;
S32 mIntVal;
F32 mFloatVal;
Point4F mPointVal;
MatrixF mMatrixVal;
Vector<Point4F> mPointArrayVal;
Vector<MatrixF> mMatrixArrayVal;
enum
{
StringType,
IntType,
FloatType,
PointType,
MatrixType,
PointArrayType,
MatrixArrayType
enum {
StringType, IntType, FloatType, PointType,
MatrixType, PointArrayType, MatrixArrayType
} mValueType;
bool mDirty;
};
typedef HashTable<StringCase,EffectConst*> EffectConstTable;
typedef HashTable<StringCase, EffectConst*> EffectConstTable;
EffectConstTable mEffectConsts;
///
virtual void _updateScreenGeometry( const Frustum &frustum,
GFXVertexBufferHandle<PFXVertex> *outVB );
//--------------------------------------------------------------------------
// Internal methods
//--------------------------------------------------------------------------
///
virtual void _setupStateBlock( const SceneRenderState *state );
///
virtual void _setupConstants( const SceneRenderState *state );
///
virtual void _updateScreenGeometry(const Frustum& frustum, GFXVertexBufferHandle<PFXVertex>* outVB);
virtual void _setupStateBlock(const SceneRenderState* state);
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 _setupCubemapTexture(U32 stage, GFXCubemapHandle& inputTex);
virtual void _setupCubemapArrayTexture(U32 slot, GFXCubemapArrayHandle& inputTex);
///
virtual void _setupTarget( const SceneRenderState *state, bool *outClearTarget );
static bool _setIsEnabled(void* object, const char* index, const char* data);
///
virtual void _setupTexture( U32 slot, GFXTexHandle &inputTex, const RectI *inTexViewport );
virtual void _setupCubemapTexture(U32 stage, GFXCubemapHandle &inputTex);
virtual void _setupCubemapArrayTexture(U32 slot, GFXCubemapArrayHandle &inputTex);
/// Protected set method for toggling the enabled state.
static bool _setIsEnabled( void *object, const char *index, const char *data );
/// Called from the light manager activate signal.
/// @see LightManager::addActivateCallback
void _onLMActivate( const char*, bool activate )
void _onLMActivate(const char*, bool activate)
{
if ( activate )
mUpdateShader = true;
if (activate) mUpdateShader = true;
}
/// We handle texture events to release named rendered targets.
/// @see GFXTextureManager::addEventDelegate
void _onTextureEvent( GFXTexCallbackCode code )
void _onTextureEvent(GFXTexCallbackCode code)
{
if ( code == GFXZombify && (mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered()) )
_cleanTargets();
if (code != GFXZombify) return;
bool anyNamed = mNamedTargetDepthStencil.isRegistered();
for (U32 c = 0; c < NumMRTTargets && !anyNamed; c++)
anyNamed = mNamedTarget[c].isRegistered();
if (anyNamed) _cleanTargets();
}
///
void _updateConditioners();
///
void _cleanTargets( bool recurse = false );
///
void _cleanTargets(bool recurse = false);
void _checkRequirements();
GFXTextureObject* _getTargetTexture(U32 index);
///
GFXTextureObject* _getTargetTexture( U32 index );
/// Map "$outTex" / "$outTex0".."$outTex3" to a slot index [0..NumMRTTargets-1].
/// Returns -1 if the name is not an $outTexN pattern.
S32 _outTexSlotFromName(const String& name)
{
if (name.compare("$outTex", 0, String::NoCase) == 0) return 0; // backwards compat
if (name.compare("$outTex0", 0, String::NoCase) == 0) return 0;
if (name.compare("$outTex1", 0, String::NoCase) == 0) return 1;
if (name.compare("$outTex2", 0, String::NoCase) == 0) return 2;
if (name.compare("$outTex3", 0, String::NoCase) == 0) return 3;
return -1;
}
S32 _inTexSlotFromName(const String& name)
{
if (name.compare("$inTex", 0, String::NoCase) == 0) return 0; // backwards compat
if (name.compare("$inTex0", 0, String::NoCase) == 0) return 0;
if (name.compare("$inTex1", 0, String::NoCase) == 0) return 1;
if (name.compare("$inTex2", 0, String::NoCase) == 0) return 2;
if (name.compare("$inTex3", 0, String::NoCase) == 0) return 3;
return -1;
}
public:
/// Constructor.
PostEffect();
/// Destructor.
virtual ~PostEffect();
DECLARE_CONOBJECT(PostEffect);
// SimObject
bool onAdd() override;
void onRemove() override;
static void initPersistFields();
/// @name Callbacks
/// @{
DECLARE_CALLBACK(void, onAdd, ());
DECLARE_CALLBACK(void, preProcess, ());
DECLARE_CALLBACK(void, setShaderConsts, ());
DECLARE_CALLBACK(bool, onEnabled, ());
DECLARE_CALLBACK(void, onDisabled, ());
DECLARE_CALLBACK( void, onAdd, () );
DECLARE_CALLBACK( void, preProcess, () );
DECLARE_CALLBACK( void, setShaderConsts, () );
DECLARE_CALLBACK( bool, onEnabled, () );
DECLARE_CALLBACK( void, onDisabled, () );
virtual void process(const SceneRenderState* state,
GFXTexHandle& inOutTex,
const RectI* inTexViewport = NULL);
/// @}
virtual void process( const SceneRenderState *state,
GFXTexHandle &inOutTex,
const RectI *inTexViewport = NULL );
///
void reload();
///
void enable();
///
void disable();
/// Dump the shader disassembly to a temporary text file.
/// Returns true and sets outFilename to the file if successful.
bool dumpShaderDisassembly( String &outFilename ) const;
/// Returns the SimSet which contains all PostEffects.
bool dumpShaderDisassembly(String& outFilename) const;
SimSet* getSet() const;
///
bool isEnabled() const { return mEnabled; }
/// Is set to skip rendering.
bool isSkipped() const { return mSkip; }
/// Set the effect to skip rendering.
void setSkip( bool skip ) { mSkip = skip; }
void setSkip(bool s) { mSkip = s; }
PFXRenderTime getRenderTime() const { return mRenderTime; }
const String& getRenderBin() const { return mRenderBin; }
F32 getPriority() const { return mRenderPriority; }
const String& getRenderBin() const { return mRenderBin; }
F32 getPriority() const { return mRenderPriority; }
void setTexture( U32 index, const String &filePath );
void setTexture(U32 index, const String& filePath);
void setTexture(U32 index, const GFXTexHandle& texHandle);
void setCubemapTexture(U32 index, const GFXCubemapHandle &cubemapHandle);
void setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle &cubemapArrayHandle);
void setCubemapTexture(U32 index, const GFXCubemapHandle& handle);
void setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle& handle);
void setShaderMacro( const String &name, const String &value = String::EmptyString );
bool removeShaderMacro( const String &name );
void setShaderMacro(const String& name, const String& value = String::EmptyString);
bool removeShaderMacro(const String& name);
void clearShaderMacros();
///
void setShaderConst( const String &name, const String &val );
void setShaderConst(const String &name, const F32 &val);
void setShaderConst(const String& name, const String& val);
void setShaderConst(const String& name, const F32& val);
void setShaderConst(const String& name, const int& val);
void setShaderConst(const String &name, const Point4F &val);
void setShaderConst(const String &name, const MatrixF &val);
void setShaderConst(const String &name, const Vector<Point4F> &val);
void setShaderConst(const String &name, const Vector<MatrixF> &val);
void setShaderConst(const String& name, const Point4F& val);
void setShaderConst(const String& name, const MatrixF& val);
void setShaderConst(const String& name, const Vector<Point4F>& val);
void setShaderConst(const String& name, const Vector<MatrixF>& val);
void setOnThisFrame( bool enabled ) { mOnThisFrame = enabled; }
void setOnThisFrame(bool e) { mOnThisFrame = e; }
bool isOnThisFrame() { return mOnThisFrame; }
void setOneFrameOnly( bool enabled ) { mOneFrameOnly = enabled; }
bool isOneFrameOnly() { return mOneFrameOnly; }
void setOneFrameOnly(bool e) { mOneFrameOnly = e; }
bool isOneFrameOnly() { return mOneFrameOnly; }
F32 getAspectRatio() const;
GFXShaderRef getShader() { return mShader; }
F32 getAspectRatio() const;
GFXShaderRef getShader() { return mShader; }
Vector<GFXShaderMacro>* getShaderMacros() { return &mShaderMacros; }
GFXShaderConstBufferRef getShaderConstBuffer() { return mShaderConsts; }
enum PostEffectRequirements
{

View file

@ -99,11 +99,10 @@ struct PFXFrameState
};
///
GFX_DeclareTextureProfile( PostFxTargetProfile) ;
GFX_DeclareTextureProfile( PostFxTextureProfile );
GFX_DeclareTextureProfile( PostFxTextureSRGBProfile );
GFX_DeclareTextureProfile( VRTextureProfile );
GFX_DeclareTextureProfile( VRDepthProfile );
///
@ -119,4 +118,4 @@ GFXDeclareVertexFormat( PFXVertex )
Point3F wsEyeRay;
};
#endif // _POSTEFFECTCOMMON_H_
#endif // _POSTEFFECTCOMMON_H_

View file

@ -228,8 +228,8 @@ void PostEffectVis::onPFXProcessed( PostEffect *pfx )
GFXTextureObject *tex;
if ( pfx->mTargetTex )
tex = pfx->mTargetTex;
if ( pfx->mTargetTex[0])
tex = pfx->mTargetTex[0];
else
tex = PFXMGR->getBackBufferTex();
@ -245,7 +245,7 @@ void PostEffectVis::onPFXProcessed( PostEffect *pfx )
if ( tex )
dSprintf( caption, 256, "%s[%i] target - %s [ %ix%i ]", name, pfx->getId(), pfx->mTargetName.c_str(), tex->getWidth(), tex->getHeight() );
dSprintf( caption, 256, "%s[%i] target - %s [ %ix%i ]", name, pfx->getId(), pfx->mTargetName[0].c_str(), tex->getWidth(), tex->getHeight());
else
dSprintf( caption, 256, "%s[%i] target", name, pfx->getId() );