@vysmo/transitions 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +618 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/inputs/normalize.d.ts +2 -0
- package/dist/inputs/normalize.d.ts.map +1 -0
- package/dist/inputs/normalize.js +2 -0
- package/dist/inputs/normalize.js.map +1 -0
- package/dist/runner/gl.d.ts +7 -0
- package/dist/runner/gl.d.ts.map +1 -0
- package/dist/runner/gl.js +59 -0
- package/dist/runner/gl.js.map +1 -0
- package/dist/runner/mesh.d.ts +28 -0
- package/dist/runner/mesh.d.ts.map +1 -0
- package/dist/runner/mesh.js +96 -0
- package/dist/runner/mesh.js.map +1 -0
- package/dist/runner/runner.d.ts +107 -0
- package/dist/runner/runner.d.ts.map +1 -0
- package/dist/runner/runner.js +410 -0
- package/dist/runner/runner.js.map +1 -0
- package/dist/transitions/all.d.ts +9 -0
- package/dist/transitions/all.d.ts.map +1 -0
- package/dist/transitions/all.js +129 -0
- package/dist/transitions/all.js.map +1 -0
- package/dist/transitions/bloom-reveal.d.ts +27 -0
- package/dist/transitions/bloom-reveal.d.ts.map +1 -0
- package/dist/transitions/bloom-reveal.js +106 -0
- package/dist/transitions/bloom-reveal.js.map +1 -0
- package/dist/transitions/chromatic-pulse.d.ts +4 -0
- package/dist/transitions/chromatic-pulse.d.ts.map +1 -0
- package/dist/transitions/chromatic-pulse.js +40 -0
- package/dist/transitions/chromatic-pulse.js.map +1 -0
- package/dist/transitions/clock-wipe.d.ts +6 -0
- package/dist/transitions/clock-wipe.d.ts.map +1 -0
- package/dist/transitions/clock-wipe.js +33 -0
- package/dist/transitions/clock-wipe.js.map +1 -0
- package/dist/transitions/color-phase.d.ts +10 -0
- package/dist/transitions/color-phase.d.ts.map +1 -0
- package/dist/transitions/color-phase.js +24 -0
- package/dist/transitions/color-phase.js.map +1 -0
- package/dist/transitions/colour-distance.d.ts.map +1 -0
- package/dist/transitions/cross-warp.d.ts.map +1 -0
- package/dist/transitions/cross-zoom.d.ts +5 -0
- package/dist/transitions/cross-zoom.d.ts.map +1 -0
- package/dist/transitions/cross-zoom.js +59 -0
- package/dist/transitions/cross-zoom.js.map +1 -0
- package/dist/transitions/crosshatch.d.ts +12 -0
- package/dist/transitions/crosshatch.d.ts.map +1 -0
- package/dist/transitions/crosshatch.js +49 -0
- package/dist/transitions/crosshatch.js.map +1 -0
- package/dist/transitions/define.d.ts +35 -0
- package/dist/transitions/define.d.ts.map +1 -0
- package/dist/transitions/define.js +37 -0
- package/dist/transitions/define.js.map +1 -0
- package/dist/transitions/directional-burn.d.ts +14 -0
- package/dist/transitions/directional-burn.d.ts.map +1 -0
- package/dist/transitions/directional-burn.js +67 -0
- package/dist/transitions/directional-burn.js.map +1 -0
- package/dist/transitions/directional-warp.d.ts +12 -0
- package/dist/transitions/directional-warp.d.ts.map +1 -0
- package/dist/transitions/directional-warp.js +46 -0
- package/dist/transitions/directional-warp.js.map +1 -0
- package/dist/transitions/dissolve.d.ts +2 -0
- package/dist/transitions/dissolve.d.ts.map +1 -0
- package/dist/transitions/dissolve.js +16 -0
- package/dist/transitions/dissolve.js.map +1 -0
- package/dist/transitions/dreamy-zoom.d.ts +25 -0
- package/dist/transitions/dreamy-zoom.d.ts.map +1 -0
- package/dist/transitions/dreamy-zoom.js +66 -0
- package/dist/transitions/dreamy-zoom.js.map +1 -0
- package/dist/transitions/dreamy.d.ts +8 -0
- package/dist/transitions/dreamy.d.ts.map +1 -0
- package/dist/transitions/dreamy.js +26 -0
- package/dist/transitions/dreamy.js.map +1 -0
- package/dist/transitions/drip-wipe.d.ts +22 -0
- package/dist/transitions/drip-wipe.d.ts.map +1 -0
- package/dist/transitions/drip-wipe.js +109 -0
- package/dist/transitions/drip-wipe.js.map +1 -0
- package/dist/transitions/ember-scatter.d.ts +22 -0
- package/dist/transitions/ember-scatter.d.ts.map +1 -0
- package/dist/transitions/ember-scatter.js +94 -0
- package/dist/transitions/ember-scatter.js.map +1 -0
- package/dist/transitions/film-burn.d.ts +17 -0
- package/dist/transitions/film-burn.d.ts.map +1 -0
- package/dist/transitions/film-burn.js +101 -0
- package/dist/transitions/film-burn.js.map +1 -0
- package/dist/transitions/film-grain.d.ts +24 -0
- package/dist/transitions/film-grain.d.ts.map +1 -0
- package/dist/transitions/film-grain.js +78 -0
- package/dist/transitions/film-grain.js.map +1 -0
- package/dist/transitions/flow-warp.d.ts +20 -0
- package/dist/transitions/flow-warp.d.ts.map +1 -0
- package/dist/transitions/flow-warp.js +51 -0
- package/dist/transitions/flow-warp.js.map +1 -0
- package/dist/transitions/fluid-flow.d.ts +26 -0
- package/dist/transitions/fluid-flow.d.ts.map +1 -0
- package/dist/transitions/fluid-flow.js +94 -0
- package/dist/transitions/fluid-flow.js.map +1 -0
- package/dist/transitions/fly-eye.d.ts.map +1 -0
- package/dist/transitions/fly-eye.js +58 -0
- package/dist/transitions/fly-eye.js.map +1 -0
- package/dist/transitions/glass-shatter.d.ts +25 -0
- package/dist/transitions/glass-shatter.d.ts.map +1 -0
- package/dist/transitions/glass-shatter.js +86 -0
- package/dist/transitions/glass-shatter.js.map +1 -0
- package/dist/transitions/glitch.d.ts +6 -0
- package/dist/transitions/glitch.d.ts.map +1 -0
- package/dist/transitions/glitch.js +59 -0
- package/dist/transitions/glitch.js.map +1 -0
- package/dist/transitions/god-rays-reveal.d.ts +32 -0
- package/dist/transitions/god-rays-reveal.d.ts.map +1 -0
- package/dist/transitions/god-rays-reveal.js +110 -0
- package/dist/transitions/god-rays-reveal.js.map +1 -0
- package/dist/transitions/gravity-pull.d.ts +16 -0
- package/dist/transitions/gravity-pull.d.ts.map +1 -0
- package/dist/transitions/gravity-pull.js +65 -0
- package/dist/transitions/gravity-pull.js.map +1 -0
- package/dist/transitions/grid-reveal.d.ts +12 -0
- package/dist/transitions/grid-reveal.d.ts.map +1 -0
- package/dist/transitions/grid-reveal.js +53 -0
- package/dist/transitions/grid-reveal.js.map +1 -0
- package/dist/transitions/heat-haze.d.ts +13 -0
- package/dist/transitions/heat-haze.d.ts.map +1 -0
- package/dist/transitions/heat-haze.js +51 -0
- package/dist/transitions/heat-haze.js.map +1 -0
- package/dist/transitions/index.d.ts +64 -0
- package/dist/transitions/index.d.ts.map +1 -0
- package/dist/transitions/index.js +63 -0
- package/dist/transitions/index.js.map +1 -0
- package/dist/transitions/ink-bloom.d.ts +15 -0
- package/dist/transitions/ink-bloom.d.ts.map +1 -0
- package/dist/transitions/ink-bloom.js +76 -0
- package/dist/transitions/ink-bloom.js.map +1 -0
- package/dist/transitions/ink-diffuse.d.ts +26 -0
- package/dist/transitions/ink-diffuse.d.ts.map +1 -0
- package/dist/transitions/ink-diffuse.js +90 -0
- package/dist/transitions/ink-diffuse.js.map +1 -0
- package/dist/transitions/iris-zoom.d.ts +13 -0
- package/dist/transitions/iris-zoom.d.ts.map +1 -0
- package/dist/transitions/iris-zoom.js +67 -0
- package/dist/transitions/iris-zoom.js.map +1 -0
- package/dist/transitions/kinetic-bands.d.ts +7 -0
- package/dist/transitions/kinetic-bands.d.ts.map +1 -0
- package/dist/transitions/kinetic-bands.js +58 -0
- package/dist/transitions/kinetic-bands.js.map +1 -0
- package/dist/transitions/lenticular-flip.d.ts +22 -0
- package/dist/transitions/lenticular-flip.d.ts.map +1 -0
- package/dist/transitions/lenticular-flip.js +73 -0
- package/dist/transitions/lenticular-flip.js.map +1 -0
- package/dist/transitions/light-leak.d.ts +7 -0
- package/dist/transitions/light-leak.d.ts.map +1 -0
- package/dist/transitions/light-leak.js +43 -0
- package/dist/transitions/light-leak.js.map +1 -0
- package/dist/transitions/lightning-strike.d.ts +22 -0
- package/dist/transitions/lightning-strike.d.ts.map +1 -0
- package/dist/transitions/lightning-strike.js +90 -0
- package/dist/transitions/lightning-strike.js.map +1 -0
- package/dist/transitions/linear-blur.d.ts +11 -0
- package/dist/transitions/linear-blur.d.ts.map +1 -0
- package/dist/transitions/linear-blur.js +40 -0
- package/dist/transitions/linear-blur.js.map +1 -0
- package/dist/transitions/liquid-chrome.d.ts +22 -0
- package/dist/transitions/liquid-chrome.d.ts.map +1 -0
- package/dist/transitions/liquid-chrome.js +114 -0
- package/dist/transitions/liquid-chrome.js.map +1 -0
- package/dist/transitions/liquid-morph.d.ts +6 -0
- package/dist/transitions/liquid-morph.d.ts.map +1 -0
- package/dist/transitions/liquid-morph.js +50 -0
- package/dist/transitions/liquid-morph.js.map +1 -0
- package/dist/transitions/lumina-melt.d.ts +11 -0
- package/dist/transitions/lumina-melt.d.ts.map +1 -0
- package/dist/transitions/lumina-melt.js +36 -0
- package/dist/transitions/lumina-melt.js.map +1 -0
- package/dist/transitions/mosaic.d.ts +13 -0
- package/dist/transitions/mosaic.d.ts.map +1 -0
- package/dist/transitions/mosaic.js +58 -0
- package/dist/transitions/mosaic.js.map +1 -0
- package/dist/transitions/noise-dissolve.d.ts +5 -0
- package/dist/transitions/noise-dissolve.d.ts.map +1 -0
- package/dist/transitions/noise-dissolve.js +41 -0
- package/dist/transitions/noise-dissolve.js.map +1 -0
- package/dist/transitions/page-curl.d.ts +32 -0
- package/dist/transitions/page-curl.d.ts.map +1 -0
- package/dist/transitions/page-curl.js +165 -0
- package/dist/transitions/page-curl.js.map +1 -0
- package/dist/transitions/paint-bleed.d.ts +12 -0
- package/dist/transitions/paint-bleed.d.ts.map +1 -0
- package/dist/transitions/paint-bleed.js +59 -0
- package/dist/transitions/paint-bleed.js.map +1 -0
- package/dist/transitions/particle-assemble.d.ts +23 -0
- package/dist/transitions/particle-assemble.d.ts.map +1 -0
- package/dist/transitions/particle-assemble.js +65 -0
- package/dist/transitions/particle-assemble.js.map +1 -0
- package/dist/transitions/pinwheel.d.ts +11 -0
- package/dist/transitions/pinwheel.d.ts.map +1 -0
- package/dist/transitions/pinwheel.js +40 -0
- package/dist/transitions/pinwheel.js.map +1 -0
- package/dist/transitions/pixelate.d.ts +4 -0
- package/dist/transitions/pixelate.d.ts.map +1 -0
- package/dist/transitions/pixelate.js +26 -0
- package/dist/transitions/pixelate.js.map +1 -0
- package/dist/transitions/plasma-pulse.d.ts.map +1 -0
- package/dist/transitions/plasma-pulse.js +92 -0
- package/dist/transitions/plasma-pulse.js.map +1 -0
- package/dist/transitions/polka-dots-curtain.d.ts +13 -0
- package/dist/transitions/polka-dots-curtain.d.ts.map +1 -0
- package/dist/transitions/polka-dots-curtain.js +46 -0
- package/dist/transitions/polka-dots-curtain.js.map +1 -0
- package/dist/transitions/polygon-flip.d.ts +27 -0
- package/dist/transitions/polygon-flip.d.ts.map +1 -0
- package/dist/transitions/polygon-flip.js +97 -0
- package/dist/transitions/polygon-flip.js.map +1 -0
- package/dist/transitions/portal-dive.d.ts +18 -0
- package/dist/transitions/portal-dive.d.ts.map +1 -0
- package/dist/transitions/portal-dive.js +83 -0
- package/dist/transitions/portal-dive.js.map +1 -0
- package/dist/transitions/prism-split.d.ts +12 -0
- package/dist/transitions/prism-split.d.ts.map +1 -0
- package/dist/transitions/prism-split.js +52 -0
- package/dist/transitions/prism-split.js.map +1 -0
- package/dist/transitions/push.d.ts +4 -0
- package/dist/transitions/push.d.ts.map +1 -0
- package/dist/transitions/push.js +34 -0
- package/dist/transitions/push.js.map +1 -0
- package/dist/transitions/radial-reveal.d.ts +5 -0
- package/dist/transitions/radial-reveal.d.ts.map +1 -0
- package/dist/transitions/radial-reveal.js +31 -0
- package/dist/transitions/radial-reveal.js.map +1 -0
- package/dist/transitions/ripple-wave.d.ts +24 -0
- package/dist/transitions/ripple-wave.d.ts.map +1 -0
- package/dist/transitions/ripple-wave.js +135 -0
- package/dist/transitions/ripple-wave.js.map +1 -0
- package/dist/transitions/ripple.d.ts +7 -0
- package/dist/transitions/ripple.d.ts.map +1 -0
- package/dist/transitions/ripple.js +43 -0
- package/dist/transitions/ripple.js.map +1 -0
- package/dist/transitions/shape-reveal.d.ts +12 -0
- package/dist/transitions/shape-reveal.d.ts.map +1 -0
- package/dist/transitions/shape-reveal.js +53 -0
- package/dist/transitions/shape-reveal.js.map +1 -0
- package/dist/transitions/shockwave.d.ts +10 -0
- package/dist/transitions/shockwave.d.ts.map +1 -0
- package/dist/transitions/shockwave.js +56 -0
- package/dist/transitions/shockwave.js.map +1 -0
- package/dist/transitions/singularity.d.ts +22 -0
- package/dist/transitions/singularity.d.ts.map +1 -0
- package/dist/transitions/singularity.js +59 -0
- package/dist/transitions/singularity.js.map +1 -0
- package/dist/transitions/slide.d.ts +10 -0
- package/dist/transitions/slide.d.ts.map +1 -0
- package/dist/transitions/slide.js +76 -0
- package/dist/transitions/slide.js.map +1 -0
- package/dist/transitions/smoldering-edge.d.ts +15 -0
- package/dist/transitions/smoldering-edge.d.ts.map +1 -0
- package/dist/transitions/smoldering-edge.js +74 -0
- package/dist/transitions/smoldering-edge.js.map +1 -0
- package/dist/transitions/split.d.ts +14 -0
- package/dist/transitions/split.d.ts.map +1 -0
- package/dist/transitions/split.js +53 -0
- package/dist/transitions/split.js.map +1 -0
- package/dist/transitions/swirl.d.ts +12 -0
- package/dist/transitions/swirl.d.ts.map +1 -0
- package/dist/transitions/swirl.js +42 -0
- package/dist/transitions/swirl.js.map +1 -0
- package/dist/transitions/tangent-motion-blur.d.ts +13 -0
- package/dist/transitions/tangent-motion-blur.d.ts.map +1 -0
- package/dist/transitions/tangent-motion-blur.js +58 -0
- package/dist/transitions/tangent-motion-blur.js.map +1 -0
- package/dist/transitions/tile-scatter.d.ts +22 -0
- package/dist/transitions/tile-scatter.d.ts.map +1 -0
- package/dist/transitions/tile-scatter.js +122 -0
- package/dist/transitions/tile-scatter.js.map +1 -0
- package/dist/transitions/tilt-sweep.d.ts +11 -0
- package/dist/transitions/tilt-sweep.d.ts.map +1 -0
- package/dist/transitions/tilt-sweep.js +31 -0
- package/dist/transitions/tilt-sweep.js.map +1 -0
- package/dist/transitions/warp-zoom.d.ts +7 -0
- package/dist/transitions/warp-zoom.d.ts.map +1 -0
- package/dist/transitions/warp-zoom.js +70 -0
- package/dist/transitions/warp-zoom.js.map +1 -0
- package/dist/transitions/wave-stripes.d.ts +16 -0
- package/dist/transitions/wave-stripes.d.ts.map +1 -0
- package/dist/transitions/wave-stripes.js +55 -0
- package/dist/transitions/wave-stripes.js.map +1 -0
- package/dist/transitions/wave-wipe.d.ts +23 -0
- package/dist/transitions/wave-wipe.d.ts.map +1 -0
- package/dist/transitions/wave-wipe.js +84 -0
- package/dist/transitions/wave-wipe.js.map +1 -0
- package/dist/transitions/wind.d.ts +9 -0
- package/dist/transitions/wind.d.ts.map +1 -0
- package/dist/transitions/wind.js +48 -0
- package/dist/transitions/wind.js.map +1 -0
- package/dist/transitions/window-slice.d.ts +11 -0
- package/dist/transitions/window-slice.d.ts.map +1 -0
- package/dist/transitions/window-slice.js +34 -0
- package/dist/transitions/window-slice.js.map +1 -0
- package/dist/transitions/wipe-directional.d.ts +5 -0
- package/dist/transitions/wipe-directional.d.ts.map +1 -0
- package/dist/transitions/wipe-directional.js +26 -0
- package/dist/transitions/wipe-directional.js.map +1 -0
- package/dist/types.d.ts +78 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +56 -0
- package/src/__tests__/__screenshots__/endpoint-correctness.test.ts/endpoint-correctness---every-transition-must-be-pixel-pure-from-to-at-progress-0-1-rippleWave-at-progress-0-is-pure--from--1.png +0 -0
- package/src/__tests__/__screenshots__/endpoint-correctness.test.ts/endpoint-correctness---every-transition-must-be-pixel-pure-from-to-at-progress-0-1-rippleWave-at-progress-1-is-pure--to--1.png +0 -0
- package/src/__tests__/endpoint-correctness.test.ts +161 -0
- package/src/__tests__/readme.test.ts +39 -0
- package/src/__tests__/ssr.test.ts +45 -0
- package/src/index.ts +75 -0
- package/src/inputs/normalize.ts +1 -0
- package/src/runner/__tests__/__screenshots__/mesh.test.ts/buildSubdividedPlane-centroid-is-shared-across-a-face-and-equals-mean-of-its-3-positions-1.png +0 -0
- package/src/runner/__tests__/__screenshots__/mesh.test.ts/buildSubdividedPlane-uv-matches-aPosition---0-5---0-5-1.png +0 -0
- package/src/runner/__tests__/mesh.test.ts +128 -0
- package/src/runner/gl.ts +69 -0
- package/src/runner/mesh.ts +135 -0
- package/src/runner/runner.ts +528 -0
- package/src/transitions/all.ts +131 -0
- package/src/transitions/bloom-reveal.ts +106 -0
- package/src/transitions/chromatic-pulse.ts +40 -0
- package/src/transitions/clock-wipe.ts +33 -0
- package/src/transitions/color-phase.ts +24 -0
- package/src/transitions/cross-zoom.ts +59 -0
- package/src/transitions/crosshatch.ts +49 -0
- package/src/transitions/define.ts +56 -0
- package/src/transitions/directional-burn.ts +67 -0
- package/src/transitions/directional-warp.ts +46 -0
- package/src/transitions/dissolve.ts +16 -0
- package/src/transitions/dreamy-zoom.ts +66 -0
- package/src/transitions/dreamy.ts +26 -0
- package/src/transitions/drip-wipe.ts +109 -0
- package/src/transitions/ember-scatter.ts +94 -0
- package/src/transitions/film-burn.ts +101 -0
- package/src/transitions/film-grain.ts +78 -0
- package/src/transitions/flow-warp.ts +51 -0
- package/src/transitions/fluid-flow.ts +94 -0
- package/src/transitions/glass-shatter.ts +86 -0
- package/src/transitions/glitch.ts +59 -0
- package/src/transitions/god-rays-reveal.ts +110 -0
- package/src/transitions/gravity-pull.ts +65 -0
- package/src/transitions/grid-reveal.ts +53 -0
- package/src/transitions/heat-haze.ts +51 -0
- package/src/transitions/index.ts +63 -0
- package/src/transitions/ink-bloom.ts +76 -0
- package/src/transitions/ink-diffuse.ts +90 -0
- package/src/transitions/iris-zoom.ts +67 -0
- package/src/transitions/kinetic-bands.ts +58 -0
- package/src/transitions/lenticular-flip.ts +73 -0
- package/src/transitions/light-leak.ts +43 -0
- package/src/transitions/linear-blur.ts +40 -0
- package/src/transitions/liquid-chrome.ts +114 -0
- package/src/transitions/liquid-morph.ts +50 -0
- package/src/transitions/lumina-melt.ts +36 -0
- package/src/transitions/mosaic.ts +58 -0
- package/src/transitions/noise-dissolve.ts +41 -0
- package/src/transitions/page-curl.ts +165 -0
- package/src/transitions/paint-bleed.ts +59 -0
- package/src/transitions/pinwheel.ts +40 -0
- package/src/transitions/pixelate.ts +26 -0
- package/src/transitions/polka-dots-curtain.ts +46 -0
- package/src/transitions/polygon-flip.ts +97 -0
- package/src/transitions/portal-dive.ts +83 -0
- package/src/transitions/prism-split.ts +52 -0
- package/src/transitions/push.ts +34 -0
- package/src/transitions/radial-reveal.ts +31 -0
- package/src/transitions/ripple-wave.ts +135 -0
- package/src/transitions/ripple.ts +43 -0
- package/src/transitions/shape-reveal.ts +53 -0
- package/src/transitions/shockwave.ts +56 -0
- package/src/transitions/singularity.ts +59 -0
- package/src/transitions/slide.ts +76 -0
- package/src/transitions/smoldering-edge.ts +74 -0
- package/src/transitions/split.ts +53 -0
- package/src/transitions/swirl.ts +42 -0
- package/src/transitions/tangent-motion-blur.ts +58 -0
- package/src/transitions/tile-scatter.ts +122 -0
- package/src/transitions/warp-zoom.ts +70 -0
- package/src/transitions/wave-stripes.ts +55 -0
- package/src/transitions/wind.ts +48 -0
- package/src/transitions/wipe-directional.ts +26 -0
- package/src/types.ts +87 -0
|
@@ -0,0 +1,528 @@
|
|
|
1
|
+
import { FramebufferPool, TextureCache } from "@vysmo/gl-core";
|
|
2
|
+
import type {
|
|
3
|
+
RenderArgs,
|
|
4
|
+
Transition,
|
|
5
|
+
UniformParams,
|
|
6
|
+
UniformValue,
|
|
7
|
+
} from "../types.js";
|
|
8
|
+
import {
|
|
9
|
+
buildProgram,
|
|
10
|
+
paramKeyToUniformName,
|
|
11
|
+
wrapFragmentShader,
|
|
12
|
+
wrapMeshVertexShader,
|
|
13
|
+
} from "./gl.js";
|
|
14
|
+
import { buildSubdividedPlane } from "./mesh.js";
|
|
15
|
+
|
|
16
|
+
interface CompiledTransition {
|
|
17
|
+
program: WebGLProgram;
|
|
18
|
+
uniforms: Map<string, WebGLUniformLocation | null>;
|
|
19
|
+
mesh?: MeshResources;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface MeshResources {
|
|
23
|
+
vao: WebGLVertexArrayObject;
|
|
24
|
+
buffers: WebGLBuffer[];
|
|
25
|
+
vertexCount: number;
|
|
26
|
+
instances: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const MESH_ATTRIBS: ReadonlyArray<{
|
|
30
|
+
name: string;
|
|
31
|
+
size: number;
|
|
32
|
+
bufferKey: "position" | "uv" | "offset" | "centroid" | "bary" | "random";
|
|
33
|
+
}> = [
|
|
34
|
+
{ name: "aPosition", size: 2, bufferKey: "position" },
|
|
35
|
+
{ name: "aUv", size: 2, bufferKey: "uv" },
|
|
36
|
+
{ name: "aOffset", size: 1, bufferKey: "offset" },
|
|
37
|
+
{ name: "aCentroid", size: 2, bufferKey: "centroid" },
|
|
38
|
+
{ name: "aBary", size: 3, bufferKey: "bary" },
|
|
39
|
+
{ name: "aRandom", size: 1, bufferKey: "random" },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
export interface RunnerOptions {
|
|
43
|
+
/** Render target. `OffscreenCanvas` works in workers; `HTMLCanvasElement` on the main thread. */
|
|
44
|
+
canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
45
|
+
/**
|
|
46
|
+
* Forwarded to `canvas.getContext("webgl2", …)`. Defaults are
|
|
47
|
+
* `{ alpha: true, antialias: true, premultipliedAlpha: false,
|
|
48
|
+
* preserveDrawingBuffer: false }` — overrideable via this field.
|
|
49
|
+
*/
|
|
50
|
+
contextAttributes?: WebGLContextAttributes;
|
|
51
|
+
/**
|
|
52
|
+
* Optional callback invoked when the WebGL context is lost. After this
|
|
53
|
+
* fires, `render()` throws until the context is restored — either
|
|
54
|
+
* automatically via the `webglcontextrestored` event (when the canvas
|
|
55
|
+
* is an `EventTarget`) or by re-creating the Runner.
|
|
56
|
+
*/
|
|
57
|
+
onContextLost?: () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Optional callback invoked once the runner has re-initialised after a
|
|
60
|
+
* `webglcontextrestored` event. After this, `render()` works again.
|
|
61
|
+
*/
|
|
62
|
+
onContextRestored?: () => void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The single object that owns a WebGL2 context, compiles transition
|
|
67
|
+
* shaders on first use, and renders frames. One Runner per canvas;
|
|
68
|
+
* one canvas per Runner.
|
|
69
|
+
*
|
|
70
|
+
* Usage shape:
|
|
71
|
+
*
|
|
72
|
+
* const runner = new Runner({ canvas });
|
|
73
|
+
* runner.render(crossZoom, { from: imgA, to: imgB, progress: 0.4 });
|
|
74
|
+
* // … animate progress 0 → 1 with your driver of choice …
|
|
75
|
+
* runner.dispose();
|
|
76
|
+
*
|
|
77
|
+
* Programs are cached per-`Transition` reference (WeakMap), so passing
|
|
78
|
+
* the same transition repeatedly compiles once and reuses thereafter.
|
|
79
|
+
* Source textures are likewise cached by identity via `@vysmo/gl-core`'s
|
|
80
|
+
* `TextureCache` — static images upload once.
|
|
81
|
+
*
|
|
82
|
+
* @throws Error if WebGL2 is unavailable in the host environment.
|
|
83
|
+
*/
|
|
84
|
+
export class Runner {
|
|
85
|
+
readonly gl: WebGL2RenderingContext;
|
|
86
|
+
private canvas: HTMLCanvasElement | OffscreenCanvas;
|
|
87
|
+
private textures: TextureCache;
|
|
88
|
+
private programs = new WeakMap<Transition<UniformParams>, CompiledTransition>();
|
|
89
|
+
private vao: WebGLVertexArrayObject;
|
|
90
|
+
private defaultDisplacement: WebGLTexture;
|
|
91
|
+
private defaultEnvironment: WebGLTexture;
|
|
92
|
+
private defaultPrevious: WebGLTexture;
|
|
93
|
+
// Ping-pong framebuffers for multi-pass transitions; lazy-allocated.
|
|
94
|
+
private fbPool: FramebufferPool;
|
|
95
|
+
private disposed = false;
|
|
96
|
+
private contextLost = false;
|
|
97
|
+
private readonly onContextLost: (() => void) | undefined;
|
|
98
|
+
private readonly onContextRestored: (() => void) | undefined;
|
|
99
|
+
private readonly handleContextLost = (e: Event): void => {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
this.contextLost = true;
|
|
102
|
+
this.programs = new WeakMap();
|
|
103
|
+
this.onContextLost?.();
|
|
104
|
+
};
|
|
105
|
+
private readonly handleContextRestored = (): void => {
|
|
106
|
+
this.contextLost = false;
|
|
107
|
+
const vao = this.gl.createVertexArray();
|
|
108
|
+
if (vao) this.vao = vao;
|
|
109
|
+
this.textures = new TextureCache(this.gl);
|
|
110
|
+
this.defaultDisplacement = this.createDefaultDisplacement();
|
|
111
|
+
this.defaultEnvironment = this.createDefaultEnvironment();
|
|
112
|
+
this.defaultPrevious = this.createDefaultPrevious();
|
|
113
|
+
// Drop cached framebuffers — they're tied to the lost context.
|
|
114
|
+
this.fbPool.resetContextState();
|
|
115
|
+
this.onContextRestored?.();
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
constructor(options: RunnerOptions) {
|
|
119
|
+
this.canvas = options.canvas;
|
|
120
|
+
this.onContextLost = options.onContextLost;
|
|
121
|
+
this.onContextRestored = options.onContextRestored;
|
|
122
|
+
|
|
123
|
+
const gl = options.canvas.getContext("webgl2", {
|
|
124
|
+
alpha: true,
|
|
125
|
+
antialias: true,
|
|
126
|
+
premultipliedAlpha: false,
|
|
127
|
+
preserveDrawingBuffer: false,
|
|
128
|
+
...options.contextAttributes,
|
|
129
|
+
}) as WebGL2RenderingContext | null;
|
|
130
|
+
|
|
131
|
+
if (!gl) {
|
|
132
|
+
throw new Error(
|
|
133
|
+
"WebGL2 is not available. This environment does not support the transitions library.",
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
this.gl = gl;
|
|
137
|
+
this.textures = new TextureCache(gl);
|
|
138
|
+
this.fbPool = new FramebufferPool(gl);
|
|
139
|
+
|
|
140
|
+
const vao = gl.createVertexArray();
|
|
141
|
+
if (!vao) throw new Error("gl.createVertexArray returned null");
|
|
142
|
+
this.vao = vao;
|
|
143
|
+
|
|
144
|
+
this.defaultDisplacement = this.createDefaultDisplacement();
|
|
145
|
+
this.defaultEnvironment = this.createDefaultEnvironment();
|
|
146
|
+
this.defaultPrevious = this.createDefaultPrevious();
|
|
147
|
+
|
|
148
|
+
if (typeof EventTarget !== "undefined" && options.canvas instanceof EventTarget) {
|
|
149
|
+
options.canvas.addEventListener("webglcontextlost", this.handleContextLost);
|
|
150
|
+
options.canvas.addEventListener("webglcontextrestored", this.handleContextRestored);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
private createDefaultDisplacement(): WebGLTexture {
|
|
155
|
+
// 1×1 mid-gray = "no displacement" for shaders that interpret
|
|
156
|
+
// (rg - 0.5) as a centered offset vector.
|
|
157
|
+
return this.createSolidTexture(128, 128, 128);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private createDefaultEnvironment(): WebGLTexture {
|
|
161
|
+
// 1×1 mid-gray = neutral environment. Transitions that sample it
|
|
162
|
+
// for reflections get a constant gray, which blends to no visible
|
|
163
|
+
// effect when combined with multiplicative / additive gain.
|
|
164
|
+
return this.createSolidTexture(128, 128, 128);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
private createDefaultPrevious(): WebGLTexture {
|
|
168
|
+
// 1×1 transparent black — pass 0's uPrevious fallback. Transitions
|
|
169
|
+
// that run with passes > 1 are expected to handle uPass == 0
|
|
170
|
+
// explicitly (seed from uFrom/uTo/uDisplacement/etc. rather than
|
|
171
|
+
// reading getPrevious).
|
|
172
|
+
return this.createSolidTexture(0, 0, 0);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
private createSolidTexture(r: number, g: number, b: number): WebGLTexture {
|
|
176
|
+
const gl = this.gl;
|
|
177
|
+
const tex = gl.createTexture();
|
|
178
|
+
if (!tex) throw new Error("gl.createTexture returned null");
|
|
179
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
180
|
+
gl.texImage2D(
|
|
181
|
+
gl.TEXTURE_2D,
|
|
182
|
+
0,
|
|
183
|
+
gl.RGBA,
|
|
184
|
+
1,
|
|
185
|
+
1,
|
|
186
|
+
0,
|
|
187
|
+
gl.RGBA,
|
|
188
|
+
gl.UNSIGNED_BYTE,
|
|
189
|
+
new Uint8Array([r, g, b, 255]),
|
|
190
|
+
);
|
|
191
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
192
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
193
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
|
|
194
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
|
|
195
|
+
return tex;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Render one frame of `transition` at the given `progress` (0..1).
|
|
200
|
+
* `from` and `to` are the source and target images; the runner samples
|
|
201
|
+
* both via the same shader and crossfades / displaces / warps according
|
|
202
|
+
* to whatever GLSL the transition declares.
|
|
203
|
+
*
|
|
204
|
+
* Endpoint correctness is enforced by tests: at `progress === 0` the
|
|
205
|
+
* output is pixel-identical to `from`; at `progress === 1` it's
|
|
206
|
+
* pixel-identical to `to`.
|
|
207
|
+
*
|
|
208
|
+
* @param transition Any `Transition` — built-in (`crossZoom`, `pageCurl`, …)
|
|
209
|
+
* or one returned from `defineTransition()`.
|
|
210
|
+
* @param args `from`, `to`, `progress`, optional `params`
|
|
211
|
+
* overrides, optional `displacement` / `environment`
|
|
212
|
+
* aux textures (see `RenderArgs`).
|
|
213
|
+
*
|
|
214
|
+
* @throws Error if the runner is disposed or the WebGL context is lost.
|
|
215
|
+
* @throws Error if shader compilation or program linking fails.
|
|
216
|
+
*/
|
|
217
|
+
render<P extends UniformParams>(
|
|
218
|
+
transition: Transition<P>,
|
|
219
|
+
args: RenderArgs<P>,
|
|
220
|
+
): void {
|
|
221
|
+
if (this.disposed) {
|
|
222
|
+
throw new Error("Runner has been disposed. Create a new Runner to render.");
|
|
223
|
+
}
|
|
224
|
+
if (this.contextLost) {
|
|
225
|
+
throw new Error(
|
|
226
|
+
"WebGL context is lost. Wait for onContextRestored before rendering again.",
|
|
227
|
+
);
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const gl = this.gl;
|
|
231
|
+
const compiled = this.getOrCompile(transition);
|
|
232
|
+
|
|
233
|
+
// Allocate/resize framebuffers BEFORE any source texture binding. FBO
|
|
234
|
+
// texture creation binds `gl.TEXTURE_2D` to whichever unit is active;
|
|
235
|
+
// hoisting this call avoids clobbering a previously-bound source on
|
|
236
|
+
// the first render.
|
|
237
|
+
const multiPass =
|
|
238
|
+
compiled.mesh === undefined && (transition.passes ?? 1) > 1;
|
|
239
|
+
if (multiPass) {
|
|
240
|
+
this.fbPool.ensure(2, this.canvas.width, this.canvas.height);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
gl.useProgram(compiled.program);
|
|
244
|
+
|
|
245
|
+
// Resolve all textures up front. TextureCache.resolve() calls
|
|
246
|
+
// gl.bindTexture() against whichever unit is currently active (to
|
|
247
|
+
// upload pixels), so if we interleave resolves with activeTexture()
|
|
248
|
+
// calls, each resolve clobbers the most recently bound unit.
|
|
249
|
+
const fromTex = this.textures.resolve(args.from);
|
|
250
|
+
const toTex = this.textures.resolve(args.to);
|
|
251
|
+
const displacementTex = args.displacement
|
|
252
|
+
? this.textures.resolve(args.displacement)
|
|
253
|
+
: this.defaultDisplacement;
|
|
254
|
+
const environmentTex = args.environment
|
|
255
|
+
? this.textures.resolve(args.environment)
|
|
256
|
+
: this.defaultEnvironment;
|
|
257
|
+
|
|
258
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
259
|
+
gl.bindTexture(gl.TEXTURE_2D, fromTex);
|
|
260
|
+
gl.uniform1i(this.uniformLoc(compiled, "uFrom"), 0);
|
|
261
|
+
|
|
262
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
263
|
+
gl.bindTexture(gl.TEXTURE_2D, toTex);
|
|
264
|
+
gl.uniform1i(this.uniformLoc(compiled, "uTo"), 1);
|
|
265
|
+
|
|
266
|
+
gl.activeTexture(gl.TEXTURE2);
|
|
267
|
+
gl.bindTexture(gl.TEXTURE_2D, displacementTex);
|
|
268
|
+
gl.uniform1i(this.uniformLoc(compiled, "uDisplacement"), 2);
|
|
269
|
+
|
|
270
|
+
gl.activeTexture(gl.TEXTURE3);
|
|
271
|
+
gl.bindTexture(gl.TEXTURE_2D, environmentTex);
|
|
272
|
+
gl.uniform1i(this.uniformLoc(compiled, "uEnvironment"), 3);
|
|
273
|
+
|
|
274
|
+
gl.uniform1f(this.uniformLoc(compiled, "uProgress"), args.progress);
|
|
275
|
+
gl.uniform2f(
|
|
276
|
+
this.uniformLoc(compiled, "uResolution"),
|
|
277
|
+
this.canvas.width,
|
|
278
|
+
this.canvas.height,
|
|
279
|
+
);
|
|
280
|
+
|
|
281
|
+
const merged = { ...transition.defaults, ...(args.params ?? {}) };
|
|
282
|
+
for (const key of Object.keys(merged)) {
|
|
283
|
+
const name = paramKeyToUniformName(key);
|
|
284
|
+
const loc = this.uniformLoc(compiled, name);
|
|
285
|
+
if (!loc) continue;
|
|
286
|
+
const value = (merged as Record<string, UniformValue>)[key];
|
|
287
|
+
if (value === undefined) continue;
|
|
288
|
+
this.setUniform(loc, value);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
if (compiled.mesh) {
|
|
292
|
+
this.renderMesh(compiled);
|
|
293
|
+
} else {
|
|
294
|
+
this.renderFullscreen(compiled, transition);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
private renderFullscreen<P extends UniformParams>(
|
|
299
|
+
compiled: CompiledTransition,
|
|
300
|
+
transition: Transition<P>,
|
|
301
|
+
): void {
|
|
302
|
+
const gl = this.gl;
|
|
303
|
+
gl.bindVertexArray(this.vao);
|
|
304
|
+
|
|
305
|
+
const passes = Math.max(1, Math.floor(transition.passes ?? 1));
|
|
306
|
+
const passLoc = this.uniformLoc(compiled, "uPass");
|
|
307
|
+
const passCountLoc = this.uniformLoc(compiled, "uPassCount");
|
|
308
|
+
const previousLoc = this.uniformLoc(compiled, "uPrevious");
|
|
309
|
+
const instancesLoc = this.uniformLoc(compiled, "uInstances");
|
|
310
|
+
if (passCountLoc) gl.uniform1i(passCountLoc, passes);
|
|
311
|
+
if (instancesLoc) gl.uniform1i(instancesLoc, 1);
|
|
312
|
+
|
|
313
|
+
const pingPong = passes > 1 ? this.fbPool.ensure(2, this.canvas.width, this.canvas.height) : undefined;
|
|
314
|
+
|
|
315
|
+
for (let i = 0; i < passes; i++) {
|
|
316
|
+
const isFinal = i === passes - 1;
|
|
317
|
+
|
|
318
|
+
// Destination: final pass renders to the canvas; intermediate
|
|
319
|
+
// passes ping-pong between pool slots 0 and 1.
|
|
320
|
+
if (isFinal || !pingPong) {
|
|
321
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
322
|
+
} else {
|
|
323
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, pingPong[i % 2]!.fb);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// uPrevious: at pass 0, bind the default black 1×1. Otherwise
|
|
327
|
+
// bind the FBO texture we just wrote on pass i-1.
|
|
328
|
+
let prevTex: WebGLTexture;
|
|
329
|
+
if (i === 0 || !pingPong) {
|
|
330
|
+
prevTex = this.defaultPrevious;
|
|
331
|
+
} else {
|
|
332
|
+
prevTex = pingPong[(i - 1) % 2]!.tex;
|
|
333
|
+
}
|
|
334
|
+
gl.activeTexture(gl.TEXTURE4);
|
|
335
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
336
|
+
if (previousLoc) gl.uniform1i(previousLoc, 4);
|
|
337
|
+
if (passLoc) gl.uniform1i(passLoc, i);
|
|
338
|
+
|
|
339
|
+
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
340
|
+
gl.clearColor(0, 0, 0, 0);
|
|
341
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
342
|
+
gl.drawArrays(gl.TRIANGLES, 0, 3);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Leave the canvas framebuffer bound for any subsequent draws.
|
|
346
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
347
|
+
gl.bindVertexArray(null);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
private renderMesh(compiled: CompiledTransition): void {
|
|
351
|
+
const gl = this.gl;
|
|
352
|
+
const mesh = compiled.mesh;
|
|
353
|
+
if (!mesh) return;
|
|
354
|
+
|
|
355
|
+
// Mesh path is single-pass in v1: passes is ignored. Report uPass=0,
|
|
356
|
+
// uPassCount=1 to the shader so uniform branches stay predictable.
|
|
357
|
+
const passLoc = this.uniformLoc(compiled, "uPass");
|
|
358
|
+
const passCountLoc = this.uniformLoc(compiled, "uPassCount");
|
|
359
|
+
const previousLoc = this.uniformLoc(compiled, "uPrevious");
|
|
360
|
+
const instancesLoc = this.uniformLoc(compiled, "uInstances");
|
|
361
|
+
if (passLoc) gl.uniform1i(passLoc, 0);
|
|
362
|
+
if (passCountLoc) gl.uniform1i(passCountLoc, 1);
|
|
363
|
+
if (instancesLoc) gl.uniform1i(instancesLoc, mesh.instances);
|
|
364
|
+
|
|
365
|
+
// Bind the default previous texture so uPrevious samples predictably.
|
|
366
|
+
gl.activeTexture(gl.TEXTURE4);
|
|
367
|
+
gl.bindTexture(gl.TEXTURE_2D, this.defaultPrevious);
|
|
368
|
+
if (previousLoc) gl.uniform1i(previousLoc, 4);
|
|
369
|
+
|
|
370
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
371
|
+
gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
372
|
+
gl.enable(gl.DEPTH_TEST);
|
|
373
|
+
gl.depthFunc(gl.LESS);
|
|
374
|
+
gl.enable(gl.BLEND);
|
|
375
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
376
|
+
gl.clearColor(0, 0, 0, 0);
|
|
377
|
+
gl.clearDepth(1);
|
|
378
|
+
gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT);
|
|
379
|
+
|
|
380
|
+
gl.bindVertexArray(mesh.vao);
|
|
381
|
+
gl.drawArraysInstanced(gl.TRIANGLES, 0, mesh.vertexCount, mesh.instances);
|
|
382
|
+
gl.bindVertexArray(null);
|
|
383
|
+
|
|
384
|
+
gl.disable(gl.DEPTH_TEST);
|
|
385
|
+
gl.disable(gl.BLEND);
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
/**
|
|
389
|
+
* Whether the underlying WebGL context is currently lost. While lost,
|
|
390
|
+
* `render()` throws; wait for the `onContextRestored` callback.
|
|
391
|
+
*/
|
|
392
|
+
get isContextLost(): boolean {
|
|
393
|
+
return this.contextLost;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Free every GPU resource the runner owns (default textures, VAO,
|
|
398
|
+
* compiled programs, framebuffers, texture cache) and detach the
|
|
399
|
+
* context-loss listeners. Idempotent; further `render()` calls throw.
|
|
400
|
+
*
|
|
401
|
+
* Call when the canvas is going away (component unmount, route change,
|
|
402
|
+
* etc.) — the WebGL context itself is freed by the canvas, but
|
|
403
|
+
* disposing here releases the in-process bookkeeping early and removes
|
|
404
|
+
* the canvas listeners so the runner can be GC'd.
|
|
405
|
+
*/
|
|
406
|
+
dispose(): void {
|
|
407
|
+
if (this.disposed) return;
|
|
408
|
+
this.disposed = true;
|
|
409
|
+
if (typeof EventTarget !== "undefined" && this.canvas instanceof EventTarget) {
|
|
410
|
+
this.canvas.removeEventListener("webglcontextlost", this.handleContextLost);
|
|
411
|
+
this.canvas.removeEventListener(
|
|
412
|
+
"webglcontextrestored",
|
|
413
|
+
this.handleContextRestored,
|
|
414
|
+
);
|
|
415
|
+
}
|
|
416
|
+
this.gl.deleteVertexArray(this.vao);
|
|
417
|
+
this.gl.deleteTexture(this.defaultDisplacement);
|
|
418
|
+
this.gl.deleteTexture(this.defaultEnvironment);
|
|
419
|
+
this.gl.deleteTexture(this.defaultPrevious);
|
|
420
|
+
this.fbPool.dispose();
|
|
421
|
+
this.textures.dispose();
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
private getOrCompile<P extends UniformParams>(
|
|
425
|
+
transition: Transition<P>,
|
|
426
|
+
): CompiledTransition {
|
|
427
|
+
const erased = transition as Transition<UniformParams>;
|
|
428
|
+
const existing = this.programs.get(erased);
|
|
429
|
+
if (existing) return existing;
|
|
430
|
+
|
|
431
|
+
const isMesh = transition.mesh !== undefined;
|
|
432
|
+
if (isMesh && transition.shader.vertex === undefined) {
|
|
433
|
+
throw new Error(
|
|
434
|
+
`Transition "${transition.name}" declares a mesh but has no vertex shader. ` +
|
|
435
|
+
"Mesh transitions must provide `vertex` source alongside `glsl`.",
|
|
436
|
+
);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
const fragmentSource = wrapFragmentShader(transition.shader.glsl);
|
|
440
|
+
const vertexSource = isMesh
|
|
441
|
+
? wrapMeshVertexShader(transition.shader.vertex as string)
|
|
442
|
+
: undefined;
|
|
443
|
+
|
|
444
|
+
let program: WebGLProgram;
|
|
445
|
+
try {
|
|
446
|
+
program = vertexSource
|
|
447
|
+
? buildProgram(this.gl, fragmentSource, vertexSource)
|
|
448
|
+
: buildProgram(this.gl, fragmentSource);
|
|
449
|
+
} catch (err) {
|
|
450
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
451
|
+
throw new Error(
|
|
452
|
+
`Transition "${transition.name}" failed to compile. ${message}`,
|
|
453
|
+
);
|
|
454
|
+
}
|
|
455
|
+
const compiled: CompiledTransition = { program, uniforms: new Map() };
|
|
456
|
+
if (isMesh) {
|
|
457
|
+
compiled.mesh = this.createMeshResources(program, transition.mesh!);
|
|
458
|
+
}
|
|
459
|
+
this.programs.set(erased, compiled);
|
|
460
|
+
return compiled;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
private createMeshResources(
|
|
464
|
+
program: WebGLProgram,
|
|
465
|
+
geometry: { subdivisions: readonly [number, number]; instances?: number },
|
|
466
|
+
): MeshResources {
|
|
467
|
+
const gl = this.gl;
|
|
468
|
+
const [nx, ny] = geometry.subdivisions;
|
|
469
|
+
const buffers = buildSubdividedPlane(nx, ny);
|
|
470
|
+
|
|
471
|
+
const vao = gl.createVertexArray();
|
|
472
|
+
if (!vao) throw new Error("gl.createVertexArray returned null");
|
|
473
|
+
gl.bindVertexArray(vao);
|
|
474
|
+
|
|
475
|
+
const glBuffers: WebGLBuffer[] = [];
|
|
476
|
+
for (const attr of MESH_ATTRIBS) {
|
|
477
|
+
const loc = gl.getAttribLocation(program, attr.name);
|
|
478
|
+
if (loc < 0) continue;
|
|
479
|
+
const buf = gl.createBuffer();
|
|
480
|
+
if (!buf) throw new Error("gl.createBuffer returned null");
|
|
481
|
+
glBuffers.push(buf);
|
|
482
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buf);
|
|
483
|
+
gl.bufferData(gl.ARRAY_BUFFER, buffers[attr.bufferKey], gl.STATIC_DRAW);
|
|
484
|
+
gl.enableVertexAttribArray(loc);
|
|
485
|
+
gl.vertexAttribPointer(loc, attr.size, gl.FLOAT, false, 0, 0);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
gl.bindVertexArray(null);
|
|
489
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, null);
|
|
490
|
+
|
|
491
|
+
return {
|
|
492
|
+
vao,
|
|
493
|
+
buffers: glBuffers,
|
|
494
|
+
vertexCount: buffers.vertexCount,
|
|
495
|
+
instances: Math.max(1, Math.floor(geometry.instances ?? 1)),
|
|
496
|
+
};
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
private uniformLoc(
|
|
500
|
+
compiled: CompiledTransition,
|
|
501
|
+
name: string,
|
|
502
|
+
): WebGLUniformLocation | null {
|
|
503
|
+
const cached = compiled.uniforms.get(name);
|
|
504
|
+
if (cached !== undefined) return cached;
|
|
505
|
+
const loc = this.gl.getUniformLocation(compiled.program, name);
|
|
506
|
+
compiled.uniforms.set(name, loc);
|
|
507
|
+
return loc;
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
private setUniform(
|
|
511
|
+
loc: WebGLUniformLocation,
|
|
512
|
+
value: UniformValue,
|
|
513
|
+
): void {
|
|
514
|
+
const gl = this.gl;
|
|
515
|
+
if (typeof value === "number") {
|
|
516
|
+
gl.uniform1f(loc, value);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
if (typeof value === "boolean") {
|
|
520
|
+
gl.uniform1i(loc, value ? 1 : 0);
|
|
521
|
+
return;
|
|
522
|
+
}
|
|
523
|
+
if (value.length === 2) gl.uniform2f(loc, value[0], value[1]);
|
|
524
|
+
else if (value.length === 3) gl.uniform3f(loc, value[0], value[1], value[2]);
|
|
525
|
+
else if (value.length === 4)
|
|
526
|
+
gl.uniform4f(loc, value[0], value[1], value[2], value[3]);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import type { Transition, UniformParams } from "../types.js";
|
|
2
|
+
|
|
3
|
+
import { bloomReveal } from "./bloom-reveal.js";
|
|
4
|
+
import { chromaticPulse } from "./chromatic-pulse.js";
|
|
5
|
+
import { clockWipe } from "./clock-wipe.js";
|
|
6
|
+
import { colorPhase } from "./color-phase.js";
|
|
7
|
+
import { crossZoom } from "./cross-zoom.js";
|
|
8
|
+
import { crosshatch } from "./crosshatch.js";
|
|
9
|
+
import { directionalBurn } from "./directional-burn.js";
|
|
10
|
+
import { directionalWarp } from "./directional-warp.js";
|
|
11
|
+
import { dissolve } from "./dissolve.js";
|
|
12
|
+
import { dreamy } from "./dreamy.js";
|
|
13
|
+
import { dreamyZoom } from "./dreamy-zoom.js";
|
|
14
|
+
import { dripWipe } from "./drip-wipe.js";
|
|
15
|
+
import { emberScatter } from "./ember-scatter.js";
|
|
16
|
+
import { filmBurn } from "./film-burn.js";
|
|
17
|
+
import { filmGrain } from "./film-grain.js";
|
|
18
|
+
import { flowWarp } from "./flow-warp.js";
|
|
19
|
+
import { fluidFlow } from "./fluid-flow.js";
|
|
20
|
+
import { glassShatter } from "./glass-shatter.js";
|
|
21
|
+
import { glitch } from "./glitch.js";
|
|
22
|
+
import { godRaysReveal } from "./god-rays-reveal.js";
|
|
23
|
+
import { gravityPull } from "./gravity-pull.js";
|
|
24
|
+
import { gridReveal } from "./grid-reveal.js";
|
|
25
|
+
import { heatHaze } from "./heat-haze.js";
|
|
26
|
+
import { inkBloom } from "./ink-bloom.js";
|
|
27
|
+
import { inkDiffuse } from "./ink-diffuse.js";
|
|
28
|
+
import { irisZoom } from "./iris-zoom.js";
|
|
29
|
+
import { kineticBands } from "./kinetic-bands.js";
|
|
30
|
+
import { lenticularFlip } from "./lenticular-flip.js";
|
|
31
|
+
import { lightLeak } from "./light-leak.js";
|
|
32
|
+
import { linearBlur } from "./linear-blur.js";
|
|
33
|
+
import { liquidChrome } from "./liquid-chrome.js";
|
|
34
|
+
import { liquidMorph } from "./liquid-morph.js";
|
|
35
|
+
import { luminaMelt } from "./lumina-melt.js";
|
|
36
|
+
import { mosaic } from "./mosaic.js";
|
|
37
|
+
import { noiseDissolve } from "./noise-dissolve.js";
|
|
38
|
+
import { pageCurl } from "./page-curl.js";
|
|
39
|
+
import { paintBleed } from "./paint-bleed.js";
|
|
40
|
+
import { pinwheel } from "./pinwheel.js";
|
|
41
|
+
import { pixelate } from "./pixelate.js";
|
|
42
|
+
import { polkaDotsCurtain } from "./polka-dots-curtain.js";
|
|
43
|
+
import { polygonFlip } from "./polygon-flip.js";
|
|
44
|
+
import { portalDive } from "./portal-dive.js";
|
|
45
|
+
import { prismSplit } from "./prism-split.js";
|
|
46
|
+
import { push } from "./push.js";
|
|
47
|
+
import { radialReveal } from "./radial-reveal.js";
|
|
48
|
+
import { ripple } from "./ripple.js";
|
|
49
|
+
import { rippleWave } from "./ripple-wave.js";
|
|
50
|
+
import { shapeReveal } from "./shape-reveal.js";
|
|
51
|
+
import { shockwave } from "./shockwave.js";
|
|
52
|
+
import { singularity } from "./singularity.js";
|
|
53
|
+
import { slide } from "./slide.js";
|
|
54
|
+
import { smolderingEdge } from "./smoldering-edge.js";
|
|
55
|
+
import { split } from "./split.js";
|
|
56
|
+
import { swirl } from "./swirl.js";
|
|
57
|
+
import { tangentMotionBlur } from "./tangent-motion-blur.js";
|
|
58
|
+
import { tileScatter } from "./tile-scatter.js";
|
|
59
|
+
import { warpZoom } from "./warp-zoom.js";
|
|
60
|
+
import { waveStripes } from "./wave-stripes.js";
|
|
61
|
+
import { wind } from "./wind.js";
|
|
62
|
+
import { wipeDirectional } from "./wipe-directional.js";
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Every built-in transition, in a single array. The catalog source of
|
|
66
|
+
* truth — counts, tests, and tooling read from here so they cannot
|
|
67
|
+
* drift from `transitions/index.ts`. Add new transitions here whenever
|
|
68
|
+
* you add them to the index re-exports.
|
|
69
|
+
*/
|
|
70
|
+
export const ALL_TRANSITIONS: readonly Transition<UniformParams>[] = [
|
|
71
|
+
bloomReveal,
|
|
72
|
+
chromaticPulse,
|
|
73
|
+
clockWipe,
|
|
74
|
+
colorPhase,
|
|
75
|
+
crossZoom,
|
|
76
|
+
crosshatch,
|
|
77
|
+
directionalBurn,
|
|
78
|
+
directionalWarp,
|
|
79
|
+
dissolve,
|
|
80
|
+
dreamy,
|
|
81
|
+
dreamyZoom,
|
|
82
|
+
dripWipe,
|
|
83
|
+
emberScatter,
|
|
84
|
+
filmBurn,
|
|
85
|
+
filmGrain,
|
|
86
|
+
flowWarp,
|
|
87
|
+
fluidFlow,
|
|
88
|
+
glassShatter,
|
|
89
|
+
glitch,
|
|
90
|
+
godRaysReveal,
|
|
91
|
+
gravityPull,
|
|
92
|
+
gridReveal,
|
|
93
|
+
heatHaze,
|
|
94
|
+
inkBloom,
|
|
95
|
+
inkDiffuse,
|
|
96
|
+
irisZoom,
|
|
97
|
+
kineticBands,
|
|
98
|
+
lenticularFlip,
|
|
99
|
+
lightLeak,
|
|
100
|
+
linearBlur,
|
|
101
|
+
liquidChrome,
|
|
102
|
+
liquidMorph,
|
|
103
|
+
luminaMelt,
|
|
104
|
+
mosaic,
|
|
105
|
+
noiseDissolve,
|
|
106
|
+
pageCurl,
|
|
107
|
+
paintBleed,
|
|
108
|
+
pinwheel,
|
|
109
|
+
pixelate,
|
|
110
|
+
polkaDotsCurtain,
|
|
111
|
+
polygonFlip,
|
|
112
|
+
portalDive,
|
|
113
|
+
prismSplit,
|
|
114
|
+
push,
|
|
115
|
+
radialReveal,
|
|
116
|
+
ripple,
|
|
117
|
+
rippleWave,
|
|
118
|
+
shapeReveal,
|
|
119
|
+
shockwave,
|
|
120
|
+
singularity,
|
|
121
|
+
slide,
|
|
122
|
+
smolderingEdge,
|
|
123
|
+
split,
|
|
124
|
+
swirl,
|
|
125
|
+
tangentMotionBlur,
|
|
126
|
+
tileScatter,
|
|
127
|
+
warpZoom,
|
|
128
|
+
waveStripes,
|
|
129
|
+
wind,
|
|
130
|
+
wipeDirectional,
|
|
131
|
+
] as const;
|