webgl-waves
v1.21.0
Published
A React component for rendering animated 3D wave terrain with WebGL. SSR-compatible for Next.js.
Maintainers
Readme
webgl-waves
A React component for rendering animated 3D wave terrain with WebGL using Three.js and React Three Fiber. SSR-compatible and ready for Next.js.

Installation
npm install webgl-wavesPeer Dependencies
This package requires the following peer dependencies to be installed:
npm install react react-dom three @react-three/fiber @react-three/drei @react-three/postprocessing lil-guiUsage
React (Client-side)
import { WebglWaves } from "webgl-waves";
function App() {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<WebglWaves
options={{
waveDepth: 2.5,
greenPointsCount: 200,
dotColor: 0x2effb5,
showControls: true,
}}
/>
</div>
);
}Next.js (SSR-compatible)
The component is SSR-safe and will automatically handle server-side rendering. You have two options:
Option 1: Direct Import (Recommended)
The component includes built-in SSR protection, so you can use it directly:
"use client"; // Required for Next.js App Router
import { WebglWaves } from "webgl-waves";
export default function Page() {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<WebglWaves
options={{
waveDepth: 2.5,
greenPointsCount: 200,
dotColor: 0x2effb5,
}}
/>
</div>
);
}Option 2: Dynamic Import (Alternative)
For more control over loading states:
import dynamic from "next/dynamic";
const WebglWaves = dynamic(
() => import("webgl-waves").then((mod) => mod.WebglWaves),
{
ssr: false,
loading: () => (
<div
style={{
width: "100vw",
height: "100vh",
background: "#000",
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "#fff",
}}
>
Loading...
</div>
),
}
);
export default function Page() {
return (
<div style={{ width: "100vw", height: "100vh" }}>
<WebglWaves
options={{
waveDepth: 2.5,
greenPointsCount: 200,
dotColor: 0x2effb5,
}}
/>
</div>
);
}Note: The component is already SSR-safe, so Option 1 is recommended. Option 2 is useful if you want custom loading states or need to prevent any client-side JavaScript from being included in the initial bundle.
SSR Requirements
When using webgl-waves in an SSR environment (e.g., Next.js), you may need to configure your build setup:
Next.js Configuration
- Transpile the package: Add
webgl-wavesto yournext.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
transpilePackages: ["webgl-waves"],
webpack: (config) => {
config.resolve.fallback = {
...config.resolve.fallback,
fs: false,
path: false,
crypto: false,
};
return config;
},
};
module.exports = nextConfig;- Use Webpack explicitly (if using Next.js 16+ with Turbopack): Update your dev script to use webpack:
{
"scripts": {
"dev": "next dev --webpack"
}
}Node Version Requirements
Some dependencies (like [email protected]) may require Node.js >=24.4.0. If you encounter engine compatibility errors:
- Option 1: Upgrade Node.js to the required version
- Option 2: Use
--ignore-enginesflag when installing (not recommended for production):yarn add webgl-waves --ignore-engines
React Three Fiber Compatibility
- React Three Fiber 9.x (alpha): Expects React 19. If you're using React 18, you may encounter peer dependency warnings. These are typically non-blocking but consider upgrading to React 19 for full compatibility.
- React Three Fiber 8.x: Compatible with React 18.
Recommended Setup for Next.js
- Next.js 16+ with webpack (not Turbopack) for better compatibility
- React 19 (if using React Three Fiber 9.x alpha)
- Node.js >=24.4.0 (or use
--ignore-enginesif needed)
Options
The options prop accepts the following configuration:
interface WebglWavesOptions {
useSpheres?: boolean;
radius?: number;
waveDepth?: number;
waveChaos?: number;
fov?: number;
greenPointsCount?: number;
dotColor?: number; // Hex color for dots (e.g., 0x2EFFB5)
cameraPosition?: [number, number, number];
cameraZoom?: number;
showControls?: boolean;
showStats?: boolean;
disableZoom?: boolean;
bloomIntensity?: number;
enableBloom?: boolean;
backgroundColor?: string | null;
showBorder?: boolean;
animate?: boolean;
brightness?: number;
quality?: "low" | "medium" | "high" | "ultra";
maxFps?: number;
}
| Option | Type | Default | Description |
| --- | --- | --- | --- |
| `useSpheres` | `boolean` | `false` | Toggles between the solid sphere field and the point-cloud grid. |
| `radius` | `number` | `0.05` | Dot or sphere radius (world units). |
| `waveDepth` | `number` | `2.2` | Overall displacement amplitude (higher = taller waves). |
| `waveChaos` | `number` | `1.7` | Secondary turbulence strength for more jittery motion. |
| `fov` | `number` | `102` | Perspective camera field of view in degrees. |
| `greenPointsCount` | `number` | `100` | How many highlighted points/spheres to place across the surface. |
| `dotColor` | `number` | `0x2EFFB5` | Hex color used for the highlighted points and bloom selection. |
| `cameraPosition` | `[number, number, number]` | `[10, 12, 16]` | Initial camera position vector. |
| `cameraZoom` | `number` | `1` | Multiplier applied when syncing zoom from the orbit controls. |
| `showControls` | `boolean` | `true` | Shows the built-in `lil-gui` control panel (requires the peer dependency). |
| `showStats` | `boolean` | `false` | Toggles the FPS panel from `@react-three/drei`. |
| `disableZoom` | `boolean` | `false` | Disables user zoom/rotate if you want a fixed camera. |
| `bloomIntensity` | `number` | `1.5` | Strength for the `Bloom` pass (only affects highlighted dots). |
| `enableBloom` | `boolean` | `true` | Completely enables/disables the `EffectComposer` bloom pipeline. |
| `backgroundColor` | `string \| null` | `"#000000"` | Canvas background (`null`/`"transparent"` keeps the DOM background). |
| `showBorder` | `boolean` | `false` | Draws a thin overlay rectangle for UI mockups. |
| `animate` | `boolean` | `true` | Freezes the wave simulation when `false`. |
| `brightness` | `number` | `1.0` | Global multiplier applied to tone mapping and lights. |
| `quality` | `"low" \| "medium" \| "high" \| "ultra"` | `"medium"` | Maps to device-pixel-ratio so you can trade resolution vs performance. |
| `maxFps` | `number` | _device refresh_ | Caps animation updates (e.g. set `30` for a filmic look, ≤0 disables the cap). |Props
options?: WebglWavesOptions- Configuration object for the wave terrainuiVisible?: boolean- Globally toggles any UI overlay (Stats, control panel, border) (default:true)
Examples
Basic Usage
<WebglWaves />Custom Configuration
<WebglWaves
options={{
waveDepth: 3.0,
waveChaos: 2.0,
greenPointsCount: 500,
dotColor: 0x00ff00,
bloomIntensity: 2.0,
showControls: false,
backgroundColor: "transparent",
quality: "high",
}}
/>Hide UI
<WebglWaves options={{ showControls: false }} uiVisible={false} />Gallery
License
MIT
