mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
75 lines
2.6 KiB
JavaScript
75 lines
2.6 KiB
JavaScript
import { structs } from "/lib/gpu-buffer.js";
|
|
import { makeComputeTarget, loadShader, makeUniformBuffer, makeBindGroup, makePass } from "./utils.js";
|
|
|
|
export default (context, getInputs) => {
|
|
const { config, device } = context;
|
|
|
|
const bloomSize = config.bloomSize;
|
|
const bloomStrength = config.newBloomStrength;
|
|
|
|
const enabled = bloomSize > 0 && bloomStrength > 0;
|
|
|
|
// If there's no bloom to apply, return a no-op pass with an empty bloom texture
|
|
if (!enabled) {
|
|
const emptyTexture = makeComputeTarget(device, 1, 1);
|
|
const getOutputs = () => ({ ...getInputs(), bloom: emptyTexture });
|
|
return makePass(getOutputs);
|
|
}
|
|
|
|
const assets = [loadShader(device, "shaders/wgsl/blur1D.wgsl")];
|
|
|
|
const nearestSampler = device.createSampler({});
|
|
|
|
let computePipeline;
|
|
let configUniforms;
|
|
let horizontalConfigBuffer;
|
|
let verticalConfigBuffer;
|
|
let intermediate;
|
|
let output;
|
|
let screenSize;
|
|
|
|
const getOutputs = () => ({
|
|
primary: getInputs().primary,
|
|
bloom: output,
|
|
});
|
|
|
|
const ready = (async () => {
|
|
const [blurShader] = await Promise.all(assets);
|
|
|
|
computePipeline = device.createComputePipeline({
|
|
compute: {
|
|
module: blurShader.module,
|
|
entryPoint: "computeMain",
|
|
},
|
|
});
|
|
|
|
configUniforms = structs.from(blurShader.code).Config;
|
|
})();
|
|
|
|
const setSize = (width, height) => {
|
|
intermediate?.destroy();
|
|
intermediate = makeComputeTarget(device, Math.floor(width * bloomSize), height);
|
|
output?.destroy();
|
|
output = makeComputeTarget(device, Math.floor(width * bloomSize), Math.floor(height * bloomSize));
|
|
screenSize = [width, height];
|
|
|
|
horizontalConfigBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength, direction: [0, bloomSize] });
|
|
verticalConfigBuffer = makeUniformBuffer(device, configUniforms, { bloomStrength, direction: [1, 0] });
|
|
};
|
|
|
|
const execute = (encoder) => {
|
|
const inputs = getInputs();
|
|
const tex = inputs.primary;
|
|
const intermediateView = intermediate.createView();
|
|
const computePass = encoder.beginComputePass();
|
|
computePass.setPipeline(computePipeline);
|
|
computePass.setBindGroup(0, makeBindGroup(device, computePipeline, 0, [horizontalConfigBuffer, nearestSampler, tex.createView(), intermediateView]));
|
|
computePass.dispatch(Math.ceil(Math.floor(screenSize[0] * bloomSize) / 32), screenSize[1], 1);
|
|
computePass.setBindGroup(0, makeBindGroup(device, computePipeline, 0, [verticalConfigBuffer, nearestSampler, intermediateView, output.createView()]));
|
|
computePass.dispatch(Math.ceil(Math.floor(screenSize[0] * bloomSize) / 32), Math.floor(screenSize[1] * bloomSize), 1);
|
|
computePass.endPass();
|
|
};
|
|
|
|
return makePass(getOutputs, ready, setSize, execute);
|
|
};
|