-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathscript.min.js
80 lines (67 loc) · 10.5 KB
/
script.min.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
"use strict";var e=document.querySelector("#fluidsim_canvas");const v=e.getContext("webgl2");v.getExtension("EXT_color_buffer_float");let t={i:1,t:.5,o:"dye",v:.1,u:.99,l:.99,p:128,_:1024,h:20},o,r,c,s,u;function i(e){return o<1?{width:e,height:Math.round(e/o)}:{width:Math.round(e*o),height:e}}function x(){var e=v.canvas.clientWidth,n=v.canvas.clientHeight;if(o=v.canvas.clientWidth/v.canvas.clientHeight,v.canvas.width!==e||v.canvas.height!==n)return v.canvas.width=e,v.canvas.height=n,e=i(t.p),n=i(t._),r=e.width,c=e.height,s=n.width,u=n.height,1}x();let a=v.createVertexArray();var n=new Float32Array([-1,-1,1,1,1,-1,-1,-1,-1,1,1,1]),l=(l=a,n=n,A=2,O=v.FLOAT,w=!1,C=M=0,v.bindVertexArray(l),l=v.createBuffer(),v.bindBuffer(v.ARRAY_BUFFER,l),v.bufferData(v.ARRAY_BUFFER,n,v.STATIC_DRAW),v.enableVertexAttribArray(0),v.vertexAttribPointer(0,A,O,w,M,C),`#version 300 es
in vec2 a_position;
out vec2 v_position;
void main() {
v_position = a_position * 0.5 + 0.5;
gl_Position = vec4(a_position, 0, 1);
}`);function R(e,n,i){n=e.createShader(n);return e.shaderSource(n,i),e.compileShader(n),e.getShaderParameter(n,e.COMPILE_STATUS)?n:(console.error(e.getShaderInfoLog(n)),e.deleteShader(n),null)}function p(e,n){var i,t,e=R(v,v.VERTEX_SHADER,e),n=R(v,v.FRAGMENT_SHADER,n),e=(i=v,e=e,n=n,t=i.createProgram(),i.attachShader(t,e),i.attachShader(t,n),i.linkProgram(t),i.getProgramParameter(t,i.LINK_STATUS)?t:(console.error(i.getProgramInfoLog(t)),i.deleteProgram(t),null)),n=function(n,i){var t={},o=n.getProgramParameter(i,n.ACTIVE_UNIFORMS);for(let e=0;e<o;++e){var r=n.getActiveUniform(i,e);t[r.name]=n.getUniformLocation(i,r.name)}return t}(v,e);return v.bindAttribLocation(e,0,"a_position"),{m:e,g:n}}const _=p(l,`#version 300 es
precision highp float;
uniform sampler2D u_v;
uniform sampler2D u_x;
uniform float u_dt;
uniform float u_dissipation;
out vec4 res;
vec4 bilerp(sampler2D tex, vec2 x_norm, vec2 size) {
vec2 x = x_norm * size - 0.5;
vec2 fx = fract(x);
ivec2 ix = ivec2(floor(x));
vec4 x00 = texelFetch(tex, ix + ivec2(0,0), 0);
vec4 x01 = texelFetch(tex, ix + ivec2(0,1), 0);
vec4 x10 = texelFetch(tex, ix + ivec2(1,0), 0);
vec4 x11 = texelFetch(tex, ix + ivec2(1,1), 0);
return mix(mix(x00, x10, fx.x), mix(x01, x11, fx.x), fx.y);
}
void main() {
vec2 size_v = vec2(textureSize(u_v, 0));
vec2 size_x = vec2(textureSize(u_x, 0));
vec2 aspect_ratio = vec2(size_x.x / size_x.y, 1.0);
vec2 normalized_pos = gl_FragCoord.xy / size_x;
vec2 prev = normalized_pos - u_dt * bilerp(u_v, normalized_pos, size_v).xy / aspect_ratio;
res = u_dissipation * bilerp(u_x, prev, size_x);
}`),h=p(l,"#version 300 es\nprecision highp float;\n\nuniform sampler2D u_x;\nuniform sampler2D u_b;\nuniform float u_alpha;\nuniform float u_beta;\nout vec4 res;\n\n\nstruct Neighbors {\n vec4 l;\n vec4 r;\n vec4 t;\n vec4 b;\n vec4 c;\n};\n\nNeighbors tex_neighbors(sampler2D tex, ivec2 pos) {\n vec4 b = texelFetch(tex, pos - ivec2(0, 1), 0);\n vec4 t = texelFetch(tex, pos + ivec2(0, 1), 0);\n vec4 l = texelFetch(tex, pos - ivec2(1, 0), 0);\n vec4 r = texelFetch(tex, pos + ivec2(1, 0), 0);\n vec4 c = texelFetch(tex, pos, 0);\n return Neighbors(l, r, t, b, c);\n}\n\nvoid main() {\n ivec2 pos = ivec2(gl_FragCoord.xy); \n Neighbors n = tex_neighbors(u_x, pos);\n vec4 b = texelFetch(u_b, pos, 0);\n res = (n.b + n.t + n.l + n.r + u_alpha * b) / u_beta;\n}"),f=p(l,"#version 300 es\nprecision highp float;\n\nuniform sampler2D u_v;\nuniform sampler2D u_p;\nout vec4 res;\n\n\nstruct Neighbors {\n vec4 l;\n vec4 r;\n vec4 t;\n vec4 b;\n vec4 c;\n};\n\nNeighbors tex_neighbors(sampler2D tex, ivec2 pos) {\n vec4 b = texelFetch(tex, pos - ivec2(0, 1), 0);\n vec4 t = texelFetch(tex, pos + ivec2(0, 1), 0);\n vec4 l = texelFetch(tex, pos - ivec2(1, 0), 0);\n vec4 r = texelFetch(tex, pos + ivec2(1, 0), 0);\n vec4 c = texelFetch(tex, pos, 0);\n return Neighbors(l, r, t, b, c);\n}\n\nvoid main() {\n ivec2 pos = ivec2(gl_FragCoord.xy); \n Neighbors n = tex_neighbors(u_p, pos);\n\n vec4 grad = vec4(n.r.x - n.l.x, n.t.x - n.b.x, 0, 0) / 2.;\n vec4 init_v = texelFetch(u_v, pos, 0);\n res = init_v - grad;\n}"),L=p(l,"#version 300 es\nprecision highp float;\n\nuniform sampler2D u_x;\nout vec4 res;\n\n\nstruct Neighbors {\n vec4 l;\n vec4 r;\n vec4 t;\n vec4 b;\n vec4 c;\n};\n\nNeighbors tex_neighbors(sampler2D tex, ivec2 pos) {\n vec4 b = texelFetch(tex, pos - ivec2(0, 1), 0);\n vec4 t = texelFetch(tex, pos + ivec2(0, 1), 0);\n vec4 l = texelFetch(tex, pos - ivec2(1, 0), 0);\n vec4 r = texelFetch(tex, pos + ivec2(1, 0), 0);\n vec4 c = texelFetch(tex, pos, 0);\n return Neighbors(l, r, t, b, c);\n}\n\nvoid main() {\n ivec2 pos = ivec2(gl_FragCoord.xy); \n Neighbors n = tex_neighbors(u_x, pos);\n\n float div = (n.r.x - n.l.x + n.t.y - n.b.y) / 2.;\n\n res = vec4(div, 0, 0, 1);\n}"),m=p(l,`#version 300 es
precision highp float;
in vec2 v_position;
uniform sampler2D u_x;
uniform vec2 u_res;
uniform float u_alpha;
out vec4 res;
void main() {
vec2 dir = vec2(0, 0);
dir += vec2(lessThan(v_position, u_res));
dir -= vec2(greaterThan(v_position, vec2(1.0) - u_res));
float coef = length(dir) > 0.0 ? u_alpha : 1.0;
res = coef * texture(u_x, v_position + dir * u_res);
}`),d=p(l,`#version 300 es
precision highp float;
in vec2 v_position;
uniform sampler2D u_x;
uniform float u_alpha;
out vec4 res;
void main() {
res = u_alpha * texture(u_x, v_position);
}`),b=p(l,`#version 300 es
precision highp float;
in vec2 v_position;
uniform sampler2D u_x;
uniform vec2 u_point;
uniform vec3 u_value;
uniform float u_radius;
uniform float u_ratio;
out vec4 res;
void main() {
vec4 init = texture(u_x, v_position);
vec2 v = v_position - u_point;
v.x *= u_ratio;
vec3 force = exp(-dot(v,v)/u_radius) * u_value;
res = vec4(init.xyz + force, 1.);
}`);function g(e,n,i,t,o,r){const c=v.createTexture(),s=(v.activeTexture(v.TEXTURE0),v.bindTexture(v.TEXTURE_2D,c),v.texParameteri(v.TEXTURE_2D,v.TEXTURE_MIN_FILTER,r),v.texParameteri(v.TEXTURE_2D,v.TEXTURE_MAG_FILTER,r),v.texParameteri(v.TEXTURE_2D,v.TEXTURE_WRAP_S,v.CLAMP_TO_EDGE),v.texParameteri(v.TEXTURE_2D,v.TEXTURE_WRAP_T,v.CLAMP_TO_EDGE),v.texImage2D(v.TEXTURE_2D,0,i,e,n,0,t,o,null),v.createFramebuffer());return v.bindFramebuffer(v.FRAMEBUFFER,s),v.framebufferTexture2D(v.FRAMEBUFFER,v.COLOR_ATTACHMENT0,v.TEXTURE_2D,c,0),{F:c,D:s,bind:()=>{v.bindFramebuffer(v.FRAMEBUFFER,s),v.viewport(0,0,e,n)},N:e=>(v.activeTexture(v.TEXTURE0+e),v.bindTexture(v.TEXTURE_2D,c),e)}}function F(e,n,i,t,o,r){return{read:g(e,n,i,t,o,r),write:g(e,n,i,t,o,r),S:function(){var e=this.read;this.read=this.write,this.write=e}}}function U(e,n,i,t,o,r,c){n=g(n,i,t,o,r,c);return v.useProgram(d.m),v.uniform1i(d.g.u_x,e.N(0)),I(n,v.TRIANGLES,6),n}function D(e,n,i,t,o,r,c){var s=F(n,i,t,o,r,c);return s.read=U(e.read,n,i,t,o,r,c),s.write=U(e.write,n,i,t,o,r,c),s}let y=F(r,c,v.RG32F,v.RG,v.FLOAT,v.NEAREST),N=F(r,c,v.R32F,v.RED,v.FLOAT,v.NEAREST),z=g(r,c,v.R32F,v.RED,v.FLOAT,v.NEAREST),Y=g(r,c,v.RG32F,v.RG,v.FLOAT,v.NEAREST),S=F(s,u,v.RGBA32F,v.RGBA,v.FLOAT,v.NEAREST);const q={F:null,D:null,bind:()=>{v.bindFramebuffer(v.FRAMEBUFFER,null),v.viewport(0,0,v.canvas.width,v.canvas.height)}};function I(e,n,i,t=!1){v.bindVertexArray(a),e.bind(),t&&(v.clearColor(0,0,0,1),v.clear(v.COLOR_BUFFER_BIT)),v.drawArrays(n,0,i)}function E(e,n){v.useProgram(m.m),v.uniform2f(m.g.u_res,1/r,1/c),v.uniform1i(m.g.u_x,e.read.N(0)),v.uniform1f(m.g.u_alpha,n),I(e.write,v.TRIANGLES,6),e.S()}let V=0;requestAnimationFrame(function e(n){var i=(n-V)/1e3,n=(V=n,x()&&(y=D(y,r,c,v.RG32F,v.RG,v.FLOAT,v.NEAREST),N=D(N,r,c,v.R32F,v.RED,v.FLOAT,v.NEAREST),S=D(S,s,u,v.RGBA32F,v.RGBA,v.FLOAT,v.NEAREST),z=g(r,c,v.R32F,v.RED,v.FLOAT,v.NEAREST),Y=g(r,c,v.RG32F,v.RG,v.FLOAT,v.NEAREST)),T.forEach(e=>{v.useProgram(b.m),v.uniform1i(b.g.u_x,y.read.N(0)),v.uniform2fv(b.g.u_point,[e.x,e.y]),v.uniform3fv(b.g.u_value,[e.dx*o,e.dy,0].map(e=>e*t.h)),v.uniform1f(b.g.u_radius,t.v),v.uniform1f(b.g.u_ratio,o),I(y.write,v.TRIANGLES,6),y.S(),v.uniform1i(b.g.u_x,S.read.N(0)),v.uniform3fv(b.g.u_value,e.color.map(e=>.2*e)),I(S.write,v.TRIANGLES,6),S.S()}),i);E(y,-1),v.useProgram(_.m),v.uniform1i(_.g.u_v,0),v.uniform1i(_.g.u_x,y.read.N(0)),v.uniform1f(_.g.u_dt,n),v.uniform1f(_.g.u_dissipation,t.u),I(y.write,v.TRIANGLES,6),y.S(),E(S,0),v.useProgram(_.m),v.uniform1i(_.g.u_v,y.read.N(0)),v.uniform1i(_.g.u_x,S.read.N(1)),v.uniform1f(_.g.u_dt,n),v.uniform1f(_.g.u_dissipation,t.l),I(S.write,v.TRIANGLES,6),S.S(),E(y,-1),v.useProgram(h.m),n=1/(t.i*n),v.uniform1f(h.g.u_alpha,n),v.uniform1f(h.g.u_beta,4+n);for(let e=0;e<20;e++)v.uniform1i(h.g.u_x,y.read.N(0)),v.uniform1i(h.g.u_b,y.read.N(0)),I(y.write,v.TRIANGLES,6),y.S();E(y,-1),v.useProgram(L.m),v.uniform1i(L.g.u_x,y.read.N(0)),I(z,v.TRIANGLES,6),v.useProgram(d.m),v.uniform1i(d.g.u_x,N.read.N(0)),v.uniform1f(d.g.u_alpha,t.t),I(N.write,v.TRIANGLES,6),N.S();for(let e=0;e<50;e++)E(N,1),v.useProgram(h.m),v.uniform1i(h.g.u_b,z.N(0)),v.uniform1i(h.g.u_x,N.read.N(1)),v.uniform1f(h.g.u_alpha,-1),v.uniform1f(h.g.u_beta,4),I(N.write,v.TRIANGLES,6),N.S();E(y,-1),E(N,1),v.useProgram(f.m),v.uniform1i(f.g.u_p,N.read.N(0)),v.uniform1i(f.g.u_v,y.read.N(1)),I(y.write,v.TRIANGLES,6),y.S(),i=("velocity"==t.o?y:"pressure"==t.o?N:S).read,v.useProgram(d.m),v.uniform1i(d.g.u_x,i.N(0)),v.uniform1f(d.g.u_alpha,1),I(q,v.TRIANGLES,6),requestAnimationFrame(e)});const T=[];function X(e){return{id:e.pointerId,x:e.offsetX/v.canvas.clientWidth,y:1-e.offsetY/v.canvas.clientHeight,dx:0,dy:0,color:[Math.random(),Math.random(),Math.random()]}}e.addEventListener("pointerdown",e=>{T.push(X(e))}),e.addEventListener("pointerup",n=>{var e=T.findIndex(e=>e.id===n.pointerId);e<0||T.splice(e,1)}),e.addEventListener("pointermove",n=>{var e,i=T.findIndex(e=>e.id===n.pointerId);i<0||(e=X(n),T[i]=(i=T[i],(e=e).color=i.color,e.dx=e.x-i.x,e.dy=e.y-i.y,e))}),e.addEventListener("pointerout",n=>{var e=T.findIndex(e=>e.id===n.pointerId);e<0||T.splice(e,1)});var n=document.querySelector("#viscosity"),A=document.querySelector("#pressure"),O=document.querySelector("#radius"),w=document.querySelector("#velocity_dissipation"),M=document.querySelector("#density_dissipation"),C=document.querySelector("#display_radio");function P(e,n,i){return n*Math.pow(i/n,e)}const j=e=>P(e,1e-4,1e3),k=e=>P(e,1e-4,.01),B=e=>1-P(e,.001,.1),G=e=>1-P(e,.001,.1);t.i=j(n.value),t.t=A.value,t.v=k(O.value),t.u=B(w.value),t.l=G(M.value),n.addEventListener("input",e=>{t.i=j(e.target.value)}),A.addEventListener("input",e=>{t.t=e.target.value}),O.addEventListener("input",e=>{t.v=k(e.target.value)}),w.addEventListener("input",e=>{t.u=B(e.target.value)}),M.addEventListener("input",e=>{t.l=G(e.target.value)}),C.addEventListener("input",e=>{t.o=e.target.value});