105 lines
3.8 KiB
Markdown
105 lines
3.8 KiB
Markdown
# WebGPU FFT Ocean Demo
|
||
|
||
An interactive WebGPU demo that simulates a tiled ocean surface using fast Fourier transforms (FFT).
|
||
The project renders a dynamic wave field in real time and exposes a small framework for building WebGPU pipelines, passes and scenes.
|
||
|
||
## Features
|
||
|
||
- Real‑time ocean surface simulation using 2D FFT.
|
||
- Tiled ocean mesh with adjustable resolution and tiling count.
|
||
- Multiple shading modes (realistic, lighting, normals, solid color, height debug).
|
||
- Wireframe / solid rendering modes.
|
||
- Pause / single‑step controls for the simulation.
|
||
- CPU vs GPU validation helpers for the FFT and spectrum (accessible from the browser console).
|
||
|
||
## Requirements
|
||
|
||
- Node.js 18+ (for the simple static file server).
|
||
- A browser with WebGPU support:
|
||
- Recent Chrome / Edge with WebGPU enabled, or
|
||
- Chrome Canary / other WebGPU‑capable build.
|
||
|
||
## Getting Started
|
||
|
||
1. Install dependencies (only used by some tools):
|
||
|
||
```bash
|
||
npm install
|
||
```
|
||
|
||
2. Start the local server:
|
||
|
||
```bash
|
||
node server.js
|
||
```
|
||
|
||
3. Open the demo in your browser:
|
||
|
||
- Navigate to: `http://localhost:3003/index.html`
|
||
|
||
If WebGPU is not available, the status label in the bottom‑left of the page will tell you that WebGPU is not supported.
|
||
|
||
## Controls
|
||
|
||
All controls are in the panel at the top‑right of the page:
|
||
|
||
- **Wave height** – overall amplitude of the waves.
|
||
- **Wave length** – scales the wave spectrum (larger values = longer waves).
|
||
- **Resolution** – underlying mesh resolution (32 → 2048).
|
||
- **Wireframe mode** – toggle wireframe rendering.
|
||
- **Pause waves** – pause / resume the simulation.
|
||
- **Next frame** – advance the simulation by one frame while paused.
|
||
- **Shading** – choose between realistic, lighting, normals, solid color, and height debug modes.
|
||
- **Dump height (debug)** – logs statistics about the current height field buffer to the console.
|
||
|
||
Camera:
|
||
|
||
- **Drag** on the canvas to orbit the camera.
|
||
- **Scroll** to zoom in/out.
|
||
|
||
On first load the camera auto‑rotates until you interact with the canvas.
|
||
|
||
## Debug / Test Helpers
|
||
|
||
The app exposes a couple of helpers on `window` for validating the GPU simulation against CPU reference implementations:
|
||
|
||
- `window.testFft()`
|
||
- Builds a deterministic 2D input field.
|
||
- Runs the GPU FFT passes.
|
||
- Computes a CPU 2D FFT.
|
||
- Logs max and RMS error between GPU and CPU results.
|
||
|
||
- `window.testSpectrum()`
|
||
- Uses the initial spectrum buffers.
|
||
- Runs a CPU reference spectrum computation.
|
||
- Runs the GPU spectrum pass.
|
||
- Logs max and RMS error between GPU and CPU spectra.
|
||
|
||
You can call these from the browser devtools console while the app is running.
|
||
|
||
## Project Structure
|
||
|
||
- `index.html` – minimal HTML shell and UI controls.
|
||
- `main.js` – application entrypoint; wires up the engine, pipelines, scene, and render loop.
|
||
- `events.js` – encapsulates DOM element lookup and all UI / input event handlers.
|
||
- `server.js` – simple Node static file server used during development.
|
||
|
||
WebGPU framework and rendering:
|
||
|
||
- `framework/` – generic engine / scene / math utilities and WebGPU plumbing.
|
||
- `pipelines/` – high‑level render and compute pipelines (e.g. `OceanPipeline`).
|
||
- `passes/` – individual compute / render passes used by pipelines.
|
||
- `shaders/` – WGSL shader programs (FFT, spectrum, rendering, etc.).
|
||
|
||
Testing / utilities:
|
||
|
||
- `tests/OceanTests.js` – CPU FFT and spectrum reference implementations wrapped in a small test helper class.
|
||
- `resources/`, `tools/` – additional assets and helper scripts.
|
||
|
||
## Notes
|
||
|
||
- The project is written as native ES modules (`type: "module"` in `package.json`).
|
||
- All WebGPU usage is routed through the small framework in `framework/` rather than direct `GPUDevice` calls scattered throughout the app.
|
||
- If you change ports or server configuration, update how you access the app accordingly (the default is port `3003`).
|
||
|