Published
Edited
Apr 8, 2021
Insert cell
Insert cell
Insert cell
Insert cell
render = quad({
uniforms: {
prevState(context, props) {
const {subtick} = props;
return state[subtick % 2];
},
},
frag: `
precision highp float;

uniform sampler2D prevState;
varying vec2 v_tex_pos;

void main() {
vec4 state = texture2D(prevState, v_tex_pos);
float rr = ${resistanceResource.toPrecision(2)};

float r = state.r;
float f = state.g;
// float b = min(1.0, state.b);
float f1Scale = 1e10;
float f1 = 1.0 * (log(abs(f)) / log(f1Scale));
float fp = max(0.0, log(f) / log(f1Scale));
float fn = -min(0.0, log(f) / log(f1Scale));

gl_FragColor = vec4(r, f, 0.0, 1.0);
}`
})
Insert cell
update = quad({
uniforms: {
tick: regl.prop("subtick"),
start: [start.x, start.y],
prevState(context, props) {
const {subtick} = props;
return state[subtick % 2];
},
},
frag: `
precision highp float;

uniform int tick;
uniform ivec2 start;
uniform sampler2D prevState;
varying vec2 v_tex_pos;

${snoise3D}
${noiseShaderFunction}

void main() {
int radius = ${radius};
ivec2 cellPos = ivec2(v_tex_pos * float(radius));

vec4 state = texture2D(prevState, v_tex_pos);
vec4 newState = vec4(0.0, 0.0, 0.0, 0.0);

float r = (noise(vec3(v_tex_pos * float(radius), float(tick) * 0.05))) * 0.4 + 0.6;
float q = state.g;
float dt = 0.05;
float dq = 0.0;
for(int dx = -1; dx <= 1; dx++) {
for(int dy = -1; dy <= 1; dy++) {
float nd = length(vec2(dx, dy));
if (nd > 0.0) {
vec4 n = texture2D(prevState, vec2(cellPos + ivec2(dx, dy)) / float(radius));
float nq = n.g;
float resistance = r * nd;
dq += (nq - q) / resistance * dt;
}
}
}

if (cellPos == start) {
dq = ${resistanceResource.toPrecision(2)};
}

newState.r = r;
newState.g = q + dq;
gl_FragColor = newState;
}`
})
Insert cell
radius = width
Insert cell
state = Array(2)
.fill()
.map(() =>
regl.framebuffer({
color: regl.texture({
radius,
data: initialState,
format: "rgba",
type: "float"
}),
depth: false,
depthStencil: false
})
)
Insert cell
initialState = {
const initialState = (Array(radius * radius * 4)).fill(0);
return initialState;
}
Insert cell
Insert cell
Insert cell
Insert cell
fps(fpsTick)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
state1 = {
let tick = 0;
while (true) {
tick++;
yield {
tick,
};
}
}
Insert cell
tick = state1.tick;
Insert cell
Insert cell
Insert cell
import {fps} from '@zzzev/fps-counter'
Insert cell
Insert cell
snoise3D = (await fetch("https://raw.githubusercontent.com/ashima/webgl-noise/ff3b5d34eafb7ad97985e896235546ceaea5b2cf/src/noise3D.glsl")).text()
Insert cell
Insert cell
Insert cell
reglLib = require('https://unpkg.com/regl@2.1.0/dist/regl.js');
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more