Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/components/ExampleEditor.vue
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
...props,
deps: {
...deps,
usegl: '0.6.0',
usegl: '0.7.0',
},
}"
>
Expand Down
31 changes: 31 additions & 0 deletions docs/examples/post-processing/builtin-bloom/dots.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
in vec2 vUv;
uniform float uTime;

const vec2 center = vec2(0.5, 0.5);
const float ringRadius = 0.3;
const float dotRadius = 0.05;

float circle(vec2 uv, vec2 center, float radius) {
float d = length(uv - center);
return 1.0 - smoothstep(radius - 0.003, radius + 0.003, d);
}

void main() {
vec3 color = vec3(0.0);
float t = - uTime * 0.15;

float offset = 0.;
for (int i = 0; i < 8; i++) {
vec2 p = center + vec2(cos(t + offset), sin(t + offset)) * ringRadius;
float r = dotRadius * (1.8 - 0.24 * float(i));
color += vec3(1., vUv) * circle(vUv, p, r);
offset += atan(4. * r, ringRadius);
}

// important !
// - the colors need to be in linear space for the bloom calculation to be correct
// - there needs to be a final pass to convert linear RGB back to sRGB
color = pow(color, vec3(2.2));

gl_FragColor = vec4(color, 1.0);
}
12 changes: 12 additions & 0 deletions docs/examples/post-processing/builtin-bloom/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
title: Bloom (builtin)
---

::: example-editor {deps=tweakpane@^4.0.5}

<<< ./index.ts
<<< ./dots.frag
<<< @/snippets/canvas-square/styles.css
<<< @/snippets/default/index.html

:::
17 changes: 17 additions & 0 deletions docs/examples/post-processing/builtin-bloom/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { useWebGLCanvas, bloom, linearToSRGB } from "usegl";
import { Pane } from "tweakpane";
import fragment from "./dots.frag?raw";
import "./styles.css";

const bloomEffect = bloom();

useWebGLCanvas({
canvas: "#glCanvas",
fragment,
postEffects: [bloomEffect, linearToSRGB()],
});

// You can dynamically update the uniforms of an effect pass, like any other pass
const pane = new Pane({ title: "Uniforms" });
pane.addBinding(bloomEffect.uniforms, "uRadius", { min: 0, max: 1 });
pane.addBinding(bloomEffect.uniforms, "uMix", { min: 0, max: 1 });
41 changes: 28 additions & 13 deletions docs/examples/post-processing/multi-pass/blur.frag
Original file line number Diff line number Diff line change
@@ -1,24 +1,39 @@
uniform sampler2D uImage;
uniform sampler2D uTexture;
uniform vec2 uResolution;
uniform vec2 uDirection;
uniform float uRadius;

in vec2 vUv;
out vec4 outColor;

const float weights[5] = float[](0.19638062, 0.29675293, 0.09442139, 0.01037598, 0.00025940);
const float offsets[5] = float[](0.0, 1.41176471, 3.29411765, 5.17647059, 7.05882353);
/*
* Directional Gaussian Blur
* /!\ Absolutely not optimized, for demonstration purposes only
*/

void main() {
vec3 color = texture(uImage, vUv).rgb * weights[0];
float weightSum = weights[0];
float sigma = float(uRadius / 2.);
vec2 sampleOffset = uDirection / uResolution;

// Build normalized Gaussian weights
float weights[51];
weights[0] = 1.0;
float sum = weights[0];
for (int i = 1; i <= int(uRadius); ++i) {
float x = float(i);
float w = exp(-0.5 * (x * x) / (sigma * sigma));
weights[i] = w;
sum += 2.0 * w;
}
for (int i = 0; i <= int(uRadius); ++i) {
weights[i] /= sum;
}

if (vUv.x < 0.52) {
for(int i = 1; i < 5; i++) {
vec2 offset = (offsets[i] / uResolution) * 0.5 * uDirection;
color += texture(uImage, vUv + offset).rgb * weights[i];
color += texture(uImage, vUv - offset).rgb * weights[i];
weightSum += 2.0 * weights[i];
}
color /= weightSum;
vec3 color = texture(uTexture, vUv).rgb * weights[0];
for (int i = 1; i <= int(uRadius); ++i) {
float fi = float(i);
color += texture(uTexture, vUv + sampleOffset * fi).rgb * weights[i];
color += texture(uTexture, vUv - sampleOffset * fi).rgb * weights[i];
}

outColor = vec4(color, 1.0);
Expand Down
19 changes: 0 additions & 19 deletions docs/examples/post-processing/multi-pass/circles.frag

This file was deleted.

29 changes: 2 additions & 27 deletions docs/examples/post-processing/multi-pass/combine.frag
Original file line number Diff line number Diff line change
Expand Up @@ -6,34 +6,9 @@ uniform float uMix;
in vec2 vUv;
out vec4 outColor;

vec2 offset(float octave) {
vec2 padding = 10.0 / uResolution;
float octaveFloor = min(1.0, floor(octave / 3.0));
vec2 offset = vec2(
-octaveFloor * (0.25 + padding.x),
-(1.0 - (1.0 / exp2(octave))) - padding.y * octave + octaveFloor * (0.35 + padding.y)
);
return offset + 0.5 / uResolution;
}

vec3 blurredMipmapLevel(float octave) {
vec2 offset = offset(octave - 1.0);
return texture(uBloomTexture, vUv / exp2(octave) - offset).rgb;
}

vec3 bloomColor() {
return blurredMipmapLevel(1.0) * 0.8
+ blurredMipmapLevel(3.0) * 0.5
+ blurredMipmapLevel(4.0) * 1.2;
}

void main() {
vec4 baseColor = texture(uBaseImage, vUv);
float baseColorGreyscale = dot(baseColor.rgb, vec3(0.299, 0.587, 0.114));
float mixFactor = (1.0 - baseColorGreyscale * baseColor.a) * uMix;

vec4 combinedColor = baseColor;
combinedColor.rgb += bloomColor() * mixFactor;
vec4 bloomColor = texture(uBloomTexture, vUv);

outColor = combinedColor;
outColor = max(baseColor, mix(baseColor, bloomColor, uMix));
}
25 changes: 25 additions & 0 deletions docs/examples/post-processing/multi-pass/dots.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
in vec2 vUv;
out vec4 outColor;

vec3 drawCircle(vec2 pos, float radius, vec3 color) {
return smoothstep(radius * 1.03, radius * .97, (length(pos) - radius)) * color;
}

void main() {
vec2 c = vec2(0.5, 0.5);
float R = 0.15;
float s60 = 0.86602540378; // sqrt(3)/2

vec2 pTop = c + vec2(0.0, R);
vec2 pBL = c + vec2(-R * s60, -R * 0.5);
vec2 pBR = c + vec2( R * s60, -R * 0.5);

vec3 color = vec3(0.0);
float r = 0.10;

color += drawCircle(vUv - pTop, r, vec3(1.0, 0.0, 0.0));
color += drawCircle(vUv - pBL, r, vec3(0.0, 1.0, 0.0));
color += drawCircle(vUv - pBR, r, vec3(0.0, 0.0, 1.0));

outColor = vec4(color, 1.0);
}
7 changes: 3 additions & 4 deletions docs/examples/post-processing/multi-pass/index.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
---
title: "Multi pass (bloom)"
title: Multi pass
---

::: example-editor {deps=tweakpane@^4.0.5}

<<< ./index.ts
<<< ./circles.frag
<<< ./mipmap.frag
<<< ./dots.frag
<<< ./blur.frag
<<< ./combine.frag
<<< ./styles.css
<<< @/snippets/canvas-square/styles.css
<<< @/snippets/default/index.html

:::
95 changes: 36 additions & 59 deletions docs/examples/post-processing/multi-pass/index.ts
Original file line number Diff line number Diff line change
@@ -1,91 +1,68 @@
import { useEffectPass, useWebGLCanvas, useCompositeEffectPass } from "usegl";
import fragment from "./circles.frag?raw";
import mipmapsShader from "./mipmap.frag?raw";
import blurShader from "./blur.frag?raw";
import combineShader from "./combine.frag?raw";
import directionalBlurFragment from "./blur.frag?raw";
import combineFragment from "./combine.frag?raw";
import dotsFragment from "./dots.frag?raw";
import { Pane } from "tweakpane";
import "./styles.css";

const mipmaps = useEffectPass({
fragment: mipmapsShader,
uniforms: {
uThreshold: 0.2,
},
});

const horizontalBlur = useEffectPass({
fragment: blurShader,
fragment: directionalBlurFragment,
uniforms: {
uTexture: ({ inputPass }) => inputPass.target!.texture, // optional, the texture uniform is automatically set
uDirection: [1, 0],
uRadius: 30,
},
});

const verticalBlur = useEffectPass({
fragment: blurShader,
fragment: directionalBlurFragment,
uniforms: {
uTexture: () => horizontalBlur.target!.texture, // optional, the texture uniform is automatically set
uDirection: [0, 1],
uRadius: 30,
},
});

const combine = useEffectPass({
fragment: combineShader,
fragment: combineFragment,
uniforms: {
uBaseImage: ({ inputPass }) => inputPass.target!.texture,
uBloomTexture: () => verticalBlur.target!.texture,
uBloomTexture: ({ previousPass }) => previousPass.target!.texture, // same as () => verticalBlur.target!.texture
uMix: 1,
},
});

const bloomEffect = useCompositeEffectPass({
mipmaps,
horizontalBlur,
verticalBlur,
combine,
});

const vignetteEffect = useEffectPass({
fragment: /* glsl */ `
uniform sampler2D uTexture;
uniform float uSize; // (0.0 - 1.0)
uniform float uRoundness; // (0.0 = rectangle, 1.0 = round)
uniform float uStrength; // (0.0 - 1.0)
varying vec2 vUv;

float vignette() {
vec2 centered = vUv * 2.0 - 1.0;
float circDist = length(centered);
float rectDist = max(abs(centered.x), abs(centered.y));
float dist = mix(rectDist, circDist, uRoundness);
return 1. - smoothstep(uSize, uSize * 2., dist) * uStrength;
}
const bloomPasses = [horizontalBlur, verticalBlur, combine];

void main() {
vec4 color = texture(uTexture, vUv);
color.rgb *= vignette();
gl_FragColor = color;
}
`,
uniforms: {
uStrength: 0.5,
uSize: 0.6,
uRoundness: 0.7,
const bloomUniforms = {
get uRadius() {
return verticalBlur.uniforms.uRadius;
},
});
set uRadius(value: number) {
verticalBlur.uniforms.uRadius = value;
horizontalBlur.uniforms.uRadius = value;
},
get uMix() {
return combine.uniforms.uMix;
},
set uMix(value: number) {
combine.uniforms.uMix = value;
},
};

const bloom = useCompositeEffectPass(bloomPasses, bloomUniforms);

useWebGLCanvas({
canvas: "#glCanvas",
fragment: fragment,
postEffects: [vignetteEffect, bloomEffect],
dpr: 1,
fragment: dotsFragment,
postEffects: [bloom],
});

const pane = new Pane({ title: "Uniforms" });

// You can update the uniforms of each individual pass, which will trigger a re-render
const bloom = pane.addFolder({ title: "Bloom" });
bloom.addBinding(bloomEffect.passes.mipmaps.uniforms, "uThreshold", { min: 0, max: 1 });
bloom.addBinding(combine.uniforms, "uMix", { min: 0, max: 1 });

const vignette = pane.addFolder({ title: "Vignette" });
vignette.addBinding(vignetteEffect.uniforms, "uStrength", { min: 0, max: 1 });
vignette.addBinding(vignetteEffect.uniforms, "uSize", { min: 0, max: 1 });
vignette.addBinding(vignetteEffect.uniforms, "uRoundness", { min: 0, max: 1 });
// Updating the uniforms of the composite pass will update those of the individual passes,
// which will trigger a re-render
const bloomFolder = pane.addFolder({ title: "Bloom" });
bloomFolder.addBinding(bloomUniforms, "uMix", { min: 0, max: 1 });
bloomFolder.addBinding(bloomUniforms, "uRadius", { min: 0, max: 50 });
41 changes: 0 additions & 41 deletions docs/examples/post-processing/multi-pass/mipmap.frag

This file was deleted.

Loading