Skip to content

Render Modes

glyphcss has three render modes. Each maps the same projected mesh to a different glyph layout.

ModeBest forCost
wireframeGeometric meshes, lattices, line artScales with edge count
solidSmooth-shaded surfaces from real mesh filesScales with triangle count × grid cells
voxelMagicaVoxel .vox files, chunky low-polyScales with visible voxel faces

Bresenham-rasterizes each edge into a Uint8Array stamp with three weight tiers, then maps the stamp to glyphs:

WeightGlyph paletteUsed for
1 (thin)·⋅∙˙·⋅∙Spokes, inner lattice, decorative scaffolding
2 (normal)╋╬┼╳◆◇◊▲△▼▽◈⬡⬢∴∵⊥⊕⊗⊙⊚⊛Main cage edges
3 (core)✦✧✩◉⊙◎Focal accents, “sun” centre
import { GlyphCamera, GlyphScene, GlyphMesh, GlyphOrbitControls } from "@glyphcss/react";
import { icosahedronPolygons } from "@glyphcss/core";
const icosa = icosahedronPolygons({ center: [0, 0, 0], size: 1, color: "#44ffcc" });
export function WireframeDemo() {
return (
<GlyphCamera rotX={25}>
<GlyphScene mode="wireframe" cols={80} rows={24}>
<GlyphOrbitControls />
<GlyphMesh polygons={icosa} />
</GlyphScene>
</GlyphCamera>
);
}

Best for: geometric meshes, lattices, iconic visuals.

Triangle scan-fill, with Lambert shading per cell mapped to a ramp:

" .:-=+*#%@"

Darker glyphs for cells facing away from the directional light, brighter glyphs for cells facing it. Per-cell normal is interpolated from the triangle’s vertex normals.

import { GlyphCamera, GlyphScene, GlyphMesh, GlyphOrbitControls } from "@glyphcss/react";
import { dodecahedronPolygons } from "@glyphcss/core";
const dodeca = dodecahedronPolygons({ center: [0, 0, 0], size: 1, color: "#cc44ff" });
export function SolidDemo() {
return (
<GlyphCamera rotX={25}>
<GlyphScene
mode="solid"
cols={100}
rows={30}
directionalLight={{ direction: [0.5, 0.7, 0.5], intensity: 1 }}
ambientLight={{ intensity: 0.4 }}
>
<GlyphOrbitControls />
<GlyphMesh polygons={dodeca} />
</GlyphScene>
</GlyphCamera>
);
}

Best for: smooth-shaded surfaces from real mesh files.

One glyph per voxel face, depth-sorted. Natural fit for MagicaVoxel .vox files where the source data is already cell-aligned.

import { GlyphCamera, GlyphScene, GlyphMesh, GlyphOrbitControls } from "@glyphcss/react";
import type { Polygon } from "@glyphcss/core";
// `polygons` comes from parseVox() — load the file outside the component.
// Replace "/tree.vox" with your own MagicaVoxel file path.
export function VoxelDemo({ polygons }: { polygons: Polygon[] }) {
return (
<GlyphCamera rotX={25}>
<GlyphScene mode="voxel" cols={80} rows={24}>
<GlyphOrbitControls />
<GlyphMesh polygons={polygons} />
</GlyphScene>
</GlyphCamera>
);
}

Each face’s color (from the VOX palette) maps to a glyph density — bright colors become # / @, dim colors become . / :. Back faces are culled.

Best for: voxel art, chunky low-poly aesthetics.

Shadows use a shadow-map technique: the rasterizer renders a depth pass from the light’s perspective, then compares each cell’s depth against it. Set shadow on <GlyphScene> to enable, then opt individual meshes in with castShadow and receiveShadow. A mesh with both flags self-shadows. <GlyphGround> defaults to receiveShadow=true.

import {
GlyphPerspectiveCamera,
GlyphScene,
GlyphMesh,
GlyphGround,
} from "@glyphcss/react";
const shadow = { color: "#000000", opacity: 0.25, lift: 0.05 };
const directionalLight = { direction: [0.5, 0.7, 0.5], intensity: 1 };
const ambientLight = { intensity: 0.35 };
export function ShadowDemo() {
return (
<GlyphPerspectiveCamera rotX={45} rotY={30} zoom={50} distance={5}>
<GlyphScene
mode="solid"
cols={100}
rows={30}
directionalLight={directionalLight}
ambientLight={ambientLight}
shadow={shadow}
>
<GlyphMesh geometry="dodecahedron" color="#4488ff"
castShadow
receiveShadow
/>
<GlyphGround />
</GlyphScene>
</GlyphPerspectiveCamera>
);
}

Shadow fields (GlyphShadowOptions):

FieldDefaultDescription
color"#000000"Shadow tint color
opacity0.25Darkness 0..1
lift0.05Depth bias — prevents self-shadow acne on flat lit surfaces
maxExtend2000Half-extent of the light-space projection volume

The <glyph-mesh> custom element and the GlyphMesh component accept a geometry string shortcut for three built-in shapes. These are runtime-internal presets, not public core helpers — for procedural code use the @glyphcss/core generators instead.

ValueShapeNotes
"cuboctahedron"Cuboctahedron with inner latticeDefault demo shape
"icosahedron"Icosahedron, edge-only wireframe20 faces
"cube"Plain cube wireframe6 faces
// Built-in preset (no import needed):
<GlyphMesh geometry="cuboctahedron" />
// Equivalent procedural form (more control):
import { icosahedronPolygons } from "@glyphcss/core";
<GlyphMesh polygons={icosahedronPolygons({ center: [0,0,0], size:1 })} />