// Bloom: the brightest ink glows, a little. The glow itself is made by the // shell at half resolution and below (bloom-down, bloom-up: a dual Kawase // filter over a bright pass, in linear light) and arrives here in // pardesBloom; this pass adds it to the frame. Only true highlights pass // the threshold, and the strength stays in ยง8.2's budget (at most 5%) and // under pardesCap, so no text or selection loses contrast below its own or // 4.5. Tags, grips, notices and the cursor are left alone (pardesSpare). // It is a Shadertoy file: pardes puts its prefix before it. layout(set = 2, binding = 1) uniform sampler2D pardesBloom; float strength() { return min(pardesByLevel(0.02, 0.035, 0.05), 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; } vec3 glow = texture(pardesBloom, uv).rgb; vec3 col = toLinear(frame.rgb) + glow * strength(); vec3 srgb = toSrgb(col); // Dithered: a glow's long falloff never bands. srgb += (ign(fragCoord) - 0.5) / 255.0 * step(1e-4, dot(glow, vec3(1.0))); fragColor = vec4(clamp(srgb, 0.0, 1.0), frame.a); }