
3d Underwater God Rays
Add volumetric underwater god rays to a Three.js scene, marching one drifting swell...
Install
npx skills add MengTo/Skills --skill 3d-underwater-god-rays -g -a claude-code -y- Repository
- MengTo/Skills7.2k
- Category
- Engineering
- Updated
- 3d ago
- License
- MIT
- Context cost
- Mediumabout 2,294 tokens
- Runs scripts
- Yes, review before use
What it does
Add volumetric underwater god rays to a Three.js scene, marching one drifting swell field along every view ray at half resolution so the light shafts converge on the sun, parallax with the camera and carry rippling caustic streaks, with a shimmering surface underside, a sun that wobbles through the ripples, and the same light dappling fish as they swim through the beams. Use for underwater scenes, oceans seen from below, aquariums, reefs, kelp forests, diving and shipwreck scenes, schools of fish, sunbeams or light shafts through water, caustics, "rays of light shining through the ocean", or watery ripples on a background. Includes a reusable module and the Blue Hour sardine-school demo.
3D Underwater God Rays
Use this when the camera is under the water and the light comes down through it. Reach for a sibling instead in these cases:
- Sun shafts in air, cut by trees and rooflines: use
3d-sky-rays. Its screen-space radial blur of an occlusion mask is the right tool there. It cannot parallax or carry ripples, so under water keep it only as a low companion for fish shadows (Blue Hour runs it at 0.25). - The ocean surface seen from above, with a horizon: use
3d-ultra-realistic-water. - Authored shaft planes through one window in a lit interior: use
3d-wood-lighting-scorecard.
Source: extracted from Blue Hour, the living-ocean wallpaper of a Three.js iPhone Duo study. A school of 2,200 Blender sardines turns behind a glass device. The light had to read as sun through water across the whole 38 s camera dolly and on the device's own screen.
Verified stack: Three.js r170, WebGL2, GLSL ShaderMaterials, one HalfFloat render target, and a hand-written ACES pass. No post-processing library.
The mechanism
Sample one drifting swell field across the sun direction, and integrate it along every view ray. Each point in the water is lit by the swell value at its position measured perpendicular to the sun. The shafts are therefore parallel columns in the world. They converge on the sun the way rails converge on a vanishing point, and they slide past the fish when the camera moves. Paint the same shafts in screen space and they stay locked to the lens.
Reuse the working effect
Copy assets/underwater-light.mjs. You pass in your own THREE, and the module does not import a second copy. The demo runs this same module inside Blue Hour's renderer. demo/build.mjs rebuilds it from the Blue Hour sources.
import { createUnderwaterLight, LIGHT_GLSL, WATER_GLSL } from './underwater-light.mjs';
