Real-time · no textures · no models
Everything you
see, you found.
There is no ambient light down here worth the name. This scene ships almost entirely black, and stays that way until you aim the lamp — which is what the water is actually like, and what a rendered film can never let you do.
Move the pointer to aim · scroll to descend
120 m
The light from above gives out
Below roughly a hundred metres there is not enough daylight left to see by. Every photon in this frame is coming from the lamp you are holding, and it is being eaten by the water at the same rate a real one would be.
400 m
Snow, not dust
The particulate drifting through the beam is marine snow — organic debris falling from the productive water above. It is the one detail that makes a dark frame read as underwater rather than as a cave, and it is the cheapest thing in this scene to draw.
700 m
Nothing here is a photograph
No texture file, no model file, no captured image. Every surface is a sphere displaced by noise and shaded by one moving light, which is why the whole scene weighs less than a single photograph of one.
Why real-time
The film cannot answer you
The demo before this one is a reel of generated footage. It is sharper than this scene, and it always will be — it was rendered once, offline, with no frame budget. But it is finished. It cannot respond to where you are looking, because every one of its pixels was decided before you arrived.
This scene is worse-looking and more alive. The lamp is a real spotlight calculation running against real geometry, so pointing it somewhere new produces an image nobody has seen, including me.
That is the whole trade, and it is worth stating plainly rather than pretending real-time has caught up with pre-rendered. It has not. What it has is the one thing film does not: it is still being computed while you watch.
Deep water happens to be the kindest possible subject for that trade. The medium hides what a real-time renderer is bad at — and the thing it is good at, a light moving through suspended matter, is exactly what the subject is about.
Measured, live
What the frame costs
Read from the renderer while you are looking at it, not typed in by hand.
- Draw calls
- —
- Triangles
- —
- Points
- —
- Textures
- —
- Shader programs
- —
- Frame
- —
Zero textures is not a boast, it is the method: there is nothing to download and
nothing to decode, so the scene starts the moment the script does. The budget in
references/08-webgl.md is under 100 draw calls; this sits at four.
Colophon
How it is made
- Renderer
- Three.js r185, WebGL, one shared uniform block
- Geometry
- One icosahedron, instanced 70 times, displaced in the vertex shader
- Surface
- Face normals from screen-space derivatives, bumped by a three-octave noise gradient
- Light
- One spot: cone, inverse-square falloff, specular sheen
- Water
- Exponential-squared fog with a cyan shift, because water absorbs red first
- Assets
- None. No textures, no models, no images
The look was not designed in a shader editor and then measured. It was measured
the whole way: the first version rendered black because a spotlight
smoothstep had an upper bound of 1.168, past anything a dot product
can return, so the cone never reached full brightness. That is written up in the
score rather than quietly fixed.