# Color Encoding

```ts
import { createGlyphPerspectiveCamera, createGlyphScene, createGlyphOrbitControls } from "glyphcss";
import { loadMesh, recenterPolygons } from "@glyphcss/core";

const host = document.getElementById("scene");
const camera = createGlyphPerspectiveCamera({ rotX: 65, rotY: 0, zoom: 0.3, distance: 0, perspective: 32000, stretch: 1 });
const scene = createGlyphScene(host, { camera, autoSize: true, mode: "solid", colorEncoding: "atlas" });
scene.output.style.fontSize = "10px";
scene.output.style.lineHeight = "1";
scene.fit();
const { polygons } = await loadMesh("/gallery/glb/Taxi.glb", { solidTextureSamples: false });
scene.add(recenterPolygons(polygons));
createGlyphOrbitControls(scene, { drag: true, wheel: true });
```



Choose Spans or Atlas on the same mesh. `colorEncoding: "atlas"` stores glyph/color pairs as Private Use Area (PUA) code points in a COLR/CPAL color font: one text node per output layer, without color spans.

The text identifies palette slots; `@font-palette-values` maps those slots to colors. Palette swaps can recolor the text without rebuilding the font. Live scenes load the font and manage its CSS automatically; unsupported output falls back to spans.

## The palette: `atlasPalette`

```ts
scene.setOptions({ atlasPalette: ["#172554", "#2563eb", "#93c5fd", "#ffffff"] });
```

Omit this option to derive and pool a palette automatically. Supply an ordered array of `#rrggbb` colors for repeatable slot assignments; stay within the chosen atlas's slot limit.

## Choosing an atlas: `fontAtlas`

```ts
import { createGlyphScene, GLYPH_FONT_ATLAS_ASCII } from "glyphcss";
const scene = createGlyphScene(host, {
  camera, colorEncoding: "atlas", fontAtlas: GLYPH_FONT_ATLAS_ASCII,
});
```

| Atlas | Glyphs | Palette slots |
|---|---|---|
| `GLYPH_FONT_ATLAS` (default) | 212; ASCII plus selected Unicode ramps/edges | 30 |
| `GLYPH_FONT_ATLAS_ASCII` | 94; printable ASCII excluding space | 68 |
| `GLYPH_FONT_ATLAS_BRAILLE_DOTS` | 256 braille patterns as rectangular dots in a 1 × 1.6 cell (used by `@glyphcss/fluid`); set `font-size` and `line-height` to the cell height | 30 |

`fontAtlas` is fixed at scene creation. React/Vue expose the same prop; custom elements take it as a JavaScript property. Space remains ordinary U+0020. A glyph outside the selected atlas triggers span fallback.

## Make an atlas from your own font

This requires a local source build. There is no public live-scene API for registering a custom font payload; passing a new `GlyphFontAtlas` object alone falls back to spans.

1. In `packages/glyphcss/assets/glyph-atlas/build-atlas.py`, change `SRC` to your font's absolute path. The script reads face 0; choose a font you can redistribute.
2. Keep its glyph enumeration and PUA mapping. The universal build requires every enumerated glyph, using the vendored fallback fonts for missing outlines.
3. From the repository root, regenerate the artifacts and rebuild the package:

```sh
python3 -m venv .venv-atlas
.venv-atlas/bin/python -m pip install fonttools brotli
.venv-atlas/bin/python packages/glyphcss/assets/glyph-atlas/build-atlas.py
.venv-atlas/bin/python packages/glyphcss/assets/glyph-atlas/build-atlas.py ascii
pnpm install
pnpm --filter glyphcss build
```

The script writes `atlas.json` (metadata) and `atlas-font.json` (WOFF2 payload); the ASCII invocation writes their `ascii-` counterparts. Your local package's shipped atlas objects then use the rebuilt fonts. Changing the page's CSS font alone cannot change the atlas outlines.

## Fallback and text handling

- Missing font/browser support, uncovered glyphs, or unusable cell colors select spans for the whole output.
- Braille character mode is outside both atlases. Halfblock/quadrant, active weight ramps, semantic output, and disabled colors bypass atlas encoding.
- A glyph-triggered fallback stays latched until `setOptions` touches `colorEncoding`, `atlasPalette`, `mode`, or `charMode`.
- Browser find-in-page cannot match PUA text. Decode it before copying; raw copy otherwise retains private code points.

```ts
import { decodeGlyphAtlasText, glyphAtlasForFamily } from "glyphcss";
const atlas = glyphAtlasForFamily(scene.output.style.fontFamily);
const text = decodeGlyphAtlasText(scene.output.textContent ?? "", atlas);
```

## Static and compiled output

`compileScene` and `GlyphSceneStatic` require an explicit `atlasPalette` and embedder-supplied CSS for atlas output. Use the same atlas for compilation, font CSS, and palette CSS:

```ts
const css = await loadGlyphAtlasFontFaceCss(atlas)
  + buildGlyphAtlasFontPaletteValuesCss("--brand", palette, atlas)
  + `.glyph-output{font-family:"${atlas.family}";font-palette:--brand}`;
```

Both helpers are exported from `glyphcss`; the loader rejects unavailable payloads. Frame-roll, interactive, and field-synth static exporters do not carry atlas options. Atlas removes span overhead; it does not reduce grid cells. See [performance](/guides/performance/).
