Builtin Library
README.md
contrastAdaptiveSharpen
One compute pass, five taps per pixel, at afterLighting order 510 with its
composite at 512 — after the antialiasing resolve at 500, since the resolve
softens edges and this is what puts the acuity back.
The kernel
Each pixel is recombined with its four neighbours:
out = ((b + d + f + h) * w + e) / (1 + 4w)
w is negative, which is what steepens the local gradient.
Why w is not a constant
A fixed negative lobe overshoots. Subtracting the neighbourhood from a pixel already near black or white pushes it past the range its neighbours occupy, and that overshoot is the bright fringe an unsharp mask leaves along a hard edge.
So w is scaled by how much headroom the neighbourhood has left:
headroom = min(mn, 2 - mx) / mx
w = sqrt(headroom) * mix(-0.125, -0.2, sharpness)
mn and mx are the neighbourhood minimum and maximum. The term is near 1 in
flat midtones and near 0 at an edge that already spans the range, so texture
sharpens hard and hard edges are left nearly alone. The square root widens the
useful range — without it the lobe collapses long before the neighbourhood
actually runs out of room.
Everything is per channel. A saturated red edge still has headroom in green and blue, and treating the channels together would either clip the red or waste the other two.
Inputs
@scene.color and the sharpen_params buffer packed by
@builtin::systems.sharpening.sharpening.