CodexCapsule / world.js
LordXido's picture
Update world.js
709f56b verified
import { createCompute } from "./gpu.js";
import shader from "./world.wgsl?raw";
export class World {
constructor(canvas, gpu) {
this.ctx = canvas.getContext("2d");
this.gpu = gpu;
this.power = 8.0;
this.time = 0;
this.image = this.ctx.createImageData(256, 256);
if (gpu.mode === "gpu") this.initGPU();
}
async initGPU() {
const d = this.gpu.device;
this.pipeline = createCompute(d, shader);
this.param = d.createBuffer({ size: 8, usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST });
this.buf = d.createBuffer({ size: 256*256*4*4, usage: GPUBufferUsage.STORAGE | GPUBufferUsage.COPY_SRC });
this.read = d.createBuffer({ size: 256*256*4*4, usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ });
}
update(dt) {
this.time += dt;
if (this.gpu.mode !== "gpu") return;
const d = this.gpu.device;
d.queue.writeBuffer(this.param, 0, new Float32Array([this.time, this.power]));
const enc = d.createCommandEncoder();
const pass = enc.beginComputePass();
pass.setPipeline(this.pipeline);
pass.setBindGroup(0, d.createBindGroup({
layout: this.pipeline.getBindGroupLayout(0),
entries: [
{ binding: 0, resource: { buffer: this.param } },
{ binding: 1, resource: { buffer: this.buf } }
]
}));
pass.dispatchWorkgroups(32, 32);
pass.end();
enc.copyBufferToBuffer(this.buf, 0, this.read, 0, 256*256*4*4);
d.queue.submit([enc.finish()]);
}
async render() {
if (this.gpu.mode !== "gpu") return;
await this.read.mapAsync(GPUMapMode.READ);
const f = new Float32Array(this.read.getMappedRange());
for (let i = 0; i < f.length; i++) {
this.image.data[i] = Math.min(255, f[i] * 255);
}
this.read.unmap();
this.ctx.putImageData(this.image, 0, 0);
}
apply(cmd) {
if (cmd.payload?.power) this.power = cmd.payload.power;
}
}