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

View file

@ -67,14 +67,6 @@ class Frustum;
class SceneRenderState; class SceneRenderState;
class ConditionerFeature; class ConditionerFeature;
///
GFX_DeclareTextureProfile( PostFxTargetProfile );
///
class PostEffect : public SimGroup class PostEffect : public SimGroup
{ {
typedef SimGroup Parent; typedef SimGroup Parent;
@ -86,389 +78,317 @@ public:
enum enum
{ {
NumTextures = 16, NumTextures = 16,
/// Maximum simultaneous color render target outputs (MRT)
NumMRTTargets = 4,
}; };
protected: protected:
//--------------------------------------------------------------------------
// Input textures
//--------------------------------------------------------------------------
DECLARE_IMAGEASSET_ARRAY(PostEffect, Texture, GFXStaticTextureSRGBProfile, NumTextures); DECLARE_IMAGEASSET_ARRAY(PostEffect, Texture, GFXStaticTextureSRGBProfile, NumTextures);
GFXTextureProfile* mTextureProfile[NumTextures]; GFXTextureProfile* mTextureProfile[NumTextures];
GFXTexHandle mTexture[NumTextures]; GFXTexHandle mTexture[NumTextures];
bool mTexSRGB[NumTextures];
bool mTexSRGB[NumTextures]; enum { NormalTextureType = 0, CubemapType, CubemapArrayType } mTextureType[NumTextures];
enum GFXCubemapHandle mCubemapTextures[NumTextures];
{
NormalTextureType = 0,
CubemapType,
CubemapArrayType,
} mTextureType[NumTextures];
GFXCubemapHandle mCubemapTextures[NumTextures];
GFXCubemapArrayHandle mCubemapArrayTextures[NumTextures]; GFXCubemapArrayHandle mCubemapArrayTextures[NumTextures];
NamedTexTarget mNamedTarget; GFXTextureObject* mActiveTextures[NumTextures];
NamedTexTarget mNamedTargetDepthStencil; 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; // These remain single values — shared across ALL active MRT slots.
Point2F mTargetScale; ///< Relative size vs current GFX render target.
GFXStateBlockRef mStateBlock; Point2I mTargetSize; ///< Absolute size override; (0,0) = use mTargetScale.
PFXTargetViewport mTargetViewport; ///< How the viewport rect is derived.
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;
/// Single GFXTextureTarget — ALL active MRT slots attach to this one object.
GFXTextureTargetRef mTarget; GFXTextureTargetRef mTarget;
String mTargetName;
GFXTexHandle mTargetTex;
S32 mMipCap; S32 mMipCap;
String mTargetDepthStencilName; //--------------------------------------------------------------------------
GFXTexHandle mTargetDepthStencil; // Depth stencil
//--------------------------------------------------------------------------
/// If mTargetSize is zero then this scale is String mTargetDepthStencilName;
/// used to make a relative texture size to the GFXTexHandle mTargetDepthStencil;
/// active render target. NamedTexTarget mNamedTargetDepthStencil;
Point2F mTargetScale;
/// If non-zero this is used as the absolute //--------------------------------------------------------------------------
/// texture target size. // State block / shader
/// @see mTargetScale //--------------------------------------------------------------------------
Point2I mTargetSize;
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. // Auto shader constant handles
LinearColorF mTargetClearColor; //--------------------------------------------------------------------------
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; PFXRenderTime mRenderTime;
PFXTargetClear mTargetClear; PFXTargetClear mTargetClear_unused; // kept for binary compat if needed — see arrays above
PFXTargetViewport mTargetViewport; String mRenderBin;
S16 mRenderPriority;
bool mIsValid;
bool mEnabled;
bool mSkip;
bool mPreProcessed;
bool mOneFrameOnly;
bool mOnThisFrame;
U32 mShaderReloadKey;
String mRenderBin; //--------------------------------------------------------------------------
// EffectConst
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;
class EffectConst class EffectConst
{ {
public: public:
EffectConst(const String& name, const String& val)
EffectConst( const String &name, const String &val ) : mName(name), mHandle(NULL), mDirty(true) {
: mName( name ), set(val);
mHandle( NULL ), }
mDirty( true ) EffectConst(const String& name, const F32& val)
{ : mName(name), mHandle(NULL), mDirty(true) {
set( val );
}
EffectConst(const String &name, const F32 &val)
: mName(name),
mHandle(NULL),
mDirty(true)
{
set(val); set(val);
} }
EffectConst(const String& name, const int& val) EffectConst(const String& name, const int& val)
: mName(name), : mName(name), mHandle(NULL), mDirty(true) {
mHandle(NULL), set(val);
mDirty(true) }
{ 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); set(val);
} }
EffectConst(const String &name, const Point4F &val) void set(const String& newVal);
: mName(name), void set(const F32& newVal);
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 int& newVal); void set(const int& newVal);
void set(const Point4F &newVal); void set(const Point4F& newVal);
void set(const MatrixF &newVal); void set(const MatrixF& newVal);
void set(const Vector<Point4F> &newVal); void set(const Vector<Point4F>& newVal);
void set(const Vector<MatrixF> &newVal); void set(const Vector<MatrixF>& newVal);
void setToBuffer(GFXShaderConstBufferRef buff);
void setToBuffer( GFXShaderConstBufferRef buff );
String mName;
GFXShaderConstHandle *mHandle;
String mStringVal;
S32 mIntVal;
F32 mFloatVal;
Point4F mPointVal;
MatrixF mMatrixVal;
String mName;
GFXShaderConstHandle* mHandle;
String mStringVal;
S32 mIntVal;
F32 mFloatVal;
Point4F mPointVal;
MatrixF mMatrixVal;
Vector<Point4F> mPointArrayVal; Vector<Point4F> mPointArrayVal;
Vector<MatrixF> mMatrixArrayVal; Vector<MatrixF> mMatrixArrayVal;
enum enum {
{ StringType, IntType, FloatType, PointType,
StringType, MatrixType, PointArrayType, MatrixArrayType
IntType,
FloatType,
PointType,
MatrixType,
PointArrayType,
MatrixArrayType
} mValueType; } mValueType;
bool mDirty; bool mDirty;
}; };
typedef HashTable<StringCase,EffectConst*> EffectConstTable; typedef HashTable<StringCase, EffectConst*> EffectConstTable;
EffectConstTable mEffectConsts; EffectConstTable mEffectConsts;
/// //--------------------------------------------------------------------------
virtual void _updateScreenGeometry( const Frustum &frustum, // Internal methods
GFXVertexBufferHandle<PFXVertex> *outVB ); //--------------------------------------------------------------------------
/// virtual void _updateScreenGeometry(const Frustum& frustum, GFXVertexBufferHandle<PFXVertex>* outVB);
virtual void _setupStateBlock( const SceneRenderState *state ); virtual void _setupStateBlock(const SceneRenderState* state);
virtual void _setupConstants(const SceneRenderState* state);
///
virtual void _setupConstants( const SceneRenderState *state );
///
virtual void _setupTransforms(); 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);
/// static bool _setIsEnabled(void* object, const char* index, const char* data);
virtual void _setupTarget( const SceneRenderState *state, bool *outClearTarget );
/// void _onLMActivate(const char*, bool activate)
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 )
{ {
if ( activate ) if (activate) mUpdateShader = true;
mUpdateShader = true;
} }
/// We handle texture events to release named rendered targets. void _onTextureEvent(GFXTexCallbackCode code)
/// @see GFXTextureManager::addEventDelegate
void _onTextureEvent( GFXTexCallbackCode code )
{ {
if ( code == GFXZombify && (mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered()) ) if (code != GFXZombify) return;
_cleanTargets(); bool anyNamed = mNamedTargetDepthStencil.isRegistered();
for (U32 c = 0; c < NumMRTTargets && !anyNamed; c++)
anyNamed = mNamedTarget[c].isRegistered();
if (anyNamed) _cleanTargets();
} }
///
void _updateConditioners(); void _updateConditioners();
void _cleanTargets(bool recurse = false);
///
void _cleanTargets( bool recurse = false );
///
void _checkRequirements(); void _checkRequirements();
GFXTextureObject* _getTargetTexture(U32 index);
/// /// Map "$outTex" / "$outTex0".."$outTex3" to a slot index [0..NumMRTTargets-1].
GFXTextureObject* _getTargetTexture( U32 index ); /// 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: public:
/// Constructor.
PostEffect(); PostEffect();
/// Destructor.
virtual ~PostEffect(); virtual ~PostEffect();
DECLARE_CONOBJECT(PostEffect); DECLARE_CONOBJECT(PostEffect);
// SimObject
bool onAdd() override; bool onAdd() override;
void onRemove() override; void onRemove() override;
static void initPersistFields(); 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, () ); virtual void process(const SceneRenderState* state,
DECLARE_CALLBACK( void, preProcess, () ); GFXTexHandle& inOutTex,
DECLARE_CALLBACK( void, setShaderConsts, () ); const RectI* inTexViewport = NULL);
DECLARE_CALLBACK( bool, onEnabled, () );
DECLARE_CALLBACK( void, onDisabled, () );
/// @}
virtual void process( const SceneRenderState *state,
GFXTexHandle &inOutTex,
const RectI *inTexViewport = NULL );
///
void reload(); void reload();
///
void enable(); void enable();
///
void disable(); void disable();
/// Dump the shader disassembly to a temporary text file. bool dumpShaderDisassembly(String& outFilename) const;
/// Returns true and sets outFilename to the file if successful.
bool dumpShaderDisassembly( String &outFilename ) const;
/// Returns the SimSet which contains all PostEffects.
SimSet* getSet() const; SimSet* getSet() const;
///
bool isEnabled() const { return mEnabled; } bool isEnabled() const { return mEnabled; }
/// Is set to skip rendering.
bool isSkipped() const { return mSkip; } bool isSkipped() const { return mSkip; }
void setSkip(bool s) { mSkip = s; }
/// Set the effect to skip rendering.
void setSkip( bool skip ) { mSkip = skip; }
PFXRenderTime getRenderTime() const { return mRenderTime; } PFXRenderTime getRenderTime() const { return mRenderTime; }
const String& getRenderBin() const { return mRenderBin; }
F32 getPriority() const { return mRenderPriority; }
const String& getRenderBin() const { return mRenderBin; } void setTexture(U32 index, const String& filePath);
F32 getPriority() const { return mRenderPriority; }
void setTexture( U32 index, const String &filePath );
void setTexture(U32 index, const GFXTexHandle& texHandle); void setTexture(U32 index, const GFXTexHandle& texHandle);
void setCubemapTexture(U32 index, const GFXCubemapHandle &cubemapHandle); void setCubemapTexture(U32 index, const GFXCubemapHandle& handle);
void setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle &cubemapArrayHandle); void setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle& handle);
void setShaderMacro( const String &name, const String &value = String::EmptyString ); void setShaderMacro(const String& name, const String& value = String::EmptyString);
bool removeShaderMacro( const String &name ); bool removeShaderMacro(const String& name);
void clearShaderMacros(); void clearShaderMacros();
/// void setShaderConst(const String& name, const String& val);
void setShaderConst( const String &name, const String &val ); void setShaderConst(const String& name, const F32& val);
void setShaderConst(const String &name, const F32 &val);
void setShaderConst(const String& name, const int& val); void setShaderConst(const String& name, const int& val);
void setShaderConst(const String &name, const Point4F &val); void setShaderConst(const String& name, const Point4F& val);
void setShaderConst(const String &name, const MatrixF &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<Point4F>& val);
void setShaderConst(const String &name, const Vector<MatrixF> &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; } bool isOnThisFrame() { return mOnThisFrame; }
void setOneFrameOnly( bool enabled ) { mOneFrameOnly = enabled; } void setOneFrameOnly(bool e) { mOneFrameOnly = e; }
bool isOneFrameOnly() { return mOneFrameOnly; } bool isOneFrameOnly() { return mOneFrameOnly; }
F32 getAspectRatio() const; F32 getAspectRatio() const;
GFXShaderRef getShader() { return mShader; }
GFXShaderRef getShader() { return mShader; }
Vector<GFXShaderMacro>* getShaderMacros() { return &mShaderMacros; } Vector<GFXShaderMacro>* getShaderMacros() { return &mShaderMacros; }
GFXShaderConstBufferRef getShaderConstBuffer() { return mShaderConsts; } GFXShaderConstBufferRef getShaderConstBuffer() { return mShaderConsts; }
enum PostEffectRequirements enum PostEffectRequirements
{ {

View file

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

View file

@ -228,8 +228,8 @@ void PostEffectVis::onPFXProcessed( PostEffect *pfx )
GFXTextureObject *tex; GFXTextureObject *tex;
if ( pfx->mTargetTex ) if ( pfx->mTargetTex[0])
tex = pfx->mTargetTex; tex = pfx->mTargetTex[0];
else else
tex = PFXMGR->getBackBufferTex(); tex = PFXMGR->getBackBufferTex();
@ -245,7 +245,7 @@ void PostEffectVis::onPFXProcessed( PostEffect *pfx )
if ( tex ) 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 else
dSprintf( caption, 256, "%s[%i] target", name, pfx->getId() ); dSprintf( caption, 256, "%s[%i] target", name, pfx->getId() );