postEffect.cpp
Engine/source/postFx/postEffect.cpp
Public Variables
Public Functions
ConsoleDocClass(PostEffect , "@brief A fullscreen shader <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effect.\n\n</a>" "@section <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PFXTextureIdentifiers\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n</a>" )
DefineEngineFunction(dumpRandomNormalMap , void , () , "Creates <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 64x64 normal map texture filled with noise. The texture is saved " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> randNormTex.png in the location of the game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">executable.\n\n</a>" "@ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )
DefineEngineMethod(PostEffect , clearShaderMacros , void , () , "Remove all shader macros." )
DefineEngineMethod(PostEffect , disable , void , () , "Disables the effect." )
DefineEngineMethod(PostEffect , dumpShaderDisassembly , String , () , "Dumps this <a href="/coding/class/classposteffect/">PostEffect</a> shader's disassembly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> temporary text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n</a>" "@return Full path <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the dumped <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> or an empty string <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> failed." )
DefineEngineMethod(PostEffect , enable , void , () , "Enables the effect." )
DefineEngineMethod(PostEffect , getAspectRatio , F32 , () , "@return Width over height of the backbuffer." )
DefineEngineMethod(PostEffect , isEnabled , bool , () , "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the effect is enabled." )
DefineEngineMethod(PostEffect , reload , void , () , "Reloads the effect shader and textures." )
DefineEngineMethod(PostEffect , removeShaderMacro , void , (const char *key) , "Remove <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> shader macro. This will usually be called within the preProcess <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback.\n</a>" "@param key Macro <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove." )
DefineEngineMethod(PostEffect , setShaderConst , void , (const char *name, const char *value) , "Sets the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> uniform defined in the shader. This will usually " "be called within the setShaderConsts callback. <a href="/coding/file/platformmemory_8cpp/#platformmemory_8cpp_1a3ffd6d180bfa999dfbafef07fab77f2caf8303e03242532eebd970f40ee509689">Array</a> type constants are " "not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">supported.\n</a>" "@param name Name of the constanst, prefixed with '$'.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set, space seperate values with more than one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">element.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function MyPfx::setShaderConsts(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//example float4 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst(\"$colorMod\", \"1.0 0.9 1.0 1.0\" );\n" " // example float1 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst( \"$strength\", \"3.0\" );\n" " // example integer <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst( \"$loops\", \"5\" );" "}\n" "@endtsexample" )
DefineEngineMethod(PostEffect , setShaderMacro , void , (const char *key, const char *value) , ("") , "Adds <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> macro <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the effect's shader or sets an existing one's value. " "This will usually be called within the onAdd or preProcess <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback.\n</a>" "@param key lval of the macro." "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> rval of the macro, or may be empty." " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function MyPfx::onAdd(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.setShaderMacro(\"NUM_SAMPLES\", \"10\" );\n" " %this.setShaderMacro( \"HIGH_QUALITY_MODE\" );\n" " \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // In the shader looks like... \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // #define NUM_SAMPLES 10\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // #define <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">HIGH_QUALITY_MODE\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@endtsexample" )
DefineEngineMethod(PostEffect , setTexture , void , (S32 index, const char *filePath) , "This is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the texture <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and load the texture on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> running effect. " "If the texture <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is not different from the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> nothing is changed. If " "the texture cannot be found <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> null texture is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assigned.\n</a>" "@param index The texture stage <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param filePath The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name of the texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" )
DefineEngineMethod(PostEffect , toggle , bool , () , "Toggles the effect between enabled / <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> effect is enabled." )
GFX_ImplementTextureProfile(PostFxTargetProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(PostFxTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82dac429cfe8dbe343378e106bc721fc96c8">GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(PostFxTextureSRGBProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82dac429cfe8dbe343378e106bc721fc96c8">GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf6773a6da8ddf28520016603401b8f23">GFXTextureProfile::SRGB , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(VRDepthProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa3a2027753aec009ced4f0818a231296">GFXTextureProfile::ZTarget , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(VRTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GFXImplementVertexFormat(PFXVertex )
IMPLEMENT_CALLBACK(PostEffect , onAdd , void , () , () , "Called when this object is first created and registered." )
IMPLEMENT_CALLBACK(PostEffect , onDisabled , void , () , () , "Called when this effect becomes disabled." )
IMPLEMENT_CALLBACK(PostEffect , onEnabled , bool , () , () , "Called when this effect becomes enabled. If the user returns false from " "this callback the effect will not be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enabled.\n</a>" "@return True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow this effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be enabled." )
IMPLEMENT_CALLBACK(PostEffect , preProcess , void , () , () , "Called when an effect is processed but before textures are bound. This " "allows the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change texture related paramaters or macros at <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">runtime.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function SSAOPostFx::preProcess( %this )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> ( $SSAOPostFx::quality !$= %this.quality )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.quality = <a href="/coding/file/mmathfn_8h/#mmathfn_8h_1a65728120acb10c58cf049e176e3b0011">mClamp</a>( <a href="/coding/file/mmathfn_8h/#mmathfn_8h_1abef53d0a7c27cf32f96fba1d65e25fed">mRound</a>( $SSAOPostFx::quality ), 0, 2 );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.setShaderMacro( \"QUALITY\", %this.quality );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.targetScale = $SSAOPostFx::targetScale;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setShaderConst\n</a>" "@see setShaderMacro" )
IMPLEMENT_CALLBACK(PostEffect , setShaderConsts , void , () , () , "Called immediate before processing this effect. This is the user's chance " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of shader uniforms (constants).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@see setShaderConst" )
ImplementEnumType(PFXRenderTime , "When <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process this effect during the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">frame.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
ImplementEnumType(PFXTargetClear , "Describes when the target texture should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cleared\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
ImplementEnumType(PFXTargetViewport , "Specifies how the viewport should be set up <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classposteffect/">PostEffect</a>'s <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">target.\n</a>" "@note Applies <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> both the diffuse target and the depth target (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> defined).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
Detailed Description
Public Variables
EndImplementEnumType
Public Functions
ConsoleDocClass(PostEffect , "@brief A fullscreen shader <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">effect.\n\n</a>" "@section <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">PFXTextureIdentifiers\n\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n</a>" )
DefineEngineFunction(dumpRandomNormalMap , void , () , "Creates <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> 64x64 normal map texture filled with noise. The texture is saved " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> randNormTex.png in the location of the game <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">executable.\n\n</a>" "@ingroup <a href="/coding/file/gfxdevice_8h/#gfxdevice_8h_1afd23debb5edac4f53e564f02e6964c62">GFX</a>" )
DefineEngineMethod(PostEffect , clearShaderMacros , void , () , "Remove all shader macros." )
DefineEngineMethod(PostEffect , disable , void , () , "Disables the effect." )
DefineEngineMethod(PostEffect , dumpShaderDisassembly , String , () , "Dumps this <a href="/coding/class/classposteffect/">PostEffect</a> shader's disassembly <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> temporary text <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">file.\n</a>" "@return Full path <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the dumped <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> or an empty string <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> failed." )
DefineEngineMethod(PostEffect , enable , void , () , "Enables the effect." )
DefineEngineMethod(PostEffect , getAspectRatio , F32 , () , "@return Width over height of the backbuffer." )
DefineEngineMethod(PostEffect , isEnabled , bool , () , "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> the effect is enabled." )
DefineEngineMethod(PostEffect , reload , void , () , "Reloads the effect shader and textures." )
DefineEngineMethod(PostEffect , removeShaderMacro , void , (const char *key) , "Remove <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> shader macro. This will usually be called within the preProcess <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback.\n</a>" "@param key Macro <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> remove." )
DefineEngineMethod(PostEffect , setShaderConst , void , (const char *name, const char *value) , "Sets the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> uniform defined in the shader. This will usually " "be called within the setShaderConsts callback. <a href="/coding/file/platformmemory_8cpp/#platformmemory_8cpp_1a3ffd6d180bfa999dfbafef07fab77f2caf8303e03242532eebd970f40ee509689">Array</a> type constants are " "not <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">supported.\n</a>" "@param name Name of the constanst, prefixed with '$'.\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " @param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> <a href="/coding/file/document_8h/#document_8h_1a071cf97155ba72ac9a1fc4ad7e63d481">Value</a> <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set, space seperate values with more than one <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">element.\n</a>" " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function MyPfx::setShaderConsts(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "//example float4 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst(\"$colorMod\", \"1.0 0.9 1.0 1.0\" );\n" " // example float1 <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst( \"$strength\", \"3.0\" );\n" " // example integer <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">uniform\n</a>" " %this.setShaderConst( \"$loops\", \"5\" );" "}\n" "@endtsexample" )
DefineEngineMethod(PostEffect , setShaderMacro , void , (const char *key, const char *value) , ("") , "Adds <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> macro <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> the effect's shader or sets an existing one's value. " "This will usually be called within the onAdd or preProcess <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">callback.\n</a>" "@param key lval of the macro." "@param <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> rval of the macro, or may be empty." " @<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function MyPfx::onAdd(%this)\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.setShaderMacro(\"NUM_SAMPLES\", \"10\" );\n" " %this.setShaderMacro( \"HIGH_QUALITY_MODE\" );\n" " \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // In the shader looks like... \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // #define NUM_SAMPLES 10\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " // #define <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">HIGH_QUALITY_MODE\n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@endtsexample" )
DefineEngineMethod(PostEffect , setTexture , void , (S32 index, const char *filePath) , "This is used <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the texture <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> and load the texture on <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> running effect. " "If the texture <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> is not different from the current <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> nothing is changed. If " "the texture cannot be found <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> null texture is <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">assigned.\n</a>" "@param index The texture stage <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">index.\n</a>" "@param filePath The <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a702945180aa732857b380a007a7e2a21">file</a> name of the texture <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">set.\n</a>" )
DefineEngineMethod(PostEffect , toggle , bool , () , "Toggles the effect between enabled / <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">disabled.\n</a>" "@return True <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> effect is enabled." )
GFX_ImplementTextureProfile(PostFxTargetProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da8e64fa44eaa9b6444614dac7bdb1dcf8">GFXTextureProfile::Pooled , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(PostFxTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82dac429cfe8dbe343378e106bc721fc96c8">GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(PostFxTextureSRGBProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::Static</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82dac429cfe8dbe343378e106bc721fc96c8">GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf6773a6da8ddf28520016603401b8f23">GFXTextureProfile::SRGB , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(VRDepthProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daa3a2027753aec009ced4f0818a231296">GFXTextureProfile::ZTarget , GFXTextureProfile::NONE )
GFX_ImplementTextureProfile(VRTextureProfile , GFXTextureProfile::DiffuseMap , GFXTextureProfile::PreserveSize</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82da75302d480adb239daa0dd3fec9fd7a0b">GFXTextureProfile::RenderTarget</a>|<a href="/coding/class/classgfxtextureprofile/#classgfxtextureprofile_1a09105f0bf717a1f2ae49ceda21b8e82daf55b13e32bd1a1746406b68ead73ba05">GFXTextureProfile::NoMipmap , GFXTextureProfile::NONE )
GFXImplementVertexFormat(PFXVertex )
IMPLEMENT_CALLBACK(PostEffect , onAdd , void , () , () , "Called when this object is first created and registered." )
IMPLEMENT_CALLBACK(PostEffect , onDisabled , void , () , () , "Called when this effect becomes disabled." )
IMPLEMENT_CALLBACK(PostEffect , onEnabled , bool , () , () , "Called when this effect becomes enabled. If the user returns false from " "this callback the effect will not be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">enabled.\n</a>" "@return True <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> allow this effect <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> be enabled." )
IMPLEMENT_CALLBACK(PostEffect , preProcess , void , () , () , "Called when an effect is processed but before textures are bound. This " "allows the user <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> change texture related paramaters or macros at <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">runtime.\n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">tsexample\n</a>" "function SSAOPostFx::preProcess( %this )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "{\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " <a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> ( $SSAOPostFx::quality !$= %this.quality )\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " {\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.quality = <a href="/coding/file/mmathfn_8h/#mmathfn_8h_1a65728120acb10c58cf049e176e3b0011">mClamp</a>( <a href="/coding/file/mmathfn_8h/#mmathfn_8h_1abef53d0a7c27cf32f96fba1d65e25fed">mRound</a>( $SSAOPostFx::quality ), 0, 2 );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " \<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.setShaderMacro( \"QUALITY\", %this.quality );\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " }\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" " %this.targetScale = $SSAOPostFx::targetScale;\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "}\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">endtsexample\n</a>" "@see <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">setShaderConst\n</a>" "@see setShaderMacro" )
IMPLEMENT_CALLBACK(PostEffect , setShaderConsts , void , () , () , "Called immediate before processing this effect. This is the user's chance " "<a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> set the <a href="/coding/file/pointer_8h/#pointer_8h_1a32aff7c6c4cd253fdf6563677afab5ce">value</a> of shader uniforms (constants).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@see setShaderConst" )
IMPLEMENT_CONOBJECT(PostEffect )
ImplementEnumType(PFXRenderTime , "When <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> process this effect during the <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">frame.\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
ImplementEnumType(PFXTargetClear , "Describes when the target texture should be <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">cleared\n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
ImplementEnumType(PFXTargetViewport , "Specifies how the viewport should be set up <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1a2732ab74fa0237854c2ba0f75f88a624">for</a> <a href="/coding/file/pointer_8h/#pointer_8h_1aeeddce917cf130d62c370b8f216026dd">a</a> <a href="/coding/class/classposteffect/">PostEffect</a>'s <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">target.\n</a>" "@note Applies <a href="/coding/file/cmdgram_8cpp/#cmdgram_8cpp_1a5bafda9519252aa2d0fd038153f77dca">to</a> both the diffuse target and the depth target (<a href="/coding/file/tsmeshintrinsics_8cpp/#tsmeshintrinsics_8cpp_1a4e4fa7e3399708e0777b5308db01278c">if</a> defined).\<a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">n</a>" "@ingroup <a href="/coding/file/cmdscan_8cpp/#cmdscan_8cpp_1aeab71244afb687f16d8c4f5ee9d6ef0e">Rendering\n\n</a>" )
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "postFx/postEffect.h" 26 27#include "console/engineAPI.h" 28#include "core/stream/fileStream.h" 29#include "core/strings/stringUnit.h" 30#include "console/consoleTypes.h" 31#include "console/engineAPI.h" 32#include "math/util/frustum.h" 33#include "math/mathUtils.h" 34#include "gfx/gfxTransformSaver.h" 35#include "gfx/gfxStringEnumTranslate.h" 36#include "gfx/gfxTextureManager.h" 37#include "gfx/gfxDebugEvent.h" 38#include "gfx/util/screenspace.h" 39#include "gfx/sim/gfxStateBlockData.h" 40#include "scene/sceneRenderState.h" 41#include "shaderGen/shaderGenVars.h" 42#include "lighting/lightInfo.h" 43#include "lighting/lightManager.h" 44#include "materials/materialManager.h" 45#include "materials/shaderData.h" 46#include "postFx/postEffectManager.h" 47#include "postFx/postEffectVis.h" 48 49using namespace Torque; 50 51ConsoleDocClass( PostEffect, 52 "@brief A fullscreen shader effect.\n\n" 53 54 "@section PFXTextureIdentifiers\n\n" 55 56 "@ingroup Rendering\n" 57); 58 59IMPLEMENT_CALLBACK( PostEffect, onAdd, void, (), (), 60 "Called when this object is first created and registered." 61); 62 63IMPLEMENT_CALLBACK( PostEffect, preProcess, void, (), (), 64 "Called when an effect is processed but before textures are bound. This " 65 "allows the user to change texture related paramaters or macros at runtime.\n" 66 "@tsexample\n" 67 "function SSAOPostFx::preProcess( %this )\n" 68 "{\n" 69 " if ( $SSAOPostFx::quality !$= %this.quality )\n" 70 " {\n" 71 " %this.quality = mClamp( mRound( $SSAOPostFx::quality ), 0, 2 );\n" 72 " \n" 73 " %this.setShaderMacro( \"QUALITY\", %this.quality );\n" 74 " }\n" 75 " %this.targetScale = $SSAOPostFx::targetScale;\n" 76 "}\n" 77 "@endtsexample\n" 78 "@see setShaderConst\n" 79 "@see setShaderMacro" 80); 81 82IMPLEMENT_CALLBACK( PostEffect, setShaderConsts, void, (), (), 83 "Called immediate before processing this effect. This is the user's chance " 84 "to set the value of shader uniforms (constants).\n" 85 "@see setShaderConst" 86); 87 88IMPLEMENT_CALLBACK( PostEffect, onEnabled, bool, (), (), 89 "Called when this effect becomes enabled. If the user returns false from " 90 "this callback the effect will not be enabled.\n" 91 "@return True to allow this effect to be enabled." 92); 93 94IMPLEMENT_CALLBACK( PostEffect, onDisabled, void, (), (), 95 "Called when this effect becomes disabled." 96); 97 98ImplementEnumType( PFXRenderTime, 99 "When to process this effect during the frame.\n" 100 "@ingroup Rendering\n\n") 101 { PFXBeforeBin, "PFXBeforeBin", "Before a RenderInstManager bin.\n" }, 102 { PFXAfterBin, "PFXAfterBin", "After a RenderInstManager bin.\n" }, 103 { PFXAfterDiffuse, "PFXAfterDiffuse", "After the diffuse rendering pass.\n" }, 104 { PFXEndOfFrame, "PFXEndOfFrame", "When the end of the frame is reached.\n" }, 105 { PFXTexGenOnDemand, "PFXTexGenOnDemand", "This PostEffect is not processed by the manager. It will generate its texture when it is requested.\n" } 106EndImplementEnumType; 107 108ImplementEnumType( PFXTargetClear, 109 "Describes when the target texture should be cleared\n" 110 "@ingroup Rendering\n\n") 111 { PFXTargetClear_None, "PFXTargetClear_None", "Never clear the PostEffect target.\n" }, 112 { PFXTargetClear_OnCreate, "PFXTargetClear_OnCreate", "Clear once on create.\n" }, 113 { PFXTargetClear_OnDraw, "PFXTargetClear_OnDraw", "Clear before every draw.\n" }, 114EndImplementEnumType; 115 116ImplementEnumType( PFXTargetViewport, 117 "Specifies how the viewport should be set up for a PostEffect's target.\n" 118 "@note Applies to both the diffuse target and the depth target (if defined).\n" 119 "@ingroup Rendering\n\n") 120 { PFXTargetViewport_TargetSize, "PFXTargetViewport_TargetSize", "Set viewport to match target size (default).\n" }, 121 { PFXTargetViewport_GFXViewport, "PFXTargetViewport_GFXViewport", "Use the current GFX viewport (scaled to match target size).\n" }, 122 { 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" }, 123EndImplementEnumType; 124 125 126GFXImplementVertexFormat( PFXVertex ) 127{ 128 addElement( "POSITION", GFXDeclType_Float3 ); 129 addElement( "TEXCOORD", GFXDeclType_Float2, 0 ); 130 addElement( "TEXCOORD", GFXDeclType_Float3, 1 ); 131}; 132 133GFX_ImplementTextureProfile( PostFxTargetProfile, 134 GFXTextureProfile::DiffuseMap, 135 GFXTextureProfile::PreserveSize | 136 GFXTextureProfile::RenderTarget | 137 GFXTextureProfile::Pooled, 138 GFXTextureProfile::NONE ); 139 140IMPLEMENT_CONOBJECT(PostEffect); 141 142 143GFX_ImplementTextureProfile( PostFxTextureProfile, 144 GFXTextureProfile::DiffuseMap, 145 GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap, 146 GFXTextureProfile::NONE ); 147 148GFX_ImplementTextureProfile( PostFxTextureSRGBProfile, 149 GFXTextureProfile::DiffuseMap, 150 GFXTextureProfile::Static | GFXTextureProfile::PreserveSize | GFXTextureProfile::NoMipmap | GFXTextureProfile::SRGB, 151 GFXTextureProfile::NONE); 152 153GFX_ImplementTextureProfile( VRTextureProfile, 154 GFXTextureProfile::DiffuseMap, 155 GFXTextureProfile::PreserveSize | 156 GFXTextureProfile::RenderTarget | 157 GFXTextureProfile::NoMipmap, 158 GFXTextureProfile::NONE ); 159 160GFX_ImplementTextureProfile( VRDepthProfile, 161 GFXTextureProfile::DiffuseMap, 162 GFXTextureProfile::PreserveSize | 163 GFXTextureProfile::NoMipmap | 164 GFXTextureProfile::ZTarget, 165 GFXTextureProfile::NONE ); 166 167void PostEffect::EffectConst::set( const String &newVal ) 168{ 169 if ( mStringVal == newVal ) 170 return; 171 172 mStringVal = newVal; 173 mDirty = true; 174 mValueType = StringType; 175} 176 177void PostEffect::EffectConst::set(const F32 &newVal) 178{ 179 if (mFloatVal == newVal) 180 return; 181 182 mFloatVal = newVal; 183 mDirty = true; 184 mValueType = FloatType; 185} 186 187void PostEffect::EffectConst::set(const int& newVal) 188{ 189 if (mIntVal == newVal) 190 return; 191 192 mIntVal = newVal; 193 mDirty = true; 194 mValueType = IntType; 195} 196 197void PostEffect::EffectConst::set(const Point4F &newVal) 198{ 199 if (mPointVal == newVal) 200 return; 201 202 mPointVal = newVal; 203 mDirty = true; 204 mValueType = PointType; 205} 206 207void PostEffect::EffectConst::set(const MatrixF &newVal) 208{ 209 if (mMatrixVal == newVal) 210 return; 211 212 mMatrixVal = newVal; 213 mDirty = true; 214 mValueType = MatrixType; 215} 216 217void PostEffect::EffectConst::set(const Vector<Point4F> &newVal) 218{ 219 //if (mPointArrayVal == newVal) 220 // return; 221 222 mPointArrayVal = newVal; 223 mDirty = true; 224 mValueType = PointArrayType; 225} 226 227void PostEffect::EffectConst::set(const Vector<MatrixF> &newVal) 228{ 229 //if (mMatrixArrayVal == newVal) 230 // return; 231 232 mMatrixArrayVal = newVal; 233 mDirty = true; 234 mValueType = MatrixArrayType; 235} 236 237void PostEffect::EffectConst::setToBuffer( GFXShaderConstBufferRef buff ) 238{ 239 // Nothing to do if the value hasn't changed. 240 if ( !mDirty ) 241 return; 242 mDirty = false; 243 244 // If we don't have a handle... get it now. 245 if ( !mHandle ) 246 mHandle = buff->getShader()->getShaderConstHandle( mName ); 247 248 // If the handle isn't valid then we're done. 249 if ( !mHandle->isValid() ) 250 return; 251 252 const GFXShaderConstType type = mHandle->getType(); 253 254 // For now, we're only going 255 // to support float4 arrays. 256 // Expand to other types as necessary. 257 U32 arraySize = mHandle->getArraySize(); 258 259 if (mValueType == StringType) 260 { 261 const char *strVal = mStringVal.c_str(); 262 263 if (type == GFXSCT_Int) 264 { 265 S32 val; 266 Con::setData(TypeS32, &val, 0, 1, &strVal); 267 buff->set(mHandle, val); 268 } 269 else if (type == GFXSCT_Float) 270 { 271 F32 val; 272 Con::setData(TypeF32, &val, 0, 1, &strVal); 273 buff->set(mHandle, val); 274 } 275 else if (type == GFXSCT_Float2) 276 { 277 Point2F val; 278 Con::setData(TypePoint2F, &val, 0, 1, &strVal); 279 buff->set(mHandle, val); 280 } 281 else if (type == GFXSCT_Float3) 282 { 283 Point3F val; 284 Con::setData(TypePoint3F, &val, 0, 1, &strVal); 285 buff->set(mHandle, val); 286 } 287 else if (type == GFXSCT_Float4) 288 { 289 Point4F val; 290 291 if (arraySize > 1) 292 { 293 // Do array setup! 294 //U32 unitCount = StringUnit::getUnitCount( strVal, "\t" ); 295 //AssertFatal( unitCount == arraySize, "" ); 296 297 String tmpString; 298 Vector<Point4F> valArray; 299 300 for (U32 i = 0; i < arraySize; i++) 301 { 302 tmpString = StringUnit::getUnit(strVal, i, "\t"); 303 valArray.increment(); 304 const char *tmpCStr = tmpString.c_str(); 305 306 Con::setData(TypePoint4F, &valArray.last(), 0, 1, &tmpCStr); 307 } 308 309 AlignedArray<Point4F> rectData(valArray.size(), sizeof(Point4F), (U8*)valArray.address(), false); 310 buff->set(mHandle, rectData); 311 } 312 else 313 { 314 // Do regular setup. 315 Con::setData(TypePoint4F, &val, 0, 1, &strVal); 316 buff->set(mHandle, val); 317 } 318 } 319 else 320 { 321#if TORQUE_DEBUG 322 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 323 Con::errorf(err); 324 GFXAssertFatal(0, err); 325#endif 326 } 327 } 328 else if (mValueType == FloatType) 329 { 330 if (type == GFXSCT_Float) 331 { 332 buff->set(mHandle, mFloatVal); 333 } 334 else 335 { 336#if TORQUE_DEBUG 337 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 338 Con::errorf(err); 339 GFXAssertFatal(0, err); 340#endif 341 } 342 } 343 else if (mValueType == IntType) 344 { 345 if (type == GFXSCT_Int) 346 { 347 buff->set(mHandle, mIntVal); 348 } 349 else 350 { 351#if TORQUE_DEBUG 352 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 353 Con::errorf(err); 354 GFXAssertFatal(0, err); 355#endif 356 } 357 } 358 else if (mValueType == PointType) 359 { 360 if (type == GFXSCT_Float2) 361 { 362 buff->set(mHandle, Point2F(mPointVal.x, mPointVal.y)); 363 } 364 else if (type == GFXSCT_Float3) 365 { 366 buff->set(mHandle, Point3F(mPointVal.x, mPointVal.y, mPointVal.z)); 367 } 368 else if (type == GFXSCT_Float4) 369 { 370 buff->set(mHandle, mPointVal); 371 } 372 else 373 { 374#if TORQUE_DEBUG 375 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 376 Con::errorf(err); 377 GFXAssertFatal(0, err); 378#endif 379 } 380 } 381 else if (mValueType == MatrixType) 382 { 383 if (type == GFXSCT_Float4x4) 384 { 385 buff->set(mHandle, mMatrixVal); 386 } 387 else 388 { 389 #if TORQUE_DEBUG 390 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 391 Con::errorf(err); 392 GFXAssertFatal(0, err); 393 #endif 394 } 395 } 396 else if (mValueType == PointArrayType) 397 { 398 if (type == GFXSCT_Float4) 399 { 400 if (arraySize != mPointArrayVal.size()) 401 { 402 #if TORQUE_DEBUG 403 const char* err = avar("PostEffect::EffectConst::setToBuffer PointArrayType, attempted to feed an array that does not match the uniform array's size!"); 404 Con::errorf(err); 405 GFXAssertFatal(0, err); 406 #endif 407 return; 408 } 409 410 AlignedArray<Point4F> alignedVal = AlignedArray<Point4F>(arraySize, sizeof(Point4F), (U8*)mPointArrayVal.address(), false); 411 412 buff->set(mHandle, alignedVal); 413 } 414 else 415 { 416 #if TORQUE_DEBUG 417 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 418 Con::errorf(err); 419 GFXAssertFatal(0, err); 420 #endif 421 } 422 } 423 else if (mValueType == MatrixArrayType) 424 { 425 if (type == GFXSCT_Float4x4) 426 { 427 if (arraySize != mMatrixArrayVal.size()) 428 { 429 #if TORQUE_DEBUG 430 const char* err = avar("PostEffect::EffectConst::setToBuffer MatrixArrayType, attempted to feed an array that does not match the uniform array's size!"); 431 Con::errorf(err); 432 GFXAssertFatal(0, err); 433 #endif 434 return; 435 } 436 437 buff->set(mHandle, mMatrixArrayVal.address(), arraySize); 438 } 439 else 440 { 441 #if TORQUE_DEBUG 442 const char* err = avar("PostEffect::EffectConst::setToBuffer $s type is not implemented", mName.c_str()); 443 Con::errorf(err); 444 GFXAssertFatal(0, err); 445 #endif 446 } 447 } 448} 449 450 451//------------------------------------------------------------------------- 452// PostEffect 453//------------------------------------------------------------------------- 454 455PostEffect::PostEffect() 456 : mRenderTime( PFXAfterDiffuse ), 457 mRenderPriority( 1.0 ), 458 mEnabled( false ), 459 mStateBlockData( NULL ), 460 mUpdateShader( true ), 461 mSkip( false ), 462 mAllowReflectPass( false ), 463 mTargetClear( PFXTargetClear_None ), 464 mTargetScale( Point2F::One ), 465 mTargetViewport( PFXTargetViewport_TargetSize ), 466 mTargetSize( Point2I::Zero ), 467 mTargetFormat( GFXFormatR8G8B8A8 ), 468 mTargetClearColor( LinearColorF::BLACK ), 469 mOneFrameOnly( false ), 470 mOnThisFrame( true ), 471 mRTSizeSC( NULL ), 472 mIsValid( false ), 473 mShaderReloadKey( 0 ), 474 mOneOverRTSizeSC( NULL ), 475 mViewportOffsetSC( NULL ), 476 mTargetViewportSC( NULL ), 477 mFogDataSC( NULL ), 478 mFogColorSC( NULL ), 479 mEyePosSC( NULL ), 480 mMatWorldToScreenSC( NULL ), 481 mMatScreenToWorldSC( NULL ), 482 mMatPrevScreenToWorldSC( NULL ), 483 mNearFarSC( NULL ), 484 mInvNearFarSC( NULL ), 485 mWorldToScreenScaleSC( NULL ), 486 mProjectionOffsetSC( NULL ), 487 mWaterColorSC( NULL ), 488 mWaterFogDataSC( NULL ), 489 mAmbientColorSC( NULL ), 490 mWaterFogPlaneSC( NULL ), 491 mWaterDepthGradMaxSC( NULL ), 492 mScreenSunPosSC( NULL ), 493 mLightDirectionSC( NULL ), 494 mCameraForwardSC( NULL ), 495 mAccumTimeSC( NULL ), 496 mDeltaTimeSC( NULL ), 497 mInvCameraMatSC( NULL ), 498 mMatCameraToWorldSC( NULL), 499 mInvCameraTransSC(NULL), 500 mMatCameraToScreenSC(NULL), 501 mMatScreenToCameraSC(NULL) 502{ 503 dMemset( mTexSRGB, 0, sizeof(bool) * NumTextures); 504 dMemset( mActiveTextures, 0, sizeof( GFXTextureObject* ) * NumTextures ); 505 dMemset( mActiveNamedTarget, 0, sizeof( NamedTexTarget* ) * NumTextures ); 506 dMemset( mActiveTextureViewport, 0, sizeof( RectI ) * NumTextures ); 507 dMemset( mTexSizeSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures ); 508 dMemset( mRenderTargetParamsSC, 0, sizeof( GFXShaderConstHandle* ) * NumTextures ); 509} 510 511PostEffect::~PostEffect() 512{ 513 EffectConstTable::Iterator iter = mEffectConsts.begin(); 514 for ( ; iter != mEffectConsts.end(); iter++ ) 515 delete iter->value; 516} 517 518void PostEffect::initPersistFields() 519{ 520 addField( "shader", TypeRealString, Offset( mShaderName, PostEffect ), 521 "Name of a GFXShaderData for this effect." ); 522 523 addField( "stateBlock", TYPEID<GFXStateBlockData>(), Offset( mStateBlockData, PostEffect ), 524 "Name of a GFXStateBlockData for this effect." ); 525 526 addField( "target", TypeRealString, Offset( mTargetName, PostEffect ), 527 "String identifier of this effect's target texture.\n" 528 "@see PFXTextureIdentifiers" ); 529 530 addField( "targetDepthStencil", TypeRealString, Offset( mTargetDepthStencilName, PostEffect ), 531 "Optional string identifier for this effect's target depth/stencil texture.\n" 532 "@see PFXTextureIdentifiers" ); 533 534 addField( "targetScale", TypePoint2F, Offset( mTargetScale, PostEffect ), 535 "If targetSize is zero this is used to set a relative size from the current target." ); 536 537 addField( "targetSize", TypePoint2I, Offset( mTargetSize, PostEffect ), 538 "If non-zero this is used as the absolute target size." ); 539 540 addField( "targetFormat", TypeGFXFormat, Offset( mTargetFormat, PostEffect ), 541 "Format of the target texture, not applicable if writing to the backbuffer." ); 542 543 addField( "targetClearColor", TypeColorF, Offset( mTargetClearColor, PostEffect ), 544 "Color to which the target texture is cleared before rendering." ); 545 546 addField( "targetClear", TYPEID< PFXTargetClear >(), Offset( mTargetClear, PostEffect ), 547 "Describes when the target texture should be cleared." ); 548 549 addField( "targetViewport", TYPEID< PFXTargetViewport >(), Offset( mTargetViewport, PostEffect ), 550 "Specifies how the viewport should be set up for a target texture." ); 551 552 addField( "texture", TypeImageFilename, Offset( mTexFilename, PostEffect ), NumTextures, 553 "Input textures to this effect ( samplers ).\n" 554 "@see PFXTextureIdentifiers" ); 555 556 addField("textureSRGB", TypeBool, Offset(mTexSRGB, PostEffect), NumTextures, 557 "Set input texture to be sRGB"); 558 559 addField( "renderTime", TYPEID< PFXRenderTime >(), Offset( mRenderTime, PostEffect ), 560 "When to process this effect during the frame." ); 561 562 addField( "renderBin", TypeRealString, Offset( mRenderBin, PostEffect ), 563 "Name of a renderBin, used if renderTime is PFXBeforeBin or PFXAfterBin." ); 564 565 addField( "renderPriority", TypeF32, Offset( mRenderPriority, PostEffect ), 566 "PostEffects are processed in DESCENDING order of renderPriority if more than one has the same renderBin/Time." ); 567 568 addField( "allowReflectPass", TypeBool, Offset( mAllowReflectPass, PostEffect ), 569 "Is this effect processed during reflection render passes." ); 570 571 addProtectedField( "enabled", TypeBool, Offset( mEnabled, PostEffect), 572 &PostEffect::_setIsEnabled, &defaultProtectedGetFn, 573 "Is the effect on." ); 574 575 addField( "onThisFrame", TypeBool, Offset( mOnThisFrame, PostEffect ), 576 "Allows you to turn on a PostEffect for only a single frame." ); 577 578 addField( "oneFrameOnly", TypeBool, Offset( mOneFrameOnly, PostEffect ), 579 "Allows you to turn on a PostEffect for only a single frame." ); 580 581 addField( "skip", TypeBool, Offset( mSkip, PostEffect ), 582 "Skip processing of this PostEffect and its children even if its parent " 583 "is enabled. Parent and sibling PostEffects in the chain are still processed." ); 584 585 Parent::initPersistFields(); 586} 587 588bool PostEffect::onAdd() 589{ 590 if( !Parent::onAdd() ) 591 return false; 592 593 LightManager::smActivateSignal.notify( this, &PostEffect::_onLMActivate ); 594 mUpdateShader = true; 595 596 // Grab the script path. 597 Torque::Path scriptPath( Con::getVariable( "$Con::File" ) ); 598 scriptPath.setFileName( String::EmptyString ); 599 scriptPath.setExtension( String::EmptyString ); 600 601 // Find additional textures 602 for( S32 i = 0; i < NumTextures; i++ ) 603 { 604 mTextureType[i] = NormalTextureType; 605 606 String texFilename = mTexFilename[i]; 607 608 // Skip empty stages or ones with variable or target names. 609 if ( texFilename.isEmpty() || 610 texFilename[0] == '$' || 611 texFilename[0] == '#' ) 612 continue; 613 614 GFXTextureProfile *profile = &PostFxTextureProfile; 615 if (mTexSRGB[i]) 616 profile = &PostFxTextureSRGBProfile; 617 618 // Try to load the texture. 619 bool success = mTextures[i].set( texFilename, &PostFxTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); 620 if (!success) 621 Con::errorf("Invalid Texture for PostEffect (%s), The Texture '%s' does not exist!", this->getName(), texFilename.c_str()); 622 } 623 624 // Is the target a named target? 625 if ( mTargetName.isNotEmpty() && mTargetName[0] == '#' ) 626 { 627 mNamedTarget.registerWithName( mTargetName.substr( 1 ) ); 628 mNamedTarget.getTextureDelegate().bind( this, &PostEffect::_getTargetTexture ); 629 } 630 if ( mTargetDepthStencilName.isNotEmpty() && mTargetDepthStencilName[0] == '#' ) 631 mNamedTargetDepthStencil.registerWithName( mTargetDepthStencilName.substr( 1 ) ); 632 633 if (mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered()) 634 GFXTextureManager::addEventDelegate( this, &PostEffect::_onTextureEvent ); 635 636 // Call onAdd in script 637 onAdd_callback(); 638 639 // Should we start enabled? 640 if ( mEnabled ) 641 { 642 mEnabled = false; 643 enable(); 644 } 645 646 getSet()->addObject( this ); 647 648 return true; 649} 650 651void PostEffect::onRemove() 652{ 653 Parent::onRemove(); 654 655 PFXMGR->_removeEffect( this ); 656 657 LightManager::smActivateSignal.remove( this, &PostEffect::_onLMActivate ); 658 659 mShader = NULL; 660 _cleanTargets(); 661 662 if ( mNamedTarget.isRegistered() || mNamedTargetDepthStencil.isRegistered() ) 663 GFXTextureManager::removeEventDelegate( this, &PostEffect::_onTextureEvent ); 664 665 if ( mNamedTarget.isRegistered() ) 666 { 667 mNamedTarget.unregister(); 668 mNamedTarget.getTextureDelegate().clear(); 669 } 670 671 if ( mNamedTargetDepthStencil.isRegistered() ) 672 mNamedTargetDepthStencil.unregister(); 673} 674 675void PostEffect::_updateScreenGeometry( const Frustum &frustum, 676 GFXVertexBufferHandle<PFXVertex> *outVB ) 677{ 678 outVB->set( GFX, 4, GFXBufferTypeVolatile ); 679 680 const Point3F *frustumPoints = frustum.getPoints(); 681 const Point3F& cameraPos = frustum.getPosition(); 682 683 // Perform a camera offset. We need to manually perform this offset on the postFx's 684 // polygon, which is at the far plane. 685 const Point2F& projOffset = frustum.getProjectionOffset(); 686 Point3F cameraOffsetPos = cameraPos; 687 if(!projOffset.isZero()) 688 { 689 // First we need to calculate the offset at the near plane. The projOffset 690 // given above can be thought of a percent as it ranges from 0..1 (or 0..-1). 691 F32 nearOffset = frustum.getNearRight() * projOffset.x; 692 693 // Now given the near plane distance from the camera we can solve the right 694 // triangle and calcuate the SIN theta for the offset at the near plane. 695 // SIN theta = x/y 696 F32 sinTheta = nearOffset / frustum.getNearDist(); 697 698 // Finally, we can calcuate the offset at the far plane, which is where our sun (or vector) 699 // light's polygon is drawn. 700 F32 farOffset = frustum.getFarDist() * sinTheta; 701 702 // We can now apply this far plane offset to the far plane itself, which then compensates 703 // for the project offset. 704 MatrixF camTrans = frustum.getTransform(); 705 VectorF offset = camTrans.getRightVector(); 706 offset *= farOffset; 707 cameraOffsetPos += offset; 708 } 709 710 PFXVertex *vert = outVB->lock(); 711 712 vert->point.set(-1.0, 1.0, 0.0); 713 vert->texCoord.set(0.0f, 0.0f); 714 vert->wsEyeRay = frustumPoints[Frustum::FarTopLeft] - cameraOffsetPos; 715 vert++; 716 717 vert->point.set(1.0, 1.0, 0.0); 718 vert->texCoord.set(1.0f, 0.0f); 719 vert->wsEyeRay = frustumPoints[Frustum::FarTopRight] - cameraOffsetPos; 720 vert++; 721 722 vert->point.set(-1.0, -1.0, 0.0); 723 vert->texCoord.set(0.0f, 1.0f); 724 vert->wsEyeRay = frustumPoints[Frustum::FarBottomLeft] - cameraOffsetPos; 725 vert++; 726 727 vert->point.set(1.0, -1.0, 0.0); 728 vert->texCoord.set(1.0f, 1.0f); 729 vert->wsEyeRay = frustumPoints[Frustum::FarBottomRight] - cameraOffsetPos; 730 vert++; 731 732 outVB->unlock(); 733} 734 735void PostEffect::_setupStateBlock( const SceneRenderState *state ) 736{ 737 if ( mStateBlock.isNull() ) 738 { 739 GFXStateBlockDesc desc; 740 if ( mStateBlockData ) 741 desc = mStateBlockData->getState(); 742 743 mStateBlock = GFX->createStateBlock( desc ); 744 } 745 746 GFX->setStateBlock( mStateBlock ); 747} 748 749void PostEffect::_setupConstants( const SceneRenderState *state ) 750{ 751 // Alloc the const buffer. 752 if ( mShaderConsts.isNull() ) 753 { 754 mShaderConsts = mShader->allocConstBuffer(); 755 756 mRTSizeSC = mShader->getShaderConstHandle( "$targetSize" ); 757 mOneOverRTSizeSC = mShader->getShaderConstHandle( "$oneOverTargetSize" ); 758 759 mTexSizeSC[0] = mShader->getShaderConstHandle( "$texSize0" ); 760 mTexSizeSC[1] = mShader->getShaderConstHandle( "$texSize1" ); 761 mTexSizeSC[2] = mShader->getShaderConstHandle( "$texSize2" ); 762 mTexSizeSC[3] = mShader->getShaderConstHandle( "$texSize3" ); 763 mTexSizeSC[4] = mShader->getShaderConstHandle( "$texSize4" ); 764 mTexSizeSC[5] = mShader->getShaderConstHandle( "$texSize5" ); 765 mTexSizeSC[6] = mShader->getShaderConstHandle( "$texSize6" ); 766 mTexSizeSC[7] = mShader->getShaderConstHandle( "$texSize7" ); 767 768 mRenderTargetParamsSC[0] = mShader->getShaderConstHandle( "$rtParams0" ); 769 mRenderTargetParamsSC[1] = mShader->getShaderConstHandle( "$rtParams1" ); 770 mRenderTargetParamsSC[2] = mShader->getShaderConstHandle( "$rtParams2" ); 771 mRenderTargetParamsSC[3] = mShader->getShaderConstHandle( "$rtParams3" ); 772 mRenderTargetParamsSC[4] = mShader->getShaderConstHandle( "$rtParams4" ); 773 mRenderTargetParamsSC[5] = mShader->getShaderConstHandle( "$rtParams5" ); 774 mRenderTargetParamsSC[6] = mShader->getShaderConstHandle( "$rtParams6" ); 775 mRenderTargetParamsSC[7] = mShader->getShaderConstHandle( "$rtParams7" ); 776 777 //mViewportSC = shader->getShaderConstHandle( "$viewport" ); 778 779 mTargetViewportSC = mShader->getShaderConstHandle( "$targetViewport" ); 780 781 mFogDataSC = mShader->getShaderConstHandle( ShaderGenVars::fogData ); 782 mFogColorSC = mShader->getShaderConstHandle( ShaderGenVars::fogColor ); 783 784 mEyePosSC = mShader->getShaderConstHandle( ShaderGenVars::eyePosWorld ); 785 786 mNearFarSC = mShader->getShaderConstHandle( "$nearFar" ); 787 mInvNearFarSC = mShader->getShaderConstHandle( "$invNearFar" ); 788 mWorldToScreenScaleSC = mShader->getShaderConstHandle( "$worldToScreenScale" ); 789 790 mMatWorldToScreenSC = mShader->getShaderConstHandle( "$matWorldToScreen" ); 791 mMatScreenToWorldSC = mShader->getShaderConstHandle( "$matScreenToWorld" ); 792 mMatPrevScreenToWorldSC = mShader->getShaderConstHandle( "$matPrevScreenToWorld" ); 793 794 mProjectionOffsetSC = mShader->getShaderConstHandle( "$projectionOffset" ); 795 796 mWaterColorSC = mShader->getShaderConstHandle( "$waterColor" ); 797 mAmbientColorSC = mShader->getShaderConstHandle( "$ambientColor" ); 798 mWaterFogDataSC = mShader->getShaderConstHandle( "$waterFogData" ); 799 mWaterFogPlaneSC = mShader->getShaderConstHandle( "$waterFogPlane" ); 800 mWaterDepthGradMaxSC = mShader->getShaderConstHandle( "$waterDepthGradMax" ); 801 mScreenSunPosSC = mShader->getShaderConstHandle( "$screenSunPos" ); 802 mLightDirectionSC = mShader->getShaderConstHandle( "$lightDirection" ); 803 mCameraForwardSC = mShader->getShaderConstHandle( "$camForward" ); 804 805 mAccumTimeSC = mShader->getShaderConstHandle( "$accumTime" ); 806 mDeltaTimeSC = mShader->getShaderConstHandle( "$deltaTime" ); 807 808 mInvCameraMatSC = mShader->getShaderConstHandle( "$invCameraMat" ); 809 810 mMatCameraToWorldSC = mShader->getShaderConstHandle("$cameraToWorld"); 811 812 mInvCameraTransSC = mShader->getShaderConstHandle("$invCameraTrans"); 813 mMatCameraToScreenSC = mShader->getShaderConstHandle("$cameraToScreen"); 814 mMatScreenToCameraSC = mShader->getShaderConstHandle("$screenToCamera"); 815 } 816 817 // Set up shader constants for source image size 818 if ( mRTSizeSC->isValid() ) 819 { 820 const Point2I &resolution = GFX->getActiveRenderTarget()->getSize(); 821 Point2F pixelShaderConstantData; 822 823 pixelShaderConstantData.x = resolution.x; 824 pixelShaderConstantData.y = resolution.y; 825 826 mShaderConsts->set( mRTSizeSC, pixelShaderConstantData ); 827 } 828 829 if ( mOneOverRTSizeSC->isValid() ) 830 { 831 const Point2I &resolution = GFX->getActiveRenderTarget()->getSize(); 832 Point2F oneOverTargetSize( 1.0f / (F32)resolution.x, 1.0f / (F32)resolution.y ); 833 834 mShaderConsts->set( mOneOverRTSizeSC, oneOverTargetSize ); 835 } 836 837 // Set up additional textures 838 Point2F texSizeConst; 839 for( U32 i = 0; i < NumTextures; i++ ) 840 { 841 if( !mActiveTextures[i] ) 842 continue; 843 844 if ( mTexSizeSC[i]->isValid() ) 845 { 846 texSizeConst.x = (F32)mActiveTextures[i]->getWidth(); 847 texSizeConst.y = (F32)mActiveTextures[i]->getHeight(); 848 mShaderConsts->set( mTexSizeSC[i], texSizeConst ); 849 } 850 } 851 852 for ( U32 i = 0; i < NumTextures; i++ ) 853 { 854 if ( !mRenderTargetParamsSC[i]->isValid() ) 855 continue; 856 857 Point4F rtParams( Point4F::One ); 858 859 if ( mActiveTextures[i] ) 860 { 861 const Point3I &targetSz = mActiveTextures[i]->getSize(); 862 RectI targetVp = mActiveTextureViewport[i]; 863 ScreenSpace::RenderTargetParameters(targetSz, targetVp, rtParams); 864 } 865 866 mShaderConsts->set( mRenderTargetParamsSC[i], rtParams ); 867 } 868 869 // Target viewport (in target space) 870 if ( mTargetViewportSC->isValid() ) 871 { 872 const Point2I& targetSize = GFX->getActiveRenderTarget()->getSize(); 873 Point3I size(targetSize.x, targetSize.y, 0); 874 const RectI& viewport = GFX->getViewport(); 875 876 Point2F offset((F32)viewport.point.x / (F32)targetSize.x, (F32)viewport.point.y / (F32)targetSize.y ); 877 Point2F scale((F32)viewport.extent.x / (F32)targetSize.x, (F32)viewport.extent.y / (F32)targetSize.y ); 878 879 Point4F targetParams; 880 targetParams.x = offset.x; 881 targetParams.y = offset.y; 882 targetParams.z = offset.x + scale.x; 883 targetParams.w = offset.y + scale.y; 884 885 mShaderConsts->set( mTargetViewportSC, targetParams ); 886 } 887 888 // Set the fog data. 889 if ( mFogDataSC->isValid() ) 890 { 891 const FogData &data = state->getSceneManager()->getFogData(); 892 893 Point3F params; 894 params.x = data.density; 895 params.y = data.densityOffset; 896 897 if ( !mIsZero( data.atmosphereHeight ) ) 898 params.z = 1.0f / data.atmosphereHeight; 899 else 900 params.z = 0.0f; 901 902 mShaderConsts->set( mFogDataSC, params ); 903 } 904 905 const PFXFrameState &thisFrame = PFXMGR->getFrameState(); 906 907 if ( mMatWorldToScreenSC->isValid() ) 908 { 909 // Screen space->world space 910 MatrixF tempMat = thisFrame.cameraToScreen; 911 tempMat.mul( thisFrame.worldToCamera ); 912 tempMat.fullInverse(); 913 tempMat.transpose(); 914 915 // Support using these matrices as float3x3 or float4x4... 916 mShaderConsts->set( mMatWorldToScreenSC, tempMat, mMatWorldToScreenSC->getType() ); 917 } 918 919 if ( mMatScreenToWorldSC->isValid() ) 920 { 921 // World space->screen space 922 MatrixF tempMat = thisFrame.cameraToScreen; 923 tempMat.mul( thisFrame.worldToCamera ); 924 tempMat.transpose(); 925 926 // Support using these matrices as float3x3 or float4x4... 927 mShaderConsts->set( mMatScreenToWorldSC, tempMat, mMatScreenToWorldSC->getType() ); 928 } 929 930 if ( mMatPrevScreenToWorldSC->isValid() ) 931 { 932 const PFXFrameState &lastFrame = PFXMGR->getLastFrameState(); 933 934 // Previous frame world space->screen space 935 MatrixF tempMat = lastFrame.cameraToScreen; 936 tempMat.mul( lastFrame.worldToCamera ); 937 tempMat.transpose(); 938 mShaderConsts->set( mMatPrevScreenToWorldSC, tempMat ); 939 } 940 941 if (mAmbientColorSC->isValid() && state) 942 { 943 const LinearColorF &sunlight = state->getAmbientLightColor(); 944 Point3F ambientColor( sunlight.red, sunlight.green, sunlight.blue ); 945 946 mShaderConsts->set( mAmbientColorSC, ambientColor ); 947 } 948 949 if (mMatCameraToWorldSC->isValid()) 950 { 951 MatrixF tempMat = thisFrame.worldToCamera; 952 tempMat.inverse(); 953 mShaderConsts->set(mMatCameraToWorldSC, tempMat); 954 } 955 956 if (mInvCameraTransSC->isValid()) 957 { 958 MatrixF mat = state->getCameraTransform(); 959 mat.fullInverse(); 960 mShaderConsts->set(mInvCameraTransSC, mat, mInvCameraTransSC->getType()); 961 } 962 //Projection Matrix 963 if (mMatCameraToScreenSC->isValid()) 964 { 965 966 MatrixF tempMat = thisFrame.cameraToScreen; 967 mShaderConsts->set(mMatCameraToScreenSC, tempMat, mMatCameraToScreenSC->getType()); 968 } 969 970 971 //Inverse Projection Matrix 972 if (mMatScreenToCameraSC->isValid()) 973 { 974 975 MatrixF tempMat = thisFrame.cameraToScreen; 976 tempMat.fullInverse(); 977 978 mShaderConsts->set(mMatScreenToCameraSC, tempMat, mMatScreenToCameraSC->getType()); 979 } 980 mShaderConsts->setSafe( mAccumTimeSC, MATMGR->getTotalTime() ); 981 mShaderConsts->setSafe( mDeltaTimeSC, MATMGR->getDeltaTime() ); 982 983 // Now set all the constants that are dependent on the scene state. 984 if ( state ) 985 { 986 mShaderConsts->setSafe( mEyePosSC, state->getDiffuseCameraPosition() ); 987 mShaderConsts->setSafe( mNearFarSC, Point2F( state->getNearPlane(), state->getFarPlane() ) ); 988 mShaderConsts->setSafe( mInvNearFarSC, Point2F( 1.0f / state->getNearPlane(), 1.0f / state->getFarPlane() ) ); 989 mShaderConsts->setSafe( mWorldToScreenScaleSC, state->getWorldToScreenScale() ); 990 mShaderConsts->setSafe( mProjectionOffsetSC, state->getCameraFrustum().getProjectionOffset() ); 991 mShaderConsts->setSafe( mFogColorSC, state->getSceneManager()->getFogData().color ); 992 993 if ( mWaterColorSC->isValid() ) 994 { 995 LinearColorF color( state->getSceneManager()->getWaterFogData().color ); 996 mShaderConsts->set( mWaterColorSC, color ); 997 } 998 999 if ( mWaterFogDataSC->isValid() ) 1000 { 1001 const WaterFogData &data = state->getSceneManager()->getWaterFogData(); 1002 Point4F params( data.density, data.densityOffset, data.wetDepth, data.wetDarkening ); 1003 mShaderConsts->set( mWaterFogDataSC, params ); 1004 } 1005 1006 if ( mWaterFogPlaneSC->isValid() ) 1007 { 1008 const PlaneF &plane = state->getSceneManager()->getWaterFogData().plane; 1009 mShaderConsts->set( mWaterFogPlaneSC, plane ); 1010 } 1011 1012 if ( mWaterDepthGradMaxSC->isValid() ) 1013 { 1014 mShaderConsts->set( mWaterDepthGradMaxSC, state->getSceneManager()->getWaterFogData().depthGradMax ); 1015 } 1016 1017 if ( mScreenSunPosSC->isValid() ) 1018 { 1019 // Grab our projection matrix 1020 // from the frustum. 1021 Frustum frust = state->getCameraFrustum(); 1022 MatrixF proj( true ); 1023 frust.getProjectionMatrix( &proj ); 1024 1025 // Grab the ScatterSky world matrix. 1026 MatrixF camMat = state->getCameraTransform(); 1027 camMat.inverse(); 1028 MatrixF tmp( true ); 1029 tmp = camMat; 1030 tmp.setPosition( Point3F( 0, 0, 0 ) ); 1031 1032 Point3F sunPos( 0, 0, 0 ); 1033 1034 // Get the light manager and sun light object. 1035 LightInfo *sunLight = LIGHTMGR->getSpecialLight( LightManager::slSunLightType ); 1036 1037 // Grab the light direction and scale 1038 // by the ScatterSky radius to get the world 1039 // space sun position. 1040 const VectorF &lightDir = sunLight->getDirection(); 1041 1042 Point3F lightPos( lightDir.x * (6378.0f * 1000.0f), 1043 lightDir.y * (6378.0f * 1000.0f), 1044 lightDir.z * (6378.0f * 1000.0f) ); 1045 1046 RectI viewPort = GFX->getViewport(); 1047 1048 // Get the screen space sun position. 1049 MathUtils::mProjectWorldToScreen(lightPos, &sunPos, viewPort, tmp, proj); 1050 1051 // And normalize it to the 0 to 1 range. 1052 sunPos.x -= (F32)viewPort.point.x; 1053 sunPos.y -= (F32)viewPort.point.y; 1054 sunPos.x /= (F32)viewPort.extent.x; 1055 sunPos.y /= (F32)viewPort.extent.y; 1056 1057 mShaderConsts->set( mScreenSunPosSC, Point2F( sunPos.x, sunPos.y ) ); 1058 } 1059 1060 if ( mLightDirectionSC->isValid() ) 1061 { 1062 LightInfo *sunLight = LIGHTMGR->getSpecialLight( LightManager::slSunLightType ); 1063 1064 const VectorF &lightDir = sunLight->getDirection(); 1065 mShaderConsts->set( mLightDirectionSC, lightDir ); 1066 } 1067 1068 if ( mCameraForwardSC->isValid() ) 1069 { 1070 const MatrixF &camMat = state->getCameraTransform(); 1071 VectorF camFwd( 0, 0, 0 ); 1072 1073 camMat.getColumn( 1, &camFwd ); 1074 1075 mShaderConsts->set( mCameraForwardSC, camFwd ); 1076 } 1077 1078 if ( mInvCameraMatSC->isValid() ) 1079 { 1080 MatrixF mat = state->getCameraTransform(); 1081 mat.inverse(); 1082 mShaderConsts->set( mInvCameraMatSC, mat, mInvCameraMatSC->getType() ); 1083 } 1084 1085 } // if ( state ) 1086 1087 // Set EffectConsts - specified from script 1088 1089 // If our shader has reloaded since last frame we must mark all 1090 // EffectConsts dirty so they will be reset. 1091 if ( mShader->getReloadKey() != mShaderReloadKey ) 1092 { 1093 mShaderReloadKey = mShader->getReloadKey(); 1094 1095 EffectConstTable::Iterator iter = mEffectConsts.begin(); 1096 for ( ; iter != mEffectConsts.end(); iter++ ) 1097 { 1098 iter->value->mDirty = true; 1099 iter->value->mHandle = NULL; 1100 } 1101 } 1102 1103 // Doesn't look like anyone is using this anymore. 1104 // But if we do want to pass this info to script, 1105 // we should do so in the same way as I am doing below. 1106 /* 1107 Point2F texSizeScriptConst( 0, 0 ); 1108 String buffer; 1109 if ( mActiveTextures[0] ) 1110 { 1111 texSizeScriptConst.x = (F32)mActiveTextures[0]->getWidth(); 1112 texSizeScriptConst.y = (F32)mActiveTextures[0]->getHeight(); 1113 1114 dSscanf( buffer.c_str(), "%g %g", texSizeScriptConst.x, texSizeScriptConst.y ); 1115 } 1116 */ 1117 1118 { 1119 PROFILE_SCOPE( PostEffect_SetShaderConsts ); 1120 1121 // Pass some data about the current render state to script. 1122 // 1123 // TODO: This is pretty messy... it should go away. This info 1124 // should be available from some other script accessible method 1125 // or field which isn't PostEffect specific. 1126 // 1127 if ( state ) 1128 { 1129 Con::setFloatVariable( "$Param::NearDist", state->getNearPlane() ); 1130 Con::setFloatVariable( "$Param::FarDist", state->getFarPlane() ); 1131 } 1132 1133 setShaderConsts_callback(); 1134 } 1135 1136 EffectConstTable::Iterator iter = mEffectConsts.begin(); 1137 for ( ; iter != mEffectConsts.end(); iter++ ) 1138 iter->value->setToBuffer( mShaderConsts ); 1139} 1140 1141void PostEffect::_setupTexture( U32 stage, GFXTexHandle &inputTex, const RectI *inTexViewport ) 1142{ 1143 const String &texFilename = mTexFilename[ stage ]; 1144 1145 GFXTexHandle theTex; 1146 NamedTexTarget *namedTarget = NULL; 1147 1148 RectI viewport = GFX->getViewport(); 1149 1150 if ( texFilename.compare( "$inTex", 0, String::NoCase ) == 0 ) 1151 { 1152 theTex = inputTex; 1153 1154 if ( inTexViewport ) 1155 { 1156 viewport = *inTexViewport; 1157 } 1158 else if ( theTex ) 1159 { 1160 viewport.set( 0, 0, theTex->getWidth(), theTex->getHeight() ); 1161 } 1162 } 1163 else if ( texFilename.compare( "$backBuffer", 0, String::NoCase ) == 0 ) 1164 { 1165 theTex = PFXMGR->getBackBufferTex(); 1166 1167 // Always use the GFX viewport when reading from the backbuffer 1168 } 1169 else if ( texFilename.isNotEmpty() && texFilename[0] == '#' ) 1170 { 1171 namedTarget = NamedTexTarget::find( texFilename.c_str() + 1 ); 1172 if ( namedTarget ) 1173 { 1174 theTex = namedTarget->getTexture( 0 ); 1175 viewport = namedTarget->getViewport(); 1176 } 1177 } 1178 else 1179 { 1180 theTex = mTextures[ stage ]; 1181 if ( theTex ) 1182 viewport.set( 0, 0, theTex->getWidth(), theTex->getHeight() ); 1183 } 1184 1185 mActiveTextures[ stage ] = theTex; 1186 mActiveNamedTarget[ stage ] = namedTarget; 1187 mActiveTextureViewport[ stage ] = viewport; 1188 1189 if ( theTex.isValid() ) 1190 GFX->setTexture( stage, theTex ); 1191} 1192 1193void PostEffect::_setupCubemapTexture(U32 stage, GFXCubemapHandle &inputTex) 1194{ 1195 RectI viewport = GFX->getViewport(); 1196 1197 mActiveTextures[stage] = nullptr; 1198 mActiveNamedTarget[stage] = nullptr; 1199 mActiveTextureViewport[stage] = viewport; 1200 1201 if (inputTex.isValid()) 1202 GFX->setCubeTexture(stage, inputTex); 1203} 1204 1205void PostEffect::_setupCubemapArrayTexture(U32 stage, GFXCubemapArrayHandle &inputTex) 1206{ 1207 RectI viewport = GFX->getViewport(); 1208 1209 mActiveTextures[stage] = nullptr; 1210 mActiveNamedTarget[stage] = nullptr; 1211 mActiveTextureViewport[stage] = viewport; 1212 1213 if (inputTex.isValid()) 1214 GFX->setCubeArrayTexture(stage, inputTex); 1215} 1216 1217void PostEffect::_setupTransforms() 1218{ 1219 // Set everything to identity. 1220 GFX->setWorldMatrix( MatrixF::Identity ); 1221 GFX->setProjectionMatrix( MatrixF::Identity ); 1222} 1223 1224void PostEffect::_setupTarget( const SceneRenderState *state, bool *outClearTarget ) 1225{ 1226 if ( mNamedTarget.isRegistered() || 1227 mTargetName.compare( "$outTex", 0, String::NoCase ) == 0 ) 1228 { 1229 // Size it relative to the texture of the first stage or 1230 // if NULL then use the current target. 1231 1232 Point2I targetSize; 1233 1234 // If we have an absolute target size then use that. 1235 if ( !mTargetSize.isZero() ) 1236 targetSize = mTargetSize; 1237 1238 // Else generate a relative size using the target scale. 1239 else if ( mActiveTextures[ 0 ] ) 1240 { 1241 const Point3I &texSize = mActiveTextures[ 0 ]->getSize(); 1242 1243 targetSize.set( texSize.x * mTargetScale.x, 1244 texSize.y * mTargetScale.y ); 1245 } 1246 else 1247 { 1248 GFXTarget *oldTarget = GFX->getActiveRenderTarget(); 1249 const Point2I &oldTargetSize = oldTarget->getSize(); 1250 1251 targetSize.set( oldTargetSize.x * mTargetScale.x, 1252 oldTargetSize.y * mTargetScale.y ); 1253 } 1254 1255 // Make sure its at least 1x1. 1256 targetSize.setMax( Point2I::One ); 1257 1258 if ( mNamedTarget.isRegistered() || 1259 !mTargetTex || 1260 mTargetTex.getWidthHeight() != targetSize ) 1261 { 1262 mTargetTex.set( targetSize.x, targetSize.y, mTargetFormat, 1263 &PostFxTargetProfile, "PostEffect::_setupTarget" ); 1264 1265 if ( mTargetClear == PFXTargetClear_OnCreate ) 1266 *outClearTarget = true; 1267 1268 if(mTargetViewport == PFXTargetViewport_GFXViewport) 1269 { 1270 // We may need to scale the GFX viewport to fit within 1271 // our target texture size 1272 GFXTarget *oldTarget = GFX->getActiveRenderTarget(); 1273 const Point2I &oldTargetSize = oldTarget->getSize(); 1274 Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); 1275 1276 const RectI &viewport = GFX->getViewport(); 1277 1278 mNamedTarget.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); 1279 } 1280 else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) 1281 { 1282 // Scale the named input texture's viewport to match our target 1283 const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); 1284 Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); 1285 1286 const RectI &viewport = mActiveNamedTarget[0]->getViewport(); 1287 1288 mNamedTarget.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); 1289 } 1290 else 1291 { 1292 // PFXTargetViewport_TargetSize 1293 mNamedTarget.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) ); 1294 } 1295 } 1296 } 1297 else 1298 mTargetTex = NULL; 1299 1300 // Do we have a named depthStencil target? 1301 if ( mNamedTargetDepthStencil.isRegistered() ) 1302 { 1303 // Size it relative to the texture of the first stage or 1304 // if NULL then use the current target. 1305 Point2I targetSize; 1306 1307 // If we have an absolute target size then use that. 1308 if ( !mTargetSize.isZero() ) 1309 targetSize = mTargetSize; 1310 1311 // Else generate a relative size using the target scale. 1312 else if ( mActiveTextures[ 0 ] ) 1313 { 1314 const Point3I &texSize = mActiveTextures[ 0 ]->getSize(); 1315 1316 targetSize.set( texSize.x * mTargetScale.x, 1317 texSize.y * mTargetScale.y ); 1318 } 1319 else 1320 { 1321 GFXTarget *oldTarget = GFX->getActiveRenderTarget(); 1322 const Point2I &oldTargetSize = oldTarget->getSize(); 1323 1324 targetSize.set( oldTargetSize.x * mTargetScale.x, 1325 oldTargetSize.y * mTargetScale.y ); 1326 } 1327 1328 // Make sure its at least 1x1. 1329 targetSize.setMax( Point2I::One ); 1330 1331 if ( mNamedTargetDepthStencil.isRegistered() && 1332 mTargetDepthStencil.getWidthHeight() != targetSize ) 1333 { 1334 mTargetDepthStencil.set( targetSize.x, targetSize.y, GFXFormatD24S8, 1335 &GFXZTargetProfile, "PostEffect::_setupTarget" ); 1336 1337 if ( mTargetClear == PFXTargetClear_OnCreate ) 1338 *outClearTarget = true; 1339 1340 if(mTargetViewport == PFXTargetViewport_GFXViewport) 1341 { 1342 // We may need to scale the GFX viewport to fit within 1343 // our target texture size 1344 GFXTarget *oldTarget = GFX->getActiveRenderTarget(); 1345 const Point2I &oldTargetSize = oldTarget->getSize(); 1346 Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); 1347 1348 const RectI &viewport = GFX->getViewport(); 1349 1350 mNamedTargetDepthStencil.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); 1351 } 1352 else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) 1353 { 1354 // Scale the named input texture's viewport to match our target 1355 const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); 1356 Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); 1357 1358 const RectI &viewport = mActiveNamedTarget[0]->getViewport(); 1359 1360 mNamedTargetDepthStencil.setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); 1361 } 1362 else 1363 { 1364 // PFXTargetViewport_TargetSize 1365 mNamedTargetDepthStencil.setViewport( RectI( 0, 0, targetSize.x, targetSize.y ) ); 1366 } 1367 } 1368 } 1369 else 1370 mTargetDepthStencil = NULL; 1371 1372 if ( mTargetClear == PFXTargetClear_OnDraw ) 1373 *outClearTarget = true; 1374 1375 if ( !mTarget && (mTargetTex || mTargetDepthStencil) ) 1376 mTarget = GFX->allocRenderToTextureTarget(); 1377} 1378 1379void PostEffect::_cleanTargets( bool recurse ) 1380{ 1381 mTargetTex = NULL; 1382 mTargetDepthStencil = NULL; 1383 mTarget = NULL; 1384 1385 if ( !recurse ) 1386 return; 1387 1388 // Clear the children too! 1389 for ( U32 i = 0; i < size(); i++ ) 1390 { 1391 PostEffect *effect = (PostEffect*)(*this)[i]; 1392 effect->_cleanTargets( true ); 1393 } 1394} 1395 1396void PostEffect::process( const SceneRenderState *state, 1397 GFXTexHandle &inOutTex, 1398 const RectI *inTexViewport ) 1399{ 1400 // If the shader is forced to be skipped... then skip. 1401 if ( mSkip ) 1402 return; 1403 1404 // Skip out if we don't support reflection passes. 1405 if ( state && state->isReflectPass() && !mAllowReflectPass ) 1406 return; 1407 1408 if ( mOneFrameOnly && !mOnThisFrame ) 1409 return; 1410 1411 // Check requirements if the shader needs updating. 1412 if ( mUpdateShader ) 1413 { 1414 _checkRequirements(); 1415 1416 // Clear the targets if we failed passing 1417 // the requirements at this time. 1418 if ( !mIsValid ) 1419 _cleanTargets( true ); 1420 } 1421 1422 // If we're not valid then we cannot render. 1423 if ( !mIsValid ) 1424 return; 1425 1426 GFXDEBUGEVENT_SCOPE_EX( PostEffect_Process, ColorI::GREEN, avar("PostEffect: %s", getName()) ); 1427 1428 preProcess_callback(); 1429 1430 GFXTransformSaver saver; 1431 1432 // Set the textures. 1433 for (U32 i = 0; i < NumTextures; i++) 1434 { 1435 if (mTextureType[i] == NormalTextureType) 1436 _setupTexture(i, inOutTex, inTexViewport); 1437 else if (mTextureType[i] == CubemapType) 1438 _setupCubemapTexture(i, mCubemapTextures[i]); 1439 else if (mTextureType[i] == CubemapArrayType) 1440 _setupCubemapArrayTexture(i, mCubemapArrayTextures[i]); 1441 } 1442 1443 _setupStateBlock( state ) ; 1444 _setupTransforms(); 1445 1446 bool clearTarget = false; 1447 _setupTarget( state, &clearTarget ); 1448 1449 if ( mTargetTex || mTargetDepthStencil ) 1450 { 1451 const RectI &oldViewport = GFX->getViewport(); 1452 GFXTarget *oldTarget = GFX->getActiveRenderTarget(); 1453 1454 GFX->pushActiveRenderTarget(); 1455 mTarget->attachTexture( GFXTextureTarget::Color0, mTargetTex ); 1456 1457 // Set the right depth stencil target. 1458 if ( !mTargetDepthStencil && mTargetTex.getWidthHeight() == GFX->getActiveRenderTarget()->getSize() ) 1459 mTarget->attachTexture( GFXTextureTarget::DepthStencil, GFXTextureTarget::sDefaultDepthStencil ); 1460 else 1461 mTarget->attachTexture( GFXTextureTarget::DepthStencil, mTargetDepthStencil ); 1462 1463 // Set the render target but not its viewport. We'll do that below. 1464 GFX->setActiveRenderTarget( mTarget, false ); 1465 1466 if(mNamedTarget.isRegistered()) 1467 { 1468 // Always use the name target's viewport, if available. It was set up in _setupTarget(). 1469 GFX->setViewport(mNamedTarget.getViewport()); 1470 } 1471 else if(mTargetViewport == PFXTargetViewport_GFXViewport) 1472 { 1473 // Go with the current viewport as scaled against our render target. 1474 const Point2I &oldTargetSize = oldTarget->getSize(); 1475 const Point2I &targetSize = mTarget->getSize(); 1476 Point2F scale(targetSize.x / F32(oldTargetSize.x), targetSize.y / F32(oldTargetSize.y)); 1477 GFX->setViewport( RectI( oldViewport.point.x*scale.x, oldViewport.point.y*scale.y, oldViewport.extent.x*scale.x, oldViewport.extent.y*scale.y ) ); 1478 } 1479 else if(mTargetViewport == PFXTargetViewport_NamedInTexture0 && mActiveNamedTarget[0] && mActiveNamedTarget[0]->getTexture()) 1480 { 1481 // Go with the first input texture, if it is named. Scale the named input texture's viewport to match our target 1482 const Point3I &namedTargetSize = mActiveNamedTarget[0]->getTexture()->getSize(); 1483 const Point2I &targetSize = mTarget->getSize(); 1484 Point2F scale(targetSize.x / F32(namedTargetSize.x), targetSize.y / F32(namedTargetSize.y)); 1485 1486 const RectI &viewport = mActiveNamedTarget[0]->getViewport(); 1487 1488 GFX->setViewport( RectI( viewport.point.x*scale.x, viewport.point.y*scale.y, viewport.extent.x*scale.x, viewport.extent.y*scale.y ) ); 1489 } 1490 else 1491 { 1492 // Default to using the whole target as the viewport 1493 GFX->setViewport( RectI( Point2I::Zero, mTarget->getSize() ) ); 1494 } 1495 } 1496 1497 if ( clearTarget ) 1498 GFX->clear( GFXClearTarget, mTargetClearColor, 1.f, 0 ); 1499 1500 // Setup the shader and constants. 1501 if ( mShader ) 1502 { 1503 GFX->setShader( mShader ); 1504 _setupConstants( state ); 1505 1506 GFX->setShaderConstBuffer( mShaderConsts ); 1507 } 1508 else 1509 GFX->setupGenericShaders(); 1510 1511 Frustum frustum; 1512 if ( state ) 1513 frustum = state->getCameraFrustum(); 1514 else 1515 { 1516 // If we don't have a scene state then setup 1517 // a dummy frustum... you better not be depending 1518 // on this being related to the camera in any way. 1519 1520 frustum = Frustum(); 1521 } 1522 1523 GFXVertexBufferHandle<PFXVertex> vb; 1524 _updateScreenGeometry( frustum, &vb ); 1525 1526 // Draw it. 1527 GFX->setVertexBuffer( vb ); 1528 GFX->drawPrimitive( GFXTriangleStrip, 0, 2 ); 1529 1530 // Allow PostEffecVis to hook in. 1531 PFXVIS->onPFXProcessed( this ); 1532 1533 if ( mTargetTex || mTargetDepthStencil ) 1534 { 1535 mTarget->resolve(); 1536 GFX->popActiveRenderTarget(); 1537 } 1538 else 1539 { 1540 // We wrote to the active back buffer, so release 1541 // the current texture copy held by the manager. 1542 // 1543 // This ensures a new copy is made. 1544 PFXMGR->releaseBackBufferTex(); 1545 } 1546 1547 // Return and release our target texture. 1548 inOutTex = mTargetTex; 1549 if ( !mNamedTarget.isRegistered() ) 1550 mTargetTex = NULL; 1551 1552 // Restore the transforms before the children 1553 // are processed as it screws up the viewport. 1554 saver.restore(); 1555 1556 // Now process my children. 1557 iterator i = begin(); 1558 for ( ; i != end(); i++ ) 1559 { 1560 PostEffect *effect = static_cast<PostEffect*>(*i); 1561 effect->process( state, inOutTex ); 1562 } 1563 1564 if ( mOneFrameOnly ) 1565 mOnThisFrame = false; 1566} 1567 1568bool PostEffect::_setIsEnabled( void *object, const char *index, const char *data ) 1569{ 1570 bool enabled = dAtob( data ); 1571 if ( enabled ) 1572 static_cast<PostEffect*>( object )->enable(); 1573 else 1574 static_cast<PostEffect*>( object )->disable(); 1575 1576 // Always return false from a protected field. 1577 return false; 1578} 1579 1580void PostEffect::enable() 1581{ 1582 // Don't add TexGen PostEffects to the PostEffectManager! 1583 if ( mRenderTime == PFXTexGenOnDemand ) 1584 return; 1585 1586 // Ignore it if its already enabled. 1587 if ( mEnabled ) 1588 return; 1589 1590 mEnabled = true; 1591 1592 // We cannot really enable the effect 1593 // until its been registed. 1594 if ( !isProperlyAdded() ) 1595 return; 1596 1597 // If the enable callback returns 'false' then 1598 // leave the effect disabled. 1599 if ( !onEnabled_callback() ) 1600 { 1601 mEnabled = false; 1602 return; 1603 } 1604 1605 PFXMGR->_addEffect( this ); 1606} 1607 1608void PostEffect::disable() 1609{ 1610 if ( !mEnabled ) 1611 return; 1612 1613 mEnabled = false; 1614 _cleanTargets( true ); 1615 1616 if ( isProperlyAdded() ) 1617 { 1618 PFXMGR->_removeEffect( this ); 1619 onDisabled_callback(); 1620 } 1621} 1622 1623void PostEffect::reload() 1624{ 1625 // Reload the shader if we have one or mark it 1626 // for updating when its processed next. 1627 if ( mShader ) 1628 mShader->reload(); 1629 else 1630 mUpdateShader = true; 1631 1632 // Null stateblock so it is reloaded. 1633 mStateBlock = NULL; 1634 1635 // Call reload on any children 1636 // this PostEffect may have. 1637 for ( U32 i = 0; i < size(); i++ ) 1638 { 1639 PostEffect *effect = (PostEffect*)(*this)[i]; 1640 effect->reload(); 1641 } 1642} 1643 1644void PostEffect::setTexture( U32 index, const String &texFilePath ) 1645{ 1646 // Set the new texture name. 1647 mTexFilename[index] = texFilePath; 1648 mTextures[index].free(); 1649 1650 // Skip empty stages or ones with variable or target names. 1651 if ( texFilePath.isEmpty() || 1652 texFilePath[0] == '$' || 1653 texFilePath[0] == '#' ) 1654 return; 1655 1656 // Try to load the texture. 1657 mTextures[index].set( texFilePath, &PostFxTextureProfile, avar( "%s() - (line %d)", __FUNCTION__, __LINE__ ) ); 1658 1659 mTextureType[index] = NormalTextureType; 1660} 1661 1662void PostEffect::setTexture(U32 index, const GFXTexHandle& texHandle) 1663{ 1664 // Set the new texture name. 1665 mTexFilename[index] = ""; 1666 mTextures[index].free(); 1667 1668 // Skip empty stages or ones with variable or target names. 1669 if (!texHandle.isValid()) 1670 return; 1671 1672 // Try to load the texture. 1673 mTextures[index] = texHandle; 1674 1675 mTextureType[index] = NormalTextureType; 1676} 1677 1678void PostEffect::setCubemapTexture(U32 index, const GFXCubemapHandle &cubemapHandle) 1679{ 1680 // Set the new texture name. 1681 mCubemapTextures[index].free(); 1682 1683 // Skip empty stages or ones with variable or target names. 1684 if (cubemapHandle.isNull()) 1685 return; 1686 1687 // Try to load the texture. 1688 mCubemapTextures[index] = cubemapHandle; 1689 1690 mTextureType[index] = CubemapType; 1691} 1692 1693void PostEffect::setCubemapArrayTexture(U32 index, const GFXCubemapArrayHandle &cubemapArrayHandle) 1694{ 1695 // Set the new texture name. 1696 mCubemapArrayTextures[index].free(); 1697 1698 // Skip empty stages or ones with variable or target names. 1699 if (cubemapArrayHandle.isNull()) 1700 return; 1701 1702 // Try to load the texture. 1703 mCubemapArrayTextures[index] = cubemapArrayHandle; 1704 1705 mTextureType[index] = CubemapArrayType; 1706} 1707 1708void PostEffect::setShaderConst( const String &name, const String &val ) 1709{ 1710 PROFILE_SCOPE( PostEffect_SetShaderConst ); 1711 1712 EffectConstTable::Iterator iter = mEffectConsts.find( name ); 1713 if ( iter == mEffectConsts.end() ) 1714 { 1715 EffectConst *newConst = new EffectConst( name, val ); 1716 iter = mEffectConsts.insertUnique( name, newConst ); 1717 } 1718 1719 iter->value->set( val ); 1720} 1721 1722void PostEffect::setShaderConst(const String &name, const F32 &val) 1723{ 1724 PROFILE_SCOPE(PostEffect_SetShaderConst_Float); 1725 1726 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1727 if (iter == mEffectConsts.end()) 1728 { 1729 EffectConst *newConst = new EffectConst(name, val); 1730 iter = mEffectConsts.insertUnique(name, newConst); 1731 } 1732 1733 iter->value->set(val); 1734} 1735 1736void PostEffect::setShaderConst(const String& name, const int& val) 1737{ 1738 PROFILE_SCOPE(PostEffect_SetShaderConst_Int); 1739 1740 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1741 if (iter == mEffectConsts.end()) 1742 { 1743 EffectConst* newConst = new EffectConst(name, val); 1744 iter = mEffectConsts.insertUnique(name, newConst); 1745 } 1746 1747 iter->value->set(val); 1748} 1749 1750void PostEffect::setShaderConst(const String &name, const Point4F &val) 1751{ 1752 PROFILE_SCOPE(PostEffect_SetShaderConst_Point); 1753 1754 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1755 if (iter == mEffectConsts.end()) 1756 { 1757 EffectConst *newConst = new EffectConst(name, val); 1758 iter = mEffectConsts.insertUnique(name, newConst); 1759 } 1760 1761 iter->value->set(val); 1762} 1763 1764void PostEffect::setShaderConst(const String &name, const MatrixF &val) 1765{ 1766 PROFILE_SCOPE(PostEffect_SetShaderConst_Matrix); 1767 1768 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1769 if (iter == mEffectConsts.end()) 1770 { 1771 EffectConst *newConst = new EffectConst(name, val); 1772 iter = mEffectConsts.insertUnique(name, newConst); 1773 } 1774 1775 iter->value->set(val); 1776} 1777 1778void PostEffect::setShaderConst(const String &name, const Vector<Point4F> &val) 1779{ 1780 PROFILE_SCOPE(PostEffect_SetShaderConst_PointArray); 1781 1782 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1783 if (iter == mEffectConsts.end()) 1784 { 1785 EffectConst *newConst = new EffectConst(name, val); 1786 iter = mEffectConsts.insertUnique(name, newConst); 1787 } 1788 1789 iter->value->set(val); 1790} 1791 1792void PostEffect::setShaderConst(const String &name, const Vector<MatrixF> &val) 1793{ 1794 PROFILE_SCOPE(PostEffect_SetShaderConst_MatrixArray); 1795 1796 EffectConstTable::Iterator iter = mEffectConsts.find(name); 1797 if (iter == mEffectConsts.end()) 1798 { 1799 EffectConst *newConst = new EffectConst(name, val); 1800 iter = mEffectConsts.insertUnique(name, newConst); 1801 } 1802 1803 iter->value->set(val); 1804} 1805 1806F32 PostEffect::getAspectRatio() const 1807{ 1808 const Point2I &rtSize = GFX->getActiveRenderTarget()->getSize(); 1809 return (F32)rtSize.x / (F32)rtSize.y; 1810} 1811 1812void PostEffect::_checkRequirements() 1813{ 1814 // This meets requirements if its shader loads 1815 // properly, we can find all the input textures, 1816 // and its formats are supported. 1817 1818 mIsValid = false; 1819 mUpdateShader = false; 1820 mShader = NULL; 1821 mShaderConsts = NULL; 1822 EffectConstTable::Iterator iter = mEffectConsts.begin(); 1823 for ( ; iter != mEffectConsts.end(); iter++ ) 1824 { 1825 iter->value->mDirty = true; 1826 iter->value->mHandle = NULL; 1827 } 1828 1829 // First make sure the target format is supported. 1830 if ( mNamedTarget.isRegistered() ) 1831 { 1832 Vector<GFXFormat> formats; 1833 formats.push_back( mTargetFormat ); 1834 GFXFormat format = GFX->selectSupportedFormat( &PostFxTargetProfile, 1835 formats, 1836 true, 1837 false, 1838 false ); 1839 1840 // If we didn't get our format out then its unsupported! 1841 if ( format != mTargetFormat ) 1842 return; 1843 } 1844 1845 // Gather macros specified on this PostEffect. 1846 Vector<GFXShaderMacro> macros( mShaderMacros ); 1847 1848 // Now check the input named targets and make sure 1849 // they exist... else we're invalid. 1850 for ( U32 i=0; i < NumTextures; i++ ) 1851 { 1852 if (mTextureType[i] == NormalTextureType) 1853 { 1854 const String &texFilename = mTexFilename[i]; 1855 1856 if (texFilename.isNotEmpty() && texFilename[0] == '#') 1857 { 1858 NamedTexTarget *namedTarget = NamedTexTarget::find(texFilename.c_str() + 1); 1859 if (!namedTarget) 1860 { 1861 return; 1862 } 1863 1864 // Grab the macros for shader initialization. 1865 namedTarget->getShaderMacros(¯os); 1866 } 1867 } 1868 } 1869 1870 // Finally find and load the shader. 1871 ShaderData *shaderData; 1872 if ( Sim::findObject( mShaderName, shaderData ) ) 1873 if ( shaderData->getPixVersion() <= GFX->getPixelShaderVersion() ) 1874 mShader = shaderData->getShader( macros ); 1875 1876 // If we didn't get a shader... we're done. 1877 if ( !mShader ) 1878 return; 1879 1880 // If we got here then we're valid. 1881 mIsValid = true; 1882} 1883 1884bool PostEffect::dumpShaderDisassembly( String &outFilename ) const 1885{ 1886 String data; 1887 1888 if ( !mShader || !mShader->getDisassembly( data ) ) 1889 return false; 1890 1891 outFilename = FS::MakeUniquePath( "", "ShaderDisassembly", "txt" ); 1892 1893 FileStream *fstream = FileStream::createAndOpen( outFilename, Torque::FS::File::Write ); 1894 if ( !fstream ) 1895 return false; 1896 1897 fstream->write( data ); 1898 fstream->close(); 1899 delete fstream; 1900 1901 return true; 1902} 1903 1904SimSet* PostEffect::getSet() const 1905{ 1906 SimSet *set; 1907 if ( !Sim::findObject( "PFXSet", set ) ) 1908 { 1909 set = new SimSet(); 1910 set->registerObject( "PFXSet" ); 1911 Sim::getRootGroup()->addObject( set ); 1912 } 1913 1914 return set; 1915} 1916 1917void PostEffect::setShaderMacro( const String &name, const String &value ) 1918{ 1919 // Check to see if we already have this macro. 1920 Vector<GFXShaderMacro>::iterator iter = mShaderMacros.begin(); 1921 for ( ; iter != mShaderMacros.end(); iter++ ) 1922 { 1923 if ( iter->name == name ) 1924 { 1925 if ( iter->value != value ) 1926 { 1927 iter->value = value; 1928 mUpdateShader = true; 1929 } 1930 return; 1931 } 1932 } 1933 1934 // Add a new macro. 1935 mShaderMacros.increment(); 1936 mShaderMacros.last().name = name; 1937 mShaderMacros.last().value = value; 1938 mUpdateShader = true; 1939} 1940 1941bool PostEffect::removeShaderMacro( const String &name ) 1942{ 1943 Vector<GFXShaderMacro>::iterator iter = mShaderMacros.begin(); 1944 for ( ; iter != mShaderMacros.end(); iter++ ) 1945 { 1946 if ( iter->name == name ) 1947 { 1948 mShaderMacros.erase( iter ); 1949 mUpdateShader = true; 1950 return true; 1951 } 1952 } 1953 1954 return false; 1955} 1956 1957void PostEffect::clearShaderMacros() 1958{ 1959 if ( mShaderMacros.empty() ) 1960 return; 1961 1962 mShaderMacros.clear(); 1963 mUpdateShader = true; 1964} 1965 1966GFXTextureObject* PostEffect::_getTargetTexture( U32 ) 1967{ 1968 // A TexGen PostEffect will generate its texture now if it 1969 // has not already. 1970 if ( mRenderTime == PFXTexGenOnDemand && 1971 ( !mTargetTex || mUpdateShader ) ) 1972 { 1973 GFXTexHandle chainTex; 1974 process( NULL, chainTex ); 1975 1976 // TODO: We should add a conditional copy 1977 // to a non-RT texture here to reduce the 1978 // amount of non-swappable RTs in use. 1979 } 1980 1981 return mTargetTex.getPointer(); 1982} 1983 1984DefineEngineMethod( PostEffect, reload, void, (),, 1985 "Reloads the effect shader and textures." ) 1986{ 1987 return object->reload(); 1988} 1989 1990DefineEngineMethod( PostEffect, enable, void, (),, 1991 "Enables the effect." ) 1992{ 1993 object->enable(); 1994} 1995 1996DefineEngineMethod( PostEffect, disable, void, (),, 1997 "Disables the effect." ) 1998{ 1999 object->disable(); 2000} 2001 2002DefineEngineMethod( PostEffect, toggle, bool, (),, 2003 "Toggles the effect between enabled / disabled.\n" 2004 "@return True if effect is enabled." ) 2005{ 2006 if ( object->isEnabled() ) 2007 object->disable(); 2008 else 2009 object->enable(); 2010 2011 return object->isEnabled(); 2012} 2013 2014DefineEngineMethod( PostEffect, isEnabled, bool, (),, 2015 "@return True if the effect is enabled." ) 2016{ 2017 return object->isEnabled(); 2018} 2019 2020DefineEngineMethod( PostEffect, setTexture, void, ( S32 index, const char *filePath ),, 2021 "This is used to set the texture file and load the texture on a running effect. " 2022 "If the texture file is not different from the current file nothing is changed. If " 2023 "the texture cannot be found a null texture is assigned.\n" 2024 "@param index The texture stage index.\n" 2025 "@param filePath The file name of the texture to set.\n" ) 2026{ 2027 if ( index > -1 && index < PostEffect::NumTextures ) 2028 object->setTexture( index, filePath ); 2029} 2030 2031DefineEngineMethod( PostEffect, setShaderConst, void, ( const char* name, const char* value ),, 2032 "Sets the value of a uniform defined in the shader. This will usually " 2033 "be called within the setShaderConsts callback. Array type constants are " 2034 "not supported.\n" 2035 "@param name Name of the constanst, prefixed with '$'.\n" 2036 "@param value Value to set, space seperate values with more than one element.\n" 2037 "@tsexample\n" 2038 "function MyPfx::setShaderConsts( %this )\n" 2039 "{\n" 2040 " // example float4 uniform\n" 2041 " %this.setShaderConst( \"$colorMod\", \"1.0 0.9 1.0 1.0\" );\n" 2042 " // example float1 uniform\n" 2043 " %this.setShaderConst( \"$strength\", \"3.0\" );\n" 2044 " // example integer uniform\n" 2045 " %this.setShaderConst( \"$loops\", \"5\" );" 2046 "}\n" 2047 "@endtsexample" ) 2048{ 2049 object->setShaderConst( name, value ); 2050} 2051 2052DefineEngineMethod( PostEffect, getAspectRatio, F32, (),, 2053 "@return Width over height of the backbuffer." ) 2054{ 2055 return object->getAspectRatio(); 2056} 2057 2058DefineEngineMethod( PostEffect, dumpShaderDisassembly, String, (),, 2059 "Dumps this PostEffect shader's disassembly to a temporary text file.\n" 2060 "@return Full path to the dumped file or an empty string if failed." ) 2061{ 2062 String fileName; 2063 object->dumpShaderDisassembly( fileName ); 2064 2065 return fileName; 2066} 2067 2068DefineEngineMethod( PostEffect, setShaderMacro, void, ( const char* key, const char* value ), ( "" ), 2069 "Adds a macro to the effect's shader or sets an existing one's value. " 2070 "This will usually be called within the onAdd or preProcess callback.\n" 2071 "@param key lval of the macro." 2072 "@param value rval of the macro, or may be empty." 2073 "@tsexample\n" 2074 "function MyPfx::onAdd( %this )\n" 2075 "{\n" 2076 " %this.setShaderMacro( \"NUM_SAMPLES\", \"10\" );\n" 2077 " %this.setShaderMacro( \"HIGH_QUALITY_MODE\" );\n" 2078 " \n" 2079 " // In the shader looks like... \n" 2080 " // #define NUM_SAMPLES 10\n" 2081 " // #define HIGH_QUALITY_MODE\n" 2082 "}\n" 2083 "@endtsexample" ) 2084{ 2085 object->setShaderMacro( key, value ); 2086} 2087 2088DefineEngineMethod( PostEffect, removeShaderMacro, void, ( const char* key ),, 2089 "Remove a shader macro. This will usually be called within the preProcess callback.\n" 2090 "@param key Macro to remove." ) 2091{ 2092 object->removeShaderMacro( key ); 2093} 2094 2095DefineEngineMethod( PostEffect, clearShaderMacros, void, (),, 2096 "Remove all shader macros." ) 2097{ 2098 object->clearShaderMacros(); 2099} 2100 2101DefineEngineFunction( dumpRandomNormalMap, void, (),, 2102 "Creates a 64x64 normal map texture filled with noise. The texture is saved " 2103 "to randNormTex.png in the location of the game executable.\n\n" 2104 "@ingroup GFX") 2105{ 2106 GFXTexHandle tex; 2107 2108 tex.set( 64, 64, GFXFormatR8G8B8A8, &GFXTexturePersistentProfile, "" ); 2109 2110 GFXLockedRect *rect = tex.lock(); 2111 U8 *f = rect->bits; 2112 2113 for ( U32 i = 0; i < 64*64; i++, f += 4 ) 2114 { 2115 VectorF vec; 2116 2117 vec.x = mRandF( -1.0f, 1.0f ); 2118 vec.y = mRandF( -1.0f, 1.0f ); 2119 vec.z = mRandF( -1.0f, 1.0f ); 2120 2121 vec.normalizeSafe(); 2122 2123 f[0] = U8_MAX * ( ( 1.0f + vec.x ) * 0.5f ); 2124 f[1] = U8_MAX * ( ( 1.0f + vec.y ) * 0.5f ); 2125 f[2] = U8_MAX * ( ( 1.0f + vec.z ) * 0.5f ); 2126 f[3] = U8_MAX; 2127 } 2128 2129 tex.unlock(); 2130 2131 String path = Torque::FS::MakeUniquePath( "", "randNormTex", "png" ); 2132 tex->dumpToDisk( "png", path ); 2133} 2134