Post

Toaster: Bakery Takes Hours, a Toaster Takes Minutes

GPU voxelizer and path tracer for Unity 6 URP. Triangle-dispatch voxelization, multi-bounce path tracing, froxel fog.

Toaster: Bakery Takes Hours, a Toaster Takes Minutes

Landing Page

I built Toaster because lightmapping in Unity is painfully slow and the results are flat. Bakery is better, but it still takes hours on large scenes, and the output is 2D lightmaps – no volumetric data at all. I wanted colored volumetric fog that responds to scene geometry and multi-bounce light, baked in seconds instead of hours. So I wrote my own pipeline.

Toaster is a lightweight GPU voxelizer and path tracer for Unity 6 URP. It voxelizes your scene, traces light bounces through the voxel grid, and renders the result as raymarched froxel fog. The whole thing runs from compute shaders. No baked lightmaps, no SH decoding, no waiting. Current version is v1.2, codename Crumb (all versions are toaster-themed).

The Pipeline

Four stages, each feeding the next:

1
2
Meta Pass --> Voxelize --> Path Trace --> Froxel Fog
(material)   (compute)    (bounces)     (volume)

Stage 1 – Meta Pass. A CommandBuffer renders each object’s Meta Pass into a temporary render texture. This extracts albedo and emission laid out in UV space. The Meta Pass is the same one Unity uses internally for lightmap baking – every URP Lit material already has it. The trick is setting unity_MetaVertexControl and unity_MetaFragmentControl in the CBUFFER so it actually rasterizes into UV space.

Stage 2 – GPU Voxelization. A compute shader dispatches one thread per triangle. Each thread transforms the triangle to world space, computes its AABB with conservative half-voxel expansion, iterates candidate voxels, and runs a full 13-axis SAT intersection test (Akenine-Moller 2001). On hit, it projects the voxel center onto the triangle plane for barycentric UV interpolation, samples the Meta texture, and writes the color via atomic fixed-point accumulation. A finalize kernel averages the results into an RWTexture3D<float4>.

Stage 3 – Path Tracing. For each occupied voxel, the tracer shoots N rays using Halton sequences for low-discrepancy sampling. Rays march through the grid with DDA (the same algorithm Wolfenstein 3D used). Each ray checks direct visibility to scene lights, and on surface hits, samples the albedo grid and bounces again for color bleeding. Wang hash seeding gives per-voxel temporal variation.

Stage 4 – Froxel Fog. A Frostbite-style froxel volume renderer samples the baked 3D lighting texture. Beer-Lambert absorption, Henyey-Greenstein phase function for anisotropic scattering, temporal reprojection for stability. Front-to-back compositing with configurable step count and density.

Key Technical Decisions

Triangle dispatch, not voxel dispatch. Most tutorials iterate per-voxel and test intersection against every triangle. Toaster flips it: iterate per-triangle, find the voxels it touches. This is dramatically faster because you only touch voxels near actual geometry, not the entire empty grid.

Atomic accumulation. Multiple triangles can hit the same voxel. Direct writes to RWTexture3D would race. The solution: a RWStructuredBuffer<uint> with fixed-point packed RGBA values and InterlockedAdd. The finalize kernel divides by the count to average. Not pretty, but correct.

L0 ambient instead of L1 SH. Bakery encodes directional lighting with 3 textures of Spherical Harmonics. Toaster uses a single RGBAHalf texture with isotropic lighting – 75% less data, 90% less decode math. The tradeoff is no directional response, but for ambient volumetric fog that’s exactly what I want.

Mesh mega-buffers. All eligible meshes get merged into mega-buffers on the CPU – vertices pre-transformed to world space, indices offset-adjusted. One upload, one bind. The compute dispatches per-submesh (each needs its own Meta texture), but the expensive buffer rebinding is eliminated.

BrowningLevels

Quality presets are toaster-themed, because of course they are:

LevelVoxel SizeGrid Resolution
Raw1.0m32 cubed
Light0.5m64 cubed
Burnt0.25m128 cubed

The pipeline also ships with 7 debug visualizers (slice, heatmap, isosurface, multi-slice, point cloud, volume fog, plus a raw data view), 3 Shader Graph custom nodes, and a one-click demo scene.

Status and What’s Next

v1.2 has the full pipeline working: material bake, GPU voxelization with SAT intersection, multi-bounce path tracing, froxel fog rendering, debug visualizers, editor window, Shader Graph integration, mesh batching, and serialized Texture3D assets.

The repo is currently private. I’m considering an Asset Store release once I’ve stress-tested it on a few more real scenes. The core compute work is solid; what remains is polish – better editor UX, documentation, and handling edge cases with non-standard materials.

Bakery takes hours. A Toaster takes minutes. That was the goal, and it works.