summaryrefslogtreecommitdiffstats
path: root/Studio/Content/Effect Library/HDRBloomTonemap.effect
diff options
context:
space:
mode:
Diffstat (limited to 'Studio/Content/Effect Library/HDRBloomTonemap.effect')
-rw-r--r--Studio/Content/Effect Library/HDRBloomTonemap.effect282
1 files changed, 282 insertions, 0 deletions
diff --git a/Studio/Content/Effect Library/HDRBloomTonemap.effect b/Studio/Content/Effect Library/HDRBloomTonemap.effect
new file mode 100644
index 0000000..4424393
--- /dev/null
+++ b/Studio/Content/Effect Library/HDRBloomTonemap.effect
@@ -0,0 +1,282 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<Effect>
+ <MetaData>
+ <Property name="GammaValue" formalName="Gamma" default="2.2" min="0.1" max="4"/>
+ <Property name="Exposure" min="-9" max="9" default="0"/>
+
+ <Property name="BloomThreshold" formalName="Bloom Threshold" description="Objects brighter than this will\ngenerate a bloom" default="1.0" />
+ <Property name="BlurFalloff" formalName="Bloom Falloff" description="Size of the bloom. Smaller\nnumber means larger bloom." default="0" min="0" max="10"/>
+
+ <Property name="TonemappingLerp" formalName="Effect Amount" description="Adjust between no change and\nfull effect." default="1" min="0" max="1" hidden="True"/>
+
+ <!--
+ <Property name="Key" formalName="Luminance Key" min="0" max="1" default="0.04"/>
+ <Property name="expLum" formalName="Exposure Luminance" default="2.0"/>
+ <Property name="TonemappingLod" formalName="Tonemapping adaptation rate" default="10" min="0" max="20"/>
+ -->
+ <Property name="ChannelThreshold" formalName="Channel Threshold" hidden="True" description="Channel threshold" default="1.0" />
+ <Property name="PoissonRotation" hidden="True" default="0"/>
+ <Property name="PoissonDistance" hidden="True" default="4"/>
+ <Property name="Downsample2" filter="linear" clamp="clamp" type="Texture" />
+ <Property name="Downsample4" filter="linear" clamp="clamp" type="Texture" />
+
+ </MetaData>
+ <Shaders>
+ <Shared>
+#include "blur.glsllib"
+#include "luminance.glsllib"
+float get_blur_falloff() { return exp2( -BlurFalloff ); }
+float get_exposure() { return exp2( Exposure ); }
+ </Shared>
+ <Shader name="LUMINOSITY">
+ <VertexShader>
+vec2 ToRotatedPoissonTexCoord( vec3 poisson, vec2 inputTex, vec2 inc, mat2 rotation )
+{
+ vec2 rotatedPoisson = rotation * vec2( poisson.xy );
+ return vec2( inputTex.x + rotatedPoisson.x * inc.x, inputTex.y + rotatedPoisson.y * inc.y );
+}
+
+void SetupPoissonBlurCoordsRotation(float inBlurAmount, vec2 inTexInfo, float inRotationRadians )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ float rotCos = cos( inRotationRadians );
+ float rotSin = sin( inRotationRadians );
+ mat2 rotMatrix = mat2( rotCos, rotSin, -rotSin, rotCos );
+ vec2 incVec = vec2( incX, incY );
+
+ TexCoord0 = ToRotatedPoissonTexCoord( poisson0, TexCoord, incVec, rotMatrix );
+ TexCoord1 = ToRotatedPoissonTexCoord( poisson1, TexCoord, incVec, rotMatrix );
+ TexCoord2 = ToRotatedPoissonTexCoord( poisson2, TexCoord, incVec, rotMatrix );
+ TexCoord3 = ToRotatedPoissonTexCoord( poisson3, TexCoord, incVec, rotMatrix );
+ TexCoord4 = ToRotatedPoissonTexCoord( poisson4, TexCoord, incVec, rotMatrix );
+ TexCoord5 = ToRotatedPoissonTexCoord( poisson5, TexCoord, incVec, rotMatrix );
+ TexCoord6 = ToRotatedPoissonTexCoord( poisson6, TexCoord, incVec, rotMatrix );
+ TexCoord7 = ToRotatedPoissonTexCoord( poisson7, TexCoord, incVec, rotMatrix );
+}
+// No op
+void vert ()
+{
+ SetupPoissonBlurCoordsRotation( 5.0 * get_blur_falloff(), Texture0Info.xy, 0.0);
+}
+ </VertexShader>
+ <FragmentShader>
+
+float cutoff( float color )
+{
+ return color >= BloomThreshold ? color : 0.0;
+}
+vec4 cutoffColor( sampler2D inSampler, vec2 texCoord )
+{
+ vec4 color = GetTextureValue(inSampler, texCoord, 1.0);
+ vec3 exposed_color = color.xyz * get_exposure();
+ vec3 cutoff_color = vec3( cutoff( color.x ), cutoff( color.y ), cutoff( color.z ) );
+ float pixelMult = dot( cutoff_color, cutoff_color ) > 0.0 ? 1.0 : 0.0;
+ return vec4( exposed_color.xyz, color.a ) * pixelMult;
+}
+
+vec4 PoissonBlur(sampler2D inSampler )
+{
+ //flatten out the poisson for this step, we really just want to smear.
+ float mult0 = 1.0;
+ float mult1 = mult0;
+ float mult2 = mult0;
+ float mult3 = mult2;
+ float mult4 = mult2;
+ float mult5 = mult2;
+ float mult6 = mult2;
+ float mult7 = mult2;
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6 + mult7;
+ float multMultiplier = ( multTotal > 0.0 ? 1.0 / multTotal : 0.0 );
+
+ vec4 outColor = cutoffColor( inSampler, TexCoord0 ) * (mult0 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord1 ) * (mult1 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord2 ) * (mult2 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord3 ) * (mult3 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord4 ) * (mult4 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord5 ) * (mult5 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord6 ) * (mult6 * multMultiplier);
+ outColor += cutoffColor( inSampler, TexCoord7 ) * (mult7 * multMultiplier);
+ return outColor;
+}
+
+void frag() // Luminosity pass with exponential color channel decay based on the threshold above.
+{
+ gl_FragColor = PoissonBlur( Texture0 );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="BLUR">
+ <VertexShader>
+
+vec2 ToRotatedPoissonTexCoord( vec3 poisson, vec2 inputTex, vec2 inc, mat2 rotation )
+{
+ vec2 rotatedPoisson = rotation * vec2( poisson.xy );
+ return vec2( inputTex.x + rotatedPoisson.x * inc.x, inputTex.y + rotatedPoisson.y * inc.y );
+}
+
+void SetupPoissonBlurCoordsRotation(float inBlurAmount, vec2 inTexInfo, float inRotationRadians )
+{
+ float incX = inBlurAmount / inTexInfo.x;
+ float incY = inBlurAmount / inTexInfo.y;
+ float rotCos = cos( inRotationRadians );
+ float rotSin = sin( inRotationRadians );
+ mat2 rotMatrix = mat2( rotCos, rotSin, -rotSin, rotCos );
+ vec2 incVec = vec2( incX, incY );
+
+ TexCoord0 = ToRotatedPoissonTexCoord( poisson0, TexCoord, incVec, rotMatrix );
+ TexCoord1 = ToRotatedPoissonTexCoord( poisson1, TexCoord, incVec, rotMatrix );
+ TexCoord2 = ToRotatedPoissonTexCoord( poisson2, TexCoord, incVec, rotMatrix );
+ TexCoord3 = ToRotatedPoissonTexCoord( poisson3, TexCoord, incVec, rotMatrix );
+ TexCoord4 = ToRotatedPoissonTexCoord( poisson4, TexCoord, incVec, rotMatrix );
+ TexCoord5 = ToRotatedPoissonTexCoord( poisson5, TexCoord, incVec, rotMatrix );
+ TexCoord6 = ToRotatedPoissonTexCoord( poisson6, TexCoord, incVec, rotMatrix );
+ TexCoord7 = ToRotatedPoissonTexCoord( poisson7, TexCoord, incVec, rotMatrix );
+}
+
+void vert ()
+{
+ SetupPoissonBlurCoordsRotation( PoissonDistance, Texture0Info.xy, PoissonRotation);
+}
+ </VertexShader>
+ <FragmentShader>
+vec4 PoissonBlur(sampler2D inSampler )
+{
+ float mult0 = (1.0 - poisson0.z);
+ float mult1 = (1.0 - poisson1.z);
+ float mult2 = (1.0 - poisson2.z);
+ float mult3 = (1.0 - poisson3.z);
+ float mult4 = (1.0 - poisson4.z);
+ float mult5 = (1.0 - poisson5.z);
+ float mult6 = (1.0 - poisson6.z);
+ float mult7 = (1.0 - poisson7.z);
+
+ float multTotal = mult0 + mult1 + mult2 + mult3 + mult4 + mult5 + mult6 + mult7;
+ float multMultiplier = ( multTotal > 0.0 ? 1.0 / multTotal : 0.0 ) * get_blur_falloff();
+
+ vec4 outColor = GetTextureValue( inSampler, TexCoord0, 1.0 ) * (mult0 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord1, 1.0 ) * (mult1 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord2, 1.0 ) * (mult2 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord3, 1.0 ) * (mult3 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord4, 1.0 ) * (mult4 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord5, 1.0 ) * (mult5 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord6, 1.0 ) * (mult6 * multMultiplier);
+ outColor += GetTextureValue( inSampler, TexCoord7, 1.0 ) * (mult7 * multMultiplier);
+ return outColor;
+}
+
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ gl_FragColor = PoissonBlur( Texture0 );
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="COMBINER">
+ <FragmentShader>
+ /*
+
+float GetAdaptedLuminance( sampler2D inSampler )
+{
+
+ vec3 col = textureLod( inSampler, TexCoord, TonemappingLod).rgb;
+ return luminance( col );
+}
+
+vec3 GetTonemappedReinhard( sampler2D inSampler, vec3 inSource, vec3 inBlurred )
+{
+ // adapted luminance value
+ float adpLm = GetAdaptedLuminance( inSampler );
+ // luminance of current color
+ float curLm = luminance( inSource.rgb );
+ // relative luminance
+ float relLm = Key/adpLm;
+ // displayable value D
+ float D = (relLm * (1.0 + relLm/(expLum*expLum)) / (1.0 + relLm));
+ // tone map result
+ vec3 color = inBlurred.xyz * relLm;
+ //vec3 gamaColor = pow(color, vec3(1.0/2.2));
+
+ //return gamaColor;
+ return vec3(relLm, relLm, relLm );
+}
+
+vec3 GetTonemappedReinhardSimple( vec3 inSource, vec3 inBlurred )
+{
+ vec3 texColor = inBlurred * 1.0; // Hardcoded Exposure Adjustment
+ texColor = texColor/(1.0 + texColor);
+ vec3 retColor = pow( texColor, vec3(1.0/2.2) );
+ return retColor;
+}
+*/
+
+void frag()
+{
+ vec4 sourceColor = texture2D_0(TexCoord);
+
+
+ vec4 summation = texture2D_Downsample2(TexCoord)
+ + texture2D_Downsample4(TexCoord);
+
+ vec3 bloom_result = sourceColor.xyz * get_exposure() + summation.xyz;
+
+ //Threshold defines the white point for the image which shouldn't be adaptive.
+ vec3 thresholded = clamp( bloom_result.xyz, 0.0, ChannelThreshold ) / ChannelThreshold;
+
+ vec3 tonemapped = pow( thresholded, vec3( 1.0 / GammaValue ) );
+
+ vec3 final_color = mix( thresholded, tonemapped, TonemappingLerp );
+
+ float resultAlpha = max( summation.a, sourceColor.a );
+
+ gl_FragColor = vec4( final_color, resultAlpha );
+
+ /*
+ gl_FragColor = vec4( texture2D_Downsample2(TexCoord).xyz
+ , 1.0 );
+ */
+}
+ </FragmentShader>
+ </Shader>
+ <Shader name="Passthrough">
+ <VertexShader>
+void vert ()
+{
+}
+ </VertexShader>
+ <FragmentShader>
+void frag()
+{
+ //Passing in 1.0 means the value will not get alpha-multiplied again
+ gl_FragColor = GetTextureValue( Texture0, TexCoord, 1.0 );
+}
+ </FragmentShader>
+ </Shader>
+ </Shaders>
+ <Passes>
+ <Buffer name="luminosity_buffer2" format="source" filter="linear" wrap="clamp" size=".5" lifetime="scene"/>
+ <Buffer name="downsample_buffer2" format="source" filter="linear" wrap="clamp" size=".5" lifetime="scene"/>
+ <Buffer name="downsample_buffer4" format="source" filter="linear" wrap="clamp" size=".25" lifetime="scene"/>
+ <Pass shader="LUMINOSITY" input="[source]" output='downsample_buffer2' >
+ </Pass>
+ <Pass shader="LUMINOSITY" input="downsample_buffer2" output='luminosity_buffer2' >
+ </Pass>
+ <!--<Pass shader='Passthrough' input='luminosity_buffer2' />-->
+
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer2">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0"/>
+ </Pass>
+ <Pass shader="BLUR" input="luminosity_buffer2" output="downsample_buffer4">
+ <SetParam name="PoissonDistance" value="4"/>
+ <SetParam name="PoissonRotation" value="0.62831"/>
+ </Pass>
+ <Pass shader="COMBINER" input="[source]">
+ <BufferInput param="Downsample2" value="downsample_buffer2"/>
+ <BufferInput param="Downsample4" value="downsample_buffer4"/>
+ <RenderState name="Stencil" value="false"/>
+ </Pass>
+ </Passes>
+</Effect>
+