Skip to content

Commit 2b7bf2d

Browse files
committed
feat: handle multi-pass post-processing effects
1 parent 5ab7a43 commit 2b7bf2d

File tree

7 files changed

+240
-162
lines changed

7 files changed

+240
-162
lines changed

lib/playground/src/pages/post-processing/bloom.astro

Lines changed: 87 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -3,103 +3,97 @@ import Layout from "../../layouts/Layout.astro";
33
---
44

55
<script>
6-
import {
7-
useEffectPass,
8-
useWebGLContext,
9-
useCompositor,
10-
useRenderPass,
11-
useResizeObserver,
12-
} from "usegl";
13-
import {
14-
fragmentShaderSource,
15-
vertexShaderSource,
16-
mipmapFragmentShaderSource,
17-
blurFragmentShaderSource,
18-
combineFragmentShaderSource,
19-
} from "../../shaders/bloom";
20-
import { incrementRenderCount } from "../../components/renderCount";
21-
22-
const canvas = document.querySelector("canvas");
23-
24-
const { gl, setSize: resizeCanvas } = useWebGLContext(canvas);
25-
26-
const positions: number[] = [];
27-
const particleCount = 100;
28-
29-
const squareSize = Math.sqrt(particleCount) / 2;
30-
for (let i = 0; i < squareSize; i++) {
31-
for (let j = 0; j < squareSize; j++) {
32-
positions.push(i / squareSize);
33-
positions.push(j / squareSize);
34-
positions.push(-i / squareSize);
35-
positions.push(-j / squareSize);
36-
positions.push(i / squareSize);
37-
positions.push(-j / squareSize);
38-
positions.push(-i / squareSize);
39-
positions.push(j / squareSize);
40-
}
41-
}
42-
43-
const particlesPass = useRenderPass(gl, {
44-
fragment: fragmentShaderSource,
45-
vertex: vertexShaderSource,
46-
attributes: {
47-
a_position: {
48-
data: positions,
49-
size: 2,
50-
},
51-
},
52-
});
53-
54-
const mipmapsPass = useEffectPass({
55-
fragment: mipmapFragmentShaderSource,
56-
});
57-
58-
const horizontalBlurPass = useEffectPass({
59-
fragment: blurFragmentShaderSource,
60-
uniforms: {
61-
u_direction: [1, 0],
62-
},
63-
});
64-
65-
const verticalBlurPass = useEffectPass({
66-
fragment: blurFragmentShaderSource,
67-
uniforms: {
68-
u_direction: [0, 1],
69-
},
70-
});
71-
72-
const combinePass = useEffectPass({
73-
fragment: combineFragmentShaderSource,
74-
uniforms: {
75-
u_image: () => particlesPass.target.texture,
76-
u_bloomTexture: () => verticalBlurPass.target.texture,
77-
},
78-
});
79-
80-
const compositor = useCompositor(gl, particlesPass, [
81-
mipmapsPass,
82-
horizontalBlurPass,
83-
verticalBlurPass,
84-
combinePass,
85-
]);
86-
87-
useResizeObserver(canvas, ({ devicePixelSize }) => {
88-
resizeCanvas(devicePixelSize.width, devicePixelSize.height);
89-
90-
compositor.setSize(devicePixelSize);
91-
compositor.render();
92-
});
93-
94-
particlesPass.onAfterRender(incrementRenderCount);
6+
import { useEffectPass, useWebGLCanvas } from "usegl";
7+
import { fragment, vertex, mipmapsShader, blurShader, combineShader } from "../../shaders/bloom";
8+
import { incrementRenderCount } from "../../components/renderCount";
9+
10+
const mipmapsPass = useEffectPass({
11+
fragment: mipmapsShader,
12+
});
13+
14+
const horizontalBlurPass = useEffectPass({
15+
fragment: blurShader,
16+
uniforms: {
17+
u_direction: [1, 0],
18+
},
19+
});
20+
21+
const verticalBlurPass = useEffectPass({
22+
fragment: blurShader,
23+
uniforms: {
24+
u_direction: [0, 1],
25+
},
26+
});
27+
28+
const combinePass = useEffectPass({
29+
fragment: combineShader,
30+
uniforms: {
31+
u_image: ({ inputPass }) => inputPass.target!.texture,
32+
u_bloomTexture: () => verticalBlurPass.target!.texture,
33+
},
34+
});
35+
36+
const bloomEffect = [mipmapsPass, horizontalBlurPass, verticalBlurPass, combinePass];
37+
38+
const vignetteEffect = useEffectPass({
39+
fragment: /* glsl */ `
40+
uniform sampler2D uTexture;
41+
varying vec2 vUv;
42+
43+
#define SIZE .6 // (0.0 - 1.0)
44+
#define ROUNDNESS .7 // (0.0 = rectangle, 1.0 = round)
45+
#define STRENGTH .6 // (0.0 - 1.0)
46+
47+
float vignette() {
48+
vec2 centered = vUv * 2.0 - 1.0;
49+
float circDist = length(centered);
50+
float rectDist = max(abs(centered.x), abs(centered.y));
51+
float dist = mix(rectDist, circDist, ROUNDNESS);
52+
return 1. - smoothstep(SIZE, SIZE * 2., dist) * STRENGTH;
53+
}
54+
55+
void main() {
56+
vec4 color = texture(uTexture, vUv);
57+
color.rgb *= vignette();
58+
gl_FragColor = color;
59+
}
60+
`,
61+
});
62+
63+
const { gl, onAfterRender } = useWebGLCanvas({
64+
canvas: "#glCanvas",
65+
fragment: fragment,
66+
vertex: vertex,
67+
attributes: {
68+
a_position: {
69+
data: [
70+
[0.1, 0.5],
71+
[-0.3, 0],
72+
[0.2, -0.1],
73+
].flat(),
74+
size: 2,
75+
},
76+
a_size: {
77+
data: [100, 300, 200],
78+
size: 1,
79+
},
80+
},
81+
postEffects: [vignetteEffect, bloomEffect],
82+
});
83+
84+
gl.enable(gl.BLEND);
85+
gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
86+
gl.clearColor(0, 0.07, 0.15, 1);
87+
88+
onAfterRender(incrementRenderCount);
9589
</script>
9690

9791
<Layout title="Bloom">
98-
<canvas></canvas>
92+
<canvas id="glCanvas"></canvas>
9993
</Layout>
10094

10195
<style>
102-
canvas {
103-
aspect-ratio: 3 / 2;
104-
}
96+
canvas {
97+
aspect-ratio: 3 / 2;
98+
}
10599
</style>

lib/playground/src/shaders/bloom.ts

Lines changed: 31 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,26 @@
1-
export const vertexShaderSource = /*glsl*/ `
2-
in vec2 a_position;
3-
out vec2 vUv;
4-
uniform vec2 u_resolution;
5-
6-
void main() {
7-
vUv = (a_position + 1.0) / 2.0;
8-
gl_Position = vec4(a_position, 0.0, 1.0);
9-
gl_PointSize = u_resolution.x / pow(30.0, .8 + length(vUv - 0.5));
10-
}
1+
export const vertex = /*glsl*/ `
2+
in vec2 a_position;
3+
in float a_size;
4+
out vec2 vUv;
5+
uniform vec2 u_resolution;
6+
7+
void main() {
8+
vUv = (a_position + 1.0) / 2.0;
9+
gl_Position = vec4(a_position, 0.0, 1.0);
10+
gl_PointSize = a_size;
11+
}
1112
`;
1213

13-
export const fragmentShaderSource = /*glsl*/ `
14-
out vec4 outColor;
15-
in vec2 vUv;
14+
export const fragment = /*glsl*/ `
15+
in vec2 vUv;
1616
17-
void main() {
18-
outColor = vec4(vUv.x, vUv.y, 1.0, 1.0);
19-
}
17+
void main() {
18+
vec2 uv = gl_PointCoord.xy;
19+
gl_FragColor.rgba = mix(vec4(0.), vec4(vUv*1.2, 1., 1.), smoothstep(0.51, 0.49, length(uv - 0.5))) ;
20+
}
2021
`;
2122

22-
export const mipmapFragmentShaderSource = /*glsl*/ `
23+
export const mipmapsShader = /*glsl*/ `
2324
uniform sampler2D u_image;
2425
uniform vec2 u_resolution;
2526
@@ -69,15 +70,14 @@ vec3 mipmapLevel(float octave) {
6970
7071
void main() {
7172
vec3 color = mipmapLevel(1.0);
72-
color += mipmapLevel(2.0);
7373
color += mipmapLevel(3.0);
74-
color += mipmapLevel(4.0);
74+
color += mipmapLevel(5.0);
7575
7676
outColor = vec4(color, 1.0);
7777
}
7878
`;
7979

80-
export const blurFragmentShaderSource = /*glsl*/ `
80+
export const blurShader = /*glsl*/ `
8181
uniform sampler2D u_image;
8282
uniform vec2 u_resolution;
8383
uniform vec2 u_direction;
@@ -129,7 +129,7 @@ void main() {
129129
}
130130
`;
131131

132-
export const combineFragmentShaderSource = /* glsl */ `
132+
export const combineShader = /* glsl */ `
133133
uniform sampler2D u_image;
134134
uniform sampler2D u_bloomTexture;
135135
uniform vec2 u_resolution;
@@ -174,20 +174,22 @@ vec3 GetBloom(vec2 coord) {
174174
vec3 bloom = vec3(0.0);
175175
176176
//Reconstruct bloom from multiple blurred images
177-
bloom += Grab(coord, 1.0, vec2(CalcOffset(0.0))) * .8;
178-
// bloom += Grab(coord, 2.0, vec2(CalcOffset(1.0))) * .4;
179-
bloom += Grab(coord, 3.0, vec2(CalcOffset(2.0))) * .5;
180-
bloom += Grab(coord, 4.0, vec2(CalcOffset(3.0))) * 1.2;
177+
bloom += Grab(coord, 1.0, vec2(CalcOffset(0.0))) * .2;
178+
bloom += Grab(coord, 3.0, vec2(CalcOffset(2.0))) * .2;
179+
bloom += Grab(coord, 5.0, vec2(CalcOffset(4.0))) * .6;
181180
182181
return bloom;
183182
}
184183
185184
void main() {
186-
vec4 baseColor = texture(u_image, vUv);
187-
vec4 bloomColor = vec4(GetBloom(vUv), 1);
185+
vec4 baseColor = texture(u_image, vUv);
186+
vec4 bloomColor = vec4(GetBloom(vUv), 1);
187+
188+
outColor = baseColor;
189+
190+
float baseColorGreyscale = dot(baseColor.rgb, vec3(0.299, 0.587, 0.114));
188191
189-
outColor = baseColor;
190192
191-
outColor = baseColor + bloomColor;
193+
outColor = mix(baseColor, bloomColor, bloomColor.a - baseColorGreyscale * baseColor.a);
192194
}
193195
`;

0 commit comments

Comments
 (0)