Renders shading as an organic two-tone stipple — a blue-noise threshold pattern that dithers between two colors without the visible grid of an ordered matrix, for a natural, hand-stippled look.
JavaScript API:
BlueNoiseDitherColorMap
This is the blue-noise member of the ColorMap family: like every
color-map it turns a driver value into a color, but it quantizes the value and
dithers between two colors using a blue-noise threshold texture, so the dots
scatter evenly with no directional structure or clumping — the quality that
distinguishes it from the regular Bayer grid of
sk-ordered-dither-color-map. (The 64×64 threshold texture is tiled
across the screen, so at a large scale its repeat can become visible.)
Key attributes. low-color/high-color are the two tones. levels is the
number of quantization bands (2 = pure two-tone). scale is the screen-space
size of the noise pattern (larger = coarser stipple). shape and softness are
the same pair sk-halftone-dither-color-map exposes: shape (default
circle) is the dot silhouette — circle draws round dots, square the plain
pixel-block look, diamond a rotated square — and softness ([0, 1],
default 0) anti-aliases the dot edge, from crisp at 0 to feathered, most
visibly at scale > 1 (at scale = 1 a cell is one pixel, so there is nothing
to feather). shadow-dot-density and highlight-dot-density bleed a fraction of
the opposite tone's dots into the darkest / lightest regions, so pure black and
pure white keep a little texture instead of going flat. It emits only the raw
dither color — the consuming sk-tonemap applies its field and base-color
compositing once.
Related. Its two-tone siblings are sk-ordered-dither-color-map
(regular Bayer grid) and sk-halftone-dither-color-map (rotated dot
screen). For a smooth gradient, use sk-ramp-color-map. It is driven by a
sk-tonemap and can be a layer of a sk-composite-color-map.
Serve these docs to run the live example.
WebGPU needs a secure context — open this page via grunt serve
rather than double-clicking the file. The Markup tab works from disk.
<!-- Two spheres, same blue-noise dither (scale="2"). LEFT draws crisp
round dots (shape="circle", softness="0"); RIGHT the same round dots with a
feathered edge (softness="0.7"). Compare the two to read what `softness`
does; set shape="square" to recover the plain pixel-block look. -->
<sk-scene>
<sk-directional-light p="42deg" h="25deg" intensity="1.0"></sk-directional-light>
<sk-ambient-light intensity="0.3"></sk-ambient-light>
<!-- LEFT: crisp round dots. -->
<sk-blue-noise-dither-color-map id="hard" levels="2" scale="2" shape="circle" softness="0"
low-color="#1a2a6c" high-color="#f7e9c4"></sk-blue-noise-dither-color-map>
<sk-tonemap id="tm-hard" color-map="#hard"></sk-tonemap>
<sk-plain-material id="mat-hard" base-color="white" tonemap="#tm-hard"></sk-plain-material>
<sk-sphere radius="1.6" x="-2.2" segments="6">
<sk-surface-paint material="#mat-hard"></sk-surface-paint>
</sk-sphere>
<!-- RIGHT: softened round dots. -->
<sk-blue-noise-dither-color-map id="soft" levels="2" scale="2" shape="circle" softness="0.7"
low-color="#1a2a6c" high-color="#f7e9c4"></sk-blue-noise-dither-color-map>
<sk-tonemap id="tm-soft" color-map="#soft"></sk-tonemap>
<sk-plain-material id="mat-soft" base-color="white" tonemap="#tm-soft"></sk-plain-material>
<sk-sphere radius="1.6" x="2.2" segments="6">
<sk-surface-paint material="#mat-soft"></sk-surface-paint>
</sk-sphere>
</sk-scene>
| Attribute | Type | Default | Description |
|---|---|---|---|
remap-curveanimatable |
<remap-curve> |
— | Reshapes the tone response: a remap-curve descriptor or a pre-built curve. Default none. |
remap-phaseanimatable |
<number> |
0 |
Horizontal remap phase — an animatable scalar that translates the tone |
screen-anchor |
<id-ref> |
— | Node whose projected screen position re-origins the dither screen reference by id |
id |
<id> |
— | The element's unique identifier — the standard HTML global id attribute. |
fieldanimatable |
<id-ref> |
— | Gets the optional field that modulates this color-map's weight reference by id |
levelsanimatable |
<number> |
2 |
Number of quantization levels (>= 2). Default 2. |
scaleanimatable |
<number> |
1 |
Screen-space pattern scale (>= 1). Default 1. |
softnessanimatable |
<number> |
0 |
Anti-aliases the quantization decision, [0, 1]. Default 0 (hard). |
shapeanimatable |
<dither-shape> ("circle" | "square" | "diamond" | "line") |
"circle" |
Dot shape (structural). Default circle. |
shadow-dot-densityanimatable |
<number> |
0 |
Fraction of lit dots persisting into shadows, [0, 0.5). Default 0. |
highlight-dot-densityanimatable |
<number> |
0 |
Fraction of shadow dots persisting into highlights, [0, 0.5). Default 0. |
low-coloranimatable |
<color> |
— | Color for low-value (dark / shadow / dot) bins. Animatable. Default: opaque black. |
high-coloranimatable |
<color> |
— | Color for high-value (bright / lit / background) bins. Animatable. Default: opaque white. |
color-interpolation |
<color-interpolation> ("auto" | "srgb" | "srgb-linear" | "oklab") |
"auto" |
The color space the dither interpolates its low↔high blend in — the |