#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 );
}