|
| 1 | +import { useEffectPass, useWebGLCanvas, useCompositeEffectPass } from "usegl"; |
| 2 | +import fragment from "./circles.frag?raw"; |
| 3 | +import mipmapsShader from "./mipmap.frag?raw"; |
| 4 | +import blurShader from "./blur.frag?raw"; |
| 5 | +import combineShader from "./combine.frag?raw"; |
| 6 | +import { Pane } from "tweakpane"; |
| 7 | +import "./styles.css"; |
| 8 | + |
| 9 | +const mipmaps = useEffectPass({ |
| 10 | + fragment: mipmapsShader, |
| 11 | + uniforms: { |
| 12 | + uThreshold: 0.2, |
| 13 | + }, |
| 14 | +}); |
| 15 | + |
| 16 | +const horizontalBlur = useEffectPass({ |
| 17 | + fragment: blurShader, |
| 18 | + uniforms: { |
| 19 | + uDirection: [1, 0], |
| 20 | + }, |
| 21 | +}); |
| 22 | + |
| 23 | +const verticalBlur = useEffectPass({ |
| 24 | + fragment: blurShader, |
| 25 | + uniforms: { |
| 26 | + uDirection: [0, 1], |
| 27 | + }, |
| 28 | +}); |
| 29 | + |
| 30 | +const combine = useEffectPass({ |
| 31 | + fragment: combineShader, |
| 32 | + uniforms: { |
| 33 | + uBaseImage: ({ inputPass }) => inputPass.target!.texture, |
| 34 | + uBloomTexture: () => verticalBlur.target!.texture, |
| 35 | + uMix: 1, |
| 36 | + }, |
| 37 | +}); |
| 38 | + |
| 39 | +const bloomEffect = useCompositeEffectPass({ |
| 40 | + mipmaps, |
| 41 | + horizontalBlur, |
| 42 | + verticalBlur, |
| 43 | + combine, |
| 44 | +}); |
| 45 | + |
| 46 | +const vignetteEffect = useEffectPass({ |
| 47 | + fragment: /* glsl */ ` |
| 48 | + uniform sampler2D uTexture; |
| 49 | + uniform float uSize; // (0.0 - 1.0) |
| 50 | + uniform float uRoundness; // (0.0 = rectangle, 1.0 = round) |
| 51 | + uniform float uStrength; // (0.0 - 1.0) |
| 52 | + varying vec2 vUv; |
| 53 | +
|
| 54 | + float vignette() { |
| 55 | + vec2 centered = vUv * 2.0 - 1.0; |
| 56 | + float circDist = length(centered); |
| 57 | + float rectDist = max(abs(centered.x), abs(centered.y)); |
| 58 | + float dist = mix(rectDist, circDist, uRoundness); |
| 59 | + return 1. - smoothstep(uSize, uSize * 2., dist) * uStrength; |
| 60 | + } |
| 61 | +
|
| 62 | + void main() { |
| 63 | + vec4 color = texture(uTexture, vUv); |
| 64 | + color.rgb *= vignette(); |
| 65 | + gl_FragColor = color; |
| 66 | + } |
| 67 | + `, |
| 68 | + uniforms: { |
| 69 | + uStrength: 0.5, |
| 70 | + uSize: 0.6, |
| 71 | + uRoundness: 0.7, |
| 72 | + }, |
| 73 | +}); |
| 74 | + |
| 75 | +useWebGLCanvas({ |
| 76 | + canvas: "#glCanvas", |
| 77 | + fragment: fragment, |
| 78 | + postEffects: [vignetteEffect, bloomEffect], |
| 79 | +}); |
| 80 | + |
| 81 | +const pane = new Pane({ title: "Uniforms" }); |
| 82 | + |
| 83 | +// You can update the uniforms of each individual pass, which will trigger a re-render |
| 84 | +const bloom = pane.addFolder({ title: "Bloom" }); |
| 85 | +bloom.addBinding(bloomEffect.passes.mipmaps.uniforms, "uThreshold", { min: 0, max: 1 }); |
| 86 | +bloom.addBinding(combine.uniforms, "uMix", { min: 0, max: 1 }); |
| 87 | + |
| 88 | +const vignette = pane.addFolder({ title: "Vignette" }); |
| 89 | +vignette.addBinding(vignetteEffect.uniforms, "uStrength", { min: 0, max: 1 }); |
| 90 | +vignette.addBinding(vignetteEffect.uniforms, "uSize", { min: 0, max: 1 }); |
| 91 | +vignette.addBinding(vignetteEffect.uniforms, "uRoundness", { min: 0, max: 1 }); |
0 commit comments