
[!IMPORTANT]
The new documentation and playground can be found here.
Table of Contents
Documentation for Outdated Version (v0.6.1 and Prior)
Install
npm install webgl-fluid-enhanced
New Features
- Ability to change config after simulation has started
- Use hover to activate
- Choose colors used in simulation
- Set background image
- Set if splats generate on initial load
- Specify how many splats should generate initially and from keypress
- Assign specific key to splats (Can be disabled)
- Trigger splats method
- Pause method
- Brightness option
- Method to splat at specific coordinates
- TypeScript support
Config options
webGLFluidEnhanced.config({
SIM_RESOLUTION: 128,
DYE_RESOLUTION: 1024,
CAPTURE_RESOLUTION: 512,
DENSITY_DISSIPATION: 1,
VELOCITY_DISSIPATION: 0.2,
PRESSURE: 0.8,
PRESSURE_ITERATIONS: 20,
CURL: 30,
INITIAL: true,
SPLAT_AMOUNT: 5,
SPLAT_RADIUS: 0.25,
SPLAT_FORCE: 6000,
SPLAT_KEY: 'Space',
SHADING: true,
COLORFUL: true,
COLOR_UPDATE_SPEED: 10,
COLOR_PALETTE: [],
HOVER: true,
BACK_COLOR: '#000000',
TRANSPARENT: false,
BRIGHTNESS: 0.5,
BLOOM: true,
BLOOM_ITERATIONS: 8,
BLOOM_RESOLUTION: 256,
BLOOM_INTENSITY: 0.8,
BLOOM_THRESHOLD: 0.6,
BLOOM_SOFT_KNEE: 0.7,
SUNRAYS: true,
SUNRAYS_RESOLUTION: 196,
SUNRAYS_WEIGHT: 1.0,
});
General info
Usage
Initialise:
webGLFluidEnhanced.simulation(document.querySelector('canvas'), {
});
Edit config:
webGLFluidEnhanced.config({
});
Trigger splats:
webGLFluidEnhanced.splats();
Splat at specific coordinates:
webGLFluidEnhanced.splat(
x,
y,
dx,
dy,
color,
);
Pause/resume the simulation:
webGLFluidEnhanced.pause(drawWhilePaused);
Download a screenshot:
webGLFluidEnhanced.screenshot();
Set background image
To set background image make sure the TRANSPARENT
option is set to true
, and in the CSS you can set background-image: url('<PHOTO-URL>');
and background-size: 100% 100%;
to fill the whole canvas.
Background color
When using the BACK_COLOR
option, the color you provided will be whitened when the BLOOM
option is set to true
.
Examples
HTML
<!doctype html>
<html>
<body>
<canvas style="width: 100vw; height: 100vh;"></canvas>
<script type="importmap">
{
"imports": {
"webgl-fluid-enhanced": "https://esm.run/webgl-fluid-enhanced@latest"
}
}
</script>
<script type="module">
import webGLFluidEnhanced from 'webgl-fluid-simulation';
webGLFluidEnhanced.simulation(document.querySelector('canvas'), {
COLOR_PALETTE: ['#cc211b', '#f1c593', '#e87e54', '#f193a7', '#ec6fa9'],
HOVER: false,
SPLAT_RADIUS: 0.1,
VELOCITY_DISSIPATION: 0.99,
BLOOM: false,
});
</script>
</body>
</html>
React
import { useEffect, useRef } from 'react';
import webGLFluidEnhanced from 'webgl-fluid-enhanced';
const App = () => {
const canvasRef = useRef(null);
useEffect(() => {
webGLFluidEnhanced.simulation(canvasRef.current, {
SIM_RESOLUTION: 256,
DENSITY_DISSIPATION: 0.8,
PRESSURE_ITERATIONS: 30,
COLOR_PALETTE: ['#61dafb', '#a8dadc', '#457b9d', '#1d3557', '#f1faee'],
});
}, []);
return <canvas ref={canvasRef} style={{ width: '100vw', height: '100vh' }} />;
};
export default App;
Next.js (tailwindcss)
'use client';
import { useEffect, useRef } from 'react';
import webGLFluidEnhanced from 'webgl-fluid-enhanced';
const App = () => {
const canvasRef = useRef(null);
useEffect(() => {
webGLFluidEnhanced.simulation(canvasRef.current!, {
PRESSURE: 0.2,
SUNRAYS: false,
START_SPLATS: 10,
DENSITY_DISSIPATION: 3,
CURL: 100,
COLOR_PALETTE: ['#0000ff', '#111111', '#1d1d1d', '#eaeaea', '#4dba87'],
});
}, []);
return <canvas ref={canvasRef} className='h-screen w-screen' />;
};
export default App;
Vue.js
<!-- Not tested! -->
<template>
<canvas ref="canvas"></canvas>
</template>
<script setup>
import { onMounted, ref } from 'vue'
import WebGLFluid from 'webgl-fluid'
const canvas = ref()
onMounted(() => {
webGLFluidEnhanced.simulation(canvas, {
SPLAT_RADIUS: 0.5,
COLOR_UPDATE_SPEED: 20,
BLOOM: false,
<>});
})
</script>
<style>
canvas {
width: 100vw;
height: 100vh;
}
</style>
Angular
import { Component, ElementRef, OnInit, ViewChild } from '@angular/core';
import webGLFluidEnhanced from 'webgl-fluid-enhanced';
@Component({
selector: 'app-root',
template: `
<canvas #canvasRef style="width: 100vw; height: 100vh;"></canvas>
`,
})
export class AppComponent implements OnInit {
@ViewChild('canvasRef', { static: true }) canvasRef!: ElementRef;
ngOnInit(): void {
webGLFluidEnhanced.simulation(this.canvasRef.nativeElement, {
COLOR_PALETTE: ['#dd0031', '#c3002f', '#dd0031'],
START_SPLATS: 50,
TRANSPARENT: true,
});
}
}
Svelte
<!-- Not tested! -->
<script>
import { onMount } from 'svelte';
let canvasRef;
onMount(() => {
import('webgl-fluid-enhanced').then(({ default: webGLFluidEnhanced }) => {
webGLFluidEnhanced.simulation(canvasRef, {
SIM_RESOLUTION: 256,
VELOCITY_DISSIPATION: 0.99,
COLOR_PALETTE: ['#ff7f00'],
});
});
});
</script>
<canvas bind:this={canvasRef} style="width: 100vw; height: 100vh;" />
Want to contribute
Feel free to open an issue or a pull request! I'm always open to suggestions and improvements, and I have tried to make the development environment as good as possible with a descriptive file structure and TypeScript definitions.
References
https://github.com/PavelDoGreat/WebGL-Fluid-Simulation
https://developer.nvidia.com/gpugems/gpugems/part-vi-beyond-triangles/chapter-38-fast-fluid-dynamics-simulation-gpu
https://github.com/mharrys/fluids-2d
https://github.com/haxiomic/GPU-Fluid-Experiments
License
The code is available under the MIT license