Newer
Older
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Fluid Simulation</title>
<link rel="stylesheet" type="text/css" href="dependencies/bootstrap.min.css">
<link rel="stylesheet" type="text/css" href="dependencies/flat-ui.min.css">
<link rel="stylesheet" type="text/css" href="main.css">
<script id="2d-vertex-shader" type="x-shader/x-vertex">
attribute vec2 a_position;
void main() {
gl_Position = vec4(a_position, 0, 1);
}
</script>
<script id="2d-render-shader" type="x-shader/x-fragment">
precision mediump float;
gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).x, 0, 1, 1);
<script id="divergenceShader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D u_velocity;
uniform vec2 u_textureSize;
uniform float u_halfReciprocalDx;
void main() {
vec2 fragCoord = gl_FragCoord.xy;
//finite difference formulation of divergence
float n = texture2D(u_velocity, (fragCoord+vec2(0.0, 1.0))/u_textureSize).y;
float s = texture2D(u_velocity, (fragCoord+vec2(0.0, -1.0))/u_textureSize).y;
float e = texture2D(u_velocity, (fragCoord+vec2(1.0, 0.0))/u_textureSize).x;
float w = texture2D(u_velocity, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).x;
gl_FragColor = vec4(u_halfReciprocalDx*(e-w + n-s), 0, 0, 0);
}
</script>
<script id="forceShader" type="x-shader/x-fragment">
precision mediump float;
uniform sampler2D u_velocity;
uniform vec2 u_textureSize;
uniform vec2 u_mouseCoord;
uniform vec2 u_mouseDir;
uniform float u_mouseEnable;
uniform float u_dt;
const float reciprocalRadius = 0.01;
void main() {
vec2 fragCoord = gl_FragCoord.xy;
vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
if (u_mouseEnable == 1.0){
vec2 pxDist = fragCoord - u_mouseCoord;
currentVelocity += u_mouseDir*u_dt*exp(-(pxDist.x*pxDist.x+pxDist.y*pxDist.y)*reciprocalRadius);
}
gl_FragColor = vec4(currentVelocity, 0, 0);
}
</script>
uniform vec2 u_textureSize;
uniform float u_alpha;
uniform float u_reciprocalBeta;
void main() {
vec2 fragCoord = gl_FragCoord.xy;
vec2 currentState = texture2D(u_b, fragCoord/u_textureSize).xy;
vec2 n = texture2D(u_x, (fragCoord+vec2(0.0, 1.0))/u_textureSize).xy;
vec2 s = texture2D(u_x, (fragCoord+vec2(0.0, -1.0))/u_textureSize).xy;
vec2 e = texture2D(u_x, (fragCoord+vec2(1.0, 0.0))/u_textureSize).xy;
vec2 w = texture2D(u_x, (fragCoord+vec2(-1.0, 0.0))/u_textureSize).xy;
vec2 nextState = (n + s + e + w + u_alpha * currentState) * u_reciprocalBeta;
gl_FragColor = vec4(nextState, 0, 0);
}
uniform sampler2D u_velocity;
uniform sampler2D u_material;
vec2 currentVelocity = texture2D(u_velocity, fragCoord/u_textureSize).xy;
gl_FragColor = vec4(texture2D(u_material, fragCoord/u_textureSize).xy, 0, 0);
return;
}
vec2 pxCenter = vec2(0.5, 0.5);
if (pos.x < 0.0 || pos.x >= u_textureSize.x-1.0 || pos.y < 0.0 || pos.y >= u_textureSize.y-1.0){
//boundary
gl_FragColor = vec4(0);
return;
}
//bilinear interp between nearest cells
vec2 ceiled = ceil(pos);
vec2 floored = floor(pos);
vec2 n = texture2D(u_material, (ceiled+pxCenter)/u_textureSize).xy;//actually ne
vec2 s = texture2D(u_material, (floored+pxCenter)/u_textureSize).xy;//actually sw
vec2 se = texture2D(u_material, (vec2(ceiled.x, floored.y)+pxCenter)/u_textureSize).xy;
vec2 nw = texture2D(u_material, (vec2(floored.x, ceiled.y)+pxCenter)/u_textureSize).xy;
n = n*(pos.x-floored.x) + nw*(ceiled.x-pos.x);
s = se*(pos.x-floored.x) + s*(ceiled.x-pos.x);
}
if (ceiled.y != floored.y){
materialVal = n*(pos.y-floored.y) + s*(ceiled.y-pos.y);
}
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision mediump float;
#define M_PI 3.1415926535897932384626433832795
//texture array
uniform sampler2D u_image;//u, v, --, -- = r, g, b, a
uniform vec2 u_textureSize;
uniform vec2 u_mouseCoord;
uniform float u_mouseEnable;
const float dt = 1.0;
void main() {
vec2 fragCoord = gl_FragCoord.xy;
vec2 currentState = texture2D(u_image, fragCoord/u_textureSize).xy;
float u = currentState.x;
float v = currentState.y;
vec2 n = texture2D(u_image, (fragCoord + vec2(0.0, 1.0))/u_textureSize).xy;//north
vec2 s = texture2D(u_image, (fragCoord + vec2(0.0, -1.0))/u_textureSize).xy;//south
vec2 e = texture2D(u_image, (fragCoord + vec2(-1.0, 0.0))/u_textureSize).xy;//east
vec2 w = texture2D(u_image, (fragCoord + vec2(1.0, 0.0))/u_textureSize).xy;//west
if (u_mouseEnable == 1.0){
vec2 pxDistFromMouse = (fragCoord - u_mouseCoord)*(fragCoord - u_mouseCoord);
float tol = 10.0;
if (length(pxDistFromMouse)<tol){
gl_FragColor = vec4(0.5, 0.35, 0, 1);
return;
}
}
gl_FragColor = vec4(0,0, 0, 1);
}
</script>
<script type="text/javascript" src="dependencies/jquery-3.1.0.min.js"></script>
<script type="text/javascript" src="dependencies/flat-ui.min.js"></script>
<script type="text/javascript" src="GLBoilerplate.js"></script>
<script type="text/javascript" src="GPUMath.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body>
<canvas id="glcanvas"></canvas>
<a href="#" id="about">?</a>
<div class="modal fade" id="aboutModal" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<b>Fluid Simulation Shader</b><br/><br/>
<a href="https://pdfs.semanticscholar.org/84b8/c7b7eecf90ebd9d54a51544ca0f8ff93c137.pdf" target="_blank">Real-time ink simulation using a grid-particle method</a> - a method for real-time simulation of ink
in water using a coarse-grained fluid simulation with a particle simulation on top.<br/>
<a href="http://http.developer.nvidia.com/GPUGems/gpugems_ch38.html" target="_blank">Fast Fluid Dynamics Simulation on the GPU</a> - a very well written tutorial about programming the Navier-Stokes equations on a GPU.<br/>
<a href="http://www.dgp.toronto.edu/people/stam/reality/Research/pdf/ns.pdf" target="_blank">Stable Fluids</a> - a paper about stable numerical methods for evaluating Navier-Stokes on a discrete grid.<br/>
<br/>
By <a href="http://www.amandaghassaei.com/" target="_blank">Amanda Ghassaei</a>, code on <a href="https://github.com/amandaghassaei/FluidSimulation" target="_blank">Github</a>.