-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1250696
commit dfe7942
Showing
4 changed files
with
145,782 additions
and
0 deletions.
There are no files selected for viewing
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,300 @@ | ||
<title>cells</title> | ||
<link rel="icon" type="image/png" href="favicon.png" /> | ||
<style> | ||
html, | ||
body { | ||
padding: 0; | ||
margin: 0; | ||
overflow: hidden; | ||
background-color: #262626; | ||
} | ||
|
||
canvas { | ||
display: block; | ||
} | ||
</style> | ||
|
||
<!-- fallback to cdn --> | ||
<script src="lib/p5.js"></script> | ||
<script>window.p5 || document.write('<script src="https://cdn.jsdelivr.net/npm/[email protected]/lib/p5.js">\x3C/script>')</script> | ||
<script src="lib/swissgl.js"></script> | ||
<script>window.SwissGL || document.write('<script src="https://cdn.jsdelivr.net/gh/google/swissgl@main/swissgl.js">\x3C/script>')</script> | ||
|
||
<script> | ||
let glsl, cells, targetMass; | ||
let pause = false; | ||
|
||
const cellsTargetParams = { | ||
scale: 1 / 6, | ||
format: "rgba16f", | ||
story: 2, | ||
tag: "cells", | ||
}; | ||
|
||
const kernels = {}; | ||
const weights = {}; | ||
const bias = []; | ||
|
||
function setup() { | ||
const canvas = createCanvas(windowWidth, windowHeight, WEBGL); | ||
glsl = SwissGL(canvas.elt); | ||
cells = glsl({ | ||
seed: Math.random() * 12417, | ||
FP: "hash(ivec3(I, seed)), 1" | ||
}, { ...cellsTargetParams }); | ||
|
||
initParams(); | ||
}; | ||
|
||
function initParams() { | ||
for (const c of "rgb") { | ||
kernels[c] = { | ||
centerVals: [], | ||
controlDists: [], | ||
controlVals: [], | ||
}; | ||
for (let i = 0; i < 4; i++) { | ||
kernels[c].centerVals.push(random(-1, 1) * 1); | ||
kernels[c].controlDists.push(random(0.1, 0.9)); | ||
kernels[c].controlVals.push(random(-1, 1) * 1); | ||
} | ||
|
||
weights[c] = []; | ||
for (let i = 0; i < 3 * 4; i++) { | ||
weights[c].push(random(-1, 1)); | ||
} | ||
weights[c] = new Float32Array(weights[c]); | ||
|
||
bias.length = 0; | ||
for (let i = 0; i < 4; i++) { | ||
bias.push(random()); | ||
} | ||
} | ||
} | ||
|
||
function keyPressed() { | ||
if (key === " ") { | ||
pause = !pause; | ||
} else if (key === "r") { | ||
glsl({ FP: "0" }, cells); | ||
step(); | ||
} else if (key === "f") { | ||
glsl({ FP: "0" }, cells); | ||
initParams(); | ||
step(); | ||
} else if (key === "ArrowRight") { | ||
step(); | ||
} | ||
} | ||
|
||
function step() { | ||
targetMass = glsl({ | ||
cells: cells[0], | ||
|
||
rCenterVals: kernels.r.centerVals, | ||
gCenterVals: kernels.g.centerVals, | ||
bCenterVals: kernels.b.centerVals, | ||
rControlDists: kernels.r.controlDists, | ||
gControlDists: kernels.g.controlDists, | ||
bControlDists: kernels.b.controlDists, | ||
rControlVals: kernels.r.controlVals, | ||
gControlVals: kernels.g.controlVals, | ||
bControlVals: kernels.b.controlVals, | ||
rW: weights.r, | ||
gW: weights.g, | ||
bW: weights.b, | ||
bias, | ||
|
||
FP: ` | ||
uniform vec4 rW[3]; | ||
uniform vec4 gW[3]; | ||
uniform vec4 bW[3]; | ||
void fragment() { | ||
// FOut = vec4(rW[0].xyz, 1.0); | ||
// return; | ||
vec4 rK = vec4(0); | ||
vec4 gK = vec4(0); | ||
vec4 bK = vec4(0); | ||
float totalContrib = 0.0; | ||
for (int k = 0; k < 81; k++) { | ||
ivec2 offset = ivec2(k % 9 - 4, k / 9 - 4); | ||
if (offset == ivec2(0)) { continue; } | ||
float dist = length(vec2(offset)) / 5.0; | ||
float contrib = dist <= 1.0 ? 1.0 : 0.0; | ||
ivec2 neighborPos = (I + offset + cells_size()) % cells_size(); | ||
rK += vec4( | ||
cells(neighborPos).r * ( | ||
dist < rControlDists[0] | ||
? mix(rCenterVals[0], rControlVals[0], dist / rControlDists[0]) | ||
: mix(rControlVals[0], 0.0, (dist - rControlDists[0]) / (1.0 - rControlDists[0])) | ||
), | ||
cells(neighborPos).r * ( | ||
dist < rControlDists[1] | ||
? mix(rCenterVals[1], rControlVals[1], dist / rControlDists[1]) | ||
: mix(rControlVals[1], 0.0, (dist - rControlDists[0]) / (1.0 - rControlDists[1])) | ||
), | ||
cells(neighborPos).r * ( | ||
dist < rControlDists[2] | ||
? mix(rCenterVals[2], rControlVals[2], dist / rControlDists[2]) | ||
: mix(rControlVals[2], 0.0, (dist - rControlDists[2]) / (1.0 - rControlDists[2])) | ||
), | ||
cells(neighborPos).r * ( | ||
dist < rControlDists[3] | ||
? mix(rCenterVals[3], rControlVals[3], dist / rControlDists[3]) | ||
: mix(rControlVals[3], 0.0, (dist - rControlDists[3]) / (1.0 - rControlDists[3])) | ||
) | ||
) * contrib; | ||
gK += vec4( | ||
cells(neighborPos).g * ( | ||
dist < gControlDists[0] | ||
? mix(gCenterVals[0], gControlVals[0], dist / gControlDists[0]) | ||
: mix(gControlVals[0], 0.0, (dist - gControlDists[0]) / (1.0 - gControlDists[0])) | ||
), | ||
cells(neighborPos).g * ( | ||
dist < gControlDists[1] | ||
? mix(gCenterVals[1], gControlVals[1], dist / gControlDists[1]) | ||
: mix(gControlVals[1], 0.0, (dist - gControlDists[0]) / (1.0 - gControlDists[1])) | ||
), | ||
cells(neighborPos).g * ( | ||
dist < gControlDists[2] | ||
? mix(gCenterVals[2], gControlVals[2], dist / gControlDists[2]) | ||
: mix(gControlVals[2], 0.0, (dist - gControlDists[2]) / (1.0 - gControlDists[2])) | ||
), | ||
cells(neighborPos).g * ( | ||
dist < gControlDists[3] | ||
? mix(gCenterVals[3], gControlVals[3], dist / gControlDists[3]) | ||
: mix(gControlVals[3], 0.0, (dist - gControlDists[3]) / (1.0 - gControlDists[3])) | ||
) | ||
) * contrib; | ||
bK += vec4( | ||
cells(neighborPos).b * ( | ||
dist < bControlDists[0] | ||
? mix(bCenterVals[0], bControlVals[0], dist / bControlDists[0]) | ||
: mix(bControlVals[0], 0.0, (dist - bControlDists[0]) / (1.0 - bControlDists[0])) | ||
), | ||
cells(neighborPos).b * ( | ||
dist < bControlDists[1] | ||
? mix(bCenterVals[1], bControlVals[1], dist / bControlDists[1]) | ||
: mix(bControlVals[1], 0.0, (dist - bControlDists[0]) / (1.0 - bControlDists[1])) | ||
), | ||
cells(neighborPos).b * ( | ||
dist < bControlDists[2] | ||
? mix(bCenterVals[2], bControlVals[2], dist / bControlDists[2]) | ||
: mix(bControlVals[2], 0.0, (dist - bControlDists[2]) / (1.0 - bControlDists[2])) | ||
), | ||
cells(neighborPos).b * ( | ||
dist < bControlDists[3] | ||
? mix(bCenterVals[3], bControlVals[3], dist / bControlDists[3]) | ||
: mix(bControlVals[3], 0.0, (dist - bControlDists[3]) / (1.0 - bControlDists[3])) | ||
) | ||
) * contrib; | ||
totalContrib += contrib; | ||
} | ||
// FOut = vec4(rK.x, gK.x, bK.x, 1.0); | ||
// rK /= totalContrib; | ||
// gK /= totalContrib; | ||
// bK /= totalContrib; | ||
float rTarget = ( | ||
bias.r | ||
+ rW[0].x * rK.x + rW[0].y * rK.y + rW[0].z * rK.z + rW[0].w * rK.w | ||
+ rW[1].x * gK.x + rW[1].y * gK.y + rW[1].z * gK.z + rW[1].w * gK.w | ||
+ rW[2].x * bK.x + rW[2].y * bK.y + rW[2].z * bK.z + rW[2].w * bK.w | ||
); | ||
float gTarget = ( | ||
bias.g | ||
+ gW[0].x * rK.x + gW[0].y * rK.y + gW[0].z * rK.z + gW[0].w * rK.w | ||
+ gW[1].x * gK.x + gW[1].y * gK.y + gW[1].z * gK.z + gW[1].w * gK.w | ||
+ gW[2].x * bK.x + gW[2].y * bK.y + gW[2].z * bK.z + gW[2].w * bK.w | ||
); | ||
float bTarget = ( | ||
bias.b | ||
+ bW[0].x * rK.x + bW[0].y * rK.y + bW[0].z * rK.z + bW[0].w * rK.w | ||
+ bW[1].x * gK.x + bW[1].y * gK.y + bW[1].z * gK.z + bW[1].w * gK.w | ||
+ bW[2].x * bK.x + bW[2].y * bK.y + bW[2].z * bK.z + bW[2].w * bK.w | ||
); | ||
vec3 targetMass = clamp( | ||
vec3(rTarget, gTarget, bTarget), | ||
0.0, | ||
1.0 | ||
); | ||
targetMass += vec3(0.5); | ||
FOut = vec4(targetMass, 1.0); | ||
} | ||
`}, { | ||
size: cells[0].size, | ||
format: "rgba16f", | ||
tag: "targetMass", | ||
}); | ||
|
||
cells = glsl({ | ||
targetMass, | ||
seed: Math.random() * 12417, | ||
FP: ` | ||
vec3 massTransfer(ivec2 pos, ivec2 dir) { | ||
pos = (pos + Src_size()) % Src_size(); | ||
vec3 iWants = targetMass(pos).rgb - Src(pos).rgb; | ||
ivec2 dirPos = (pos + dir + Src_size()) % Src_size(); | ||
vec3 dirWants = targetMass(dirPos).rgb - Src(dirPos).rgb; | ||
vec3 iMassClamped = clamp(Src(pos).rgb, 0.0, 1.0); | ||
vec3 dirMassClamped = clamp(Src(dirPos).rgb, 0.0, 1.0); | ||
vec3 maxDirAccept = (1.0 - dirMassClamped) / 8.0; | ||
vec3 minDirAccept = -dirMassClamped / 8.0; | ||
vec3 maxIAccept = (1.0 - iMassClamped) / 8.0; | ||
vec3 minIAccept = -iMassClamped / 8.0; | ||
vec3 giveDir = clamp( | ||
(dirWants - iWants) / 32.0, | ||
max(minDirAccept, -maxIAccept), | ||
min(maxDirAccept, -minIAccept) | ||
); | ||
return giveDir; | ||
} | ||
void fragment() { | ||
FOut = Src(I); | ||
if (FOut.a == 0.0) { | ||
FOut = vec4(hash(ivec3(I, seed)), 1); | ||
return; | ||
} | ||
for (int k = 0; k < 9; k++) { | ||
ivec2 offset = ivec2(k % 3 - 1, k / 3 - 1); | ||
if (offset == ivec2(0)) { continue; } | ||
FOut.rgb += ( | ||
massTransfer(I + offset, -offset) | ||
- massTransfer(I, offset) | ||
); | ||
} | ||
// TODO: fix evaporation | ||
FOut.rgb += vec3(0.00013); | ||
} | ||
`}, { ...cellsTargetParams }); | ||
} | ||
|
||
function draw() { | ||
if (!pause) { step(); } | ||
|
||
glsl({ | ||
cells: cells[0], | ||
FP: "cells(UV)", | ||
}); | ||
}; | ||
|
||
function windowResized() { | ||
resizeCanvas(windowWidth, windowHeight); | ||
}; | ||
</script> |
Oops, something went wrong.