xxxxxxxxxx
99
// Reaction-diffusion by the Gray-Scott model
// Based on https://editor.p5js.org/codingtrain/sketches/govdEW5aE
// Speed up processing thanks to Tensorflow (still really slow 🐢)
// By juancer (github/ajuancer) on 22 jun 21'
var grid, next, grid_buffer, next_buffer;
var dA = 1;
var dB = 0.5;
var feed = 0.055;
var k = 0.062;
var laplace_filter = tf.tensor2d(
[0.05, 0.2, 0.05, 0.2, -1, 0.2, 0.05, 0.2, 0.05],
[3, 3]
);
function setup() {
createCanvas(200, 200);
pixelDensity(1);
grid = tf.stack(
[tf.fill([width, height], 1), tf.fill([width, height], 0)],
2
);
next = grid.clone();
// Make b dot
grid_buffer = tf.buffer(grid.shape, grid.dtype, grid.dataSync());
for (var i = 100; i < 110; i++) {
for (var j = 100; j < 110; j++) {
grid_buffer.set(1, i, j, 1);
}
}
grid = grid_buffer.toTensor();
// console.log(`${laplace_a.get(105, 105)} ${laplace(105, 105, "a")}`);
}
function draw() {
background(51);
// Generate laplace matrix using tensorflow
// https://stackoverflow.com/a/55599631/11688263
laplace_a = tf.split(grid, 2, (axis = 2))[0];
laplace_b = tf.split(grid, 2, (axis = 2))[1];
laplace_a = laplace_a.squeeze();
laplace_b = laplace_b.squeeze();
laplace_a = laplace_a
.reshape([1, laplace_a.shape, 1])
.conv2d(laplace_filter.reshape([laplace_filter.shape, 1, 1]), 1, "same")
.squeeze();
laplace_b = laplace_b
.reshape([1, laplace_b.shape, 1])
.conv2d(laplace_filter.reshape([laplace_filter.shape, 1, 1]), 1, "same")
.squeeze();
next_buffer = tf.buffer(next.shape, next.dtype, next.dataSync());
// Timeconsuming iteration
for (var x = 1; x < width - 1; x++) {
for (var y = 1; y < height - 1; y++) {
var a = grid.get(x, y, 0);
var b = grid.get(x, y, 1);
temp_a = a + dA * laplace_a.get(x, y) - a * b * b + feed * (1 - a)
temp_b = b + dB * laplace_b.get(x, y) + a * b * b - (k + feed) * b
next_buffer.set(constrain(temp_a, 0, 1), x, y, 0);
next_buffer.set(constrain(temp_b, 0, 1), x, y, 1);
}
next = next_buffer.toTensor();
}
// Timeconsuming iteration
loadPixels();
for (var x = 0; x < width; x++) {
for (var y = 0; y < height; y++) {
var pix = (x + y * width) * 4;
var a = next.get(x, y, 0);
var b = next.get(x, y, 1);
var c = floor((a - b) * 255);
c = constrain(c, 0, 255);
pixels[pix + 0] = c;
pixels[pix + 1] = c;
pixels[pix + 2] = c;
pixels[pix + 3] = 255;
}
}
updatePixels();
// No need to swap variables as next
// will be overwritten in the loop.
grid = next.clone();
}