---
name: gradient-engine
description: Build, extract, extend, and reuse configurable WebGL gradient engines based on the PhotoGradient-style architecture. Use when adding generative gradients, palette-driven backgrounds, Bezier or mesh gradients, warp functions, noise controls, deterministic seeds, presets, image palette extraction, or Three.js shader backgrounds.
---

# Gradient Engine

Keep application UI, palette sources, rendering host, and shader mathematics separate.

## Public API

```js
const engine = createGradientEngine({ initialColor, settings });

engine.setSolid(color);
engine.setGradient(palette, positions);
engine.randomize(palette, seed);
engine.setSettings({
  classicPreset,
  gradientType,
  warpShape,
  warpRatio,
  warpSize,
  noiseRatio,
  sigma,
  seed,
});
engine.resize(drawingBufferWidth, drawingBufferHeight);
engine.render(renderer);
engine.dispose();
```

## Gradient Functions

| Name | Index |
|---|---:|
| Simple | 0 |
| Soft Bézier | 1 |
| Mesh Static | 2 |
| Mesh Grid | 3 |
| Enhanced Bézier | 4 |

## Warp Functions

| Name | Index |
|---|---:|
| Simplex Noise | 0 |
| Circular | 1 |
| Value Noise | 2 |
| Worley Noise | 3 |
| FBM Noise | 4 |
| Voronoi Noise | 5 |
| Domain Warping | 6 |
| Waves | 7 |
| Smooth Noise | 8 |
| Oval | 9 |
| Rows | 10 |
| Columns | 11 |
| Flat | 12 |
| Gravity | 13 |

## BookLab Preset

- Gradient: Soft Bézier
- Warp shape: Voronoi Noise
- Warp: `0.4`
- Warp size: `1`
- Noise: `0.08`
- Softness: `0.2`

Randomize changes the deterministic seed and all color-point positions while preserving the palette.

BookLab uses `classicPreset: true`. This bypasses experimental gradient and warp dispatch and preserves the original smooth Soft Bézier + Voronoi shader behavior.

Keep the public integer seed for deterministic point placement, but normalize it before passing it to GLSL. Large integers lose precision in shader floats and produce visible block artifacts in hash noise.

## Palette Sources

The studied PhotoGradient source contains four hand-curated palettes and randomly selects one at startup. It also supports extracting a palette from an uploaded image.

Image extraction quantizes the source into color bins, preserves the dominant color, then reserves palette slots for distinct hue families and a dark neutral. Do not rank raw samples only by saturation or distance from gray: small typography can overpower the actual cover color. Do not rank only by area either: meaningful accent colors can disappear.

## Known Failure Modes

- Do not render an opaque foreground `scene.background` after the gradient scene.
- Pass drawing-buffer dimensions to `resolution`.
- Keep color and position counts synchronized.
- Cache-bust independently served ES modules while developing.
- Do not confuse position randomization with palette randomization.
