The lights problem
Every developer who has pushed Three.js into a complex scene has hit the same ceiling: lights are expensive. Traditional forward rendering evaluates every light against every fragment, so adding more lights multiplies the cost. The usual workaround — a maximum of 8–16 dynamic lights in most scenes — has been a silent constraint on what's feasible in browser 3D for years.
Three.js r185 breaks that ceiling. The release ships ClusteredLighting, a forward+ shading system that partitions the view frustum into a 3D grid of "clusters" — tiles of screen space combined with depth slices. At render time, only lights that intersect a given cluster are evaluated for pixels inside it. Community benchmarks from the beta show approximately 240 fps vs 50 fps with 1,024 point lights on an RTX 4090 running the WebGPU renderer, and a measured 1,588% throughput improvement at 16,384 lights. That's a different category of scene complexity than what was previously feasible.
ClusteredLighting lives on the WebGPURenderer path and replaces the older TiledLighting addon, which has been removed. Migration is a drop-in swap — add the node to your post-processing chain and the renderer handles the rest.
The Nanite rasterizer
The second major addition in r185 is architecturally bolder: a GPU-driven compute rasterizer inspired by Unreal Engine's Nanite LOD system. Rather than issuing traditional draw calls that funnel geometry through the fixed-function rasterizer, this path submits geometry processing as compute shader workloads — enabling GPU-driven culling, LOD selection, and rasterization without CPU round-trips.
Two new examples ship with it: a base version and a variant with image-based lighting. It's experimental territory, but the direction is clear — the Three.js team is building toward scenes where the CPU is almost entirely removed from the per-frame draw decision loop.
WebGPU maturation
r185 is the release where the WebGPU renderer crosses from "interesting experiment" to "handles real-world scenes." Several long-standing gaps are closed:
- WebXR + WebGPU now work together — immersive sessions run on the modern renderer path for the first time.
- ExternalTexture fully supported — live
<video>elements and camera feeds can be used as textures on WebGPU without fallback. - textureGather / textureGatherCompare — TSL now supports these WGSL gather operations, enabling efficient PCF soft shadows in a single sample.
- storageTexture3D — new node type for 3D storage textures, useful for volumetric effects and compute-driven rendering.
- WGSL diagnostic messages — GPU shader errors now surface meaningful diagnostics in the console instead of opaque failures.
Breaking changes worth knowing
r185 also does housecleaning. Several deprecated APIs are removed:
TiledLightingis gone — useClusteredLighting.AnamorphicNodeis removed — useBloomNode.positionLocalno longer mutates internal vertex transformations; usepositionGeometryinstead.- TSL function renames:
directionToColor()→packNormalToRGB(),colorToDirection()→unpackRGBToNormal(). DRACOLoaderandDRACOExporterno longer bundle encoders/decoders — switch to CDN loading.
The r184 → r185 migration guide is comprehensive. For most projects not using the removed addons, the upgrade is straightforward.
The bigger picture
Taken together — ClusteredLighting, the compute rasterizer, WebXR/WebGPU parity, and the ongoing TSL API stabilization — r185 reads as the release where the library's WebGPU bet starts paying off. The browser is getting a GPU API capable of competitive real-time rendering, and Three.js is increasingly able to use the full depth of it. For anyone building in-browser 3D today, this is the version to be on.