# Dither Morph

Aperveil / Light, shaped for the web.

A WebGPU form that keeps changing — twelve geometric and organic shapes — lit as a solid and printed in ordered Bayer pixels, a 45° halftone, or surface-stable dots that ride the form at one spacing on screen.

[Aperveil integration guide](https://www.aperveil.com/docs)

## What it does

The form is a signed distance field that travels through twelve shapes, holding each and then flowing into the next, because a blend of two distance fields is a surface too — so the morph has no seams, and a slow three-sine breathing keeps even the held shape alive. It is lit as a solid, by a key, its own occlusion, a highlight and a rim, and only then is the light turned into ink. Bayer samples the form once per cell and compares that cell's light with an 8×8 threshold built by interleaving the bits of x⊕y and y, so every level adds dots as evenly as the grid allows. Halftone turns the grid 45° and sizes each dot so its area is the light, r = s√(L/π). Surface puts the dots on the form itself and keeps their spacing on screen constant: a power-of-two lattice is chosen from how much of the form one pixel covers, and between two levels the finer one's extra dots leave in Bayer order, three of every four, so a lattice doubles without a dot jumping. Ink reproduces light either way round: a dot lighter than the ground stands for light, a darker one for shadow, the way ink on paper does.

## Choose it for

Give a developer tool, a music release or a retro-leaning product page a hero object with character: it never holds one shape for long, and it prints like a screen from before colour. Keep the copy on the open ground beside it.

## Limits

The shapes are analytic and the light is one key with a rim — there are no cast shadows and no reflections. Surface dots are projected along the dominant axis of the normal, so they seam where that axis changes, and the method follows Rune Skovbo Johansen's surface-stable fractal dithering without its 3D pattern texture or anisotropic dot stretching. Bayer and Halftone are screen-space: they are stable because the camera never moves.

## Current look

Default. Color Looks change colors only; motion, geometry and typography remain unchanged.

[Open editor](https://www.aperveil.com/shaders/dither-morph/edit?look=default&scene=landing)

## Landing scene

This preview uses `position`: [0.7,0.5], `size`: 0.62. The editor link carries these settings with your Look. Direct editor visits use the product defaults; Reset all restores those defaults.

## Install

Download the Export Kit from the editor. No shader-specific npm package or CLI is published yet.

```sh
npm install ./vendor/aperveil-runtime-0.1.0.tgz ./vendor/aperveil-react-0.1.0.tgz
```

Every control in the editor is a typed prop. Leave a prop out to keep the value you exported; change one and the running shader updates without restarting. Give the surface a size and pass fallback for browsers without WebGPU.

```tsx
"use client";

import DitherMorph from "./DitherMorph";

export default function Hero() {
  return (
    <DitherMorph
      className="hero-shader"
      cell={4} colorDot="#e9e4d6"
      fallback={<div className="hero-shader-fallback" />}
    />
  );
}

// .hero-shader { width: 100%; height: 560px; }
```

Component props: `pattern`, `cell`, `accent`, `position`, `size`, `morphSpeed`, `hold`, `wobble`, `spin`, `tilt`, `lightAngle`, `lightHeight`, `exposure`, `contrast`, `rim`, `interaction`, `colorDot`, `colorAccent`, `background`, `opacity`, `backgroundOpacity`, `className`, `style`, `paused`, `fallback`, `onReady`, `onError`.

Raw WGSL is included for a custom WebGPU host; it is not CSS. Keep semantic headings and links in HTML.

## Controls

- Pattern (`pattern`, radio): How the light becomes ink: ordered Bayer pixels, a 45° halftone of dots sized by area, or dots that belong to the form's surface and keep one spacing on screen.
- Cell size (`cell`, slider): Size of one dither cell, or the dot spacing, in device pixels.
- Accent (`accent`, slider): How much of the brightest light is printed in the accent colour.
- Position (`position`, xy): default [0.5,0.5]
- Form size (`size`, slider): Size of the form in the frame.
- Morph rate (`morphSpeed`, slider): Shapes per second. Each shape is held, then flows into the next; all twelve come round in turn.
- Hold (`hold`, slider): Share of each shape's turn spent holding it before it starts flowing into the next.
- Breathing (`wobble`, slider): How far the surface breathes in slow standing waves on top of the morph.
- Turn (`spin`, slider): How fast the form turns.
- Tilt (`tilt`, slider): How far the form leans toward the camera, in degrees.
- Light direction (`lightAngle`, slider): Direction the key light comes from, in degrees.
- Light height (`lightHeight`, slider): How high the key light sits; higher lights shade the form more evenly.
- Exposure (`exposure`, slider): Scales the light before it is turned into ink.
- Contrast (`contrast`, slider): Curve applied to the light before dithering. Above one pushes the midtones down, so the shadows open into bare ground.
- Rim light (`rim`, slider): Light along the silhouette, which keeps the edge of the form printed against the ground.
- Pointer turn (`interaction`, slider): How far the pointer turns the form toward it.
- Ink (`colorDot`, color): Colour of the printed dots.
- Accent (`colorAccent`, color): Colour the dots take on in the brightest highlights.
- Ground (`background`, color): Paper colour behind the dots.
- Opacity (`opacity`, slider): default 1
- Background opacity (`backgroundOpacity`, slider): default 1

## Compatibility

WebGPU rendering requires a supported browser and secure context. The landing shows a real poster for the selected Look when live rendering is unavailable. The standard exported component does not bundle a poster fallback. Supply your own fallback in the host layout. Text exports also retain readable HTML typography.

## Performance

2.425 ms GPU timestamp median; p95 3.67 ms. 1440x900 @ dpr 2; Metal driver on macOS Version 26.6.2 (Build 25G83); measured 2026-09-18. This is a recorded headless sample, not a browser FPS or mobile-performance guarantee.

## Questions

### How does it change shape without a seam?

Each shape is a signed distance field, and a weighted mix of two distance fields is itself a surface that moves from one to the other. The form holds each shape for part of its turn, then flows into the next; Hold sets how long it stays.

### What is the difference between the three patterns?

Bayer prints one flat sample per cell against an 8×8 ordered threshold, the pixel look. Halftone prints round dots on a grid turned 45°, each with the area of its light. Surface prints dots that belong to the form, so they travel with it as it turns, while a fractal lattice keeps their spacing on screen the same.

### Why don't the surface dots swim or pop as the form turns?

The lattice lives in the form's own coordinates, so dots travel with it. When the form comes nearer or turns away, the lattice level changes by a power of two, and the in-between dots fade out in Bayer order until only the coarser level remains — no dot ever jumps to a new place.

### Why does the Newsprint Look put more ink on the shadows?

Because its ink is darker than its paper. Ink reproduces light either way round: light dots on a dark ground stand for light, dark dots on a light ground stand for shadow, so the lit faces print almost bare paper. The accent then goes to the deepest shadow, like a second plate.

### What does the cursor do?

It turns the form toward it. The morph and the slow spin carry on underneath.

### What happens without WebGPU?

This landing shows a still poster of your selected Color Look. The raw WGSL needs a WebGPU host. Landing posters are not bundled in the Export Kit: add your own fallback around the exported component.

### Can I use this shader commercially?

Part of the Free collection for Aperveil 1.0. Public live preview and Color Looks are open. Free Export Kits do not require an account. Purchasing is not available yet. Follow the license notices supplied with the source you download. The planned Free collection permits personal and commercial interface projects. An alpha access grant is not a purchase or a replacement for those license terms.

## License

Part of the Free collection for Aperveil 1.0. Public live preview and Color Looks are open. Free Export Kits do not require an account. Purchasing is not available yet. Follow the license notices supplied with the source you download. The planned Free collection permits personal and commercial interface projects. An alpha access grant is not a purchase or a replacement for those license terms.

## Related shaders

- [Dither](https://www.aperveil.com/shaders/dither)
- [Halftone](https://www.aperveil.com/shaders/halftone)
- [Moiré Flow](https://www.aperveil.com/shaders/gyroid-bloom)
