updateSprites = regl({
vert: `
precision mediump float;
attribute vec2 position;
void main () {
gl_Position = vec4(position, 0, 1);
}
`,
frag: `
precision highp float;
uniform sampler2D state;
uniform float shapeX, shapeY, deltaT, gravity;
uniform float tick;
uniform float friction;
uniform float noiseScale;
uniform float balance;
uniform float spectrumBin0;
uniform float spectrumBin1;
uniform float spectrumBin2;
uniform float mouseX;
uniform float mouseY;
vec2 random2(vec2 st){
st = vec2( dot(st,vec2(127.1,311.7)),
dot(st,vec2(269.5,183.3)) );
return -1.0 + 2.0*fract(sin(st)*43758.5453123);
}
float WaveletNoise(vec2 p, float z, float k) {
float d=0.,s=1.,m=0., a;
for(float i=0.; i<4.; i++) {
vec2 q = p*s, g=fract(floor(q)*vec2(123.34,233.53));
g += dot(g, g+23.234);
a = fract(g.x*g.y)*1e3;// +z*(mod(g.x+g.y, 2.)-1.); // add vorticity
q = (fract(q)-.5)*mat2(cos(a),-sin(a),sin(a),cos(a));
d += sin(q.x*10.+z)*smoothstep(.25, .0, dot(q,q))/s;
p = p*mat2(.54,-.84, .84, .54)+i;
m += 1./s;
s *= k;
}
return d/m;
}
void main () {
vec2 shape = vec2(shapeX, shapeY);
vec4 prevState = texture2D(state,
gl_FragCoord.xy / shape);
vec2 position = prevState.xy;
vec2 velocity = prevState.zw;
position += 0.5 * velocity * deltaT;
// if (position.x < -1.0 || position.x > 1.0) {
// velocity.x *= -1.0;
// }
// if (position.y < -1.0 || position.y > 1.0) {
// velocity.y *= -1.0;
// }
if (abs(position.x) > 2. || abs(position.y) > 2.) {
position = random2(position) * 1.5;
}
position += 0.5 * velocity * deltaT;
vec2 force_noise = vec2(
// noise(position * noiseScale),
// noise(position * noiseScale)
// noise(vec2(0.), 1., 1.),
// noise(vec2(0.), 1., 1.)
WaveletNoise(position * fract(spectrumBin2 + 0.5) * 20. + tick / 100., 1., 0.5),
WaveletNoise(position + 1000. * fract(spectrumBin2 + 0.5) * 20. + tick / 100., 1., 0.5)
);
vec2 force_radial = -1. * vec2(vec2(mouseX, mouseY) - position);
// velocity.y = velocity.y + gravity * deltaT;
velocity *= (1. - friction);
vec2 force = mix(force_noise, force_radial, fract(spectrumBin1));
velocity = force * (spectrumBin0 - 1.) / 50.;
gl_FragColor = vec4(position, velocity);
}
`,
depth: {enable: false},
// buffer for next state rendering
// ?? can the frag shader have several buffers?
framebuffer: ({tick}) => vars.SPRITES[(tick + 1) % 2],
uniforms: {
// prev state
state: ({tick}) => vars.SPRITES[(tick) % 2],
// is it size of current buffer?
shapeX: regl.context('viewportWidth'),
shapeY: regl.context('viewportHeight'),
deltaT: 0.0005,
gravity: -0.05,
tick: regl.context('tick'),
friction,
// noiseScale,
// balance,
spectrumBin0: regl.prop('spectrumBin0'),
spectrumBin1: regl.prop('spectrumBin1'),
spectrumBin2: regl.prop('spectrumBin2'),
mouseX: regl.prop('mouseX'),
mouseY: regl.prop('mouseY'),
},
attributes: {
position: [
0, -4,
4, 4,
-4, 4
]
},
primitive: 'triangles',
elements: null,
offset: 0,
count: 3
})