mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
83 lines
2.5 KiB
JavaScript
83 lines
2.5 KiB
JavaScript
import uniforms from "/lib/gpu-uniforms.js";
|
|
import { getCanvasSize, makeUniformBuffer, makePipeline } from "./utils.js";
|
|
|
|
import makeRain from "./rainPass.js";
|
|
// import makeBloomPass from "./bloomPass.js";
|
|
import makePalettePass from "./palettePass.js";
|
|
import makeStripePass from "./stripePass.js";
|
|
import makeImagePass from "./imagePass.js";
|
|
import makeResurrectionPass from "./resurrectionPass.js";
|
|
|
|
const effects = {
|
|
none: null,
|
|
plain: makePalettePass,
|
|
customStripes: makeStripePass,
|
|
stripes: makeStripePass,
|
|
pride: makeStripePass,
|
|
transPride: makeStripePass,
|
|
trans: makeStripePass,
|
|
image: makeImagePass,
|
|
resurrection: makeResurrectionPass,
|
|
resurrections: makeResurrectionPass,
|
|
};
|
|
|
|
export default async (canvas, config) => {
|
|
const adapter = await navigator.gpu.requestAdapter();
|
|
const device = await adapter.requestDevice();
|
|
const canvasContext = canvas.getContext("webgpu");
|
|
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
|
|
// console.table(device.limits);
|
|
|
|
const canvasConfig = {
|
|
device,
|
|
format: presentationFormat,
|
|
size: [NaN, NaN],
|
|
usage:
|
|
// GPUTextureUsage.STORAGE_BINDING |
|
|
GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_DST,
|
|
};
|
|
|
|
const timeUniforms = uniforms.read(`[[block]] struct Time { seconds : f32; frames : i32; };`).Time;
|
|
const timeBuffer = makeUniformBuffer(device, timeUniforms);
|
|
|
|
const context = {
|
|
config,
|
|
adapter,
|
|
device,
|
|
canvasContext,
|
|
timeBuffer,
|
|
};
|
|
|
|
const effectName = config.effect in effects ? config.effect : "plain";
|
|
const pipeline = makePipeline(context, [makeRain, /*makeBloomPass,*/ effects[effectName]]);
|
|
|
|
await Promise.all(pipeline.map((step) => step.ready));
|
|
|
|
let frames = 0;
|
|
let start = NaN;
|
|
|
|
const renderLoop = (now) => {
|
|
if (isNaN(start)) {
|
|
start = now;
|
|
}
|
|
const canvasSize = getCanvasSize(canvas);
|
|
if (canvasSize[0] !== canvasConfig.size[0] || canvasSize[1] !== canvasConfig.size[1]) {
|
|
canvasConfig.size = canvasSize;
|
|
canvasContext.configure(canvasConfig);
|
|
pipeline.forEach((step) => step.setSize(...canvasSize));
|
|
}
|
|
|
|
device.queue.writeBuffer(timeBuffer, 0, timeUniforms.write({ seconds: (now - start) / 1000, frames }));
|
|
frames++;
|
|
|
|
const encoder = device.createCommandEncoder();
|
|
pipeline.forEach((step) => step.execute(encoder));
|
|
encoder.copyTextureToTexture({ texture: pipeline[pipeline.length - 1].getOutputs().primary }, { texture: canvasContext.getCurrentTexture() }, canvasSize);
|
|
device.queue.submit([encoder.finish()]);
|
|
requestAnimationFrame(renderLoop);
|
|
};
|
|
|
|
requestAnimationFrame(renderLoop);
|
|
};
|