mirror of
https://github.com/Rezmason/matrix.git
synced 2026-04-14 12:29:30 -07:00
141 lines
3.5 KiB
JavaScript
141 lines
3.5 KiB
JavaScript
import { makePassFBO, makePyramid, resizePyramid } from "./utils.js";
|
|
|
|
const pyramidHeight = 5;
|
|
const levelStrengths = Array(pyramidHeight)
|
|
.fill()
|
|
.map((_, index) =>
|
|
Math.pow(index / (pyramidHeight * 2) + 0.5, 1 / 3).toPrecision(5)
|
|
)
|
|
.reverse();
|
|
|
|
export default (regl, config, input) => {
|
|
if (config.effect === "none") {
|
|
return {
|
|
fbo: input,
|
|
resize: () => {},
|
|
render: () => {}
|
|
};
|
|
}
|
|
|
|
const highPassPyramid = makePyramid(regl, pyramidHeight);
|
|
const horizontalBlurPyramid = makePyramid(regl, pyramidHeight);
|
|
const verticalBlurPyramid = makePyramid(regl, pyramidHeight);
|
|
const fbo = makePassFBO(regl);
|
|
|
|
const highPass = regl({
|
|
frag: `
|
|
precision mediump float;
|
|
varying vec2 vUV;
|
|
uniform sampler2D tex;
|
|
uniform float highPassThreshold;
|
|
void main() {
|
|
float value = texture2D(tex, vUV).r;
|
|
if (value < highPassThreshold) {
|
|
value = 0.;
|
|
}
|
|
gl_FragColor = vec4(vec3(value), 1.0);
|
|
}
|
|
`,
|
|
uniforms: {
|
|
tex: regl.prop("tex")
|
|
},
|
|
framebuffer: regl.prop("fbo")
|
|
});
|
|
|
|
const blur = regl({
|
|
frag: `
|
|
precision mediump float;
|
|
varying vec2 vUV;
|
|
uniform sampler2D tex;
|
|
uniform vec2 direction;
|
|
uniform float width, height;
|
|
void main() {
|
|
vec2 size = width > height ? vec2(width / height, 1.) : vec2(1., height / width);
|
|
gl_FragColor =
|
|
texture2D(tex, vUV) * 0.442 +
|
|
(
|
|
texture2D(tex, vUV + direction / max(width, height) * size) +
|
|
texture2D(tex, vUV - direction / max(width, height) * size)
|
|
) * 0.279;
|
|
}
|
|
`,
|
|
uniforms: {
|
|
tex: regl.prop("tex"),
|
|
direction: regl.prop("direction"),
|
|
height: regl.context("viewportWidth"),
|
|
width: regl.context("viewportHeight")
|
|
},
|
|
framebuffer: regl.prop("fbo")
|
|
});
|
|
|
|
const combineBloom = regl({
|
|
frag: `
|
|
precision mediump float;
|
|
varying vec2 vUV;
|
|
${verticalBlurPyramid
|
|
.map((_, index) => `uniform sampler2D tex_${index};`)
|
|
.join("\n")}
|
|
uniform sampler2D tex;
|
|
uniform float bloomStrength;
|
|
void main() {
|
|
vec4 total = vec4(0.);
|
|
${verticalBlurPyramid
|
|
.map(
|
|
(_, index) =>
|
|
`total += texture2D(tex_${index}, vUV) * ${levelStrengths[index]};`
|
|
)
|
|
.join("\n")}
|
|
gl_FragColor = total * bloomStrength + texture2D(tex, vUV);
|
|
}
|
|
`,
|
|
uniforms: Object.assign(
|
|
{
|
|
tex: input
|
|
},
|
|
Object.fromEntries(
|
|
verticalBlurPyramid.map((fbo, index) => [`tex_${index}`, fbo])
|
|
)
|
|
),
|
|
framebuffer: fbo
|
|
});
|
|
|
|
return {
|
|
fbo,
|
|
resize: (viewportWidth, viewportHeight) => {
|
|
resizePyramid(
|
|
highPassPyramid,
|
|
viewportWidth,
|
|
viewportHeight,
|
|
config.bloomSize
|
|
);
|
|
resizePyramid(
|
|
horizontalBlurPyramid,
|
|
viewportWidth,
|
|
viewportHeight,
|
|
config.bloomSize
|
|
);
|
|
resizePyramid(
|
|
verticalBlurPyramid,
|
|
viewportWidth,
|
|
viewportHeight,
|
|
config.bloomSize
|
|
);
|
|
fbo.resize(viewportWidth, viewportHeight);
|
|
},
|
|
render: () => {
|
|
highPassPyramid.forEach(fbo => highPass({ fbo, tex: input }));
|
|
horizontalBlurPyramid.forEach((fbo, index) =>
|
|
blur({ fbo, tex: highPassPyramid[index], direction: [1, 0] })
|
|
);
|
|
verticalBlurPyramid.forEach((fbo, index) =>
|
|
blur({
|
|
fbo,
|
|
tex: horizontalBlurPyramid[index],
|
|
direction: [0, 1]
|
|
})
|
|
);
|
|
combineBloom();
|
|
}
|
|
};
|
|
};
|