Voxel volumetric clouds
Minecraft-style clouds, two ways. Same voxels, same Worley noise.
Left: a voxel turns solid once its density passes 0.
Right: each voxel is a bit of fog, lit by 8 samples marched toward the sun.
The problem
Volumetric clouds look soft because every sample is a little fog. Voxel games want hard edges. The quick fix is to threshold the density: a voxel above 0 becomes a solid block. That is the left half. You get the shape, but every block has the same flat shading, so a thick cloud core and a thin wisp look identical.
How it works
The right half keeps the volumetric lighting and only changes where the density is read.
- Every density lookup snaps to the centre of a 40 x 16 x 40 voxel.
- The view ray walks voxel by voxel with a DDA (Amanatides & Woo), so the voxel faces stay sharp.
- At each voxel, 8 light samples march toward the sun, also snapped to voxels, and Beer's law turns that into how much sunlight arrives.
- Front-to-back accumulation: transmittance *= exp(-density × step × 1.05), and the march stops once transmittance drops below 0.01.
The density itself is Sebastian Lague's: 3 tiled Worley layers per channel, shaped by a height gradient, eroded at the edges by a detail texture weighted by (1 - shape)³.
What I hit
At the repo values (densityMultiplier 0.82, densityOffset -3.64) the clouds came out thin and covered the whole sky once snapped to 40-unit voxels. I raised the multiplier to 12 and ran the offset from -5.6 to -5.0 over the clip. That ramp is the weather: coverage grows as you watch.
The repo walks fixed 11-unit steps. With voxels that blurred the faces, so I replaced the step loop with the DDA.
My build
three.js 0.170. Worley textures generated on the CPU from the repo's compute shader logic (64³ shape, 32³ detail). Clouds render at 640x360 and composite over a 2560x1440 voxel terrain with water, shadows, bloom and ACES. Animation runs 6x faster than the repo speeds as a time-lapse.
Trade-offs
- Light still scatters through the cloud, so thick cores read darker than thin edges
- Voxel snapping hides low-resolution noise textures
- 8 light samples per voxel on top of the view march
- No cloud shadows on the terrain in this build
- Half-resolution clouds look softer than the full-resolution blocks
When to use it
Block-style worlds that want clouds matching the terrain grid but still lit like volumes. For a fully smooth sky, drop the snapping and use the repo as-is.
Source and credits
Repo: github.com/SebLague/Clouds (MIT license)
Code: I ported the cloud raymarcher from Clouds.shader (rayBoxDst, sampleDensity, lightmarch, the 2-lobe Henyey-Greenstein phase) to GLSL, and the Worley noise generator from NoiseGenCompute.compute to JavaScript, using the repo's "Flight Demo" settings. Changes: listed in notes (density snapped to voxels, voxel-by-voxel ray walk, higher density multiplier, smaller noise textures). The terrain, sky, water and the opaque-voxel comparison are my own. No assets or screenshots from the repo.
Topic inspired by @cazfps1's CazToon shader posts. No CazToon code or assets were used.