2012-09-19 15:15:01 +00:00
//-----------------------------------------------------------------------------
// Copyright (c) 2012 GarageGames, LLC
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to
// deal in the Software without restriction, including without limitation the
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
// IN THE SOFTWARE.
//-----------------------------------------------------------------------------
# include "platform/platform.h"
# include "postFx/postEffect.h"
# include "console/engineAPI.h"
# include "core/stream/fileStream.h"
# include "core/strings/stringUnit.h"
# include "console/consoleTypes.h"
# include "console/engineAPI.h"
# include "math/util/frustum.h"
# include "math/mathUtils.h"
# include "gfx/gfxTransformSaver.h"
# include "gfx/gfxStringEnumTranslate.h"
# include "gfx/gfxTextureManager.h"
# include "gfx/gfxDebugEvent.h"
# include "gfx/util/screenspace.h"
# include "gfx/sim/gfxStateBlockData.h"
# include "scene/sceneRenderState.h"
# include "shaderGen/shaderGenVars.h"
# include "lighting/lightInfo.h"
# include "lighting/lightManager.h"
# include "materials/materialManager.h"
# include "materials/shaderData.h"
# include "postFx/postEffectManager.h"
# include "postFx/postEffectVis.h"
2013-07-28 17:55:52 +00:00
using namespace Torque ;
2012-09-19 15:15:01 +00:00
ConsoleDocClass ( PostEffect ,
" @brief A fullscreen shader effect. \n \n "
" @section PFXTextureIdentifiers \n \n "
" @ingroup Rendering \n "
) ;
IMPLEMENT_CALLBACK ( PostEffect , onAdd , void , ( ) , ( ) ,
" Called when this object is first created and registered. "
) ;
IMPLEMENT_CALLBACK ( PostEffect , preProcess , void , ( ) , ( ) ,
" Called when an effect is processed but before textures are bound. This "
" allows the user to change texture related paramaters or macros at runtime. \n "
" @tsexample \n "
" function SSAOPostFx::preProcess( %this ) \n "
" { \n "
" if ( $SSAOPostFx::quality !$= %this.quality ) \n "
" { \n "
" %this.quality = mClamp( mRound( $SSAOPostFx::quality ), 0, 2 ); \n "
" \n "
" %this.setShaderMacro( \" QUALITY \" , %this.quality ); \n "
" } \n "
" %this.targetScale = $SSAOPostFx::targetScale; \n "
" } \n "
" @endtsexample \n "
" @see setShaderConst \n "
" @see setShaderMacro "
) ;
IMPLEMENT_CALLBACK ( PostEffect , setShaderConsts , void , ( ) , ( ) ,
" Called immediate before processing this effect. This is the user's chance "
" to set the value of shader uniforms (constants). \n "
" @see setShaderConst "
) ;
IMPLEMENT_CALLBACK ( PostEffect , onEnabled , bool , ( ) , ( ) ,
" Called when this effect becomes enabled. If the user returns false from "
" this callback the effect will not be enabled. \n "
" @return True to allow this effect to be enabled. "
) ;
IMPLEMENT_CALLBACK ( PostEffect , onDisabled , void , ( ) , ( ) ,
" Called when this effect becomes disabled. "
) ;
ImplementEnumType ( PFXRenderTime ,
" When to process this effect during the frame. \n "
" @ingroup Rendering \n \n " )
{ PFXBeforeBin , " PFXBeforeBin " , " Before a RenderInstManager bin. \n " } ,
{ PFXAfterBin , " PFXAfterBin " , " After a RenderInstManager bin. \n " } ,
{ PFXAfterDiffuse , " PFXAfterDiffuse " , " After the diffuse rendering pass. \n " } ,
{ PFXEndOfFrame , " PFXEndOfFrame " , " When the end of the frame is reached. \n " } ,
{ PFXTexGenOnDemand , " PFXTexGenOnDemand " , " This PostEffect is not processed by the manager. It will generate its texture when it is requested. \n " }
EndImplementEnumType ;
ImplementEnumType ( PFXTargetClear ,
" Describes when the target texture should be cleared \n "
" @ingroup Rendering \n \n " )
{ PFXTargetClear_None , " PFXTargetClear_None " , " Never clear the PostEffect target. \n " } ,
{ PFXTargetClear_OnCreate , " PFXTargetClear_OnCreate " , " Clear once on create. \n " } ,
{ PFXTargetClear_OnDraw , " PFXTargetClear_OnDraw " , " Clear before every draw. \n " } ,
EndImplementEnumType ;
2013-10-24 04:28:13 +00:00
ImplementEnumType ( PFXTargetViewport ,
" Specifies how the viewport should be set up for a PostEffect's target. \n "
" @note Applies to both the diffuse target and the depth target (if defined). \n "
" @ingroup Rendering \n \n " )
{ PFXTargetViewport_TargetSize , " PFXTargetViewport_TargetSize " , " Set viewport to match target size (default). \n " } ,
{ PFXTargetViewport_GFXViewport , " PFXTargetViewport_GFXViewport " , " Use the current GFX viewport (scaled to match target size). \n " } ,
2013-10-24 17:40:44 +00:00
{ PFXTargetViewport_NamedInTexture0 , " PFXTargetViewport_NamedInTexture0 " , " Use the input texture 0 if it is named (scaled to match target size), otherwise revert to PFXTargetViewport_TargetSize if there is none. \n " } ,
2013-10-24 04:28:13 +00:00
EndImplementEnumType ;
2012-09-19 15:15:01 +00:00
GFXImplementVertexFormat ( PFXVertex )
{
addElement ( " POSITION " , GFXDeclType_Float3 ) ;
addElement ( " TEXCOORD " , GFXDeclType_Float2 , 0 ) ;
addElement ( " TEXCOORD " , GFXDeclType_Float3 , 1 ) ;
} ;
GFX_ImplementTextureProfile ( PostFxTargetProfile ,
GFXTextureProfile : : DiffuseMap ,
GFXTextureProfile : : PreserveSize |
GFXTextureProfile : : RenderTarget |
GFXTextureProfile : : Pooled ,
2014-04-06 22:03:52 +00:00
GFXTextureProfile : : NONE ) ;
2012-09-19 15:15:01 +00:00
IMPLEMENT_CONOBJECT ( PostEffect ) ;
GFX_ImplementTextureProfile ( PostFxTextureProfile ,
GFXTextureProfile : : DiffuseMap ,
GFXTextureProfile : : Static | GFXTextureProfile : : PreserveSize | GFXTextureProfile : : NoMipmap ,
2014-04-06 22:03:52 +00:00
GFXTextureProfile : : NONE ) ;
2012-09-19 15:15:01 +00:00
2017-06-23 16:36:20 +00:00
GFX_ImplementTextureProfile ( PostFxTextureSRGBProfile ,
GFXTextureProfile : : DiffuseMap ,
GFXTextureProfile : : Static | GFXTextureProfile : : PreserveSize | GFXTextureProfile : : NoMipmap | GFXTextureProfile : : SRGB ,
GFXTextureProfile : : NONE ) ;
2015-05-06 22:07:48 +00:00
GFX_ImplementTextureProfile ( VRTextureProfile ,
GFXTextureProfile : : DiffuseMap ,
GFXTextureProfile : : PreserveSize |
GFXTextureProfile : : RenderTarget |
GFXTextureProfile : : NoMipmap ,
GFXTextureProfile : : NONE ) ;
GFX_ImplementTextureProfile ( VRDepthProfile ,
GFXTextureProfile : : DiffuseMap ,
GFXTextureProfile : : PreserveSize |
GFXTextureProfile : : NoMipmap |
GFXTextureProfile : : ZTarget ,
GFXTextureProfile : : NONE ) ;
2012-09-19 15:15:01 +00:00
void PostEffect : : EffectConst : : set ( const String & newVal )
{
if ( mStringVal = = newVal )
return ;
mStringVal = newVal ;
mDirty = true ;
2019-02-12 07:10:30 +00:00
mValueType = StringType ;
}
void PostEffect : : EffectConst : : set ( const F32 & newVal )
{
if ( mFloatVal = = newVal )
return ;
mFloatVal = newVal ;
mDirty = true ;
mValueType = FloatType ;
}
2019-06-13 05:37:12 +00:00
void PostEffect : : EffectConst : : set ( const int & newVal )
{
if ( mIntVal = = newVal )
return ;
mIntVal = newVal ;
mDirty = true ;
mValueType = IntType ;
}
2019-02-12 07:10:30 +00:00
void PostEffect : : EffectConst : : set ( const Point4F & newVal )
{
if ( mPointVal = = newVal )
return ;
mPointVal = newVal ;
mDirty = true ;
mValueType = PointType ;
}
void PostEffect : : EffectConst : : set ( const MatrixF & newVal )
{
if ( mMatrixVal = = newVal )
return ;
mMatrixVal = newVal ;
mDirty = true ;
mValueType = MatrixType ;
}
void PostEffect : : EffectConst : : set ( const Vector < Point4F > & newVal )
{
//if (mPointArrayVal == newVal)
// return;
mPointArrayVal = newVal ;
mDirty = true ;
mValueType = PointArrayType ;
}
void PostEffect : : EffectConst : : set ( const Vector < MatrixF > & newVal )
{
//if (mMatrixArrayVal == newVal)
// return;
mMatrixArrayVal = newVal ;
mDirty = true ;
mValueType = MatrixArrayType ;
2012-09-19 15:15:01 +00:00
}
void PostEffect : : EffectConst : : setToBuffer ( GFXShaderConstBufferRef buff )
{
// Nothing to do if the value hasn't changed.
if ( ! mDirty )
return ;
mDirty = false ;
// If we don't have a handle... get it now.
if ( ! mHandle )
mHandle = buff - > getShader ( ) - > getShaderConstHandle ( mName ) ;
// If the handle isn't valid then we're done.
if ( ! mHandle - > isValid ( ) )
return ;
const GFXShaderConstType type = mHandle - > getType ( ) ;
// For now, we're only going
// to support float4 arrays.
// Expand to other types as necessary.
U32 arraySize = mHandle - > getArraySize ( ) ;
2019-02-12 07:10:30 +00:00
if ( mValueType = = StringType )
2014-11-08 08:42:01 +00:00
{
2019-02-12 07:10:30 +00:00
const char * strVal = mStringVal . c_str ( ) ;
if ( type = = GFXSCT_Int )
{
S32 val ;
Con : : setData ( TypeS32 , & val , 0 , 1 , & strVal ) ;
buff - > set ( mHandle , val ) ;
}
else if ( type = = GFXSCT_Float )
{
F32 val ;
Con : : setData ( TypeF32 , & val , 0 , 1 , & strVal ) ;
buff - > set ( mHandle , val ) ;
}
else if ( type = = GFXSCT_Float2 )
{
Point2F val ;
Con : : setData ( TypePoint2F , & val , 0 , 1 , & strVal ) ;
buff - > set ( mHandle , val ) ;
}
else if ( type = = GFXSCT_Float3 )
{
Point3F val ;
Con : : setData ( TypePoint3F , & val , 0 , 1 , & strVal ) ;
buff - > set ( mHandle , val ) ;
}
else if ( type = = GFXSCT_Float4 )
{
Point4F val ;
if ( arraySize > 1 )
{
// Do array setup!
//U32 unitCount = StringUnit::getUnitCount( strVal, "\t" );
//AssertFatal( unitCount == arraySize, "" );
String tmpString ;
Vector < Point4F > valArray ;
for ( U32 i = 0 ; i < arraySize ; i + + )
{
tmpString = StringUnit : : getUnit ( strVal , i , " \t " ) ;
valArray . increment ( ) ;
const char * tmpCStr = tmpString . c_str ( ) ;
Con : : setData ( TypePoint4F , & valArray . last ( ) , 0 , 1 , & tmpCStr ) ;
}
AlignedArray < Point4F > rectData ( valArray . size ( ) , sizeof ( Point4F ) , ( U8 * ) valArray . address ( ) , false ) ;
buff - > set ( mHandle , rectData ) ;
}
else
{
// Do regular setup.
Con : : setData ( TypePoint4F , & val , 0 , 1 , & strVal ) ;
buff - > set ( mHandle , val ) ;
}
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
}
2014-11-08 08:42:01 +00:00
}
2019-02-12 07:10:30 +00:00
else if ( mValueType = = FloatType )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( type = = GFXSCT_Float )
{
buff - > set ( mHandle , mFloatVal ) ;
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
2019-06-13 05:37:12 +00:00
# endif
}
}
else if ( mValueType = = IntType )
{
if ( type = = GFXSCT_Int )
{
buff - > set ( mHandle , mIntVal ) ;
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
2019-02-12 07:10:30 +00:00
# endif
}
2012-09-19 15:15:01 +00:00
}
2019-02-12 07:10:30 +00:00
else if ( mValueType = = PointType )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( type = = GFXSCT_Float2 )
{
buff - > set ( mHandle , Point2F ( mPointVal . x , mPointVal . y ) ) ;
}
else if ( type = = GFXSCT_Float3 )
{
buff - > set ( mHandle , Point3F ( mPointVal . x , mPointVal . y , mPointVal . z ) ) ;
}
else if ( type = = GFXSCT_Float4 )
{
buff - > set ( mHandle , mPointVal ) ;
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
}
2012-09-19 15:15:01 +00:00
}
2019-02-12 07:10:30 +00:00
else if ( mValueType = = MatrixType )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( type = = GFXSCT_Float4x4 )
{
buff - > set ( mHandle , mMatrixVal ) ;
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
}
2012-09-19 15:15:01 +00:00
}
2019-02-12 07:10:30 +00:00
else if ( mValueType = = PointArrayType )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( type = = GFXSCT_Float4 )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( arraySize ! = mPointArrayVal . size ( ) )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer PointArrayType, attempted to feed an array that does not match the uniform array's size! " ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
return ;
2012-09-19 15:15:01 +00:00
}
2019-02-12 07:10:30 +00:00
AlignedArray < Point4F > alignedVal = AlignedArray < Point4F > ( arraySize , sizeof ( Point4F ) , ( U8 * ) mPointArrayVal . address ( ) , false ) ;
buff - > set ( mHandle , alignedVal ) ;
2012-09-19 15:15:01 +00:00
}
else
{
2019-02-12 07:10:30 +00:00
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
2012-09-19 15:15:01 +00:00
}
}
2019-02-12 07:10:30 +00:00
else if ( mValueType = = MatrixArrayType )
2014-11-08 08:42:01 +00:00
{
2019-02-12 07:10:30 +00:00
if ( type = = GFXSCT_Float4x4 )
{
if ( arraySize ! = mMatrixArrayVal . size ( ) )
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer MatrixArrayType, attempted to feed an array that does not match the uniform array's size! " ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
return ;
}
buff - > set ( mHandle , mMatrixArrayVal . address ( ) , arraySize ) ;
}
else
{
# if TORQUE_DEBUG
const char * err = avar ( " PostEffect::EffectConst::setToBuffer $s type is not implemented " , mName . c_str ( ) ) ;
Con : : errorf ( err ) ;
GFXAssertFatal ( 0 , err ) ;
# endif
}
2014-11-08 08:42:01 +00:00
}
2012-09-19 15:15:01 +00:00
}
//-------------------------------------------------------------------------
// PostEffect
//-------------------------------------------------------------------------
PostEffect : : PostEffect ( )
: mRenderTime ( PFXAfterDiffuse ) ,
mRenderPriority ( 1.0 ) ,
mEnabled ( false ) ,
mStateBlockData ( NULL ) ,
2017-04-11 04:45:02 +00:00
mUpdateShader ( true ) ,
mSkip ( false ) ,
2012-09-19 15:15:01 +00:00
mAllowReflectPass ( false ) ,
mTargetClear ( PFXTargetClear_None ) ,
mTargetScale ( Point2F : : One ) ,
2017-04-11 04:45:02 +00:00
mTargetViewport ( PFXTargetViewport_TargetSize ) ,
2012-09-19 15:15:01 +00:00
mTargetSize ( Point2I : : Zero ) ,
mTargetFormat ( GFXFormatR8G8B8A8 ) ,
2017-06-23 16:36:20 +00:00
mTargetClearColor ( LinearColorF : : BLACK ) ,
2012-09-19 15:15:01 +00:00
mOneFrameOnly ( false ) ,
mOnThisFrame ( true ) ,
mRTSizeSC ( NULL ) ,
2017-04-11 04:45:02 +00:00
mIsValid ( false ) ,
mShaderReloadKey ( 0 ) ,
2012-09-19 15:15:01 +00:00
mOneOverRTSizeSC ( NULL ) ,
mViewportOffsetSC ( NULL ) ,
2013-11-01 20:18:48 +00:00
mTargetViewportSC ( NULL ) ,
2012-09-19 15:15:01 +00:00
mFogDataSC ( NULL ) ,
mFogColorSC ( NULL ) ,
mEyePosSC ( NULL ) ,
mMatWorldToScreenSC ( NULL ) ,
mMatScreenToWorldSC ( NULL ) ,
mMatPrevScreenToWorldSC ( NULL ) ,
mNearFarSC ( NULL ) ,
mInvNearFarSC ( NULL ) ,
mWorldToScreenScaleSC ( NULL ) ,
2013-11-01 20:18:48 +00:00
mProjectionOffsetSC ( NULL ) ,
2012-09-19 15:15:01 +00:00
mWaterColorSC ( NULL ) ,
mWaterFogDataSC ( NULL ) ,
mAmbientColorSC ( NULL ) ,
mWaterFogPlaneSC ( NULL ) ,
mWaterDepthGradMaxSC ( NULL ) ,
mScreenSunPosSC ( NULL ) ,
mLightDirectionSC ( NULL ) ,
mCameraForwardSC ( NULL ) ,
mAccumTimeSC ( NULL ) ,
mDeltaTimeSC ( NULL ) ,
2018-11-01 23:08:45 +00:00
mInvCameraMatSC ( NULL ) ,
2019-09-06 19:48:15 +00:00
mMatCameraToWorldSC ( NULL ) ,
mInvCameraTransSC ( NULL ) ,
mMatCameraToScreenSC ( NULL ) ,
mMatScreenToCameraSC ( NULL )
2012-09-19 15:15:01 +00:00
{
2017-06-23 16:36:20 +00:00
dMemset ( mTexSRGB , 0 , sizeof ( bool ) * NumTextures ) ;
2012-09-19 15:15:01 +00:00
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 ) ;
2021-07-19 06:07:08 +00:00
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
2021-11-03 17:30:52 +00:00
INIT_IMAGEASSET_ARRAY ( Texture , PostFxTextureProfile , i ) ;
2021-07-19 06:07:08 +00:00
}
2012-09-19 15:15:01 +00:00
}
PostEffect : : ~ PostEffect ( )
{
EffectConstTable : : Iterator iter = mEffectConsts . begin ( ) ;
for ( ; iter ! = mEffectConsts . end ( ) ; iter + + )
delete iter - > value ;
}
void PostEffect : : initPersistFields ( )
{
addField ( " shader " , TypeRealString , Offset ( mShaderName , PostEffect ) ,
" Name of a GFXShaderData for this effect. " ) ;
addField ( " stateBlock " , TYPEID < GFXStateBlockData > ( ) , Offset ( mStateBlockData , PostEffect ) ,
" Name of a GFXStateBlockData for this effect. " ) ;
addField ( " target " , TypeRealString , Offset ( mTargetName , PostEffect ) ,
" String identifier of this effect's target texture. \n "
" @see PFXTextureIdentifiers " ) ;
addField ( " targetDepthStencil " , TypeRealString , Offset ( mTargetDepthStencilName , PostEffect ) ,
" Optional string identifier for this effect's target depth/stencil texture. \n "
" @see PFXTextureIdentifiers " ) ;
addField ( " targetScale " , TypePoint2F , Offset ( mTargetScale , PostEffect ) ,
" If targetSize is zero this is used to set a relative size from the current target. " ) ;
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. " ) ;
2013-10-24 04:28:13 +00:00
addField ( " targetViewport " , TYPEID < PFXTargetViewport > ( ) , Offset ( mTargetViewport , PostEffect ) ,
" Specifies how the viewport should be set up for a target texture. " ) ;
2021-07-19 06:07:08 +00:00
INITPERSISTFIELD_IMAGEASSET_ARRAY ( Texture , NumTextures , PostEffect , " Input textures to this effect ( samplers ). \n "
" @see PFXTextureIdentifiers " ) ;
2012-09-19 15:15:01 +00:00
2017-06-23 16:36:20 +00:00
addField ( " textureSRGB " , TypeBool , Offset ( mTexSRGB , PostEffect ) , NumTextures ,
" Set input texture to be sRGB " ) ;
2012-09-19 15:15:01 +00:00
addField ( " renderTime " , TYPEID < PFXRenderTime > ( ) , Offset ( mRenderTime , PostEffect ) ,
" When to process this effect during the frame. " ) ;
addField ( " renderBin " , TypeRealString , Offset ( mRenderBin , PostEffect ) ,
" Name of a renderBin, used if renderTime is PFXBeforeBin or PFXAfterBin. " ) ;
addField ( " renderPriority " , TypeF32 , Offset ( mRenderPriority , PostEffect ) ,
" PostEffects are processed in DESCENDING order of renderPriority if more than one has the same renderBin/Time. " ) ;
addField ( " allowReflectPass " , TypeBool , Offset ( mAllowReflectPass , PostEffect ) ,
" Is this effect processed during reflection render passes. " ) ;
2019-08-03 10:47:31 +00:00
addProtectedField ( " enabled " , TypeBool , Offset ( mEnabled , PostEffect ) ,
2012-09-19 15:15:01 +00:00
& PostEffect : : _setIsEnabled , & defaultProtectedGetFn ,
" Is the effect on. " ) ;
addField ( " onThisFrame " , TypeBool , Offset ( mOnThisFrame , PostEffect ) ,
" Allows you to turn on a PostEffect for only a single frame. " ) ;
addField ( " oneFrameOnly " , TypeBool , Offset ( mOneFrameOnly , PostEffect ) ,
" Allows you to turn on a PostEffect for only a single frame. " ) ;
addField ( " skip " , TypeBool , Offset ( mSkip , PostEffect ) ,
" Skip processing of this PostEffect and its children even if its parent "
" is enabled. Parent and sibling PostEffects in the chain are still processed. " ) ;
Parent : : initPersistFields ( ) ;
}
bool PostEffect : : onAdd ( )
{
if ( ! Parent : : onAdd ( ) )
return false ;
LightManager : : smActivateSignal . notify ( this , & PostEffect : : _onLMActivate ) ;
mUpdateShader = true ;
// Grab the script path.
Torque : : Path scriptPath ( Con : : getVariable ( " $Con::File " ) ) ;
scriptPath . setFileName ( String : : EmptyString ) ;
scriptPath . setExtension ( String : : EmptyString ) ;
// Find additional textures
2021-11-03 17:30:52 +00:00
for ( S32 i = 0 ; i < NumTextures ; i + + )
2012-09-19 15:15:01 +00:00
{
2019-02-12 07:10:30 +00:00
mTextureType [ i ] = NormalTextureType ;
2021-11-03 17:30:52 +00:00
String texFilename = getTexture ( i ) ;
// Skip empty stages or ones with variable or target names.
if ( texFilename . isEmpty ( ) | |
texFilename [ 0 ] = = ' $ ' | |
texFilename [ 0 ] = = ' # ' )
continue ;
mTextureProfile [ i ] = ( mTexSRGB [ i ] ) ? & PostFxTextureSRGBProfile : & PostFxTextureProfile ;
_setTexture ( texFilename , i ) ;
2012-09-19 15:15:01 +00:00
}
// Is the target a named target?
if ( mTargetName . isNotEmpty ( ) & & mTargetName [ 0 ] = = ' # ' )
{
mNamedTarget . registerWithName ( mTargetName . substr ( 1 ) ) ;
mNamedTarget . getTextureDelegate ( ) . bind ( this , & PostEffect : : _getTargetTexture ) ;
}
if ( mTargetDepthStencilName . isNotEmpty ( ) & & mTargetDepthStencilName [ 0 ] = = ' # ' )
mNamedTargetDepthStencil . registerWithName ( mTargetDepthStencilName . substr ( 1 ) ) ;
if ( mNamedTarget . isRegistered ( ) | | mNamedTargetDepthStencil . isRegistered ( ) )
GFXTextureManager : : addEventDelegate ( this , & PostEffect : : _onTextureEvent ) ;
// Call onAdd in script
onAdd_callback ( ) ;
// Should we start enabled?
if ( mEnabled )
{
mEnabled = false ;
enable ( ) ;
}
getSet ( ) - > addObject ( this ) ;
return true ;
}
void PostEffect : : onRemove ( )
{
Parent : : onRemove ( ) ;
PFXMGR - > _removeEffect ( this ) ;
LightManager : : smActivateSignal . remove ( this , & PostEffect : : _onLMActivate ) ;
mShader = NULL ;
_cleanTargets ( ) ;
if ( mNamedTarget . isRegistered ( ) | | mNamedTargetDepthStencil . isRegistered ( ) )
GFXTextureManager : : removeEventDelegate ( this , & PostEffect : : _onTextureEvent ) ;
if ( mNamedTarget . isRegistered ( ) )
{
mNamedTarget . unregister ( ) ;
mNamedTarget . getTextureDelegate ( ) . clear ( ) ;
}
if ( mNamedTargetDepthStencil . isRegistered ( ) )
mNamedTargetDepthStencil . unregister ( ) ;
}
void PostEffect : : _updateScreenGeometry ( const Frustum & frustum ,
GFXVertexBufferHandle < PFXVertex > * outVB )
{
outVB - > set ( GFX , 4 , GFXBufferTypeVolatile ) ;
const Point3F * frustumPoints = frustum . getPoints ( ) ;
const Point3F & cameraPos = frustum . getPosition ( ) ;
2013-04-09 19:19:18 +00:00
// Perform a camera offset. We need to manually perform this offset on the postFx's
// polygon, which is at the far plane.
const Point2F & projOffset = frustum . getProjectionOffset ( ) ;
Point3F cameraOffsetPos = cameraPos ;
if ( ! projOffset . isZero ( ) )
{
// First we need to calculate the offset at the near plane. The projOffset
// given above can be thought of a percent as it ranges from 0..1 (or 0..-1).
F32 nearOffset = frustum . getNearRight ( ) * projOffset . x ;
// Now given the near plane distance from the camera we can solve the right
// triangle and calcuate the SIN theta for the offset at the near plane.
// SIN theta = x/y
F32 sinTheta = nearOffset / frustum . getNearDist ( ) ;
// Finally, we can calcuate the offset at the far plane, which is where our sun (or vector)
// light's polygon is drawn.
F32 farOffset = frustum . getFarDist ( ) * sinTheta ;
// We can now apply this far plane offset to the far plane itself, which then compensates
// for the project offset.
MatrixF camTrans = frustum . getTransform ( ) ;
VectorF offset = camTrans . getRightVector ( ) ;
offset * = farOffset ;
cameraOffsetPos + = offset ;
}
2012-09-19 15:15:01 +00:00
PFXVertex * vert = outVB - > lock ( ) ;
2016-03-20 11:52:11 +00:00
vert - > point . set ( - 1.0 , 1.0 , 0.0 ) ;
vert - > texCoord . set ( 0.0f , 0.0f ) ;
2013-04-09 19:19:18 +00:00
vert - > wsEyeRay = frustumPoints [ Frustum : : FarTopLeft ] - cameraOffsetPos ;
2012-09-19 15:15:01 +00:00
vert + + ;
2016-03-20 11:52:11 +00:00
vert - > point . set ( 1.0 , 1.0 , 0.0 ) ;
vert - > texCoord . set ( 1.0f , 0.0f ) ;
2013-04-09 19:19:18 +00:00
vert - > wsEyeRay = frustumPoints [ Frustum : : FarTopRight ] - cameraOffsetPos ;
2012-09-19 15:15:01 +00:00
vert + + ;
2016-03-20 11:52:11 +00:00
vert - > point . set ( - 1.0 , - 1.0 , 0.0 ) ;
vert - > texCoord . set ( 0.0f , 1.0f ) ;
vert - > wsEyeRay = frustumPoints [ Frustum : : FarBottomLeft ] - cameraOffsetPos ;
vert + + ;
vert - > point . set ( 1.0 , - 1.0 , 0.0 ) ;
vert - > texCoord . set ( 1.0f , 1.0f ) ;
2013-04-09 19:19:18 +00:00
vert - > wsEyeRay = frustumPoints [ Frustum : : FarBottomRight ] - cameraOffsetPos ;
2012-09-19 15:15:01 +00:00
vert + + ;
outVB - > unlock ( ) ;
}
void PostEffect : : _setupStateBlock ( const SceneRenderState * state )
{
if ( mStateBlock . isNull ( ) )
{
GFXStateBlockDesc desc ;
if ( mStateBlockData )
desc = mStateBlockData - > getState ( ) ;
mStateBlock = GFX - > createStateBlock ( desc ) ;
}
GFX - > setStateBlock ( mStateBlock ) ;
}
void PostEffect : : _setupConstants ( const SceneRenderState * state )
{
// Alloc the const buffer.
if ( mShaderConsts . isNull ( ) )
{
mShaderConsts = mShader - > allocConstBuffer ( ) ;
mRTSizeSC = mShader - > getShaderConstHandle ( " $targetSize " ) ;
mOneOverRTSizeSC = mShader - > getShaderConstHandle ( " $oneOverTargetSize " ) ;
2021-07-19 06:07:08 +00:00
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
mTexSizeSC [ i ] = mShader - > getShaderConstHandle ( String : : ToString ( " $texSize%d " , i ) ) ;
mRenderTargetParamsSC [ i ] = mShader - > getShaderConstHandle ( String : : ToString ( " $rtParams%d " , i ) ) ;
}
2012-09-19 15:15:01 +00:00
2013-11-01 20:18:48 +00:00
mTargetViewportSC = mShader - > getShaderConstHandle ( " $targetViewport " ) ;
2012-09-19 15:15:01 +00:00
mFogDataSC = mShader - > getShaderConstHandle ( ShaderGenVars : : fogData ) ;
mFogColorSC = mShader - > getShaderConstHandle ( ShaderGenVars : : fogColor ) ;
mEyePosSC = mShader - > getShaderConstHandle ( ShaderGenVars : : eyePosWorld ) ;
mNearFarSC = mShader - > getShaderConstHandle ( " $nearFar " ) ;
mInvNearFarSC = mShader - > getShaderConstHandle ( " $invNearFar " ) ;
mWorldToScreenScaleSC = mShader - > getShaderConstHandle ( " $worldToScreenScale " ) ;
mMatWorldToScreenSC = mShader - > getShaderConstHandle ( " $matWorldToScreen " ) ;
mMatScreenToWorldSC = mShader - > getShaderConstHandle ( " $matScreenToWorld " ) ;
mMatPrevScreenToWorldSC = mShader - > getShaderConstHandle ( " $matPrevScreenToWorld " ) ;
2013-11-01 20:18:48 +00:00
mProjectionOffsetSC = mShader - > getShaderConstHandle ( " $projectionOffset " ) ;
2012-09-19 15:15:01 +00:00
mWaterColorSC = mShader - > getShaderConstHandle ( " $waterColor " ) ;
mAmbientColorSC = mShader - > getShaderConstHandle ( " $ambientColor " ) ;
mWaterFogDataSC = mShader - > getShaderConstHandle ( " $waterFogData " ) ;
mWaterFogPlaneSC = mShader - > getShaderConstHandle ( " $waterFogPlane " ) ;
mWaterDepthGradMaxSC = mShader - > getShaderConstHandle ( " $waterDepthGradMax " ) ;
mScreenSunPosSC = mShader - > getShaderConstHandle ( " $screenSunPos " ) ;
mLightDirectionSC = mShader - > getShaderConstHandle ( " $lightDirection " ) ;
mCameraForwardSC = mShader - > getShaderConstHandle ( " $camForward " ) ;
mAccumTimeSC = mShader - > getShaderConstHandle ( " $accumTime " ) ;
mDeltaTimeSC = mShader - > getShaderConstHandle ( " $deltaTime " ) ;
mInvCameraMatSC = mShader - > getShaderConstHandle ( " $invCameraMat " ) ;
2018-11-01 23:08:45 +00:00
mMatCameraToWorldSC = mShader - > getShaderConstHandle ( " $cameraToWorld " ) ;
2019-09-06 19:48:15 +00:00
mInvCameraTransSC = mShader - > getShaderConstHandle ( " $invCameraTrans " ) ;
mMatCameraToScreenSC = mShader - > getShaderConstHandle ( " $cameraToScreen " ) ;
mMatScreenToCameraSC = mShader - > getShaderConstHandle ( " $screenToCamera " ) ;
2012-09-19 15:15:01 +00:00
}
// Set up shader constants for source image size
if ( mRTSizeSC - > isValid ( ) )
{
const Point2I & resolution = GFX - > getActiveRenderTarget ( ) - > getSize ( ) ;
Point2F pixelShaderConstantData ;
pixelShaderConstantData . x = resolution . x ;
pixelShaderConstantData . y = resolution . y ;
mShaderConsts - > set ( mRTSizeSC , pixelShaderConstantData ) ;
}
if ( mOneOverRTSizeSC - > isValid ( ) )
{
const Point2I & resolution = GFX - > getActiveRenderTarget ( ) - > getSize ( ) ;
Point2F oneOverTargetSize ( 1.0f / ( F32 ) resolution . x , 1.0f / ( F32 ) resolution . y ) ;
mShaderConsts - > set ( mOneOverRTSizeSC , oneOverTargetSize ) ;
}
// Set up additional textures
Point2F texSizeConst ;
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
if ( ! mActiveTextures [ i ] )
continue ;
if ( mTexSizeSC [ i ] - > isValid ( ) )
{
texSizeConst . x = ( F32 ) mActiveTextures [ i ] - > getWidth ( ) ;
texSizeConst . y = ( F32 ) mActiveTextures [ i ] - > getHeight ( ) ;
mShaderConsts - > set ( mTexSizeSC [ i ] , texSizeConst ) ;
}
}
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
if ( ! mRenderTargetParamsSC [ i ] - > isValid ( ) )
continue ;
Point4F rtParams ( Point4F : : One ) ;
if ( mActiveTextures [ i ] )
{
const Point3I & targetSz = mActiveTextures [ i ] - > getSize ( ) ;
RectI targetVp = mActiveTextureViewport [ i ] ;
ScreenSpace : : RenderTargetParameters ( targetSz , targetVp , rtParams ) ;
}
mShaderConsts - > set ( mRenderTargetParamsSC [ i ] , rtParams ) ;
}
2013-11-01 20:18:48 +00:00
// Target viewport (in target space)
if ( mTargetViewportSC - > isValid ( ) )
{
const Point2I & targetSize = GFX - > getActiveRenderTarget ( ) - > getSize ( ) ;
Point3I size ( targetSize . x , targetSize . y , 0 ) ;
const RectI & viewport = GFX - > getViewport ( ) ;
Point2F offset ( ( F32 ) viewport . point . x / ( F32 ) targetSize . x , ( F32 ) viewport . point . y / ( F32 ) targetSize . y ) ;
Point2F scale ( ( F32 ) viewport . extent . x / ( F32 ) targetSize . x , ( F32 ) viewport . extent . y / ( F32 ) targetSize . y ) ;
Point4F targetParams ;
2017-05-28 21:51:31 +00:00
targetParams . x = offset . x ;
targetParams . y = offset . y ;
targetParams . z = offset . x + scale . x ;
targetParams . w = offset . y + scale . y ;
2013-11-01 20:18:48 +00:00
mShaderConsts - > set ( mTargetViewportSC , targetParams ) ;
}
2012-09-19 15:15:01 +00:00
// Set the fog data.
if ( mFogDataSC - > isValid ( ) )
{
const FogData & data = state - > getSceneManager ( ) - > getFogData ( ) ;
Point3F params ;
params . x = data . density ;
params . y = data . densityOffset ;
if ( ! mIsZero ( data . atmosphereHeight ) )
params . z = 1.0f / data . atmosphereHeight ;
else
params . z = 0.0f ;
mShaderConsts - > set ( mFogDataSC , params ) ;
}
const PFXFrameState & thisFrame = PFXMGR - > getFrameState ( ) ;
if ( mMatWorldToScreenSC - > isValid ( ) )
{
// Screen space->world space
MatrixF tempMat = thisFrame . cameraToScreen ;
tempMat . mul ( thisFrame . worldToCamera ) ;
tempMat . fullInverse ( ) ;
tempMat . transpose ( ) ;
// Support using these matrices as float3x3 or float4x4...
mShaderConsts - > set ( mMatWorldToScreenSC , tempMat , mMatWorldToScreenSC - > getType ( ) ) ;
}
if ( mMatScreenToWorldSC - > isValid ( ) )
{
// World space->screen space
MatrixF tempMat = thisFrame . cameraToScreen ;
tempMat . mul ( thisFrame . worldToCamera ) ;
tempMat . transpose ( ) ;
// Support using these matrices as float3x3 or float4x4...
mShaderConsts - > set ( mMatScreenToWorldSC , tempMat , mMatScreenToWorldSC - > getType ( ) ) ;
}
if ( mMatPrevScreenToWorldSC - > isValid ( ) )
{
const PFXFrameState & lastFrame = PFXMGR - > getLastFrameState ( ) ;
// Previous frame world space->screen space
MatrixF tempMat = lastFrame . cameraToScreen ;
tempMat . mul ( lastFrame . worldToCamera ) ;
tempMat . transpose ( ) ;
mShaderConsts - > set ( mMatPrevScreenToWorldSC , tempMat ) ;
}
2015-07-29 04:19:59 +00:00
if ( mAmbientColorSC - > isValid ( ) & & state )
2012-09-19 15:15:01 +00:00
{
2017-06-23 16:36:20 +00:00
const LinearColorF & sunlight = state - > getAmbientLightColor ( ) ;
2012-09-19 15:15:01 +00:00
Point3F ambientColor ( sunlight . red , sunlight . green , sunlight . blue ) ;
mShaderConsts - > set ( mAmbientColorSC , ambientColor ) ;
}
2018-11-01 23:08:45 +00:00
if ( mMatCameraToWorldSC - > isValid ( ) )
{
MatrixF tempMat = thisFrame . worldToCamera ;
tempMat . inverse ( ) ;
mShaderConsts - > set ( mMatCameraToWorldSC , tempMat ) ;
}
2019-09-06 19:25:17 +00:00
if ( mInvCameraTransSC - > isValid ( ) )
{
MatrixF mat = state - > getCameraTransform ( ) ;
mat . fullInverse ( ) ;
mShaderConsts - > set ( mInvCameraTransSC , mat , mInvCameraTransSC - > getType ( ) ) ;
}
//Projection Matrix
if ( mMatCameraToScreenSC - > isValid ( ) )
{
MatrixF tempMat = thisFrame . cameraToScreen ;
mShaderConsts - > set ( mMatCameraToScreenSC , tempMat , mMatCameraToScreenSC - > getType ( ) ) ;
}
//Inverse Projection Matrix
if ( mMatScreenToCameraSC - > isValid ( ) )
{
MatrixF tempMat = thisFrame . cameraToScreen ;
tempMat . fullInverse ( ) ;
mShaderConsts - > set ( mMatScreenToCameraSC , tempMat , mMatScreenToCameraSC - > getType ( ) ) ;
}
2012-09-19 15:15:01 +00:00
mShaderConsts - > setSafe ( mAccumTimeSC , MATMGR - > getTotalTime ( ) ) ;
mShaderConsts - > setSafe ( mDeltaTimeSC , MATMGR - > getDeltaTime ( ) ) ;
// Now set all the constants that are dependent on the scene state.
if ( state )
{
mShaderConsts - > setSafe ( mEyePosSC , state - > getDiffuseCameraPosition ( ) ) ;
mShaderConsts - > setSafe ( mNearFarSC , Point2F ( state - > getNearPlane ( ) , state - > getFarPlane ( ) ) ) ;
mShaderConsts - > setSafe ( mInvNearFarSC , Point2F ( 1.0f / state - > getNearPlane ( ) , 1.0f / state - > getFarPlane ( ) ) ) ;
mShaderConsts - > setSafe ( mWorldToScreenScaleSC , state - > getWorldToScreenScale ( ) ) ;
2013-11-07 20:07:16 +00:00
mShaderConsts - > setSafe ( mProjectionOffsetSC , state - > getCameraFrustum ( ) . getProjectionOffset ( ) ) ;
2012-09-19 15:15:01 +00:00
mShaderConsts - > setSafe ( mFogColorSC , state - > getSceneManager ( ) - > getFogData ( ) . color ) ;
if ( mWaterColorSC - > isValid ( ) )
{
2017-06-23 16:36:20 +00:00
LinearColorF color ( state - > getSceneManager ( ) - > getWaterFogData ( ) . color ) ;
2012-09-19 15:15:01 +00:00
mShaderConsts - > set ( mWaterColorSC , color ) ;
}
if ( mWaterFogDataSC - > isValid ( ) )
{
const WaterFogData & data = state - > getSceneManager ( ) - > getWaterFogData ( ) ;
Point4F params ( data . density , data . densityOffset , data . wetDepth , data . wetDarkening ) ;
mShaderConsts - > set ( mWaterFogDataSC , params ) ;
}
if ( mWaterFogPlaneSC - > isValid ( ) )
{
const PlaneF & plane = state - > getSceneManager ( ) - > getWaterFogData ( ) . plane ;
mShaderConsts - > set ( mWaterFogPlaneSC , plane ) ;
}
if ( mWaterDepthGradMaxSC - > isValid ( ) )
{
mShaderConsts - > set ( mWaterDepthGradMaxSC , state - > getSceneManager ( ) - > getWaterFogData ( ) . depthGradMax ) ;
}
if ( mScreenSunPosSC - > isValid ( ) )
{
// Grab our projection matrix
// from the frustum.
2013-11-07 20:07:16 +00:00
Frustum frust = state - > getCameraFrustum ( ) ;
2012-09-19 15:15:01 +00:00
MatrixF proj ( true ) ;
frust . getProjectionMatrix ( & proj ) ;
// Grab the ScatterSky world matrix.
MatrixF camMat = state - > getCameraTransform ( ) ;
camMat . inverse ( ) ;
MatrixF tmp ( true ) ;
tmp = camMat ;
tmp . setPosition ( Point3F ( 0 , 0 , 0 ) ) ;
Point3F sunPos ( 0 , 0 , 0 ) ;
// Get the light manager and sun light object.
LightInfo * sunLight = LIGHTMGR - > getSpecialLight ( LightManager : : slSunLightType ) ;
// Grab the light direction and scale
// by the ScatterSky radius to get the world
// space sun position.
const VectorF & lightDir = sunLight - > getDirection ( ) ;
Point3F lightPos ( lightDir . x * ( 6378.0f * 1000.0f ) ,
lightDir . y * ( 6378.0f * 1000.0f ) ,
lightDir . z * ( 6378.0f * 1000.0f ) ) ;
2015-07-14 03:51:17 +00:00
RectI viewPort = GFX - > getViewport ( ) ;
2012-09-19 15:15:01 +00:00
// Get the screen space sun position.
2015-07-14 03:51:17 +00:00
MathUtils : : mProjectWorldToScreen ( lightPos , & sunPos , viewPort , tmp , proj ) ;
2012-09-19 15:15:01 +00:00
// And normalize it to the 0 to 1 range.
2015-07-14 03:51:17 +00:00
sunPos . x - = ( F32 ) viewPort . point . x ;
sunPos . y - = ( F32 ) viewPort . point . y ;
sunPos . x / = ( F32 ) viewPort . extent . x ;
sunPos . y / = ( F32 ) viewPort . extent . y ;
2012-09-19 15:15:01 +00:00
mShaderConsts - > set ( mScreenSunPosSC , Point2F ( sunPos . x , sunPos . y ) ) ;
}
if ( mLightDirectionSC - > isValid ( ) )
{
LightInfo * sunLight = LIGHTMGR - > getSpecialLight ( LightManager : : slSunLightType ) ;
const VectorF & lightDir = sunLight - > getDirection ( ) ;
mShaderConsts - > set ( mLightDirectionSC , lightDir ) ;
}
if ( mCameraForwardSC - > isValid ( ) )
{
const MatrixF & camMat = state - > getCameraTransform ( ) ;
VectorF camFwd ( 0 , 0 , 0 ) ;
camMat . getColumn ( 1 , & camFwd ) ;
mShaderConsts - > set ( mCameraForwardSC , camFwd ) ;
}
if ( mInvCameraMatSC - > isValid ( ) )
{
MatrixF mat = state - > getCameraTransform ( ) ;
mat . inverse ( ) ;
mShaderConsts - > set ( mInvCameraMatSC , mat , mInvCameraMatSC - > getType ( ) ) ;
}
} // if ( state )
// Set EffectConsts - specified from script
// If our shader has reloaded since last frame we must mark all
// EffectConsts dirty so they will be reset.
if ( mShader - > getReloadKey ( ) ! = mShaderReloadKey )
{
mShaderReloadKey = mShader - > getReloadKey ( ) ;
EffectConstTable : : Iterator iter = mEffectConsts . begin ( ) ;
for ( ; iter ! = mEffectConsts . end ( ) ; iter + + )
2014-11-08 08:42:01 +00:00
{
2012-09-19 15:15:01 +00:00
iter - > value - > mDirty = true ;
2014-11-08 08:42:01 +00:00
iter - > value - > mHandle = NULL ;
}
2012-09-19 15:15:01 +00:00
}
// Doesn't look like anyone is using this anymore.
// But if we do want to pass this info to script,
// we should do so in the same way as I am doing below.
/*
Point2F texSizeScriptConst ( 0 , 0 ) ;
String buffer ;
if ( mActiveTextures [ 0 ] )
{
texSizeScriptConst . x = ( F32 ) mActiveTextures [ 0 ] - > getWidth ( ) ;
texSizeScriptConst . y = ( F32 ) mActiveTextures [ 0 ] - > getHeight ( ) ;
dSscanf ( buffer . c_str ( ) , " %g %g " , texSizeScriptConst . x , texSizeScriptConst . y ) ;
}
*/
{
PROFILE_SCOPE ( PostEffect_SetShaderConsts ) ;
// Pass some data about the current render state to script.
//
// TODO: This is pretty messy... it should go away. This info
// should be available from some other script accessible method
// or field which isn't PostEffect specific.
//
if ( state )
{
Con : : setFloatVariable ( " $Param::NearDist " , state - > getNearPlane ( ) ) ;
Con : : setFloatVariable ( " $Param::FarDist " , state - > getFarPlane ( ) ) ;
}
setShaderConsts_callback ( ) ;
}
EffectConstTable : : Iterator iter = mEffectConsts . begin ( ) ;
for ( ; iter ! = mEffectConsts . end ( ) ; iter + + )
iter - > value - > setToBuffer ( mShaderConsts ) ;
}
void PostEffect : : _setupTexture ( U32 stage , GFXTexHandle & inputTex , const RectI * inTexViewport )
{
2021-11-04 20:44:43 +00:00
const String & texFilename = getTexture ( stage ) ;
2012-09-19 15:15:01 +00:00
GFXTexHandle theTex ;
NamedTexTarget * namedTarget = NULL ;
RectI viewport = GFX - > getViewport ( ) ;
if ( texFilename . compare ( " $inTex " , 0 , String : : NoCase ) = = 0 )
{
theTex = inputTex ;
if ( inTexViewport )
{
viewport = * inTexViewport ;
}
else if ( theTex )
{
viewport . set ( 0 , 0 , theTex - > getWidth ( ) , theTex - > getHeight ( ) ) ;
}
}
else if ( texFilename . compare ( " $backBuffer " , 0 , String : : NoCase ) = = 0 )
{
theTex = PFXMGR - > getBackBufferTex ( ) ;
// Always use the GFX viewport when reading from the backbuffer
}
else if ( texFilename . isNotEmpty ( ) & & texFilename [ 0 ] = = ' # ' )
{
namedTarget = NamedTexTarget : : find ( texFilename . c_str ( ) + 1 ) ;
if ( namedTarget )
{
theTex = namedTarget - > getTexture ( 0 ) ;
viewport = namedTarget - > getViewport ( ) ;
}
}
else
{
2021-07-19 06:07:08 +00:00
theTex = mTexture [ stage ] ;
2012-09-19 15:15:01 +00:00
if ( theTex )
viewport . set ( 0 , 0 , theTex - > getWidth ( ) , theTex - > getHeight ( ) ) ;
}
mActiveTextures [ stage ] = theTex ;
mActiveNamedTarget [ stage ] = namedTarget ;
mActiveTextureViewport [ stage ] = viewport ;
if ( theTex . isValid ( ) )
GFX - > setTexture ( stage , theTex ) ;
}
2019-02-12 07:10:30 +00:00
void PostEffect : : _setupCubemapTexture ( U32 stage , GFXCubemapHandle & inputTex )
{
RectI viewport = GFX - > getViewport ( ) ;
mActiveTextures [ stage ] = nullptr ;
mActiveNamedTarget [ stage ] = nullptr ;
mActiveTextureViewport [ stage ] = viewport ;
if ( inputTex . isValid ( ) )
GFX - > setCubeTexture ( stage , inputTex ) ;
}
void PostEffect : : _setupCubemapArrayTexture ( U32 stage , GFXCubemapArrayHandle & inputTex )
{
RectI viewport = GFX - > getViewport ( ) ;
mActiveTextures [ stage ] = nullptr ;
mActiveNamedTarget [ stage ] = nullptr ;
mActiveTextureViewport [ stage ] = viewport ;
if ( inputTex . isValid ( ) )
GFX - > setCubeArrayTexture ( stage , inputTex ) ;
}
2012-09-19 15:15:01 +00:00
void PostEffect : : _setupTransforms ( )
{
// Set everything to identity.
GFX - > setWorldMatrix ( MatrixF : : Identity ) ;
GFX - > setProjectionMatrix ( MatrixF : : Identity ) ;
}
void PostEffect : : _setupTarget ( const SceneRenderState * state , bool * outClearTarget )
{
if ( mNamedTarget . isRegistered ( ) | |
mTargetName . compare ( " $outTex " , 0 , String : : NoCase ) = = 0 )
{
// 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 ] )
{
const Point3I & texSize = mActiveTextures [ 0 ] - > getSize ( ) ;
targetSize . set ( texSize . x * mTargetScale . x ,
texSize . y * mTargetScale . y ) ;
}
else
{
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 . isRegistered ( ) | |
! mTargetTex | |
mTargetTex . getWidthHeight ( ) ! = targetSize )
{
mTargetTex . set ( targetSize . x , targetSize . y , mTargetFormat ,
& PostFxTargetProfile , " PostEffect::_setupTarget " ) ;
if ( mTargetClear = = PFXTargetClear_OnCreate )
* outClearTarget = true ;
2013-10-24 04:28:13 +00:00
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 ) ) ;
2013-10-24 17:40:44 +00:00
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 ( ) ;
2013-10-24 04:28:13 +00:00
mNamedTarget . setViewport ( RectI ( viewport . point . x * scale . x , viewport . point . y * scale . y , viewport . extent . x * scale . x , viewport . extent . y * scale . y ) ) ;
}
else
{
// PFXTargetViewport_TargetSize
mNamedTarget . setViewport ( RectI ( 0 , 0 , targetSize . x , targetSize . y ) ) ;
}
2012-09-19 15:15:01 +00:00
}
}
else
mTargetTex = NULL ;
// Do we have a named depthStencil target?
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 ( ) )
targetSize = mTargetSize ;
// Else generate a relative size using the target scale.
else if ( mActiveTextures [ 0 ] )
{
const Point3I & texSize = mActiveTextures [ 0 ] - > getSize ( ) ;
targetSize . set ( texSize . x * mTargetScale . x ,
texSize . y * mTargetScale . y ) ;
}
else
{
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 ( mNamedTargetDepthStencil . isRegistered ( ) & &
mTargetDepthStencil . getWidthHeight ( ) ! = targetSize )
{
mTargetDepthStencil . set ( targetSize . x , targetSize . y , GFXFormatD24S8 ,
2017-06-23 16:36:20 +00:00
& GFXZTargetProfile , " PostEffect::_setupTarget " ) ;
2012-09-19 15:15:01 +00:00
if ( mTargetClear = = PFXTargetClear_OnCreate )
* outClearTarget = true ;
2013-10-24 04:28:13 +00:00
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 ) ) ;
2013-10-24 17:40:44 +00:00
const RectI & viewport = GFX - > getViewport ( ) ;
mNamedTargetDepthStencil . setViewport ( RectI ( viewport . point . x * scale . x , viewport . point . y * scale . y , viewport . extent . x * scale . x , viewport . extent . y * scale . y ) ) ;
}
else if ( mTargetViewport = = PFXTargetViewport_NamedInTexture0 & & mActiveNamedTarget [ 0 ] & & mActiveNamedTarget [ 0 ] - > getTexture ( ) )
{
// Scale the named input texture's viewport to match our target
const Point3I & namedTargetSize = mActiveNamedTarget [ 0 ] - > getTexture ( ) - > getSize ( ) ;
Point2F scale ( targetSize . x / F32 ( namedTargetSize . x ) , targetSize . y / F32 ( namedTargetSize . y ) ) ;
const RectI & viewport = mActiveNamedTarget [ 0 ] - > getViewport ( ) ;
2013-10-24 04:28:13 +00:00
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 ) ) ;
}
2012-09-19 15:15:01 +00:00
}
}
else
mTargetDepthStencil = NULL ;
if ( mTargetClear = = PFXTargetClear_OnDraw )
* outClearTarget = true ;
if ( ! mTarget & & ( mTargetTex | | mTargetDepthStencil ) )
mTarget = GFX - > allocRenderToTextureTarget ( ) ;
}
void PostEffect : : _cleanTargets ( bool recurse )
{
mTargetTex = NULL ;
mTargetDepthStencil = NULL ;
mTarget = NULL ;
if ( ! recurse )
return ;
// Clear the children too!
for ( U32 i = 0 ; i < size ( ) ; i + + )
{
PostEffect * effect = ( PostEffect * ) ( * this ) [ i ] ;
effect - > _cleanTargets ( true ) ;
}
}
void PostEffect : : process ( const SceneRenderState * state ,
GFXTexHandle & inOutTex ,
const RectI * inTexViewport )
{
// If the shader is forced to be skipped... then skip.
if ( mSkip )
return ;
// Skip out if we don't support reflection passes.
if ( state & & state - > isReflectPass ( ) & & ! mAllowReflectPass )
return ;
if ( mOneFrameOnly & & ! mOnThisFrame )
return ;
// Check requirements if the shader needs updating.
if ( mUpdateShader )
{
_checkRequirements ( ) ;
// Clear the targets if we failed passing
// the requirements at this time.
if ( ! mIsValid )
_cleanTargets ( true ) ;
}
// If we're not valid then we cannot render.
if ( ! mIsValid )
return ;
GFXDEBUGEVENT_SCOPE_EX ( PostEffect_Process , ColorI : : GREEN , avar ( " PostEffect: %s " , getName ( ) ) ) ;
preProcess_callback ( ) ;
GFXTransformSaver saver ;
// Set the textures.
2019-02-12 07:10:30 +00:00
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
if ( mTextureType [ i ] = = NormalTextureType )
_setupTexture ( i , inOutTex , inTexViewport ) ;
else if ( mTextureType [ i ] = = CubemapType )
_setupCubemapTexture ( i , mCubemapTextures [ i ] ) ;
else if ( mTextureType [ i ] = = CubemapArrayType )
_setupCubemapArrayTexture ( i , mCubemapArrayTextures [ i ] ) ;
}
2012-09-19 15:15:01 +00:00
_setupStateBlock ( state ) ;
_setupTransforms ( ) ;
bool clearTarget = false ;
_setupTarget ( state , & clearTarget ) ;
if ( mTargetTex | | mTargetDepthStencil )
{
2013-10-24 17:40:44 +00:00
const RectI & oldViewport = GFX - > getViewport ( ) ;
2013-10-24 04:28:13 +00:00
GFXTarget * oldTarget = GFX - > getActiveRenderTarget ( ) ;
2012-09-19 15:15:01 +00:00
GFX - > pushActiveRenderTarget ( ) ;
mTarget - > attachTexture ( GFXTextureTarget : : Color0 , mTargetTex ) ;
// Set the right depth stencil target.
if ( ! mTargetDepthStencil & & mTargetTex . getWidthHeight ( ) = = GFX - > getActiveRenderTarget ( ) - > getSize ( ) )
mTarget - > attachTexture ( GFXTextureTarget : : DepthStencil , GFXTextureTarget : : sDefaultDepthStencil ) ;
else
mTarget - > attachTexture ( GFXTextureTarget : : DepthStencil , mTargetDepthStencil ) ;
2013-10-24 17:40:44 +00:00
// Set the render target but not its viewport. We'll do that below.
GFX - > setActiveRenderTarget ( mTarget , false ) ;
2013-10-24 04:28:13 +00:00
if ( mNamedTarget . isRegistered ( ) )
{
2013-10-24 17:40:44 +00:00
// Always use the name target's viewport, if available. It was set up in _setupTarget().
2013-10-24 04:28:13 +00:00
GFX - > setViewport ( mNamedTarget . getViewport ( ) ) ;
}
else if ( mTargetViewport = = PFXTargetViewport_GFXViewport )
{
2013-10-24 17:40:44 +00:00
// Go with the current viewport as scaled against our render target.
2013-10-24 04:28:13 +00:00
const Point2I & oldTargetSize = oldTarget - > getSize ( ) ;
const Point2I & targetSize = mTarget - > getSize ( ) ;
Point2F scale ( targetSize . x / F32 ( oldTargetSize . x ) , targetSize . y / F32 ( oldTargetSize . y ) ) ;
GFX - > setViewport ( RectI ( oldViewport . point . x * scale . x , oldViewport . point . y * scale . y , oldViewport . extent . x * scale . x , oldViewport . extent . y * scale . y ) ) ;
}
2013-10-24 17:40:44 +00:00
else if ( mTargetViewport = = PFXTargetViewport_NamedInTexture0 & & mActiveNamedTarget [ 0 ] & & mActiveNamedTarget [ 0 ] - > getTexture ( ) )
{
// Go with the first input texture, if it is named. Scale the named input texture's viewport to match our target
const Point3I & namedTargetSize = mActiveNamedTarget [ 0 ] - > getTexture ( ) - > getSize ( ) ;
const Point2I & targetSize = mTarget - > getSize ( ) ;
Point2F scale ( targetSize . x / F32 ( namedTargetSize . x ) , targetSize . y / F32 ( namedTargetSize . y ) ) ;
const RectI & viewport = mActiveNamedTarget [ 0 ] - > getViewport ( ) ;
GFX - > setViewport ( RectI ( viewport . point . x * scale . x , viewport . point . y * scale . y , viewport . extent . x * scale . x , viewport . extent . y * scale . y ) ) ;
}
else
{
// Default to using the whole target as the viewport
GFX - > setViewport ( RectI ( Point2I : : Zero , mTarget - > getSize ( ) ) ) ;
}
2012-09-19 15:15:01 +00:00
}
if ( clearTarget )
GFX - > clear ( GFXClearTarget , mTargetClearColor , 1.f , 0 ) ;
// Setup the shader and constants.
if ( mShader )
{
2014-11-08 08:42:01 +00:00
GFX - > setShader ( mShader ) ;
2012-09-19 15:15:01 +00:00
_setupConstants ( state ) ;
GFX - > setShaderConstBuffer ( mShaderConsts ) ;
}
else
2014-04-13 15:55:02 +00:00
GFX - > setupGenericShaders ( ) ;
2012-09-19 15:15:01 +00:00
Frustum frustum ;
if ( state )
2013-11-07 20:07:16 +00:00
frustum = state - > getCameraFrustum ( ) ;
2012-09-19 15:15:01 +00:00
else
{
// If we don't have a scene state then setup
// a dummy frustum... you better not be depending
// on this being related to the camera in any way.
frustum = Frustum ( ) ;
}
GFXVertexBufferHandle < PFXVertex > vb ;
_updateScreenGeometry ( frustum , & vb ) ;
// Draw it.
GFX - > setVertexBuffer ( vb ) ;
2016-03-20 11:52:11 +00:00
GFX - > drawPrimitive ( GFXTriangleStrip , 0 , 2 ) ;
2012-09-19 15:15:01 +00:00
// Allow PostEffecVis to hook in.
PFXVIS - > onPFXProcessed ( this ) ;
if ( mTargetTex | | mTargetDepthStencil )
{
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 ;
// Restore the transforms before the children
// are processed as it screws up the viewport.
saver . restore ( ) ;
// Now process my children.
iterator i = begin ( ) ;
for ( ; i ! = end ( ) ; i + + )
{
PostEffect * effect = static_cast < PostEffect * > ( * i ) ;
effect - > process ( state , inOutTex ) ;
}
if ( mOneFrameOnly )
mOnThisFrame = false ;
}
bool PostEffect : : _setIsEnabled ( void * object , const char * index , const char * data )
{
bool enabled = dAtob ( data ) ;
if ( enabled )
static_cast < PostEffect * > ( object ) - > enable ( ) ;
else
static_cast < PostEffect * > ( object ) - > disable ( ) ;
// Always return false from a protected field.
return false ;
}
void PostEffect : : enable ( )
{
// Don't add TexGen PostEffects to the PostEffectManager!
if ( mRenderTime = = PFXTexGenOnDemand )
return ;
// Ignore it if its already enabled.
if ( mEnabled )
return ;
mEnabled = true ;
// We cannot really enable the effect
// until its been registed.
if ( ! isProperlyAdded ( ) )
return ;
// If the enable callback returns 'false' then
// leave the effect disabled.
if ( ! onEnabled_callback ( ) )
{
mEnabled = false ;
return ;
}
PFXMGR - > _addEffect ( this ) ;
}
void PostEffect : : disable ( )
{
if ( ! mEnabled )
return ;
mEnabled = false ;
_cleanTargets ( true ) ;
if ( isProperlyAdded ( ) )
{
PFXMGR - > _removeEffect ( this ) ;
onDisabled_callback ( ) ;
}
}
void PostEffect : : reload ( )
{
// Reload the shader if we have one or mark it
// for updating when its processed next.
if ( mShader )
mShader - > reload ( ) ;
else
mUpdateShader = true ;
// Null stateblock so it is reloaded.
mStateBlock = NULL ;
// Call reload on any children
// this PostEffect may have.
for ( U32 i = 0 ; i < size ( ) ; i + + )
{
PostEffect * effect = ( PostEffect * ) ( * this ) [ i ] ;
effect - > reload ( ) ;
}
}
void PostEffect : : setTexture ( U32 index , const String & texFilePath )
{
// Set the new texture name.
2021-07-19 06:07:08 +00:00
mTextureName [ index ] = texFilePath ;
mTexture [ index ] . free ( ) ;
2012-09-19 15:15:01 +00:00
// Skip empty stages or ones with variable or target names.
if ( texFilePath . isEmpty ( ) | |
texFilePath [ 0 ] = = ' $ ' | |
texFilePath [ 0 ] = = ' # ' )
return ;
2021-11-03 17:30:52 +00:00
mTextureProfile [ index ] = ( mTexSRGB [ index ] ) ? & PostFxTextureSRGBProfile : & PostFxTextureProfile ;
_setTexture ( texFilePath , index ) ;
2019-02-12 07:10:30 +00:00
mTextureType [ index ] = NormalTextureType ;
}
2019-06-03 07:47:30 +00:00
void PostEffect : : setTexture ( U32 index , const GFXTexHandle & texHandle )
{
// Set the new texture name.
2021-11-16 18:40:22 +00:00
mTextureName [ index ] = StringTable - > EmptyString ( ) ;
2021-07-19 06:07:08 +00:00
mTexture [ index ] . free ( ) ;
2019-06-03 07:47:30 +00:00
// Skip empty stages or ones with variable or target names.
if ( ! texHandle . isValid ( ) )
return ;
// Try to load the texture.
2021-07-19 06:07:08 +00:00
mTexture [ index ] = texHandle ;
2019-06-03 07:47:30 +00:00
mTextureType [ index ] = NormalTextureType ;
}
2019-02-12 07:10:30 +00:00
void PostEffect : : setCubemapTexture ( U32 index , const GFXCubemapHandle & cubemapHandle )
{
// Set the new texture name.
mCubemapTextures [ index ] . free ( ) ;
// Skip empty stages or ones with variable or target names.
if ( cubemapHandle . isNull ( ) )
return ;
// Try to load the texture.
mCubemapTextures [ index ] = cubemapHandle ;
mTextureType [ index ] = CubemapType ;
}
void PostEffect : : setCubemapArrayTexture ( U32 index , const GFXCubemapArrayHandle & cubemapArrayHandle )
{
// Set the new texture name.
mCubemapArrayTextures [ index ] . free ( ) ;
// Skip empty stages or ones with variable or target names.
if ( cubemapArrayHandle . isNull ( ) )
return ;
// Try to load the texture.
mCubemapArrayTextures [ index ] = cubemapArrayHandle ;
mTextureType [ index ] = CubemapArrayType ;
2012-09-19 15:15:01 +00:00
}
void PostEffect : : setShaderConst ( const String & name , const String & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
2019-02-12 07:10:30 +00:00
void PostEffect : : setShaderConst ( const String & name , const F32 & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst_Float ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
2019-06-13 05:37:12 +00:00
void PostEffect : : setShaderConst ( const String & name , const int & val )
{
2019-06-17 07:30:45 +00:00
PROFILE_SCOPE ( PostEffect_SetShaderConst_Int ) ;
2019-06-13 05:37:12 +00:00
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
2019-02-12 07:10:30 +00:00
void PostEffect : : setShaderConst ( const String & name , const Point4F & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst_Point ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
void PostEffect : : setShaderConst ( const String & name , const MatrixF & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst_Matrix ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
void PostEffect : : setShaderConst ( const String & name , const Vector < Point4F > & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst_PointArray ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
void PostEffect : : setShaderConst ( const String & name , const Vector < MatrixF > & val )
{
PROFILE_SCOPE ( PostEffect_SetShaderConst_MatrixArray ) ;
EffectConstTable : : Iterator iter = mEffectConsts . find ( name ) ;
if ( iter = = mEffectConsts . end ( ) )
{
EffectConst * newConst = new EffectConst ( name , val ) ;
iter = mEffectConsts . insertUnique ( name , newConst ) ;
}
iter - > value - > set ( val ) ;
}
2012-09-19 15:15:01 +00:00
F32 PostEffect : : getAspectRatio ( ) const
{
const Point2I & rtSize = GFX - > getActiveRenderTarget ( ) - > getSize ( ) ;
return ( F32 ) rtSize . x / ( F32 ) rtSize . y ;
}
void PostEffect : : _checkRequirements ( )
{
// This meets requirements if its shader loads
// properly, we can find all the input textures,
// and its formats are supported.
mIsValid = false ;
mUpdateShader = false ;
mShader = NULL ;
2014-11-08 08:42:01 +00:00
mShaderConsts = NULL ;
EffectConstTable : : Iterator iter = mEffectConsts . begin ( ) ;
for ( ; iter ! = mEffectConsts . end ( ) ; iter + + )
{
iter - > value - > mDirty = true ;
iter - > value - > mHandle = NULL ;
}
2012-09-19 15:15:01 +00:00
// First make sure the target format is supported.
if ( mNamedTarget . isRegistered ( ) )
{
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 ;
}
// Gather macros specified on this PostEffect.
Vector < GFXShaderMacro > macros ( mShaderMacros ) ;
// Now check the input named targets and make sure
// they exist... else we're invalid.
for ( U32 i = 0 ; i < NumTextures ; i + + )
{
2019-02-12 07:10:30 +00:00
if ( mTextureType [ i ] = = NormalTextureType )
2012-09-19 15:15:01 +00:00
{
2021-07-19 06:07:08 +00:00
const String & texFilename = mTextureName [ i ] ;
2019-02-12 07:10:30 +00:00
if ( texFilename . isNotEmpty ( ) & & texFilename [ 0 ] = = ' # ' )
2019-02-11 06:17:53 +00:00
{
2019-02-12 07:10:30 +00:00
NamedTexTarget * namedTarget = NamedTexTarget : : find ( texFilename . c_str ( ) + 1 ) ;
if ( ! namedTarget )
{
return ;
}
// Grab the macros for shader initialization.
namedTarget - > getShaderMacros ( & macros ) ;
2019-02-11 06:17:53 +00:00
}
2012-09-19 15:15:01 +00:00
}
}
// Finally find and load the shader.
ShaderData * shaderData ;
if ( Sim : : findObject ( mShaderName , shaderData ) )
if ( shaderData - > getPixVersion ( ) < = GFX - > getPixelShaderVersion ( ) )
mShader = shaderData - > getShader ( macros ) ;
// If we didn't get a shader... we're done.
if ( ! mShader )
return ;
// If we got here then we're valid.
mIsValid = true ;
}
bool PostEffect : : dumpShaderDisassembly ( String & outFilename ) const
{
String data ;
if ( ! mShader | | ! mShader - > getDisassembly ( data ) )
return false ;
outFilename = FS : : MakeUniquePath ( " " , " ShaderDisassembly " , " txt " ) ;
FileStream * fstream = FileStream : : createAndOpen ( outFilename , Torque : : FS : : File : : Write ) ;
if ( ! fstream )
return false ;
fstream - > write ( data ) ;
fstream - > close ( ) ;
delete fstream ;
return true ;
}
SimSet * PostEffect : : getSet ( ) const
{
SimSet * set ;
if ( ! Sim : : findObject ( " PFXSet " , set ) )
{
set = new SimSet ( ) ;
set - > registerObject ( " PFXSet " ) ;
Sim : : getRootGroup ( ) - > addObject ( set ) ;
}
return set ;
}
void PostEffect : : setShaderMacro ( const String & name , const String & value )
{
// Check to see if we already have this macro.
Vector < GFXShaderMacro > : : iterator iter = mShaderMacros . begin ( ) ;
for ( ; iter ! = mShaderMacros . end ( ) ; iter + + )
{
if ( iter - > name = = name )
{
if ( iter - > value ! = value )
{
iter - > value = value ;
mUpdateShader = true ;
}
return ;
}
}
// Add a new macro.
mShaderMacros . increment ( ) ;
mShaderMacros . last ( ) . name = name ;
mShaderMacros . last ( ) . value = value ;
mUpdateShader = true ;
}
bool PostEffect : : removeShaderMacro ( const String & name )
{
Vector < GFXShaderMacro > : : iterator iter = mShaderMacros . begin ( ) ;
for ( ; iter ! = mShaderMacros . end ( ) ; iter + + )
{
if ( iter - > name = = name )
{
mShaderMacros . erase ( iter ) ;
mUpdateShader = true ;
return true ;
}
}
return false ;
}
void PostEffect : : clearShaderMacros ( )
{
if ( mShaderMacros . empty ( ) )
return ;
mShaderMacros . clear ( ) ;
mUpdateShader = true ;
}
GFXTextureObject * PostEffect : : _getTargetTexture ( U32 )
{
// A TexGen PostEffect will generate its texture now if it
// has not already.
if ( mRenderTime = = PFXTexGenOnDemand & &
( ! mTargetTex | | mUpdateShader ) )
{
GFXTexHandle chainTex ;
process ( NULL , chainTex ) ;
// TODO: We should add a conditional copy
// to a non-RT texture here to reduce the
// amount of non-swappable RTs in use.
}
return mTargetTex . getPointer ( ) ;
}
DefineEngineMethod ( PostEffect , reload , void , ( ) , ,
" Reloads the effect shader and textures. " )
{
return object - > reload ( ) ;
}
DefineEngineMethod ( PostEffect , enable , void , ( ) , ,
" Enables the effect. " )
{
object - > enable ( ) ;
}
DefineEngineMethod ( PostEffect , disable , void , ( ) , ,
" Disables the effect. " )
{
object - > disable ( ) ;
}
DefineEngineMethod ( PostEffect , toggle , bool , ( ) , ,
" Toggles the effect between enabled / disabled. \n "
" @return True if effect is enabled. " )
{
if ( object - > isEnabled ( ) )
object - > disable ( ) ;
else
object - > enable ( ) ;
return object - > isEnabled ( ) ;
}
DefineEngineMethod ( PostEffect , isEnabled , bool , ( ) , ,
" @return True if the effect is enabled. " )
{
return object - > isEnabled ( ) ;
}
DefineEngineMethod ( PostEffect , setTexture , void , ( S32 index , const char * filePath ) , ,
" This is used to set the texture file and load the texture on a running effect. "
" If the texture file is not different from the current file nothing is changed. If "
" the texture cannot be found a null texture is assigned. \n "
" @param index The texture stage index. \n "
" @param filePath The file name of the texture to set. \n " )
{
if ( index > - 1 & & index < PostEffect : : NumTextures )
object - > setTexture ( index , filePath ) ;
}
DefineEngineMethod ( PostEffect , setShaderConst , void , ( const char * name , const char * value ) , ,
" Sets the value of a uniform defined in the shader. This will usually "
" be called within the setShaderConsts callback. Array type constants are "
" not supported. \n "
" @param name Name of the constanst, prefixed with '$'. \n "
" @param value Value to set, space seperate values with more than one element. \n "
" @tsexample \n "
" function MyPfx::setShaderConsts( %this ) \n "
" { \n "
" // example float4 uniform \n "
" %this.setShaderConst( \" $colorMod \" , \" 1.0 0.9 1.0 1.0 \" ); \n "
" // example float1 uniform \n "
" %this.setShaderConst( \" $strength \" , \" 3.0 \" ); \n "
" // example integer uniform \n "
" %this.setShaderConst( \" $loops \" , \" 5 \" ); "
" } \n "
" @endtsexample " )
{
object - > setShaderConst ( name , value ) ;
}
DefineEngineMethod ( PostEffect , getAspectRatio , F32 , ( ) , ,
" @return Width over height of the backbuffer. " )
{
return object - > getAspectRatio ( ) ;
}
DefineEngineMethod ( PostEffect , dumpShaderDisassembly , String , ( ) , ,
" Dumps this PostEffect shader's disassembly to a temporary text file. \n "
" @return Full path to the dumped file or an empty string if failed. " )
{
String fileName ;
object - > dumpShaderDisassembly ( fileName ) ;
return fileName ;
}
DefineEngineMethod ( PostEffect , setShaderMacro , void , ( const char * key , const char * value ) , ( " " ) ,
" Adds a macro to the effect's shader or sets an existing one's value. "
" This will usually be called within the onAdd or preProcess callback. \n "
" @param key lval of the macro. "
" @param value rval of the macro, or may be empty. "
" @tsexample \n "
" function MyPfx::onAdd( %this ) \n "
" { \n "
" %this.setShaderMacro( \" NUM_SAMPLES \" , \" 10 \" ); \n "
" %this.setShaderMacro( \" HIGH_QUALITY_MODE \" ); \n "
" \n "
" // In the shader looks like... \n "
" // #define NUM_SAMPLES 10 \n "
" // #define HIGH_QUALITY_MODE \n "
" } \n "
" @endtsexample " )
{
object - > setShaderMacro ( key , value ) ;
}
DefineEngineMethod ( PostEffect , removeShaderMacro , void , ( const char * key ) , ,
" Remove a shader macro. This will usually be called within the preProcess callback. \n "
" @param key Macro to remove. " )
{
object - > removeShaderMacro ( key ) ;
}
DefineEngineMethod ( PostEffect , clearShaderMacros , void , ( ) , ,
" Remove all shader macros. " )
{
object - > clearShaderMacros ( ) ;
}
DefineEngineFunction ( dumpRandomNormalMap , void , ( ) , ,
" Creates a 64x64 normal map texture filled with noise. The texture is saved "
" to randNormTex.png in the location of the game executable. \n \n "
" @ingroup GFX " )
{
GFXTexHandle tex ;
2017-06-23 16:36:20 +00:00
tex . set ( 64 , 64 , GFXFormatR8G8B8A8 , & GFXTexturePersistentProfile , " " ) ;
2012-09-19 15:15:01 +00:00
GFXLockedRect * rect = tex . lock ( ) ;
U8 * f = rect - > bits ;
for ( U32 i = 0 ; i < 64 * 64 ; i + + , f + = 4 )
{
VectorF vec ;
vec . x = mRandF ( - 1.0f , 1.0f ) ;
vec . y = mRandF ( - 1.0f , 1.0f ) ;
vec . z = mRandF ( - 1.0f , 1.0f ) ;
vec . normalizeSafe ( ) ;
f [ 0 ] = U8_MAX * ( ( 1.0f + vec . x ) * 0.5f ) ;
f [ 1 ] = U8_MAX * ( ( 1.0f + vec . y ) * 0.5f ) ;
f [ 2 ] = U8_MAX * ( ( 1.0f + vec . z ) * 0.5f ) ;
f [ 3 ] = U8_MAX ;
}
tex . unlock ( ) ;
String path = Torque : : FS : : MakeUniquePath ( " " , " randNormTex " , " png " ) ;
tex - > dumpToDisk ( " png " , path ) ;
2019-06-03 07:47:30 +00:00
}