#version 450 core // Bloom mix, color grading, ACES tonemap, vignette, chromatic aberration, grain. in vec2 vUV; layout(binding = 0) uniform sampler2D uHdr; layout(binding = 1) uniform sampler2D uBloom; uniform float uBloomStrength; uniform float uBloomNorm; uniform float uExposure; uniform float uContrast; uniform float uSaturation; uniform vec3 uLift; uniform vec3 uGain; uniform float uVignette; uniform float uChromatic; uniform float uGrain; uniform float uTimeSeed; layout(location = 0) out vec4 fragColor; vec3 acesFitted(vec3 x) { const mat3 inM = mat3(0.59719, 0.07600, 0.02840, 0.35458, 0.90834, 0.13383, 0.04823, 0.01566, 0.83777); const mat3 outM = mat3(1.60475, -0.10208, -0.00327, -0.53108, 1.10813, -0.07276, -0.07367, -0.00605, 1.07602); vec3 v = inM * x; vec3 a = v * (v + 0.0245786) - 0.000090537; vec3 b = v * (0.983729 * v + 0.4329510) + 0.238081; return clamp(outM * (a / b), 0.0, 1.0); } float hash12(vec2 p) { vec3 p3 = fract(vec3(p.xyx) * 0.1031); p3 += dot(p3, p3.yzx + 33.33); return fract((p3.x + p3.y) * p3.z); } void main() { vec2 dir = vUV - 0.5; vec3 c; c.r = texture(uHdr, vUV - dir * uChromatic * 2.0).r; c.g = texture(uHdr, vUV).g; c.b = texture(uHdr, vUV + dir * uChromatic * 2.0).b; vec3 bloom = texture(uBloom, vUV).rgb * uBloomNorm; c = mix(c, bloom, uBloomStrength); c *= uExposure; // Contrast in log space around middle grey, then saturation. const float mid = 0.18; c = exp2((log2(max(c, vec3(1e-6))) - log2(mid)) * uContrast + log2(mid)); float l = dot(c, vec3(0.2126, 0.7152, 0.0722)); c = max(mix(vec3(l), c, uSaturation), 0.0); c *= uGain; c = acesFitted(c); c += uLift * (1.0 - c); float v = 1.0 - smoothstep(0.25, 1.1, length(dir * vec2(1.25, 1.0)) * (0.6 + uVignette)); c *= mix(1.0, v, clamp(uVignette * 1.6, 0.0, 1.0)); c = pow(c, vec3(1.0 / 2.2)); c += (hash12(gl_FragCoord.xy + uTimeSeed) - 0.5) * uGrain; fragColor = vec4(c, 1.0); }