diff options
Diffstat (limited to 'Studio/Content/Effect Library/HDRBloomTonemap.effect')
-rw-r--r-- | Studio/Content/Effect Library/HDRBloomTonemap.effect | 282 |
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> + |