# FluidSim

A real-time interactive fluid dynamics simulation running entirely in the browser. Move your mouse or touch the screen to inject colourful dye into a GPU-driven fluid, creating swirling vortices and turbulence that gradually settle to rest.

This is a basic spike/stripped-back version heavily inspired by Pavel Dobryakov's [WebGL Fluid Simulation](https://paveldogreat.github.io/WebGL-Fluid-Simulation/) — definitely check out the original as it is very good and has many more features.

![WebGL](https://img.shields.io/badge/WebGL-1.0-blue) ![No Dependencies](https://img.shields.io/badge/dependencies-none-brightgreen) ![License](https://img.shields.io/badge/license-MIT-green)

## How It Works

The simulation solves an approximation of the **Navier-Stokes equations** on the GPU using WebGL fragment shaders. Each frame runs a multi-step pipeline:

1. **Curl** — compute the curl of the velocity field
2. **Vorticity Confinement** — amplify small-scale rotational detail that numerical dissipation would otherwise destroy
3. **Advection** — move the velocity field through itself (self-advection)
4. **Divergence** — calculate how much fluid is expanding/compressing at each point
5. **Pressure Solve** — iteratively solve for pressure using Jacobi iteration (30 iterations per frame)
6. **Gradient Subtraction** — subtract the pressure gradient from velocity to enforce incompressibility
7. **Dye Advection** — carry the visible colour field along with the velocity

User interaction (mouse/touch) injects velocity impulses and randomly coloured dye via a Gaussian **splat** into the simulation fields.

## Tech Stack

- **Plain HTML/CSS/JS** — no build step, no frameworks, no dependencies
- **WebGL 1.0** with `OES_texture_half_float` / `OES_texture_float` extensions
- **GLSL fragment shaders** loaded at runtime via `fetch()`
- Double-buffered framebuffer objects (ping-pong) for read/write separation

## Project Structure

```
FluidSim/
├── index.html              # Minimal page with a full-screen <canvas>
├── css/
│   └── style.css           # Full-bleed canvas, no scrollbars, touch-action: none
├── js/
│   └── fluid.js            # WebGL setup, shader compilation, input handling, render loop
└── shaders/
    ├── baseVertex.vert     # Shared full-screen quad vertex shader
    ├── advection.frag      # Advects velocity & dye fields
    ├── curl.frag           # Computes velocity curl
    ├── vorticity.frag      # Vorticity confinement force
    ├── splat.frag          # Injects colour + velocity at interaction point
    ├── divergence.frag     # Computes velocity divergence
    ├── pressure.frag       # Jacobi pressure solve iteration
    ├── gradient.frag       # Subtracts pressure gradient from velocity
    └── display.frag        # Final output / colour mapping
```

## Getting Started

No build or install required. Serve the files with any static HTTP server:

```bash
# Python
python -m http.server 8000

# Node.js (npx)
npx serve .
```

Then open `http://localhost:8000` in a modern browser and move your mouse over the canvas.

> **Note:** The files must be served over HTTP(S) — opening `index.html` directly via `file://` will not work because the shaders are loaded with `fetch()`.

## Configuration

Key constants at the top of `js/fluid.js`:

| Constant | Default | Description |
|---|---|---|
| `SIM_RESOLUTION` | 256 | Simulation grid size (velocity/pressure) |
| `DYE_RESOLUTION` | 1024 | Dye field resolution (visual output) |
| `SPLAT_RADIUS` | 0.25 | Size of each colour/velocity injection |
| `SPLAT_FORCE` | 4000 | Strength of velocity impulse on interaction |
| `VISCOSITY` | 0.8 | Rate at which velocity dissipates |
| `PRESSURE_ITERATIONS` | 30 | Jacobi solver iterations per frame |
| `CURL_STRENGTH` | 20 | Vorticity confinement intensity |

## Browser Support

Modern evergreen browsers on desktop and mobile (Chrome, Firefox, Safari, Edge). Requires WebGL 1.0 with float texture support. The canvas honours `devicePixelRatio` (capped at 2×) for crisp HiDPI rendering.

## License

[MIT](LICENSE)
