A differentiable geometry library for Slang: 2D/3D signed distance fields, typed CSG combinators, raymarching, autodiff surface normals, quaternions, noise, color spaces, and PBR helpers — designed so call-site code reads like geometry, not like inline assembly.
import geom;
// Composition is a value; Slang monomorphises it into one inlined function.
let scene = smoothUnion3(
translated3(Sphere(1.0), float3(1.0, 0.0, 0.0)),
Box3D(float3(0.6)),
0.2
);
let hit = scene.raymarch(ray); // sphere trace + autodiff normal
let n = scene.surfaceNormal(p); // one backward-AD pass, not 6 SDF evals
let d = (Circle(20.0) | Box2D(float2(15.0))).distance(p); // operator CSG- Autodiff-first. SDFs, CSG operators, transforms, noise, colour and BRDF
math are
[Differentiable], kinks included. Aminin a union or anabsin a fold is non-smooth only on a measure-zero set, and Slang pushes a subgradient through it (at an exact tie it splits the gradient evenly between both operands). Lattice indices go throughno_diff(floor(...)), which is exact because they are piecewise constant. What stays out is code whose output has no meaningful derivative, such ashexAxialRoundand the degenerate-input fallbacks insafeNormalizeorquatFromTo; each says so in its doc comment. Surface normals come from one backward-mode pass through the SDF instead of six central-difference evaluations. - Two API styles, one codegen. A functional layer (
sdCircle,opSmoothUnion, …) and a typed-generic layer (Circle,SmoothUnion2<A, B>, operators|/&/-). Slang specialises the generics at compile time, so both styles emit the same machine code — pick per call site. One difference under autodiff: typed shapes are[NoDiffThis], so they differentiate with respect to the query point only. For gradients with respect to shape parameters (radius, offset, blendk), use the functional layer. - Batteries for procedural scenes. Hex-grid math (axial coords, cube rounding), path extrusion along polylines and arbitrary parametric curves (closest-point solved per pixel with bracketed Newton iterations; the closest-point parameter carries its implicit-function derivative, so autodiff normals stay correct for non-circular sections), Perlin/value/Worley noise with compile-time-unrolled FBM, Oklab, ACES, GGX, and a fast terrain erosion filter with analytically tracked slopes.
See geom/README.md for the full API overview.
Every demo in playground/ has a single-file bundle in playground/dist/
with the library inlined. Paste one into the
Slang playground and run —
no install, no build.
Good starting points: csg_2d (typed CSG), raymarch_3d (lit 3D scene),
helix (a user-defined parametric curve extruded into a solid — the library
does the closest-point solve), terrain_3d (FBM heightfield, AD normals,
Oklab altitude ramp, ACES), and advanced_erosion_terrain (the erosion
filter end-to-end — a faithful port of Rune Skovbo Johansen's Shadertoy,
with the filter's analytically tracked slopes driving the shading).
After editing library or demo sources, regenerate the bundles with
scripts/playground-bundle.sh.
Put the geom/ directory on your include path and import the module:
slangc your_shader.slang -I path/to/geom.slang/geom -target metal ...import geom;geom/geom.slang is the public umbrella module; implementation files live
under geom/src/ and are __included into it, so callers see one stable
module.
The known-good compiler is Slang 2026.9.1 — the newest release that builds this library on all five targets (WGSL, GLSL, SPIR-V, HLSL, Metal).
ℹ️ Slang 2026.9.2 and 2026.10 break
__bwd_diffof a member method (shader-slang/slang#11356), which is the natural way to write the library's autodiff normals — and it is what the online Slang playground runs. The library sidesteps the bug (thegradientdefault methods differentiate free-function relays instead ofthis.distance), so validation passes on 2026.7.1 / 2026.9.1 / 2026.9.2 / 2026.10 and the playground bundles load on current compilers. 2026.9.1 remains the most-tested release. If you extend the library: never apply__bwd_diff/__fwd_diffto a member method — route it through a free generic function.
A versioned install with a stable symlink makes the pin painless:
~/.local/slang/
├── 2026.9.1/ # known-good
└── current -> 2026.9.1 # put current/bin on PATH
scripts/validate.shCompiles the test shaders under geom/tests/ to WGSL, GLSL, SPIR-V, HLSL and
Metal with slangc ($SLANGC if set, otherwise slangc on PATH) and
validates the WGSL with naga
(brew install naga-cli or cargo install naga-cli).
geom/tests/compile_test.slang exercises every public symbol;
geom/tests/robustness_test.slang covers degenerate inputs. CI runs the same
script on every push.
| path | contents |
|---|---|
geom/ |
the library — see geom/README.md |
geom/tests/ |
compile + robustness test shaders |
playground/ |
demo shaders for the Slang playground |
playground/dist/ |
generated single-file bundles (library inlined) |
scripts/ |
validation + bundling |
Apache-2.0, with one exception: geom/src/erosion.slang is a port
of Rune Skovbo Johansen's MPL-2.0 erosion filter and remains
MPL-2.0 (MPL applies per file; see that
file's header).
- Inigo Quilez's distance functions: 2D & 3D
- hg_sdf (Mercury)
- Red Blob Games — hexagons
- Slang autodiff documentation
- Fast and Gorgeous Erosion Filter (Rune Skovbo Johansen)