shadcn.io is not affiliated with official shadcn/ui
Shaders
ProBioluminescence Shader for React
Night surf drawn on the GPU: slow waves roll onto a dark beach, their breaking crests light up electric cyan and fade, and the wet sand mirrors the glow. For React with Base UI, when an ocean, marine or resort hero needs a dark, calm scene with a spark of light.
Bioluminescence Shader draws a beach at night, seen from low down. Slow waves roll in under a starless navy sky, and wherever a crest breaks, plankton in the water light up electric cyan along its lip, then fade to black behind it within a couple of seconds. Near the shore the glow runs a little way up the sand, and the wet sand mirrors it. A WGSL fragment shader on WebGPU maps each pixel below the horizon to a point on the beach, then lights it from three sets of wave crests that cross at slight angles, each bent by noise and breaking in sections.
Use it behind an ocean nonprofit, a marine-biotech or a resort hero, or any dark page that wants a calm scene with a spark of life. For a daylit sea, use Sea Shader; for the same night in plain CSS, with no GPU, the Deep Sea background has glowing jellyfish instead of surf. The sky stays dark and empty for your headline. It runs only while it's on screen, holds a still frame with reduced motion, and shows a gradient of the same night and surf in browsers without WebGPU.
Installation
Usage
import {
BioluminescenceShader,
} from "@/components/ui/bioluminescence-shader";<BioluminescenceShader className="flex min-h-[32rem] flex-col items-center pt-24">
<h1 className="text-5xl font-semibold text-white">Into the blue</h1>
<p className="mt-3 text-slate-400">Protecting the reefs since 1998.</p>
</BioluminescenceShader>Bioluminescence Shader is a container: your content sits on top of the beach, in normal flow. It fills its own box, so give it a height or content. For a backdrop behind the whole page, render it empty with className="fixed inset-0 -z-10". The night is the same in both color schemes, so use light text: put the headline in the sky, the top 42% by default, where white text stays above 18:1 and text-slate-400 above 7:1. Over the sea, white still reads on 93% of the area, but not over a bright crest.
Demos
Green plankton
glowColor="#a6ff4d" turns the surf the green of some plankton blooms, and the brightest crests still run to white. afterglow={0.8} lets each crest leave a longer trail, about three seconds, so more of the sea glows at once.
In a card
horizon={0.3} raises the horizon so the beach fills more of a small box, and waves={2} keeps two sets of crests, a calmer sea that doesn't crowd the card.
Performance
About 0.7 ms of GPU time a frame at 1280×720, measured on an M2 Max laptop at full quality. Slower GPUs take several times longer. Each set of waves adds about 0.15 ms, so waves={2} is a little cheaper; on a slow GPU, quality={0.5} renders a quarter of the pixels, and the soft glow hides it well. The animation stops when the shader scrolls out of view, and the browser pauses it in a hidden tab. Every shader on a page shares one GPU device and one frame loop, and vgpu loads only when the first one mounts.
Browser support
The shader needs WebGPU: Chrome and Edge, Safari 26 and later, and Firefox on Windows and macOS. Elsewhere, and until the first frame, the box shows a CSS gradient of the same scene, a navy sky over dark water with two soft cyan glows near the shore, so the layout never jumps. data-state on the root reads unsupported there, if you want to style around it. See Shader Canvas.
Accessibility
The beach is decoration: it's hidden from assistive tech and lets every click through to your content. With reduced motion it draws one still frame, two crests breaking near the shore, and stops. Nothing flashes: a crest brightens over seconds as it nears the shore, and any one point of the sea lights up about once every three seconds at the default speed, once a second at speed={3}. For text, the sky is the place: white text there stays above 18:1 on every frame we measured.
FAQ
How is it drawn?
There's no 3D model. Each pixel below the horizon maps to a point on a flat beach, farther away the closer it is to the horizon. Three sets of wave crests roll toward you across it, at slight angles to each other, bent by noise. Each crest is treated as a low wall: the pixels just past it see its face, which glows toward a bright lip, and behind it the plankton it stirred fade out. Crests light up only near the shore, in sections that shift along the wave, and the wet sand reflects the surf beyond it.
How do I make the glow linger longer, or shorter?
afterglow sets how long the water keeps glowing after a crest passes: at 0 only the lip glows, at 0.5 (the default) the trail fades in about two seconds, and at 1 it lasts about four. foam sets how much of that trail lights up, from scattered sparks at 0 to an almost solid sheet at 1.
Can I change the colors?
Yes. glowColor is the light of the plankton; the brightest crests run to white whatever you pick. skyColor, waterColor and sandColor set the night, the sea and the dry sand, and the wet sand is a darker, glossy shade of the sand. All four take any CSS color and follow a theme switch, so var(--primary) works for the glow. Keep the others dark: the glow only shows against a night.
Can I move the horizon or calm the sea?
horizon sets where the sky ends, as a fraction of the height from the top, from 0.2 to 0.6; a higher value gives the beach more room, a lower one leaves more sky for text. waves sets how many sets of crests cross, from 1 (one slow, regular swell) to 4 (a busier sea), and intensity dims or brightens the glow, from 0 to 2.
Will it slow my page down?
It's light: about 0.7 ms of GPU time a frame at 1280×720 on an M2 Max laptop, and it stops when it's off screen. waves is the only prop that changes the cost, by about 0.15 ms per set. On a slow GPU or a large screen, quality={0.5} renders a quarter of the pixels, and the soft glow hides the difference.
API Reference
BioluminescenceShader
data-slot="bioluminescence-shader"
afterglow?number
How long the glow lingers behind each crest, from 0 (a thin line) to 1 (a long trail, about 4 seconds). @default 0.5.
- Default
0.5
fallback?string
What shows until the first frame and in browsers without WebGPU: a CSS
background value (gradients, sizes, a colour) that looks like the
shader. It can use the colour props' --shader-<field> variables.
foam?number
How much of the surf glows, from 0 (sparse sparks) to 1 (a solid sheet of light). @default 0.6.
- Default
0.6
glowColor?string
The light of the plankton; the brightest crests run to white. Any CSS colour. @default "#3ff5ff".
- Default
"#3ff5ff"
horizon?number
Where the horizon sits, as a fraction of the height from the top, from 0.2 to 0.6. @default 0.42.
- Default
0.42
intensity?number
How bright the glow is, from 0 to 2. @default 1.
- Default
1
interactive?boolean
Whether u.pointer follows the pointer. @default false.
paused?boolean
Holds the current frame. @default false.
quality?number
Render scale, from 0.25 to 1, of the screen's pixels (capped at 2×). @default 1.
sandColor?string
The dry sand in the foreground; the wet sand is a darker, glossy shade of it. Any CSS colour. @default "#0d0f14".
- Default
"#0d0f14"
skyColor?string
The night sky, a little lighter at the horizon. Any CSS colour. @default "#050913".
- Default
"#050913"
speed?number
Animation speed: 1 is normal, 0 holds the frame. @default 1.
time?number
A fixed moment, in seconds: draws it and doesn't animate.
waterColor?string
The dark sea between the breakers. Any CSS colour. @default "#04101c".
- Default
"#04101c"
waves?number
How many sets of waves cross each other, from 1 to 4. @default 3.
- Default
3
render?ReactElement | ((props: object, state: object) => ReactElement)
Replace the host element or compose it with another component.
- Type
ReactElement | ((props: object, state: object) => ReactElement)
className?string
Forwarded to the part.
Related
- Pro


Sea Shader
Water & landscapesA daylit sea
- Pro


Aurora 3D Shader
Water & landscapesNorthern lights over a still lake
- Pro


Water Shader
Water & landscapesDeep water from above
- Pro


City Lights Shader
Water & landscapesAnother calm night scene, lit


Nebula Shader
SpaceA calm, dark backdrop, free
- Pro


Biomine Shader
Tunnels & 3DLiving red light in a cavern