mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-18 22:29:28 -07:00
Moved the makePyramid and resizePyramid methods from the regl solution's util module to bloomPass.
Adding the canvas context's preferred format to the shared pass context (named "canvasFormat"). Added a placeholder bloomPass, which the existing passes now receive input from.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { loadText, makePassFBO, makePyramid, resizePyramid, makePass } from "./utils.js";
|
import { loadText, makePassFBO, makePass } from "./utils.js";
|
||||||
|
|
||||||
// The bloom pass is basically an added high-pass blur.
|
// The bloom pass is basically an added high-pass blur.
|
||||||
// The blur approximation is the sum of a pyramid of downscaled textures.
|
// The blur approximation is the sum of a pyramid of downscaled textures.
|
||||||
@@ -9,6 +9,16 @@ const levelStrengths = Array(pyramidHeight)
|
|||||||
.map((_, index) => Math.pow(index / (pyramidHeight * 2) + 0.5, 1 / 3).toPrecision(5))
|
.map((_, index) => Math.pow(index / (pyramidHeight * 2) + 0.5, 1 / 3).toPrecision(5))
|
||||||
.reverse();
|
.reverse();
|
||||||
|
|
||||||
|
// A pyramid is just an array of FBOs, where each FBO is half the width
|
||||||
|
// and half the height of the FBO below it.
|
||||||
|
const makePyramid = (regl, height, halfFloat) =>
|
||||||
|
Array(height)
|
||||||
|
.fill()
|
||||||
|
.map((_) => makePassFBO(regl, halfFloat));
|
||||||
|
|
||||||
|
const resizePyramid = (pyramid, vw, vh, scale) =>
|
||||||
|
pyramid.forEach((fbo, index) => fbo.resize(Math.floor((vw * scale) / 2 ** index), Math.floor((vh * scale) / 2 ** index)));
|
||||||
|
|
||||||
export default ({ regl, config }, inputs) => {
|
export default ({ regl, config }, inputs) => {
|
||||||
const { bloomStrength, bloomSize, highPassThreshold } = config;
|
const { bloomStrength, bloomSize, highPassThreshold } = config;
|
||||||
const enabled = bloomSize > 0 && bloomStrength > 0;
|
const enabled = bloomSize > 0 && bloomStrength > 0;
|
||||||
|
|||||||
@@ -10,13 +10,6 @@ const makePassTexture = (regl, halfFloat) =>
|
|||||||
|
|
||||||
const makePassFBO = (regl, halfFloat) => regl.framebuffer({ color: makePassTexture(regl, halfFloat) });
|
const makePassFBO = (regl, halfFloat) => regl.framebuffer({ color: makePassTexture(regl, halfFloat) });
|
||||||
|
|
||||||
// A pyramid is just an array of FBOs, where each FBO is half the width
|
|
||||||
// and half the height of the FBO below it.
|
|
||||||
const makePyramid = (regl, height, halfFloat) =>
|
|
||||||
Array(height)
|
|
||||||
.fill()
|
|
||||||
.map((_) => makePassFBO(regl, halfFloat));
|
|
||||||
|
|
||||||
const makeDoubleBuffer = (regl, props) => {
|
const makeDoubleBuffer = (regl, props) => {
|
||||||
const state = Array(2)
|
const state = Array(2)
|
||||||
.fill()
|
.fill()
|
||||||
@@ -32,9 +25,6 @@ const makeDoubleBuffer = (regl, props) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const resizePyramid = (pyramid, vw, vh, scale) =>
|
|
||||||
pyramid.forEach((fbo, index) => fbo.resize(Math.floor((vw * scale) / 2 ** index), Math.floor((vh * scale) / 2 ** index)));
|
|
||||||
|
|
||||||
const loadImage = (regl, url) => {
|
const loadImage = (regl, url) => {
|
||||||
let texture = regl.texture([[0]]);
|
let texture = regl.texture([[0]]);
|
||||||
let loaded = false;
|
let loaded = false;
|
||||||
@@ -139,16 +129,4 @@ const makePass = (outputs, ready, setSize, execute) => ({
|
|||||||
const makePipeline = (context, steps) =>
|
const makePipeline = (context, steps) =>
|
||||||
steps.filter((f) => f != null).reduce((pipeline, f, i) => [...pipeline, f(context, i == 0 ? null : pipeline[i - 1].outputs)], []);
|
steps.filter((f) => f != null).reduce((pipeline, f, i) => [...pipeline, f(context, i == 0 ? null : pipeline[i - 1].outputs)], []);
|
||||||
|
|
||||||
export {
|
export { makePassTexture, makePassFBO, makeDoubleBuffer, loadImage, loadText, makeFullScreenQuad, make1DTexture, makePass, makePipeline };
|
||||||
makePassTexture,
|
|
||||||
makePassFBO,
|
|
||||||
makeDoubleBuffer,
|
|
||||||
makePyramid,
|
|
||||||
resizePyramid,
|
|
||||||
loadImage,
|
|
||||||
loadText,
|
|
||||||
makeFullScreenQuad,
|
|
||||||
make1DTexture,
|
|
||||||
makePass,
|
|
||||||
makePipeline,
|
|
||||||
};
|
|
||||||
|
|||||||
125
js/webgpu/bloomPass.js
Normal file
125
js/webgpu/bloomPass.js
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
import { structs } from "/lib/gpu-buffer.js";
|
||||||
|
import { loadShader, makeUniformBuffer, makeBindGroup, makePassFBO, makePass } from "./utils.js";
|
||||||
|
|
||||||
|
export default (context, getInputs) => {
|
||||||
|
const { config, device, canvasFormat } = context;
|
||||||
|
const fbo = makePassFBO(device, 1, 1, canvasFormat);
|
||||||
|
return makePass(() => ({ ...getInputs(), bloom: fbo }));
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
import { loadText, makePassFBO, makePass } from "./utils.js";
|
||||||
|
|
||||||
|
// The bloom pass is basically an added high-pass blur.
|
||||||
|
// The blur approximation is the sum of a pyramid of downscaled textures.
|
||||||
|
|
||||||
|
const pyramidHeight = 5;
|
||||||
|
const levelStrengths = Array(pyramidHeight)
|
||||||
|
.fill()
|
||||||
|
.map((_, index) => Math.pow(index / (pyramidHeight * 2) + 0.5, 1 / 3).toPrecision(5))
|
||||||
|
.reverse();
|
||||||
|
|
||||||
|
// A pyramid is just an array of FBOs, where each FBO is half the width
|
||||||
|
// and half the height of the FBO below it.
|
||||||
|
const makePyramid = (regl, height, halfFloat) =>
|
||||||
|
Array(height)
|
||||||
|
.fill()
|
||||||
|
.map((_) => makePassFBO(regl, halfFloat));
|
||||||
|
|
||||||
|
const resizePyramid = (pyramid, vw, vh, scale) =>
|
||||||
|
pyramid.forEach((fbo, index) => fbo.resize(Math.floor((vw * scale) / 2 ** index), Math.floor((vh * scale) / 2 ** index)));
|
||||||
|
|
||||||
|
export default ({ regl, config }, inputs) => {
|
||||||
|
const { bloomStrength, bloomSize, highPassThreshold } = config;
|
||||||
|
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) {
|
||||||
|
return makePass({
|
||||||
|
primary: inputs.primary,
|
||||||
|
bloom: makePassFBO(regl),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build three pyramids of FBOs, one for each step in the process
|
||||||
|
const highPassPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
|
||||||
|
const hBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
|
||||||
|
const vBlurPyramid = makePyramid(regl, pyramidHeight, config.useHalfFloat);
|
||||||
|
const output = makePassFBO(regl, config.useHalfFloat);
|
||||||
|
|
||||||
|
// The high pass restricts the blur to bright things in our input texture.
|
||||||
|
const highPassFrag = loadText("shaders/glsl/highPass.frag.glsl");
|
||||||
|
const highPass = regl({
|
||||||
|
frag: regl.prop("frag"),
|
||||||
|
uniforms: {
|
||||||
|
highPassThreshold,
|
||||||
|
tex: regl.prop("tex"),
|
||||||
|
},
|
||||||
|
framebuffer: regl.prop("fbo"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// A 2D gaussian blur is just a 1D blur done horizontally, then done vertically.
|
||||||
|
// The FBO pyramid's levels represent separate levels of detail;
|
||||||
|
// by blurring them all, this basic blur approximates a more complex gaussian:
|
||||||
|
// https://web.archive.org/web/20191124072602/https://software.intel.com/en-us/articles/compute-shader-hdr-and-bloom
|
||||||
|
|
||||||
|
const blurFrag = loadText("shaders/glsl/blur.frag.glsl");
|
||||||
|
const blur = regl({
|
||||||
|
frag: regl.prop("frag"),
|
||||||
|
uniforms: {
|
||||||
|
tex: regl.prop("tex"),
|
||||||
|
direction: regl.prop("direction"),
|
||||||
|
height: regl.context("viewportWidth"),
|
||||||
|
width: regl.context("viewportHeight"),
|
||||||
|
},
|
||||||
|
framebuffer: regl.prop("fbo"),
|
||||||
|
});
|
||||||
|
|
||||||
|
// The pyramid of textures gets flattened (summed) into a final blurry "bloom" texture
|
||||||
|
const sumPyramid = regl({
|
||||||
|
frag: `
|
||||||
|
precision mediump float;
|
||||||
|
varying vec2 vUV;
|
||||||
|
${vBlurPyramid.map((_, index) => `uniform sampler2D pyr_${index};`).join("\n")}
|
||||||
|
uniform float bloomStrength;
|
||||||
|
void main() {
|
||||||
|
vec4 total = vec4(0.);
|
||||||
|
${vBlurPyramid.map((_, index) => `total += texture2D(pyr_${index}, vUV) * ${levelStrengths[index]};`).join("\n")}
|
||||||
|
gl_FragColor = total * bloomStrength;
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
uniforms: {
|
||||||
|
bloomStrength,
|
||||||
|
...Object.fromEntries(vBlurPyramid.map((fbo, index) => [`pyr_${index}`, fbo])),
|
||||||
|
},
|
||||||
|
framebuffer: output,
|
||||||
|
});
|
||||||
|
|
||||||
|
return makePass(
|
||||||
|
{
|
||||||
|
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];
|
||||||
|
const hBlurFBO = hBlurPyramid[i];
|
||||||
|
const vBlurFBO = vBlurPyramid[i];
|
||||||
|
highPass({ fbo: highPassFBO, frag: highPassFrag.text(), tex: inputs.primary });
|
||||||
|
blur({ fbo: hBlurFBO, frag: blurFrag.text(), tex: highPassFBO, direction: [1, 0] });
|
||||||
|
blur({ fbo: vBlurFBO, frag: blurFrag.text(), tex: hBlurFBO, direction: [0, 1] });
|
||||||
|
}
|
||||||
|
|
||||||
|
sumPyramid();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
*/
|
||||||
@@ -6,7 +6,7 @@ const defaultBGURL = "https://upload.wikimedia.org/wikipedia/commons/thumb/0/0a/
|
|||||||
const numVerticesPerQuad = 2 * 3;
|
const numVerticesPerQuad = 2 * 3;
|
||||||
|
|
||||||
export default (context, getInputs) => {
|
export default (context, getInputs) => {
|
||||||
const { config, adapter, device, canvasContext } = context;
|
const { config, device, canvasFormat } = context;
|
||||||
|
|
||||||
const linearSampler = device.createSampler({
|
const linearSampler = device.createSampler({
|
||||||
magFilter: "linear",
|
magFilter: "linear",
|
||||||
@@ -23,8 +23,6 @@ export default (context, getInputs) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
||||||
|
|
||||||
let renderPipeline;
|
let renderPipeline;
|
||||||
let output;
|
let output;
|
||||||
let backgroundTex;
|
let backgroundTex;
|
||||||
@@ -47,7 +45,7 @@ export default (context, getInputs) => {
|
|||||||
entryPoint: "fragMain",
|
entryPoint: "fragMain",
|
||||||
targets: [
|
targets: [
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -56,7 +54,7 @@ export default (context, getInputs) => {
|
|||||||
|
|
||||||
const setSize = (width, height) => {
|
const setSize = (width, height) => {
|
||||||
output?.destroy();
|
output?.destroy();
|
||||||
output = makePassFBO(device, width, height, presentationFormat);
|
output = makePassFBO(device, width, height, canvasFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOutputs = () => ({
|
const getOutputs = () => ({
|
||||||
@@ -66,7 +64,7 @@ export default (context, getInputs) => {
|
|||||||
const execute = (encoder) => {
|
const execute = (encoder) => {
|
||||||
const inputs = getInputs();
|
const inputs = getInputs();
|
||||||
const tex = inputs.primary;
|
const tex = inputs.primary;
|
||||||
const bloomTex = inputs.primary; // TODO: bloom
|
const bloomTex = inputs.bloom; // TODO: bloom
|
||||||
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [linearSampler, tex.createView(), bloomTex.createView(), backgroundTex.createView()]);
|
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [linearSampler, tex.createView(), bloomTex.createView(), backgroundTex.createView()]);
|
||||||
renderPassConfig.colorAttachments[0].view = output.createView();
|
renderPassConfig.colorAttachments[0].view = output.createView();
|
||||||
const renderPass = encoder.beginRenderPass(renderPassConfig);
|
const renderPass = encoder.beginRenderPass(renderPassConfig);
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { structs } from "/lib/gpu-buffer.js";
|
|||||||
import { getCanvasSize, makeUniformBuffer, makePipeline } from "./utils.js";
|
import { getCanvasSize, makeUniformBuffer, makePipeline } from "./utils.js";
|
||||||
|
|
||||||
import makeRain from "./rainPass.js";
|
import makeRain from "./rainPass.js";
|
||||||
// import makeBloomPass from "./bloomPass.js";
|
import makeBloomPass from "./bloomPass.js";
|
||||||
import makePalettePass from "./palettePass.js";
|
import makePalettePass from "./palettePass.js";
|
||||||
import makeStripePass from "./stripePass.js";
|
import makeStripePass from "./stripePass.js";
|
||||||
import makeImagePass from "./imagePass.js";
|
import makeImagePass from "./imagePass.js";
|
||||||
@@ -25,13 +25,13 @@ export default async (canvas, config) => {
|
|||||||
const adapter = await navigator.gpu.requestAdapter();
|
const adapter = await navigator.gpu.requestAdapter();
|
||||||
const device = await adapter.requestDevice();
|
const device = await adapter.requestDevice();
|
||||||
const canvasContext = canvas.getContext("webgpu");
|
const canvasContext = canvas.getContext("webgpu");
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
const canvasFormat = canvasContext.getPreferredFormat(adapter);
|
||||||
|
|
||||||
// console.table(device.limits);
|
// console.table(device.limits);
|
||||||
|
|
||||||
const canvasConfig = {
|
const canvasConfig = {
|
||||||
device,
|
device,
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
size: [NaN, NaN],
|
size: [NaN, NaN],
|
||||||
usage:
|
usage:
|
||||||
// GPUTextureUsage.STORAGE_BINDING |
|
// GPUTextureUsage.STORAGE_BINDING |
|
||||||
@@ -47,10 +47,11 @@ export default async (canvas, config) => {
|
|||||||
device,
|
device,
|
||||||
canvasContext,
|
canvasContext,
|
||||||
timeBuffer,
|
timeBuffer,
|
||||||
|
canvasFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
const effectName = config.effect in effects ? config.effect : "plain";
|
const effectName = config.effect in effects ? config.effect : "plain";
|
||||||
const pipeline = makePipeline(context, [makeRain, /*makeBloomPass,*/ effects[effectName]]);
|
const pipeline = makePipeline(context, [makeRain, makeBloomPass, effects[effectName]]);
|
||||||
|
|
||||||
await Promise.all(pipeline.map((step) => step.ready));
|
await Promise.all(pipeline.map((step) => step.ready));
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ const makePalette = (device, paletteUniforms, entries) => {
|
|||||||
// in screen space.
|
// in screen space.
|
||||||
|
|
||||||
export default (context, getInputs) => {
|
export default (context, getInputs) => {
|
||||||
const { config, adapter, device, canvasContext, timeBuffer } = context;
|
const { config, device, timeBuffer, canvasFormat } = context;
|
||||||
|
|
||||||
const linearSampler = device.createSampler({
|
const linearSampler = device.createSampler({
|
||||||
magFilter: "linear",
|
magFilter: "linear",
|
||||||
@@ -95,8 +95,6 @@ export default (context, getInputs) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
||||||
|
|
||||||
let renderPipeline;
|
let renderPipeline;
|
||||||
let configBuffer;
|
let configBuffer;
|
||||||
let paletteBuffer;
|
let paletteBuffer;
|
||||||
@@ -117,7 +115,7 @@ export default (context, getInputs) => {
|
|||||||
entryPoint: "fragMain",
|
entryPoint: "fragMain",
|
||||||
targets: [
|
targets: [
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -133,7 +131,7 @@ export default (context, getInputs) => {
|
|||||||
|
|
||||||
const setSize = (width, height) => {
|
const setSize = (width, height) => {
|
||||||
output?.destroy();
|
output?.destroy();
|
||||||
output = makePassFBO(device, width, height, presentationFormat);
|
output = makePassFBO(device, width, height, canvasFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOutputs = () => ({
|
const getOutputs = () => ({
|
||||||
@@ -143,7 +141,7 @@ export default (context, getInputs) => {
|
|||||||
const execute = (encoder) => {
|
const execute = (encoder) => {
|
||||||
const inputs = getInputs();
|
const inputs = getInputs();
|
||||||
const tex = inputs.primary;
|
const tex = inputs.primary;
|
||||||
const bloomTex = inputs.primary; // TODO: bloom
|
const bloomTex = inputs.bloom; // TODO: bloom
|
||||||
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
||||||
configBuffer,
|
configBuffer,
|
||||||
paletteBuffer,
|
paletteBuffer,
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ const makeConfigBuffer = (device, configUniforms, config, density, gridSize) =>
|
|||||||
};
|
};
|
||||||
|
|
||||||
export default (context, getInputs) => {
|
export default (context, getInputs) => {
|
||||||
const { config, adapter, device, canvasContext, timeBuffer } = context;
|
const { config, device, timeBuffer, canvasFormat } = context;
|
||||||
|
|
||||||
const assets = [loadTexture(device, config.glyphTexURL), loadShader(device, "shaders/wgsl/rainPass.wgsl")];
|
const assets = [loadTexture(device, config.glyphTexURL), loadShader(device, "shaders/wgsl/rainPass.wgsl")];
|
||||||
|
|
||||||
@@ -82,8 +82,6 @@ export default (context, getInputs) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
||||||
|
|
||||||
let configBuffer;
|
let configBuffer;
|
||||||
let sceneUniforms;
|
let sceneUniforms;
|
||||||
let sceneBuffer;
|
let sceneBuffer;
|
||||||
@@ -126,14 +124,14 @@ export default (context, getInputs) => {
|
|||||||
entryPoint: "fragMain",
|
entryPoint: "fragMain",
|
||||||
targets: [
|
targets: [
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
blend: {
|
blend: {
|
||||||
color: additiveBlendComponent,
|
color: additiveBlendComponent,
|
||||||
alpha: additiveBlendComponent,
|
alpha: additiveBlendComponent,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
blend: {
|
blend: {
|
||||||
color: additiveBlendComponent,
|
color: additiveBlendComponent,
|
||||||
alpha: additiveBlendComponent,
|
alpha: additiveBlendComponent,
|
||||||
@@ -164,10 +162,10 @@ export default (context, getInputs) => {
|
|||||||
|
|
||||||
// Update
|
// Update
|
||||||
output?.destroy();
|
output?.destroy();
|
||||||
output = makePassFBO(device, width, height, presentationFormat);
|
output = makePassFBO(device, width, height, canvasFormat);
|
||||||
|
|
||||||
highPassOutput?.destroy();
|
highPassOutput?.destroy();
|
||||||
highPassOutput = makePassFBO(device, width, height, presentationFormat);
|
highPassOutput = makePassFBO(device, width, height, canvasFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOutputs = () => ({
|
const getOutputs = () => ({
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { loadShader, makeUniformBuffer, makePassFBO, makePass } from "./utils.js
|
|||||||
const numVerticesPerQuad = 2 * 3;
|
const numVerticesPerQuad = 2 * 3;
|
||||||
|
|
||||||
export default (context, getInputs) => {
|
export default (context, getInputs) => {
|
||||||
const { config, adapter, device, canvasContext, timeBuffer } = context;
|
const { config, device, timeBuffer, canvasFormat } = context;
|
||||||
|
|
||||||
const linearSampler = device.createSampler({
|
const linearSampler = device.createSampler({
|
||||||
magFilter: "linear",
|
magFilter: "linear",
|
||||||
@@ -29,8 +29,6 @@ export default (context, getInputs) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
||||||
|
|
||||||
let renderPipeline;
|
let renderPipeline;
|
||||||
let configBuffer;
|
let configBuffer;
|
||||||
let output;
|
let output;
|
||||||
@@ -50,7 +48,7 @@ export default (context, getInputs) => {
|
|||||||
entryPoint: "fragMain",
|
entryPoint: "fragMain",
|
||||||
targets: [
|
targets: [
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -62,7 +60,7 @@ export default (context, getInputs) => {
|
|||||||
|
|
||||||
const setSize = (width, height) => {
|
const setSize = (width, height) => {
|
||||||
output?.destroy();
|
output?.destroy();
|
||||||
output = makePassFBO(device, width, height, presentationFormat);
|
output = makePassFBO(device, width, height, canvasFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOutputs = () => ({
|
const getOutputs = () => ({
|
||||||
@@ -72,7 +70,7 @@ export default (context, getInputs) => {
|
|||||||
const execute = (encoder) => {
|
const execute = (encoder) => {
|
||||||
const inputs = getInputs();
|
const inputs = getInputs();
|
||||||
const tex = inputs.primary;
|
const tex = inputs.primary;
|
||||||
const bloomTex = inputs.primary; // TODO: bloom
|
const bloomTex = inputs.bloom; // TODO: bloom
|
||||||
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [configBuffer, timeBuffer, linearSampler, tex.createView(), bloomTex.createView()]);
|
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [configBuffer, timeBuffer, linearSampler, tex.createView(), bloomTex.createView()]);
|
||||||
|
|
||||||
renderPassConfig.colorAttachments[0].view = output.createView();
|
renderPassConfig.colorAttachments[0].view = output.createView();
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const numVerticesPerQuad = 2 * 3;
|
|||||||
// in screen space.
|
// in screen space.
|
||||||
|
|
||||||
export default (context, getInputs) => {
|
export default (context, getInputs) => {
|
||||||
const { config, adapter, device, canvasContext, timeBuffer } = context;
|
const { config, device, timeBuffer, canvasFormat } = context;
|
||||||
|
|
||||||
// Expand and convert stripe colors into 1D texture data
|
// Expand and convert stripe colors into 1D texture data
|
||||||
const stripeColors =
|
const stripeColors =
|
||||||
@@ -64,8 +64,6 @@ export default (context, getInputs) => {
|
|||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
const presentationFormat = canvasContext.getPreferredFormat(adapter);
|
|
||||||
|
|
||||||
let renderPipeline;
|
let renderPipeline;
|
||||||
let configBuffer;
|
let configBuffer;
|
||||||
let output;
|
let output;
|
||||||
@@ -85,7 +83,7 @@ export default (context, getInputs) => {
|
|||||||
entryPoint: "fragMain",
|
entryPoint: "fragMain",
|
||||||
targets: [
|
targets: [
|
||||||
{
|
{
|
||||||
format: presentationFormat,
|
format: canvasFormat,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
@@ -97,7 +95,7 @@ export default (context, getInputs) => {
|
|||||||
|
|
||||||
const setSize = (width, height) => {
|
const setSize = (width, height) => {
|
||||||
output?.destroy();
|
output?.destroy();
|
||||||
output = makePassFBO(device, width, height, presentationFormat);
|
output = makePassFBO(device, width, height, canvasFormat);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getOutputs = () => ({
|
const getOutputs = () => ({
|
||||||
@@ -107,7 +105,7 @@ export default (context, getInputs) => {
|
|||||||
const execute = (encoder) => {
|
const execute = (encoder) => {
|
||||||
const inputs = getInputs();
|
const inputs = getInputs();
|
||||||
const tex = inputs.primary;
|
const tex = inputs.primary;
|
||||||
const bloomTex = inputs.primary; // TODO: bloom
|
const bloomTex = inputs.bloom; // TODO: bloom
|
||||||
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
const renderBindGroup = makeBindGroup(device, renderPipeline, 0, [
|
||||||
configBuffer,
|
configBuffer,
|
||||||
timeBuffer,
|
timeBuffer,
|
||||||
|
|||||||
Reference in New Issue
Block a user