EdgesMesh + wireframe pipeline
Sharp-edge derivation + 1px hairline rendering. Mirrors THREE.EdgesGeometry(geometry, 8°).
Derivation
For every triangle edge:
- Bucket on a 1e-4-quantised endpoint pair (so face-duplicated meshes — the pyramid's "apex appears 4 times" layout — still share edges).
- Count owning triangles.
- Boundary edge (1 triangle): always emit.
- Interior edge (2 triangles): emit iff the angle between their face normals exceeds
angle_threshold_deg. - Non-manifold edge (3+ triangles): always emit (to surface the mesh bug).
The pyramid at 8° produces 8 edges: 4 apex-to-base + 4 base perimeter. The internal diagonal of the square base is coplanar (180° dihedral) so it doesn't make the cut.
Pipeline state
WireframePipeline uses PrimitiveTopology::LineList + carefully tuned depth state:
| Field | Value | Why |
|---|---|---|
depth_compare | LessEqual | edges coincident with the mesh draw on top instead of z-fighting away |
depth_write_enabled | false | wireframe doesn't occlude anything behind |
bias.constant / slope_scale | -1 / -1.0 | push edges toward the viewer to break ties |
cull_mode | None | line segments are 1D, no front/back |
PrimitiveTopology::LineList produces 1-device-pixel-wide lines on every wgpu backend. Wider lines need screen-space-expanded quads (a follow-up — W3D.5.1). For the 404 page this is fine: the THREE version is also 1px (LineBasicMaterial({ linewidth: 1 })).
```admonish warning title="Browser WebGPU bans depth_bias on LineList"
Native wgpu (Metal / Vulkan / DX12) silently accepts a non-zero depth_bias on line topology, so the obvious "push wireframe a hair toward the camera to win z-fight" trick works locally. Browser WebGPU rejects it with depthBias must be 0 when using PrimitiveTopology::LineList and the pipeline never builds — your wireframe vanishes silently.
The WireframePipeline declares depth_compare: Always for that reason. The wireframe layers on top of the mesh's color attachment regardless of depth, which means edges are visible from both front and back of the model. For the 404 pyramid use case (rotating around a single object) this reads identical to a depth-tested edge; for use cases where back-edge hiding matters, the alternatives are front-face cull on the wireframe or per-face edge emission.
