mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-17 05:49:30 -07:00
Unifying the interfaces of regl and webgpu makePass and makePipeline.
This commit is contained in:
@@ -9,7 +9,7 @@ const levelStrengths = Array(pyramidHeight)
|
||||
.map((_, index) => Math.pow(index / (pyramidHeight * 2) + 0.5, 1 / 3).toPrecision(5))
|
||||
.reverse();
|
||||
|
||||
export default (regl, config, inputs) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const { bloomStrength, bloomSize, highPassThreshold } = config;
|
||||
const enabled = bloomSize > 0 && bloomStrength > 0;
|
||||
|
||||
@@ -80,6 +80,14 @@ export default (regl, config, inputs) => {
|
||||
primary: inputs.primary,
|
||||
bloom: output,
|
||||
},
|
||||
Promise.all([highPassFrag.loaded, blurFrag.loaded]),
|
||||
(w, h) => {
|
||||
// The blur pyramids can be lower resolution than the screen.
|
||||
resizePyramid(highPassPyramid, w, h, bloomSize);
|
||||
resizePyramid(hBlurPyramid, w, h, bloomSize);
|
||||
resizePyramid(vBlurPyramid, w, h, bloomSize);
|
||||
output.resize(w, h);
|
||||
},
|
||||
() => {
|
||||
for (let i = 0; i < pyramidHeight; i++) {
|
||||
const highPassFBO = highPassPyramid[i];
|
||||
@@ -91,14 +99,6 @@ export default (regl, config, inputs) => {
|
||||
}
|
||||
|
||||
sumPyramid();
|
||||
},
|
||||
(w, h) => {
|
||||
// The blur pyramids can be lower resolution than the screen.
|
||||
resizePyramid(highPassPyramid, w, h, bloomSize);
|
||||
resizePyramid(hBlurPyramid, w, h, bloomSize);
|
||||
resizePyramid(vBlurPyramid, w, h, bloomSize);
|
||||
output.resize(w, h);
|
||||
},
|
||||
[highPassFrag.loaded, blurFrag.loaded]
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,7 +4,7 @@ import { loadImage, loadText, makePassFBO, makePass } from "./utils.js";
|
||||
|
||||
const defaultBGURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/Flammarion_Colored.jpg/917px-Flammarion_Colored.jpg";
|
||||
|
||||
export default (regl, config, inputs) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
const bgURL = "bgURL" in config ? config.bgURL : defaultBGURL;
|
||||
const background = loadImage(regl, bgURL);
|
||||
@@ -22,8 +22,8 @@ export default (regl, config, inputs) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
() => render({ frag: imagePassFrag.text() }),
|
||||
null,
|
||||
[background.loaded, imagePassFrag.loaded]
|
||||
Promise.all([background.loaded, imagePassFrag.loaded]),
|
||||
(w, h) => output.resize(w, h),
|
||||
() => render({ frag: imagePassFrag.text() })
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,7 +40,7 @@ export default async (canvas, config) => {
|
||||
// All this takes place in a full screen quad.
|
||||
const fullScreenQuad = makeFullScreenQuad(regl);
|
||||
const effectName = config.effect in effects ? config.effect : "plain";
|
||||
const pipeline = makePipeline([makeRain, makeBloomPass, effects[effectName]], (p) => p.outputs, regl, config);
|
||||
const pipeline = makePipeline({ regl, config }, [makeRain, makeBloomPass, effects[effectName]]);
|
||||
const screenUniforms = { tex: pipeline[pipeline.length - 1].outputs.primary };
|
||||
const drawToScreen = regl({ uniforms: screenUniforms });
|
||||
await Promise.all(pipeline.map((step) => step.ready));
|
||||
@@ -50,12 +50,12 @@ export default async (canvas, config) => {
|
||||
dimensions.width = viewportWidth;
|
||||
dimensions.height = viewportHeight;
|
||||
for (const step of pipeline) {
|
||||
step.resize(viewportWidth, viewportHeight);
|
||||
step.setSize(viewportWidth, viewportHeight);
|
||||
}
|
||||
}
|
||||
fullScreenQuad(() => {
|
||||
for (const step of pipeline) {
|
||||
step.render();
|
||||
step.execute();
|
||||
}
|
||||
drawToScreen();
|
||||
});
|
||||
|
||||
@@ -62,7 +62,7 @@ const makePalette = (regl, entries) => {
|
||||
// won't persist across subsequent frames. This is a safe trick
|
||||
// in screen space.
|
||||
|
||||
export default (regl, config, inputs) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
const palette = makePalette(regl, config.paletteEntries);
|
||||
const { backgroundColor } = config;
|
||||
@@ -86,8 +86,8 @@ export default (regl, config, inputs) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
() => render({ frag: palettePassFrag.text() }),
|
||||
null,
|
||||
palettePassFrag.loaded
|
||||
palettePassFrag.loaded,
|
||||
(w, h) => output.resize(w, h),
|
||||
() => render({ frag: palettePassFrag.text() })
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,7 +19,7 @@ const blVert = [1, 0];
|
||||
const brVert = [1, 1];
|
||||
const quadVertices = [tlVert, trVert, brVert, tlVert, brVert, blVert];
|
||||
|
||||
export default (regl, config) => {
|
||||
export default ({ regl, config }) => {
|
||||
// The volumetric mode multiplies the number of columns
|
||||
// to reach the desired density, and then overlaps them
|
||||
const volumetric = config.volumetric;
|
||||
@@ -170,15 +170,7 @@ export default (regl, config) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
() => {
|
||||
compute({ frag: rainPassCompute.text() });
|
||||
regl.clear({
|
||||
depth: 1,
|
||||
color: [0, 0, 0, 1],
|
||||
framebuffer: output,
|
||||
});
|
||||
render({ camera, transform, screenSize, vert: rainPassVert.text(), frag: rainPassFrag.text() });
|
||||
},
|
||||
Promise.all([msdf.loaded, rainPassCompute.loaded, rainPassVert.loaded, rainPassFrag.loaded]),
|
||||
(w, h) => {
|
||||
output.resize(w, h);
|
||||
const aspectRatio = w / h;
|
||||
@@ -193,6 +185,14 @@ export default (regl, config) => {
|
||||
}
|
||||
[screenSize[0], screenSize[1]] = aspectRatio > 1 ? [1, aspectRatio] : [1 / aspectRatio, 1];
|
||||
},
|
||||
[msdf.loaded, rainPassCompute.loaded, rainPassVert.loaded, rainPassFrag.loaded]
|
||||
() => {
|
||||
compute({ frag: rainPassCompute.text() });
|
||||
regl.clear({
|
||||
depth: 1,
|
||||
color: [0, 0, 0, 1],
|
||||
framebuffer: output,
|
||||
});
|
||||
render({ camera, transform, screenSize, vert: rainPassVert.text(), frag: rainPassFrag.text() });
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
@@ -8,7 +8,7 @@ import { loadText, make1DTexture, makePassFBO, makePass } from "./utils.js";
|
||||
// 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
|
||||
|
||||
export default (regl, config, inputs) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
const { backgroundColor } = config;
|
||||
const resurrectionPassFrag = loadText("shaders/glsl/resurrectionPass.frag.glsl");
|
||||
@@ -29,8 +29,8 @@ export default (regl, config, inputs) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
() => render({ frag: resurrectionPassFrag.text() }),
|
||||
null,
|
||||
resurrectionPassFrag.loaded
|
||||
resurrectionPassFrag.loaded,
|
||||
(w, h) => output.resize(w, h),
|
||||
() => render({ frag: resurrectionPassFrag.text() })
|
||||
);
|
||||
};
|
||||
|
||||
@@ -28,7 +28,7 @@ const prideStripeColors = [
|
||||
[0.8, 0, 1],
|
||||
].flat();
|
||||
|
||||
export default (regl, config, inputs) => {
|
||||
export default ({ regl, config }, inputs) => {
|
||||
const output = makePassFBO(regl, config.useHalfFloat);
|
||||
|
||||
const { backgroundColor } = config;
|
||||
@@ -61,8 +61,8 @@ export default (regl, config, inputs) => {
|
||||
{
|
||||
primary: output,
|
||||
},
|
||||
() => render({ frag: stripePassFrag.text() }),
|
||||
null,
|
||||
stripePassFrag.loaded
|
||||
stripePassFrag.loaded,
|
||||
(w, h) => output.resize(w, h),
|
||||
() => render({ frag: stripePassFrag.text() })
|
||||
);
|
||||
};
|
||||
|
||||
@@ -129,28 +129,15 @@ const make1DTexture = (regl, data) =>
|
||||
min: "linear",
|
||||
});
|
||||
|
||||
const makePass = (outputs, render, resize, ready) => {
|
||||
if (render == null) {
|
||||
render = () => {};
|
||||
}
|
||||
if (resize == null) {
|
||||
resize = (w, h) => Object.values(outputs).forEach((output) => output.resize(w, h));
|
||||
}
|
||||
if (ready == null) {
|
||||
ready = Promise.resolve();
|
||||
} else if (ready instanceof Array) {
|
||||
ready = Promise.all(ready);
|
||||
}
|
||||
return {
|
||||
outputs,
|
||||
render,
|
||||
resize,
|
||||
ready,
|
||||
};
|
||||
};
|
||||
const makePass = (outputs, ready, setSize, execute) => ({
|
||||
outputs: outputs ?? {},
|
||||
ready: ready ?? Promise.resolve(),
|
||||
setSize: setSize ?? (() => {}),
|
||||
execute: execute ?? (() => {}),
|
||||
});
|
||||
|
||||
const makePipeline = (steps, getInputs, ...params) =>
|
||||
steps.filter((f) => f != null).reduce((pipeline, f, i) => [...pipeline, f(...params, i == 0 ? null : getInputs(pipeline[i - 1]))], []);
|
||||
const makePipeline = (context, steps) =>
|
||||
steps.filter((f) => f != null).reduce((pipeline, f, i) => [...pipeline, f(context, i == 0 ? null : pipeline[i - 1].outputs)], []);
|
||||
|
||||
export {
|
||||
makePassTexture,
|
||||
|
||||
@@ -76,5 +76,5 @@ export default (context, getInputs) => {
|
||||
renderPass.endPass();
|
||||
};
|
||||
|
||||
return makePass(ready, setSize, getOutputs, execute);
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
};
|
||||
|
||||
@@ -161,5 +161,5 @@ export default (context, getInputs) => {
|
||||
renderPass.endPass();
|
||||
};
|
||||
|
||||
return makePass(ready, setSize, getOutputs, execute);
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
};
|
||||
|
||||
@@ -193,5 +193,5 @@ export default (context, getInputs) => {
|
||||
renderPass.endPass();
|
||||
};
|
||||
|
||||
return makePass(ready, setSize, getOutputs, execute);
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
};
|
||||
|
||||
@@ -83,5 +83,5 @@ export default (context, getInputs) => {
|
||||
renderPass.endPass();
|
||||
};
|
||||
|
||||
return makePass(ready, setSize, getOutputs, execute);
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
};
|
||||
|
||||
@@ -125,5 +125,5 @@ export default (context, getInputs) => {
|
||||
renderPass.endPass();
|
||||
};
|
||||
|
||||
return makePass(ready, setSize, getOutputs, execute);
|
||||
return makePass(getOutputs, ready, setSize, execute);
|
||||
};
|
||||
|
||||
@@ -80,10 +80,10 @@ const makeBindGroup = (device, pipeline, index, entries) =>
|
||||
})),
|
||||
});
|
||||
|
||||
const makePass = (ready, setSize, getOutputs, execute) => ({
|
||||
const makePass = (getOutputs, ready, setSize, execute) => ({
|
||||
getOutputs: getOutputs ?? (() => ({})),
|
||||
ready: ready ?? Promise.resolve(),
|
||||
setSize: setSize ?? (() => {}),
|
||||
getOutputs: getOutputs ?? (() => ({})),
|
||||
execute: execute ?? (() => {}),
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user