Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

wisp-3d overview

wisp-3d is a sibling crate to wisp that adds real-3D rendering — perspective camera, indexed mesh, depth-tested render pass — without touching wisp's 2D scene-graph-ordered draw contract.

Why the sibling-crate split

wisp's render-stage contract has NO depth buffer. Everything draws in scene-graph insertion order, batched per pipeline-type. That's load-bearing for the filter chain's last-wins semantics + the mask system.

3D demands break that contract: a spinning solid needs Z-test so the back face doesn't paint over the front; a PerspectiveCamera needs a view+projection pair; an indexed mesh needs per-vertex normals. wisp-3d introduces those in its own module tree so the 2D contract stays clean.

Surface

flowchart LR
  app["wisp::Application<br/>(shared wgpu device)"]
  cam["Camera3D"]
  mesh["Mesh3D"]
  mat["Material3D"]
  pass["Render3DPass<br/>(MSAA + depth)"]
  app --> pass
  cam --> pass
  mesh --> pass
  mat --> pass
  pass --> out["wgpu::TextureView"]

  classDef ours fill:#312e81,stroke:#4f46e5,color:#e0e7ff
  class cam,mesh,mat,pass ours

First customer

The engmanager.xyz 404 page renders a spinning Catppuccin-palette pyramid via THREE.js (loaded from a jsDelivr CDN). wisp-3d + wisp-3d-web replace that with a same-origin wasm bundle, dropping the third-party JS dep.

Pyramid rendered by wisp-3d's integration test — 5-stop palette ramp + off-white wireframe overlay, port-for-port match of the 404 page's THREE composition

The screenshot above is the committed output of cargo nextest run -p wisp-3d --test render_pyramid — the test color-picks pixels to assert the pyramid actually drew (centre is NOT the background, corners ARE), so the PNG is verified PR-side proof that the integration works on every gate run.

Crate layout

ModulePurposeChapter
cameraCamera3D perspective + ViewProj UBOcamera-3d
meshMesh3D indexed positions/normals + pyramid()mesh-3d
renderRender3DPass depth + MSAArender-3d-pass
materialMaterial3D trait + PaletteRampMaterialmaterial-3d
edgesEdgesMesh + wireframe pipelineedges-mesh
spriteSprite3D (ring/circle/quad), depth-write offsprite-3d
reduced_motionprefers-reduced-motion: reduce query(inline)