Skip to content

Commit 4c81351

Browse files
committed
feat: add a blending option and assume premultiplied alpha everywhere
1 parent 4c23a83 commit 4c81351

File tree

14 files changed

+108
-16
lines changed

14 files changed

+108
-16
lines changed
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
import Layout from "../../layouts/Layout.astro";
3+
---
4+
5+
<script>
6+
import {
7+
createRenderTarget,
8+
linearToneMapping,
9+
useCompositor,
10+
useQuadRenderPass,
11+
useWebGLCanvas,
12+
useWebGLContext,
13+
} from "usegl";
14+
import { incrementRenderCount } from "../../components/renderCount";
15+
16+
const ctx = useWebGLContext("#glCanvas");
17+
const target = createRenderTarget(ctx.gl);
18+
19+
const glCanvas = useWebGLCanvas({
20+
canvas: "#glCanvas",
21+
target,
22+
fragment: /* glsl */ `
23+
varying vec2 vUv;
24+
uniform vec2 uResolution;
25+
26+
void main() {
27+
vec2 uv = (vUv - .5) * 2.0 * uResolution / min(uResolution.x, uResolution.y);
28+
29+
float circleLeft = 1. - smoothstep(.3,.6, distance(uv, vec2(-.3, .2)));
30+
float circleRight = 1. - smoothstep(.3,.6, distance(uv, vec2(.3, .2)));
31+
float alpha = max(circleLeft, circleRight);
32+
33+
gl_FragColor = vec4(circleLeft, circleRight, 0, alpha);
34+
}
35+
`,
36+
});
37+
glCanvas.onAfterRender(incrementRenderCount);
38+
39+
const bluePass = useQuadRenderPass(glCanvas.gl, {
40+
target,
41+
fragment: /* glsl */ `
42+
varying vec2 vUv;
43+
uniform vec2 uResolution;
44+
45+
void main() {
46+
vec2 uv = (vUv - .5) * 2.0 * uResolution / min(uResolution.x, uResolution.y);
47+
48+
float circleMiddle = 1. - smoothstep(.3,.6, distance(uv, vec2(0, -.3)));
49+
gl_FragColor = vec4(0, 0, circleMiddle, circleMiddle);
50+
}
51+
`,
52+
uniforms: {
53+
uResolution: () => glCanvas.uniforms.uResolution,
54+
},
55+
blending: "additive",
56+
});
57+
bluePass.onAfterRender(incrementRenderCount);
58+
59+
const compositor = useCompositor(glCanvas.gl, bluePass, [linearToneMapping()]);
60+
61+
glCanvas.onAfterRender(() => {
62+
compositor.render({ clear: false });
63+
});
64+
</script>
65+
66+
<Layout title="Blending">
67+
<canvas id="glCanvas"></canvas>
68+
</Layout>
69+
70+
<style>
71+
canvas {
72+
background: darkgray;
73+
}
74+
</style>

lib/playground/src/pages/gpgpu/boids (static).astro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ import Layout from "../../layouts/Layout.astro";
6666
attributes: {
6767
aCoords: positions.coords,
6868
},
69-
transparent: true,
7069
});
7170

7271
renderPass.onAfterRender(incrementRenderCount);

lib/playground/src/pages/gpgpu/boids.astro

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ import Layout from "../../layouts/Layout.astro";
6767
attributes: {
6868
aCoords: positions.coords,
6969
},
70-
transparent: true,
70+
blending: "normal",
7171
});
7272

7373
renderPass.onAfterRender(incrementRenderCount);

lib/playground/src/pages/gpgpu/particles - FBO (static).astro

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ import Layout from "../../layouts/Layout.astro";
8181
attributes: {
8282
aCoords: positions.coords,
8383
},
84-
transparent: true,
8584
});
8685

8786
renderPass.onAfterRender(incrementRenderCount);

lib/playground/src/pages/gpgpu/particles - FBO.astro

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ import Layout from "../../layouts/Layout.astro";
7979

8080
void main() {
8181
vec2 uv = gl_PointCoord.xy;
82-
outColor = vec4(0, 1, .5, smoothstep(0.5, 0.4, length(uv - 0.5)));
82+
outColor.a = smoothstep(0.5, 0.4, length(uv - 0.5));
83+
outColor.rgb = vec3(0, 1, .5) * outColor.a;
8384
}
8485
`,
8586
uniforms: {
@@ -88,7 +89,7 @@ import Layout from "../../layouts/Layout.astro";
8889
attributes: {
8990
aCoords: positions.coords,
9091
},
91-
transparent: true,
92+
blending: "normal",
9293
});
9394

9495
renderPass.onAfterRender(incrementRenderCount);

lib/playground/src/shaders/boids.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,7 @@ out vec4 outColor;
155155
156156
void main() {
157157
vec2 uv = gl_PointCoord.xy;
158-
outColor = vec4(vColor.rgb, vColor.a * smoothstep(0.5, 0.4, length(uv - 0.5)));
158+
outColor.a = vColor.a * smoothstep(0.5, 0.4, length(uv - 0.5));
159+
outColor.rgb = vColor.rgb * outColor.a;
159160
}
160161
`;

lib/src/effects/toneMapping/glsl/_main.glsl

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,11 @@
11
void main() {
2-
vec4 color = texture(uTexture, vUv) * uExposure;
2+
vec4 color = texture(uTexture, vUv);
3+
color.rgb *= uExposure;
4+
color.rgb = color.a == 0.0 ? vec3(0.0) : color.rgb / color.a; // premultiplied -> straight alpha
5+
36
color.rgb = toneMapping(color.rgb);
7+
8+
color.rgb *= color.a; // back to premultiplied alpha
49
color = clamp(color, 0.0, 1.0);
510

611
if (uConvertToSRGB) {

lib/src/hooks/useRenderPass.ts

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export type RenderPassOptions<U extends Uniforms = Record<string, never>> = {
1919
vertex: string;
2020
attributes?: Record<string, Attribute>;
2121
uniforms?: U;
22-
transparent?: boolean;
22+
blending?: "none" | "normal" | "additive";
2323
drawMode?: DrawMode;
2424
transformFeedbackVaryings?: string[];
2525
resolutionScale?: number;
@@ -33,7 +33,7 @@ export function useRenderPass<U extends Uniforms>(
3333
vertex,
3434
attributes = {},
3535
uniforms: userUniforms = {} as U,
36-
transparent = false,
36+
blending = "none",
3737
drawMode: userDrawMode,
3838
transformFeedbackVaryings,
3939
resolutionScale = 1,
@@ -125,15 +125,9 @@ export function useRenderPass<U extends Uniforms>(
125125
setRenderTarget(_gl, target ?? _target, clear);
126126
_gl.useProgram(_program);
127127

128-
if (transparent) {
129-
_gl.enable(_gl.BLEND);
130-
_gl.blendFunc(_gl.SRC_ALPHA, _gl.ONE_MINUS_SRC_ALPHA);
131-
} else {
132-
_gl.disable(_gl.BLEND);
133-
}
134-
135128
bindVAO();
136129
setUniforms();
130+
setBlending(_gl, blending);
137131

138132
executeBeforeRenderCallbacks({ uniforms: getUniformsSnapshot() });
139133

@@ -164,3 +158,21 @@ export function useRenderPass<U extends Uniforms>(
164158
onResize,
165159
};
166160
}
161+
162+
function setBlending(gl: WebGL2RenderingContext, blending: "none" | "normal" | "additive") {
163+
if (blending === "none") {
164+
return gl.disable(gl.BLEND);
165+
}
166+
167+
gl.enable(gl.BLEND);
168+
169+
// assuming premultiplied alpha
170+
switch (blending) {
171+
case "normal": {
172+
return gl.blendFunc(gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
173+
}
174+
case "additive": {
175+
return gl.blendFunc(gl.ONE, gl.ONE);
176+
}
177+
}
178+
}
34.6 KB
Loading
43.2 KB
Loading

0 commit comments

Comments
 (0)