#include "blur.glsllib" #include "luminance.glsllib" float get_blur_falloff() { return exp2( -BlurFalloff ); } float get_exposure() { return exp2( Exposure ); } 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); } 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 ); } 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); } 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 ); } /* 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 ); */ } void vert () { } void frag() { //Passing in 1.0 means the value will not get alpha-multiplied again gl_FragColor = GetTextureValue( Texture0, TexCoord, 1.0 ); }