diff options
Diffstat (limited to 'shaders/post/vignette.glsl')
| -rw-r--r-- | shaders/post/vignette.glsl | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/shaders/post/vignette.glsl b/shaders/post/vignette.glsl new file mode 100644 index 00000000..30dc2e0f --- /dev/null +++ b/shaders/post/vignette.glsl @@ -0,0 +1,38 @@ +// Vignette: the window's corners fall a little into shade, in linear light, +// so the eye settles on the middle. Round, whatever the window's shape; +// nothing within half the way to a corner is touched. At most 28% at the +// far corners (level 3), and never more than pardesCap, so text and its +// selection keep their own contrast or 4.5. Tags, grips, notices and the +// cursor are left alone (pardesSpare): the focus indicators never darken. +// It is a Shadertoy file: pardes puts its prefix before it. + +float strength() { return min(pardesByLevel(0.10, 0.18, 0.28), pardesCap); } + +vec3 toLinear(vec3 c) { + return mix(pow((c + 0.055) / 1.055, vec3(2.4)), c / 12.92, lessThanEqual(c, vec3(0.04045))); +} + +vec3 toSrgb(vec3 c) { + c = max(c, vec3(0.0)); + return mix(1.055 * pow(c, vec3(1.0 / 2.4)) - 0.055, c * 12.92, lessThanEqual(c, vec3(0.0031308))); +} + +float ign(vec2 p) { + return fract(52.9829189 * fract(dot(p, vec2(0.06711056, 0.00583715)))); +} + +void mainImage(out vec4 fragColor, in vec2 fragCoord) { + vec2 uv = fragCoord / iResolution.xy; + vec4 frame = texture(iChannel0, uv); + if (pardesSpared(fragCoord)) { + fragColor = frame; + return; + } + // 0 at the middle, 1 at a corner, on a circle's measure. + vec2 half_size = 0.5 * iResolution.xy; + float r = length(fragCoord - half_size) / length(half_size); + float shade = strength() * pow(smoothstep(0.5, 1.0, r), 1.5); + vec3 srgb = toSrgb(toLinear(frame.rgb) * (1.0 - shade)); + srgb += (ign(fragCoord) - 0.5) / 255.0 * step(1e-4, shade); + fragColor = vec4(clamp(srgb, 0.0, 1.0), frame.a); +} |
