原文链接: regl fbo 生命游戏
上一篇: github 自定义个人主页
下一篇: 使用storage事件实现跨窗口通讯
官网例子, 主要是使用了fbo, 一个用来更新, 一个用来绘制, 不知只使用一个, 因为不能读写同时进行, 不过好像也可以先读, 然后写, 不过这样效率减半
一个frame中tick相同, 但是使用函数嵌套的方式可以共享上下文, 所以一个是不需要顶点数组的
import Regl from "regl";
const regl = Regl();
export default async () => {
const RADIUS = 512;
const INITIAL_CONDITIONS = Array(RADIUS * RADIUS * 4)
.fill(0)
.map(() => (Math.random() > 0.9 ? 255 : 0));
const state = Array(2)
.fill(0)
.map(() =>
regl.framebuffer({
color: regl.texture({
radius: RADIUS,
data: INITIAL_CONDITIONS,
wrap: "repeat",
}),
depthStencil: false,
})
);
const updateLife = regl({
frag: `
precision mediump float;
uniform sampler2D prevState;
varying vec2 uv;
void main() {
float n = 0.0;
for(int dx=-1; dx<=1; ++dx)
for(int dy=-1; dy<=1; ++dy) {
n += texture2D(prevState, uv+vec2(dx,dy)/float(${RADIUS})).r;
}
float s = texture2D(prevState, uv).r;
if(n > 3.0+s || n < 3.0) {
gl_FragColor = vec4(0,0,0,1);
} else {
gl_FragColor = vec4(1,1,1,1);
}
}`,
framebuffer: ({ tick }) => state[(tick + 1) % 2],
});
const setupQuad = regl({
frag: `
precision mediump float;
uniform sampler2D prevState;
varying vec2 uv;
void main() {
float state = texture2D(prevState, uv).r;
gl_FragColor = vec4(vec3(state), 1);
}`,
vert: `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
void main() {
uv = 0.5 * (position + 1.0);
gl_Position = vec4(position, 0, 1);
}`,
attributes: {
position: [-4, -4, 4, -4, 0, 4].map((i) => i / 8),
},
uniforms: {
prevState: ({ tick }) => state[tick % 2],
},
depth: { enable: false },
count: 3,
});
regl.frame(() => {
setupQuad(() => {
regl.draw();
updateLife();
});
});
};