Log inGet started
World

Builtin Library

Branchmain
Branchesmainpublish
Commitdd348ac6c3

readme.md

sharpening

Contrast-adaptive sharpening — local acuity restored to a finished frame without the halo an unsharp mask leaves along high-contrast edges.

Layout

AssetIdentityRole
ImageSharpening.component@builtin::systems.sharpening.ImageSharpeningAttach to any entity to sharpen the frame.
sharpening.module@builtin::systems.sharpening.sharpeningStrength, buffer packing, and the pass's lifetime.
contrastAdaptiveSharpen.renderFeature@builtin::systems.sharpening.contrastAdaptiveSharpenThe compute pass (order 510) and its composite (512).

Quick start

local id = entity.spawn("sharpening").id
entity(id).component.add("ImageSharpening", { sharpness = 0.5 })

or directly:

local Sharpening = require("@builtin::systems.sharpening.sharpening")
Sharpening.enable(0.5)

What it does

Each pixel is recombined with its four neighbours through a kernel with a negative outer lobe, which steepens every local gradient.

A fixed kernel 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 fringe an unsharp mask leaves along a hard edge. So the lobe's strength is scaled by how much room the neighbourhood has left — the smaller of the distance to black and the distance to white, over the neighbourhood maximum. That measure 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.

It is computed 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.

Ordering

Runs at afterLighting order 510, after the antialiasing resolve at 500 — the resolve softens edges and this is what puts the acuity back.

Cost

One compute pass, five taps per pixel. At sharpness = 0 the module releases the feature entirely, so a scene that is not sharpening pays nothing and its output is identical to a build without the package.