mirror of
https://github.com/PavelDoGreat/WebGL-Fluid-Simulation.git
synced 2025-10-03 17:31:53 +02:00
update
This commit is contained in:
BIN
iconfont.ttf
Normal file
BIN
iconfont.ttf
Normal file
Binary file not shown.
55
index.html
55
index.html
@@ -1,7 +1,19 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
|
||||||
<head>
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Fluid Simulation</title>
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
|
||||||
|
<meta property="og:type" content="website">
|
||||||
|
<meta property="og:title" content="webgl fluid simulation">
|
||||||
|
<meta property="og:url" content="https://paveldogreat.github.io/WebGL-Fluid-Simulation/">
|
||||||
|
<meta property="og:image" content="logo.png">
|
||||||
|
<script type="text/javascript" src="dat.gui.min.js"></script>
|
||||||
<style>
|
<style>
|
||||||
|
* {
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
html, body {
|
html, body {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
@@ -17,9 +29,48 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dg {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dg .property-name {
|
||||||
|
overflow: visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
src: url('iconfont.ttf') format('truetype');
|
||||||
|
}
|
||||||
|
|
||||||
|
.bigFont {
|
||||||
|
font-size: 150%;
|
||||||
|
color: #8C8C8C;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon {
|
||||||
|
font-family: 'iconfont';
|
||||||
|
font-size: 130%;
|
||||||
|
float: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.twitter:before {
|
||||||
|
content: 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
.github:before {
|
||||||
|
content: 'b';
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
<script>
|
||||||
|
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||||
|
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||||
|
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||||
|
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||||
|
ga('create', 'UA-105392568-1', 'auto');
|
||||||
|
ga('send', 'pageview');
|
||||||
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<script type="text/javascript" src="dat.gui.min.js"></script>
|
|
||||||
<body>
|
<body>
|
||||||
<canvas></canvas>
|
<canvas></canvas>
|
||||||
<script src="./script.js"></script>
|
<script src="./script.js"></script>
|
||||||
|
62
script.js
62
script.js
@@ -11,6 +11,7 @@ if (!isWebGL2) {
|
|||||||
gl = canvas.getContext('webgl', params) || canvas.getContext('experimental-webgl', params);
|
gl = canvas.getContext('webgl', params) || canvas.getContext('experimental-webgl', params);
|
||||||
}
|
}
|
||||||
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
gl.clearColor(0.0, 0.0, 0.0, 1.0);
|
||||||
|
gl.enable(gl.BLEND);
|
||||||
|
|
||||||
const halfFloat = gl.getExtension('OES_texture_half_float');
|
const halfFloat = gl.getExtension('OES_texture_half_float');
|
||||||
let support_linear_float = gl.getExtension('OES_texture_half_float_linear');
|
let support_linear_float = gl.getExtension('OES_texture_half_float_linear');
|
||||||
@@ -23,20 +24,34 @@ let config = {
|
|||||||
TEXTURE_DOWNSAMPLE: 1,
|
TEXTURE_DOWNSAMPLE: 1,
|
||||||
DENSITY_DISSIPATION: 0.98,
|
DENSITY_DISSIPATION: 0.98,
|
||||||
VELOCITY_DISSIPATION: 0.99,
|
VELOCITY_DISSIPATION: 0.99,
|
||||||
SPLAT_RADIUS: 0.005,
|
PRESSURE_CONCENTRATION: 0.8,
|
||||||
CURL: 30,
|
|
||||||
PRESSURE_ITERATIONS: 25,
|
PRESSURE_ITERATIONS: 25,
|
||||||
CLEAR_PRESSURE: false
|
CURL: 30,
|
||||||
|
SPLAT_RADIUS: 0.005
|
||||||
}
|
}
|
||||||
|
|
||||||
var gui = new dat.GUI();
|
var gui = new dat.GUI({ width: 270 });
|
||||||
gui.add(config, 'TEXTURE_DOWNSAMPLE', { Full: 0, Half: 1, Quarter: 2 }).name('Resolution').onFinishChange(initFramebuffers);
|
gui.add(config, 'TEXTURE_DOWNSAMPLE', { Full: 0, Half: 1, Quarter: 2 }).name('resolution').onFinishChange(initFramebuffers);
|
||||||
gui.add(config, 'DENSITY_DISSIPATION', 0.9, 1.0).name('Density dissipation');
|
gui.add(config, 'DENSITY_DISSIPATION', 0.9, 1.0).name('density diffusion');
|
||||||
gui.add(config, 'VELOCITY_DISSIPATION', 0.9, 1.0).name('Velocity dissipation');
|
gui.add(config, 'VELOCITY_DISSIPATION', 0.9, 1.0).name('velocity diffusion');
|
||||||
gui.add(config, 'SPLAT_RADIUS', 0.001, 0.01).name('Splat radius');
|
gui.add(config, 'PRESSURE_CONCENTRATION', 0.0, 1.0).name('jelly');
|
||||||
gui.add(config, 'CURL', 0, 50).name('Vorticity').step(1);
|
gui.add(config, 'PRESSURE_ITERATIONS', 1, 60).name('iterations');
|
||||||
gui.add(config, 'PRESSURE_ITERATIONS', 1, 60).name('Iterations');
|
gui.add(config, 'CURL', 0, 50).name('vorticity').step(1);
|
||||||
gui.add(config, 'CLEAR_PRESSURE').name('Clear pressure');
|
gui.add(config, 'SPLAT_RADIUS', 0.0001, 0.01).name('splat radius');
|
||||||
|
|
||||||
|
let github = gui.add({ fun : function () { window.open('https://github.com/PavelDoGreat/WebGL-Fluid-Simulation'); } }, 'fun').name('Github');
|
||||||
|
github.__li.className = 'cr function bigFont';
|
||||||
|
github.__li.style.borderLeft = '3px solid #8C8C8C';
|
||||||
|
let githubIcon = document.createElement('span');
|
||||||
|
github.domElement.parentElement.appendChild(githubIcon);
|
||||||
|
githubIcon.className = 'icon github';
|
||||||
|
|
||||||
|
let twitter = gui.add({ fun : function () { window.open('https://twitter.com/PavelDoGreat'); } }, 'fun').name('Twitter');
|
||||||
|
twitter.__li.className = 'cr function bigFont';
|
||||||
|
twitter.__li.style.borderLeft = '3px solid #8C8C8C';
|
||||||
|
let twitterIcon = document.createElement('span');
|
||||||
|
twitter.domElement.parentElement.appendChild(twitterIcon);
|
||||||
|
twitterIcon.className = 'icon twitter';
|
||||||
|
|
||||||
class GLProgram {
|
class GLProgram {
|
||||||
constructor (vertexShader, fragmentShader) {
|
constructor (vertexShader, fragmentShader) {
|
||||||
@@ -95,6 +110,19 @@ const baseVertexShader = compileShader(gl.VERTEX_SHADER, `
|
|||||||
}
|
}
|
||||||
`);
|
`);
|
||||||
|
|
||||||
|
const clearShader = compileShader(gl.FRAGMENT_SHADER, `
|
||||||
|
precision highp float;
|
||||||
|
precision mediump sampler2D;
|
||||||
|
|
||||||
|
varying vec2 vUv;
|
||||||
|
uniform sampler2D uTexture;
|
||||||
|
uniform float value;
|
||||||
|
|
||||||
|
void main () {
|
||||||
|
gl_FragColor = value * texture2D(uTexture, vUv);
|
||||||
|
}
|
||||||
|
`);
|
||||||
|
|
||||||
const displayShader = compileShader(gl.FRAGMENT_SHADER, `
|
const displayShader = compileShader(gl.FRAGMENT_SHADER, `
|
||||||
precision highp float;
|
precision highp float;
|
||||||
precision mediump sampler2D;
|
precision mediump sampler2D;
|
||||||
@@ -397,6 +425,7 @@ function initFramebuffers () {
|
|||||||
|
|
||||||
initFramebuffers();
|
initFramebuffers();
|
||||||
|
|
||||||
|
const clearProgram = new GLProgram(baseVertexShader, clearShader);
|
||||||
const displayProgram = new GLProgram(baseVertexShader, displayShader);
|
const displayProgram = new GLProgram(baseVertexShader, displayShader);
|
||||||
const splatProgram = new GLProgram(baseVertexShader, splatShader);
|
const splatProgram = new GLProgram(baseVertexShader, splatShader);
|
||||||
const advectionProgram = new GLProgram(baseVertexShader, support_linear_float ? advectionShader : advectionManualFilteringShader);
|
const advectionProgram = new GLProgram(baseVertexShader, support_linear_float ? advectionShader : advectionManualFilteringShader);
|
||||||
@@ -482,9 +511,12 @@ function Update () {
|
|||||||
gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.first[2]);
|
gl.uniform1i(divergenceProgram.uniforms.uVelocity, velocity.first[2]);
|
||||||
blit(divergence[1]);
|
blit(divergence[1]);
|
||||||
|
|
||||||
if (config.CLEAR_PRESSURE) {
|
clearProgram.bind();
|
||||||
clear(pressure.first[1]);
|
gl.uniform1i(clearProgram.uniforms.uTexture, pressure.first[2]);
|
||||||
}
|
gl.uniform1f(clearProgram.uniforms.value, config.PRESSURE_CONCENTRATION);
|
||||||
|
blit(pressure.second[1]);
|
||||||
|
pressure.swap();
|
||||||
|
|
||||||
pressureProgram.bind();
|
pressureProgram.bind();
|
||||||
gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
gl.uniform2f(pressureProgram.uniforms.texelSize, 1.0 / textureWidth, 1.0 / textureHeight);
|
||||||
gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]);
|
gl.uniform1i(pressureProgram.uniforms.uDivergence, divergence[2]);
|
||||||
@@ -544,7 +576,7 @@ canvas.addEventListener('mousemove', (e) => {
|
|||||||
canvas.addEventListener('touchmove', (e) => {
|
canvas.addEventListener('touchmove', (e) => {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
const touches = e.targetTouches;
|
const touches = e.targetTouches;
|
||||||
for (let i = 0; i < e.touches.length; i++) {
|
for (let i = 0; i < touches.length; i++) {
|
||||||
let pointer = pointers[i];
|
let pointer = pointers[i];
|
||||||
pointer.moved = pointer.down;
|
pointer.moved = pointer.down;
|
||||||
pointer.dx = (touches[i].pageX - pointer.x) * 10.0;
|
pointer.dx = (touches[i].pageX - pointer.x) * 10.0;
|
||||||
|
Reference in New Issue
Block a user