Re
ReTina, raymarch engine for the gang.
- basic-game-of-life — Click again to open in new tab
- basic-voronoi
- rm-collisions
- rm-fbm-terrain
- rm-fractal-env
- rm-mandelbulb
- rm-modeling
- rm-periodic-surface
- rm-simplex-noise-terrain
basic-game-of-life
import { ReTina } from '@ReTina'
import TinaLogo from '@src/assets/img/tina.jpeg'
import { loadImage } from './utils/loadImage'
const img = await loadImage(TinaLogo.src)
const rt = new ReTina({
fps: 24,
height: 128,
texs: [{ width: img.width, height: img.height }],
usePrevFrameTex: true,
functions: /* wgsl */ `
fn isPixAlive(pos: vec2f) -> vec3f {
return step(vec3f(0.5), getPrevFrameTexSample(pos).rgb);
}
fn golRule(_isAlive: f32, _nCount: f32) -> f32 {
let isAlive = round(_isAlive) > 0.5;
let nCount = round(_nCount);
if isAlive {
if nCount == 2 || nCount == 3 {
return 1f;
}
} else if nCount == 3 {
return 1f;
}
return 0f;
}
`,
main: /* wgsl */ `
if (U.time < 1) {
return getTex0Sample(uv);
} else {
let res = vec2f(U.width, U.height);
var nCount = vec3f(0);
for (var i = -1; i <= 1; i = i + 1) {
for (var j = -1; j <= 1; j = j + 1) {
if (i == 0 && j == 0) {
continue;
}
let pos = uv + vec2f(f32(i), f32(j)) / res;
nCount += isPixAlive(pos);
}
}
let isAlive = isPixAlive(uv);
let newState = vec3f(
golRule(isAlive.x, nCount.x),
golRule(isAlive.y, nCount.y),
golRule(isAlive.z, nCount.z)
);
return vec4f(newState, 1);
}
`,
})
rt.start({
onBuild() {
rt.setTex(0, img.textureData)
},
})