Overview
Crust Render is a Rust workspace of seven crates. Each owns one job and knows nothing about the others’ internals.
This section is for readers who want to know how Crust Render works inside: to judge whether it suits a use, to read its code, or to contribute. You don't need it to render.
The Design choices page explains why it is built
this way, and Limitations lists what it doesn't do.
The contributor-level map, with every module and invariant, is
docs/architecture.md
in the repository.
The crates
crust-render (the CLI binary)
│ │
│ ▼
│ crust-assets ──► ptex-rs
│ (file decoders, texture caches)
▼ │
crust-core ◄┘
(USD import, integrator, materials, lights, volumes, guiding)
│ │ │ │ │ │
▼ ▼ ▼ ▼ ▼ ▼
crust-rt crust-mtlx crust-jit utils openqmc-rs openusd,
(kernel) (MaterialX) (JIT) (math) (sampling) opensubdiv-rs
| crate | owns | knows nothing about |
|---|---|---|
crust-rt | geometry, the BVH build, ray intersection, instancing, motion blur | materials, lights, USD |
crust-mtlx | reading .mtlx documents, compiling node graphs into programs, the BSDF closure tree | any Crust type |
crust-jit | compiling MaterialX programs to machine code (optional, the jit feature) | everything but crust-mtlx |
crust-core | USD import, the scene, the integrator, materials, lights, volumes, path guiding, statistics | decoding images, textures or IES files |
crust-assets | every file decoder (EXR, PNG/HDR, Ptex, IES, .tx), the texture tile caches, .tx conversion | the integrator |
crust-render | the command line, logging, the progress bar, writing the EXR and PNG | decoding anything |
utils | stateless math: sampling warps, MIS heuristics, luminance | everything |
Three libraries come from outside the workspace, all pure Rust:
openusdreads and composes USD stages.openqmc-rsis a port of the Academy Software Foundation's OpenQMC quasi-Monte Carlo sampler. It produces exactly the same samples as the C++ library.opensubdiv-rsandptex-rsrefine subdivision surfaces and read Ptex files.
openqmc-rs started inside this repository and was extracted once it had no Crust types
in its interface. crust-rt and crust-mtlx are kept the same way, so that they could be
extracted too.
A render, end to end
- Command line.
crust-renderparses its flags and builds the asset loader, which reads theCRUST_*texture settings. - USD import (
crust-core). A light "index" stage is opened with payloads unloaded, to read the render settings, pick the camera and list the top-level subtrees. Each subtree is then composed on its own masked stage, traversed and dropped. Prims become meshes, spheres, curves, instances, lights, volumes or the camera. Materials are resolved and cached. Every image, Ptex or IES file is decoded bycrust-assets. - Geometry build (
crust-rt). Meshes are either baked into world space or kept as instances, then the top-level acceleration structure is built. - Renderer setup. Light-selection tables are built, plus the learned light cache when
crust:lightSelectionislearned. - Rendering. Tiles run in parallel. For each pixel and sample, a path is traced: intersect, shade the hit once, sample a light, pick the next direction, repeat. Path guiding (training passes) and adaptive sampling (stopping pixels early) wrap that same per-pixel routine.
- Output (
crust-render). The linear EXR and the tone-mapped PNG are written, and the--statsreport is printed.
--stats times each of these phases, and --profile breaks the rendering phase down
further. See Command line.
Where things plug in
The crates meet at a few interfaces. Each has one contract that both sides keep:
| interface | contract |
|---|---|
the kernel's Geometry / SceneBuilder / Scene | modelled on Embree: attach geometry, commit(), then intersect or occluded. A hit is only a geometry id and a primitive id. |
AssetLoader | the host decodes files. Returning nothing means "fall back to the constant value", never an error. |
Texture2D, PtexTexture | texture values come out linear. UDIM tile addressing is the host's job. |
Material | shaded once per path vertex into a ShadingPoint, which answers every later question about that hit |
Light | light sampling and BSDF sampling compute the same density for the same point on a light |
ProgressCallback | the engine reports progress and never prints |