Files
matrix/js/webgpu/resurrectionPass.js

75 lines
2.0 KiB
JavaScript

import { structs } from "../../lib/gpu-buffer.js";
import { loadShader, makeUniformBuffer, makeComputeTarget, makeBindGroup, makePass } from "./utils.js";
// Matrix Resurrections isn't in theaters yet,
// and this version of the effect is still a WIP.
// Criteria:
// Upward-flowing glyphs should be golden
// Downward-flowing glyphs should be tinted slightly blue on top and golden on the bottom
// Cheat a lens blur, interpolating between the texture and bloom at the edges
const numVerticesPerQuad = 2 * 3;
export default ({ config, device, timeBuffer }) => {
const linearSampler = device.createSampler({
magFilter: "linear",
minFilter: "linear",
});
let computePipeline;
let configBuffer;
let computeBindGroup;
let output;
let screenSize;
const assets = [loadShader(device, "shaders/wgsl/resurrectionPass.wgsl")];
const loaded = (async () => {
const [resurrectionShader] = await Promise.all(assets);
computePipeline = device.createComputePipeline({
compute: {
module: resurrectionShader.module,
entryPoint: "computeMain",
},
});
const configUniforms = structs.from(resurrectionShader.code).Config;
configBuffer = makeUniformBuffer(device, configUniforms, {
bloomStrength: config.bloomStrength,
ditherMagnitude: config.ditherMagnitude,
backgroundColor: config.backgroundColor,
});
})();
const build = (size, inputs) => {
output?.destroy();
output = makeComputeTarget(device, size);
screenSize = size;
computeBindGroup = makeBindGroup(device, computePipeline, 0, [
configBuffer,
timeBuffer,
linearSampler,
inputs.primary.createView(),
inputs.bloom.createView(),
output.createView(),
]);
return {
primary: output,
};
};
const run = (encoder) => {
const computePass = encoder.beginComputePass();
computePass.setPipeline(computePipeline);
computePass.setBindGroup(0, computeBindGroup);
computePass.dispatch(Math.ceil(screenSize[0] / 32), screenSize[1], 1);
computePass.endPass();
};
return makePass(loaded, build, run);
};