# Fluid Dynamics Simulation — Requirements

## Overview

An interactive, full-screen webpage that simulates fluid dynamics driven by user input. Mouse or touch movement disturbs the fluid, creating realistic motion, vortices, and turbulence. When input stops, the fluid gradually settles to rest. The simulation is rendered using WebGL shaders for high-performance, visually vibrant output.

---

## 1. Core Simulation

| Requirement | Detail |
|---|---|
| **Algorithm** | Navier-Stokes based fluid solver running on the GPU via fragment shaders. Performed in a multi-step pipeline: advection → diffusion → pressure solve (Jacobi iteration) → projection. |
| **Vortex generation** | Mouse/touch velocity is injected as a force impulse (splat) into the velocity field, naturally producing vortices and swirling patterns. |
| **Settling behaviour** | When no input is detected, no new forces are applied. Existing velocity dissipates over time via configurable viscosity/decay, causing the fluid to come to rest. |
| **Resolution** | Simulation grid resolution scales with device capability. Target: 512×512 minimum on mobile, up to 1024×1024+ on desktop. Configurable via a `SIM_RESOLUTION` constant. |
| **Timestep** | Fixed-timestep update loop (e.g. `dt = 0.016`) decoupled from render frame rate for deterministic behaviour. |

---

## 2. Visual Presentation

| Requirement | Detail |
|---|---|
| **Colour palette** | Bright, saturated colours. Each force splat injects a randomised vivid colour (high saturation, varied hue) into a dye/colour field that is advected alongside velocity. |
| **Rendering** | Final output composites the dye field to a full-screen quad. Optional bloom/glow post-process pass for added vibrancy. |
| **Background** | Solid black background so colours pop. |
| **Particle look** | The dye field naturally produces a smooth, slightly pixelated/painterly fluid appearance — no discrete particle sprites needed. |

---

## 3. User Interaction

| Input | Behaviour |
|---|---|
| **Mouse move** | Inject velocity + colour splat at cursor position, sized proportionally to cursor speed. |
| **Mouse down + drag** | Same as mouse move (no distinction needed; movement alone drives the sim). |
| **Touch move** | Same behaviour as mouse, supporting single-finger drag. Multi-touch: each active touch injects its own splat. |
| **No input** | No forces applied; fluid decays to stillness. |

---

## 4. File Structure

```
FluidSim/
├── index.html          # Page markup, canvas element, stylesheet link, script imports
├── css/
│   └── style.css       # Full-screen canvas styles, reset, responsive rules
├── js/
│   └── fluid.js        # Simulation logic: WebGL setup, shader compilation,
│                        #   framebuffer management, input handling, render loop
└── shaders/
    ├── advection.frag       # Advects velocity & dye fields
    ├── 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
    └── baseVertex.vert      # Shared full-screen quad vertex shader
```

- **HTML** — minimal: a `<canvas>` element, CSS link, and a single `<script>` tag.
- **CSS** — in its own file; handles full-bleed canvas, removal of scrollbars, and responsive sizing.
- **JS** — one entry-point script that fetches shader source files at startup, compiles them, and runs the simulation.
- **Shaders** — each GLSL program lives in its own `.frag` / `.vert` file, loaded at runtime via `fetch()`.

---

## 5. Responsive / Full-Screen Behaviour

| Requirement | Detail |
|---|---|
| **Canvas sizing** | Canvas fills `100vw × 100vh` with no scrollbars. CSS `margin: 0; overflow: hidden` on `body`. |
| **Resize handling** | On `window.resize`, recreate framebuffers at new resolution and update `gl.viewport`. Debounced to avoid excessive reallocation. |
| **Pixel ratio** | Honour `window.devicePixelRatio` (capped at 2×) for crisp rendering on HiDPI screens without killing mobile performance. |
| **Orientation** | Works in both portrait and landscape; no fixed aspect ratio assumed. |

---

## 6. Mobile Support

| Requirement | Detail |
|---|---|
| **Touch events** | Listen for `touchstart`, `touchmove`, `touchend`. Convert touch coordinates to canvas-relative positions. Prevent default to suppress scroll/zoom. |
| **Performance** | Reduce simulation resolution automatically on mobile (detect via `navigator.userAgent` or screen size heuristic). Target 30 fps minimum on mid-range phones. |
| **Viewport meta** | `<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">` to prevent pinch-zoom and ensure correct sizing. |
| **WebGL compatibility** | Use WebGL 1 with `OES_texture_half_float` / `OES_texture_float` extensions as primary target for broadest mobile support. Fall back gracefully or show an error if unavailable. |
| **Pointer Events** | Prefer `PointerEvent` API where available (unified mouse + touch + pen) with `touch-action: none` on the canvas. Fall back to separate mouse/touch listeners. |

---

## 7. Technical Constraints

| Area | Constraint |
|---|---|
| **No build step** | Plain HTML/CSS/JS served statically. No bundler, no framework, no transpiler. |
| **No external dependencies** | Zero third-party libraries. All WebGL and shader code is hand-written. |
| **Browser support** | Modern evergreen browsers (Chrome, Firefox, Safari, Edge) on desktop and mobile. |
| **Shader precision** | Use `mediump float` as default precision in fragment shaders for mobile compatibility; promote to `highp` only where required (e.g. pressure solve). |
| **Framebuffer strategy** | Double-buffered (ping-pong) textures for velocity and dye fields. Use `FLOAT` or `HALF_FLOAT` texture format for accuracy. |

---

## 8. Configurable Parameters

Exposed as constants at the top of `fluid.js` for easy tuning:

| Parameter | Default | Purpose |
|---|---|---|
| `SIM_RESOLUTION` | `256` | Simulation grid size (width in texels; height derived from aspect ratio) |
| `DYE_RESOLUTION` | `1024` | Dye/colour field resolution (can be higher than sim for visual detail) |
| `SPLAT_RADIUS` | `0.25` | Radius of force/colour injection (% of screen height) |
| `SPLAT_FORCE` | `6000` | Strength of velocity impulse |
| `VISCOSITY` | `0.3` | Fluid viscosity / velocity decay rate |
| `PRESSURE_ITERATIONS` | `20` | Jacobi solver iterations per frame |
| `CURL_STRENGTH` | `30` | Vorticity confinement strength (amplifies swirling) |
| `COLOR_UPDATE_SPEED` | `10` | How fast dye dissipates |

---

## 9. Acceptance Criteria

1. Page loads and begins rendering within 2 seconds on desktop broadband.
2. Moving the mouse/finger across the canvas produces colourful, swirling fluid motion.
3. Releasing all input causes the fluid to gradually settle to a still, dark canvas.
4. Resizing the browser window smoothly re-adapts the canvas — no letterboxing, no distortion.
5. Works on iOS Safari and Android Chrome with touch input.
6. All shader code resides in `.frag` / `.vert` files, not inline strings.
7. No console errors or WebGL warnings on supported browsers.
8. Achieves ≥ 30 fps on a mid-range mobile device and ≥ 60 fps on desktop.

---

## 10. Out of Scope (for v1)

- Audio reactivity
- UI controls / settings panel
- Obstacle / boundary objects in the fluid
- Saving / exporting frames
- Multi-user / networked interaction
- 3D fluid simulation

---
