@smoove/transitions 0.1.1
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 +55 -0
- package/dist/gl/compositor.d.ts +67 -0
- package/dist/gl/compositor.d.ts.map +1 -0
- package/dist/gl/compositor.js +147 -0
- package/dist/gl/compositor.js.map +1 -0
- package/dist/gl/gl-transition.d.ts +8 -0
- package/dist/gl/gl-transition.d.ts.map +1 -0
- package/dist/gl/gl-transition.js +9 -0
- package/dist/gl/gl-transition.js.map +1 -0
- package/dist/gl/shared.d.ts +10 -0
- package/dist/gl/shared.d.ts.map +1 -0
- package/dist/gl/shared.js +56 -0
- package/dist/gl/shared.js.map +1 -0
- package/dist/gl/transpile.d.ts +16 -0
- package/dist/gl/transpile.d.ts.map +1 -0
- package/dist/gl/transpile.js +29 -0
- package/dist/gl/transpile.js.map +1 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/presentations/book-flip.d.ts +8 -0
- package/dist/presentations/book-flip.d.ts.map +1 -0
- package/dist/presentations/book-flip.js +124 -0
- package/dist/presentations/book-flip.js.map +1 -0
- package/dist/presentations/clock-wipe.d.ts +12 -0
- package/dist/presentations/clock-wipe.d.ts.map +1 -0
- package/dist/presentations/clock-wipe.js +27 -0
- package/dist/presentations/clock-wipe.js.map +1 -0
- package/dist/presentations/cross-zoom.d.ts +7 -0
- package/dist/presentations/cross-zoom.d.ts.map +1 -0
- package/dist/presentations/cross-zoom.js +80 -0
- package/dist/presentations/cross-zoom.js.map +1 -0
- package/dist/presentations/crosswarp.d.ts +5 -0
- package/dist/presentations/crosswarp.d.ts.map +1 -0
- package/dist/presentations/crosswarp.js +32 -0
- package/dist/presentations/crosswarp.js.map +1 -0
- package/dist/presentations/dissolve.d.ts +11 -0
- package/dist/presentations/dissolve.d.ts.map +1 -0
- package/dist/presentations/dissolve.js +69 -0
- package/dist/presentations/dissolve.js.map +1 -0
- package/dist/presentations/dreamy-zoom.d.ts +8 -0
- package/dist/presentations/dreamy-zoom.d.ts.map +1 -0
- package/dist/presentations/dreamy-zoom.js +52 -0
- package/dist/presentations/dreamy-zoom.js.map +1 -0
- package/dist/presentations/fade.d.ts +9 -0
- package/dist/presentations/fade.d.ts.map +1 -0
- package/dist/presentations/fade.js +17 -0
- package/dist/presentations/fade.js.map +1 -0
- package/dist/presentations/film-burn.d.ts +7 -0
- package/dist/presentations/film-burn.d.ts.map +1 -0
- package/dist/presentations/film-burn.js +146 -0
- package/dist/presentations/film-burn.js.map +1 -0
- package/dist/presentations/flip.d.ts +13 -0
- package/dist/presentations/flip.d.ts.map +1 -0
- package/dist/presentations/flip.js +39 -0
- package/dist/presentations/flip.js.map +1 -0
- package/dist/presentations/index.d.ts +19 -0
- package/dist/presentations/index.d.ts.map +1 -0
- package/dist/presentations/index.js +21 -0
- package/dist/presentations/index.js.map +1 -0
- package/dist/presentations/iris.d.ts +12 -0
- package/dist/presentations/iris.d.ts.map +1 -0
- package/dist/presentations/iris.js +21 -0
- package/dist/presentations/iris.js.map +1 -0
- package/dist/presentations/linear-blur.d.ts +7 -0
- package/dist/presentations/linear-blur.d.ts.map +1 -0
- package/dist/presentations/linear-blur.js +47 -0
- package/dist/presentations/linear-blur.js.map +1 -0
- package/dist/presentations/none.d.ts +8 -0
- package/dist/presentations/none.d.ts.map +1 -0
- package/dist/presentations/none.js +12 -0
- package/dist/presentations/none.js.map +1 -0
- package/dist/presentations/ripple.d.ts +8 -0
- package/dist/presentations/ripple.d.ts.map +1 -0
- package/dist/presentations/ripple.js +39 -0
- package/dist/presentations/ripple.js.map +1 -0
- package/dist/presentations/slide.d.ts +11 -0
- package/dist/presentations/slide.d.ts.map +1 -0
- package/dist/presentations/slide.js +43 -0
- package/dist/presentations/slide.js.map +1 -0
- package/dist/presentations/swap.d.ts +9 -0
- package/dist/presentations/swap.d.ts.map +1 -0
- package/dist/presentations/swap.js +95 -0
- package/dist/presentations/swap.js.map +1 -0
- package/dist/presentations/wipe.d.ts +12 -0
- package/dist/presentations/wipe.d.ts.map +1 -0
- package/dist/presentations/wipe.js +31 -0
- package/dist/presentations/wipe.js.map +1 -0
- package/dist/presentations/zoom-blur.d.ts +7 -0
- package/dist/presentations/zoom-blur.d.ts.map +1 -0
- package/dist/presentations/zoom-blur.js +69 -0
- package/dist/presentations/zoom-blur.js.map +1 -0
- package/dist/presentations/zoom-in-out.d.ts +5 -0
- package/dist/presentations/zoom-in-out.d.ts.map +1 -0
- package/dist/presentations/zoom-in-out.js +33 -0
- package/dist/presentations/zoom-in-out.js.map +1 -0
- package/dist/timings/index.d.ts +4 -0
- package/dist/timings/index.d.ts.map +1 -0
- package/dist/timings/index.js +4 -0
- package/dist/timings/index.js.map +1 -0
- package/dist/timings/linear-timing.d.ts +12 -0
- package/dist/timings/linear-timing.d.ts.map +1 -0
- package/dist/timings/linear-timing.js +20 -0
- package/dist/timings/linear-timing.js.map +1 -0
- package/dist/timings/spring/index.d.ts +19 -0
- package/dist/timings/spring/index.d.ts.map +1 -0
- package/dist/timings/spring/index.js +30 -0
- package/dist/timings/spring/index.js.map +1 -0
- package/dist/timings/spring/measure-spring.d.ts +12 -0
- package/dist/timings/spring/measure-spring.d.ts.map +1 -0
- package/dist/timings/spring/measure-spring.js +37 -0
- package/dist/timings/spring/measure-spring.js.map +1 -0
- package/dist/timings/spring/spring-utils.d.ts +20 -0
- package/dist/timings/spring/spring-utils.d.ts.map +1 -0
- package/dist/timings/spring/spring-utils.js +65 -0
- package/dist/timings/spring/spring-utils.js.map +1 -0
- package/dist/timings/spring-timing.d.ts +16 -0
- package/dist/timings/spring-timing.d.ts.map +1 -0
- package/dist/timings/spring-timing.js +28 -0
- package/dist/timings/spring-timing.js.map +1 -0
- package/dist/transition-series.d.ts +52 -0
- package/dist/transition-series.d.ts.map +1 -0
- package/dist/transition-series.js +217 -0
- package/dist/transition-series.js.map +1 -0
- package/dist/types.d.ts +40 -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 +38 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 shemi
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @smoove/transitions
|
|
2
|
+
|
|
3
|
+
Scene transitions for [smoove](https://smoove.dev) — blend one scene into
|
|
4
|
+
the next with cross-fades, slides, wipes, and WebGL shader effects.
|
|
5
|
+
|
|
6
|
+
A transition overlaps the end of one scene with the start of the next while
|
|
7
|
+
a **presentation** mixes them. You build them with `TransitionSeries`, which
|
|
8
|
+
plays scenes in order and overlaps each pair where they meet; `comp.add(series)`
|
|
9
|
+
expands the whole thing into one `Sequence` per scene.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
pnpm add konva @smoove/core @smoove/transitions
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`konva` and `@smoove/core` are peer dependencies.
|
|
18
|
+
|
|
19
|
+
## Quick example
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
import { Composition } from "@smoove/core";
|
|
23
|
+
import { fade, linearTiming, TransitionSeries } from "@smoove/transitions";
|
|
24
|
+
|
|
25
|
+
const comp = new Composition({ id: "intro", fps: 60, durationInFrames: 200, width: 1280, height: 720 });
|
|
26
|
+
|
|
27
|
+
const series = new TransitionSeries({ composition: comp });
|
|
28
|
+
series.scene({ durationInFrames: 80 }, (seq) => seq.add(sceneA));
|
|
29
|
+
series.transition({ presentation: fade(), timing: linearTiming({ durationInFrames: 20 }) });
|
|
30
|
+
series.scene({ durationInFrames: 80 }, (seq) => seq.add(sceneB));
|
|
31
|
+
|
|
32
|
+
comp.add(series);
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Presentations
|
|
36
|
+
|
|
37
|
+
**Geometric** — run on Konva transforms, work everywhere the player does and
|
|
38
|
+
render headlessly with no extra setup: `fade`, `slide`, `wipe`, `clockWipe`,
|
|
39
|
+
`iris`, `flip`, `none`.
|
|
40
|
+
|
|
41
|
+
**Shader** — run on WebGL2 fragment shaders in the browser and fall back to
|
|
42
|
+
`fade()` without it: `dissolve`, `crosswarp`, `crossZoom`, and more. To
|
|
43
|
+
render them headlessly, import `@smoove/renderer/gl` before building the
|
|
44
|
+
composition.
|
|
45
|
+
|
|
46
|
+
Two timings drive any presentation: `linearTiming` and `springTiming`.
|
|
47
|
+
|
|
48
|
+
## Docs
|
|
49
|
+
|
|
50
|
+
Full documentation, including the complete presentation catalog, lives at
|
|
51
|
+
[smoove.dev](https://smoove.dev).
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { GlUniforms } from "../types.js";
|
|
2
|
+
import { type GlContext } from "./shared.js";
|
|
3
|
+
type CanvasImage = HTMLCanvasElement | OffscreenCanvas;
|
|
4
|
+
/**
|
|
5
|
+
* A rendering backend for the compositor. The DOM and Node (skia + headless-gl)
|
|
6
|
+
* environments share all the WebGL plumbing but differ in three places: which
|
|
7
|
+
* GLSL dialect the program is compiled in, how a captured scene canvas is
|
|
8
|
+
* uploaded into a texture, and how the drawn frame is handed back to Konva.
|
|
9
|
+
*/
|
|
10
|
+
export interface GlPlatform {
|
|
11
|
+
/** The (WebGL1 or WebGL2) context the compositor draws into. */
|
|
12
|
+
readonly gl: GlContext;
|
|
13
|
+
/** Vertex shader matching this platform's GLSL dialect. */
|
|
14
|
+
readonly vertexShader: string;
|
|
15
|
+
/** Adapt a `#version 300 es` fragment to this platform's dialect (identity on WebGL2). */
|
|
16
|
+
prepareFragment(fragment: string): string;
|
|
17
|
+
/** Resize the backing draw buffer before a frame. */
|
|
18
|
+
resize(width: number, height: number): void;
|
|
19
|
+
/**
|
|
20
|
+
* Upload `source` into the currently bound `TEXTURE_2D` (the compositor has
|
|
21
|
+
* already selected the texture unit and bound the texture).
|
|
22
|
+
*/
|
|
23
|
+
uploadScene(source: CanvasImage, width: number, height: number): void;
|
|
24
|
+
/**
|
|
25
|
+
* After `drawArrays`, return an image Konva can draw (reused across calls —
|
|
26
|
+
* copy/draw it immediately).
|
|
27
|
+
*/
|
|
28
|
+
result(width: number, height: number): CanvasImageSource;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* One shared WebGL surface that runs any Tier B fragment shader over two
|
|
32
|
+
* captured scene canvases. `u_prev` is bound to the **incoming** scene and
|
|
33
|
+
* `u_next` to the **outgoing** scene (Remotion's inverted binding); `u_time` is
|
|
34
|
+
* the transition progress. Pure in `(progress, textures)` → reproducible.
|
|
35
|
+
*
|
|
36
|
+
* The actual GL surface is supplied by a {@link GlPlatform}: a DOM/WebGL2
|
|
37
|
+
* backend in the browser, or a headless-gl/skia backend during server
|
|
38
|
+
* rendering (see `@smoove/renderer/gl`).
|
|
39
|
+
*/
|
|
40
|
+
export declare class GlCompositor {
|
|
41
|
+
private readonly platform;
|
|
42
|
+
private readonly gl;
|
|
43
|
+
private readonly prevTex;
|
|
44
|
+
private readonly nextTex;
|
|
45
|
+
private readonly programs;
|
|
46
|
+
private constructor();
|
|
47
|
+
/** Wrap a custom backend (e.g. the Node headless-gl platform). */
|
|
48
|
+
static fromPlatform(platform: GlPlatform): GlCompositor;
|
|
49
|
+
/** Create a DOM/WebGL2 compositor, or `null` when no WebGL2 context is available. */
|
|
50
|
+
static create(): GlCompositor | null;
|
|
51
|
+
private getEntry;
|
|
52
|
+
/**
|
|
53
|
+
* Render the blended frame and return an image to draw (reused across calls —
|
|
54
|
+
* copy/draw it immediately).
|
|
55
|
+
*/
|
|
56
|
+
render(fragment: string, incoming: CanvasImage, outgoing: CanvasImage, progress: number, uniforms: GlUniforms, width: number, height: number): CanvasImageSource;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Override how the shared compositor is created — used by server renderers to
|
|
60
|
+
* inject a headless GL backend. Clears any memoized compositor so the next
|
|
61
|
+
* {@link getCompositor} call rebuilds. Call before building a `TransitionSeries`.
|
|
62
|
+
*/
|
|
63
|
+
export declare function setCompositorFactory(create: (() => GlCompositor | null) | null): void;
|
|
64
|
+
/** Lazily create (and memoize) the shared compositor; `null` if unavailable. */
|
|
65
|
+
export declare function getCompositor(): GlCompositor | null;
|
|
66
|
+
export {};
|
|
67
|
+
//# sourceMappingURL=compositor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compositor.d.ts","sourceRoot":"","sources":["../../src/gl/compositor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,EAAgC,KAAK,SAAS,EAAiB,MAAM,aAAa,CAAC;AAE1F,KAAK,WAAW,GAAG,iBAAiB,GAAG,eAAe,CAAC;AAUvD;;;;;GAKG;AACH,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,0FAA0F;IAC1F,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;IAC1C,qDAAqD;IACrD,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5C;;;OAGG;IACH,WAAW,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtE;;;OAGG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,iBAAiB,CAAC;CAC1D;AAED;;;;;;;;;GASG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAY;IAC/B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAe;IACvC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAmC;IAE5D,OAAO;IAYP,kEAAkE;IAClE,MAAM,CAAC,YAAY,CAAC,QAAQ,EAAE,UAAU,GAAG,YAAY;IAIvD,qFAAqF;IACrF,MAAM,CAAC,MAAM,IAAI,YAAY,GAAG,IAAI;IA2BpC,OAAO,CAAC,QAAQ;IAyBhB;;;OAGG;IACH,MAAM,CACJ,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,UAAU,EACpB,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GACb,iBAAiB;CAmDrB;AAKD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,CAAC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,IAAI,GAAG,IAAI,CAGrF;AAED,gFAAgF;AAChF,wBAAgB,aAAa,IAAI,YAAY,GAAG,IAAI,CAGnD"}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { createProgram, createTexture, VERTEX_SHADER } from "./shared.js";
|
|
2
|
+
/**
|
|
3
|
+
* One shared WebGL surface that runs any Tier B fragment shader over two
|
|
4
|
+
* captured scene canvases. `u_prev` is bound to the **incoming** scene and
|
|
5
|
+
* `u_next` to the **outgoing** scene (Remotion's inverted binding); `u_time` is
|
|
6
|
+
* the transition progress. Pure in `(progress, textures)` → reproducible.
|
|
7
|
+
*
|
|
8
|
+
* The actual GL surface is supplied by a {@link GlPlatform}: a DOM/WebGL2
|
|
9
|
+
* backend in the browser, or a headless-gl/skia backend during server
|
|
10
|
+
* rendering (see `@smoove/renderer/gl`).
|
|
11
|
+
*/
|
|
12
|
+
export class GlCompositor {
|
|
13
|
+
platform;
|
|
14
|
+
gl;
|
|
15
|
+
prevTex;
|
|
16
|
+
nextTex;
|
|
17
|
+
programs = new Map();
|
|
18
|
+
constructor(platform) {
|
|
19
|
+
this.platform = platform;
|
|
20
|
+
this.gl = platform.gl;
|
|
21
|
+
const gl = this.gl;
|
|
22
|
+
const buffer = gl.createBuffer();
|
|
23
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
24
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
25
|
+
this.prevTex = createTexture(gl);
|
|
26
|
+
this.nextTex = createTexture(gl);
|
|
27
|
+
}
|
|
28
|
+
/** Wrap a custom backend (e.g. the Node headless-gl platform). */
|
|
29
|
+
static fromPlatform(platform) {
|
|
30
|
+
return new GlCompositor(platform);
|
|
31
|
+
}
|
|
32
|
+
/** Create a DOM/WebGL2 compositor, or `null` when no WebGL2 context is available. */
|
|
33
|
+
static create() {
|
|
34
|
+
if (typeof document === "undefined")
|
|
35
|
+
return null;
|
|
36
|
+
let canvas;
|
|
37
|
+
try {
|
|
38
|
+
canvas = document.createElement("canvas");
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
const gl = canvas.getContext("webgl2", { premultipliedAlpha: true });
|
|
44
|
+
if (!gl)
|
|
45
|
+
return null;
|
|
46
|
+
return new GlCompositor({
|
|
47
|
+
gl,
|
|
48
|
+
vertexShader: VERTEX_SHADER,
|
|
49
|
+
prepareFragment: (fragment) => fragment,
|
|
50
|
+
resize(width, height) {
|
|
51
|
+
if (canvas.width !== width)
|
|
52
|
+
canvas.width = width;
|
|
53
|
+
if (canvas.height !== height)
|
|
54
|
+
canvas.height = height;
|
|
55
|
+
},
|
|
56
|
+
uploadScene(source) {
|
|
57
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
58
|
+
},
|
|
59
|
+
result() {
|
|
60
|
+
return canvas;
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
getEntry(fragment, extraNames) {
|
|
65
|
+
let entry = this.programs.get(fragment);
|
|
66
|
+
if (!entry) {
|
|
67
|
+
const program = createProgram(this.gl, this.platform.prepareFragment(fragment), this.platform.vertexShader);
|
|
68
|
+
entry = {
|
|
69
|
+
program,
|
|
70
|
+
uTime: this.gl.getUniformLocation(program, "u_time"),
|
|
71
|
+
uPrev: this.gl.getUniformLocation(program, "u_prev"),
|
|
72
|
+
uNext: this.gl.getUniformLocation(program, "u_next"),
|
|
73
|
+
extra: new Map(),
|
|
74
|
+
};
|
|
75
|
+
this.programs.set(fragment, entry);
|
|
76
|
+
}
|
|
77
|
+
for (const name of extraNames) {
|
|
78
|
+
if (!entry.extra.has(name)) {
|
|
79
|
+
entry.extra.set(name, this.gl.getUniformLocation(entry.program, name));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return entry;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Render the blended frame and return an image to draw (reused across calls —
|
|
86
|
+
* copy/draw it immediately).
|
|
87
|
+
*/
|
|
88
|
+
render(fragment, incoming, outgoing, progress, uniforms, width, height) {
|
|
89
|
+
const gl = this.gl;
|
|
90
|
+
this.platform.resize(width, height);
|
|
91
|
+
const extraNames = Object.keys(uniforms);
|
|
92
|
+
const entry = this.getEntry(fragment, extraNames);
|
|
93
|
+
gl.viewport(0, 0, width, height);
|
|
94
|
+
gl.clearColor(0, 0, 0, 0);
|
|
95
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
96
|
+
gl.useProgram(entry.program);
|
|
97
|
+
const aPos = gl.getAttribLocation(entry.program, "a_pos");
|
|
98
|
+
gl.enableVertexAttribArray(aPos);
|
|
99
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
100
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
101
|
+
gl.bindTexture(gl.TEXTURE_2D, this.prevTex);
|
|
102
|
+
this.platform.uploadScene(incoming, width, height);
|
|
103
|
+
gl.uniform1i(entry.uPrev, 0);
|
|
104
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
105
|
+
gl.bindTexture(gl.TEXTURE_2D, this.nextTex);
|
|
106
|
+
this.platform.uploadScene(outgoing, width, height);
|
|
107
|
+
gl.uniform1i(entry.uNext, 1);
|
|
108
|
+
gl.uniform1f(entry.uTime, progress);
|
|
109
|
+
for (const [name, value] of Object.entries(uniforms)) {
|
|
110
|
+
const loc = entry.extra.get(name) ?? null;
|
|
111
|
+
if (loc === null)
|
|
112
|
+
continue;
|
|
113
|
+
if (typeof value === "number") {
|
|
114
|
+
gl.uniform1f(loc, value);
|
|
115
|
+
}
|
|
116
|
+
else if (value.length === 2) {
|
|
117
|
+
gl.uniform2f(loc, value[0], value[1]);
|
|
118
|
+
}
|
|
119
|
+
else if (value.length === 3) {
|
|
120
|
+
gl.uniform3f(loc, value[0], value[1], value[2]);
|
|
121
|
+
}
|
|
122
|
+
else if (value.length === 4) {
|
|
123
|
+
gl.uniform4f(loc, value[0], value[1], value[2], value[3]);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
127
|
+
return this.platform.result(width, height);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
let cached;
|
|
131
|
+
let factory = null;
|
|
132
|
+
/**
|
|
133
|
+
* Override how the shared compositor is created — used by server renderers to
|
|
134
|
+
* inject a headless GL backend. Clears any memoized compositor so the next
|
|
135
|
+
* {@link getCompositor} call rebuilds. Call before building a `TransitionSeries`.
|
|
136
|
+
*/
|
|
137
|
+
export function setCompositorFactory(create) {
|
|
138
|
+
factory = create;
|
|
139
|
+
cached = undefined;
|
|
140
|
+
}
|
|
141
|
+
/** Lazily create (and memoize) the shared compositor; `null` if unavailable. */
|
|
142
|
+
export function getCompositor() {
|
|
143
|
+
if (cached === undefined)
|
|
144
|
+
cached = factory ? factory() : GlCompositor.create();
|
|
145
|
+
return cached;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=compositor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compositor.js","sourceRoot":"","sources":["../../src/gl/compositor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { GlUniforms, Presentation, PresentationDims } from "../types.js";
|
|
2
|
+
/**
|
|
3
|
+
* Wrap a fragment shader (+ optional per-effect uniforms) into a Tier B
|
|
4
|
+
* `Presentation`. The shared GL compositor supplies `u_time`/`u_prev`/`u_next`;
|
|
5
|
+
* `uniforms` returns everything else this shader needs for the frame.
|
|
6
|
+
*/
|
|
7
|
+
export declare function glTransition(fragment: string, uniforms?: (progress: number, dims: PresentationDims) => GlUniforms): Presentation;
|
|
8
|
+
//# sourceMappingURL=gl-transition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gl-transition.d.ts","sourceRoot":"","sources":["../../src/gl/gl-transition.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAE9E;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,QAAQ,EAAE,MAAM,EAChB,QAAQ,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,gBAAgB,KAAK,UAAU,GAClE,YAAY,CAEd"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wrap a fragment shader (+ optional per-effect uniforms) into a Tier B
|
|
3
|
+
* `Presentation`. The shared GL compositor supplies `u_time`/`u_prev`/`u_next`;
|
|
4
|
+
* `uniforms` returns everything else this shader needs for the frame.
|
|
5
|
+
*/
|
|
6
|
+
export function glTransition(fragment, uniforms) {
|
|
7
|
+
return { gl: { fragment, uniforms } };
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=gl-transition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gl-transition.js","sourceRoot":"","sources":["../../src/gl/gl-transition.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC1B,QAAgB,EAChB,QAAmE;IAEnE,OAAO,EAAE,EAAE,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** A WebGL1 or WebGL2 context — the compositor only uses the shared subset. */
|
|
2
|
+
export type GlContext = WebGLRenderingContext | WebGL2RenderingContext;
|
|
3
|
+
/** Full-screen quad. `v_uv` is Y-flipped so screen-top samples texture-top. */
|
|
4
|
+
export declare const VERTEX_SHADER = "#version 300 es\nin vec2 a_pos;\nout vec2 v_uv;\nvoid main() {\n\tv_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);\n\tgl_Position = vec4(a_pos, 0.0, 1.0);\n}";
|
|
5
|
+
/** GLSL ES 1.00 twin of {@link VERTEX_SHADER} for WebGL1 contexts. */
|
|
6
|
+
export declare const VERTEX_SHADER_100 = "attribute vec2 a_pos;\nvarying vec2 v_uv;\nvoid main() {\n\tv_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);\n\tgl_Position = vec4(a_pos, 0.0, 1.0);\n}";
|
|
7
|
+
export declare function compileShader(gl: GlContext, source: string, type: number): WebGLShader;
|
|
8
|
+
export declare function createProgram(gl: GlContext, fragment: string, vertex?: string): WebGLProgram;
|
|
9
|
+
export declare function createTexture(gl: GlContext): WebGLTexture;
|
|
10
|
+
//# sourceMappingURL=shared.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../src/gl/shared.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,MAAM,SAAS,GAAG,qBAAqB,GAAG,sBAAsB,CAAC;AAEvE,+EAA+E;AAC/E,eAAO,MAAM,aAAa,wKAMxB,CAAC;AAEH,sEAAsE;AACtE,eAAO,MAAM,iBAAiB,kKAK5B,CAAC;AAEH,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAWtF;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,SAAS,EACb,QAAQ,EAAE,MAAM,EAChB,MAAM,GAAE,MAAsB,GAC7B,YAAY,CAcd;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,SAAS,GAAG,YAAY,CASzD"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/** Full-screen quad. `v_uv` is Y-flipped so screen-top samples texture-top. */
|
|
2
|
+
export const VERTEX_SHADER = `#version 300 es
|
|
3
|
+
in vec2 a_pos;
|
|
4
|
+
out vec2 v_uv;
|
|
5
|
+
void main() {
|
|
6
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
7
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
8
|
+
}`;
|
|
9
|
+
/** GLSL ES 1.00 twin of {@link VERTEX_SHADER} for WebGL1 contexts. */
|
|
10
|
+
export const VERTEX_SHADER_100 = `attribute vec2 a_pos;
|
|
11
|
+
varying vec2 v_uv;
|
|
12
|
+
void main() {
|
|
13
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
14
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
15
|
+
}`;
|
|
16
|
+
export function compileShader(gl, source, type) {
|
|
17
|
+
const shader = gl.createShader(type);
|
|
18
|
+
if (!shader)
|
|
19
|
+
throw new Error("transitions: failed to create shader");
|
|
20
|
+
gl.shaderSource(shader, source);
|
|
21
|
+
gl.compileShader(shader);
|
|
22
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
23
|
+
const log = gl.getShaderInfoLog(shader);
|
|
24
|
+
gl.deleteShader(shader);
|
|
25
|
+
throw new Error(`transitions: failed to compile shader: ${log}`);
|
|
26
|
+
}
|
|
27
|
+
return shader;
|
|
28
|
+
}
|
|
29
|
+
export function createProgram(gl, fragment, vertex = VERTEX_SHADER) {
|
|
30
|
+
const program = gl.createProgram();
|
|
31
|
+
if (!program)
|
|
32
|
+
throw new Error("transitions: failed to create WebGL program");
|
|
33
|
+
const vs = compileShader(gl, vertex, gl.VERTEX_SHADER);
|
|
34
|
+
const fs = compileShader(gl, fragment, gl.FRAGMENT_SHADER);
|
|
35
|
+
gl.attachShader(program, vs);
|
|
36
|
+
gl.attachShader(program, fs);
|
|
37
|
+
gl.linkProgram(program);
|
|
38
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
39
|
+
const log = gl.getProgramInfoLog(program);
|
|
40
|
+
gl.deleteProgram(program);
|
|
41
|
+
throw new Error(`transitions: failed to link program: ${log}`);
|
|
42
|
+
}
|
|
43
|
+
return program;
|
|
44
|
+
}
|
|
45
|
+
export function createTexture(gl) {
|
|
46
|
+
const tex = gl.createTexture();
|
|
47
|
+
if (!tex)
|
|
48
|
+
throw new Error("transitions: failed to create texture");
|
|
49
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
50
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
51
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
52
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
53
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
54
|
+
return tex;
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared.js","sourceRoot":"","sources":["../../src/gl/shared.ts"],"names":[],"mappings":"AAGA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,aAAa,GAAG;;;;;;EAM3B,CAAC;AAEH,sEAAsE;AACtE,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;EAK/B,CAAC;AAEH,MAAM,UAAU,aAAa,CAAC,EAAa,EAAE,MAAc,EAAE,IAAY;IACvE,MAAM,MAAM,GAAG,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;IACrE,EAAE,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,EAAE,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC;IACzB,IAAI,CAAC,EAAE,CAAC,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,CAAC;QACtD,MAAM,GAAG,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAC;QACxC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAC3B,EAAa,EACb,QAAgB,EAChB,SAAiB,aAAa;IAE9B,MAAM,OAAO,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IACnC,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,6CAA6C,CAAC,CAAC;IAC7E,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;IACvD,MAAM,EAAE,GAAG,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC;IAC3D,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7B,EAAE,CAAC,YAAY,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IAC7B,EAAE,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;IACxB,IAAI,CAAC,EAAE,CAAC,mBAAmB,CAAC,OAAO,EAAE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC;QACrD,MAAM,GAAG,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAC1C,EAAE,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC;QAC1B,MAAM,IAAI,KAAK,CAAC,wCAAwC,GAAG,EAAE,CAAC,CAAC;IACjE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,EAAa;IACzC,MAAM,GAAG,GAAG,EAAE,CAAC,aAAa,EAAE,CAAC;IAC/B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IACnE,EAAE,CAAC,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;IACnC,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,cAAc,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC;IACrE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAClE,EAAE,CAAC,aAAa,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,CAAC,kBAAkB,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC;IAClE,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanically downgrade a GLSL ES 3.00 (`#version 300 es`) fragment shader —
|
|
3
|
+
* the form every Tier B presentation is authored in — to GLSL ES 1.00, so it
|
|
4
|
+
* can run on a WebGL 1 context (e.g. `headless-gl` during server rendering,
|
|
5
|
+
* which has no WebGL2). The presentations follow a single, regular pattern:
|
|
6
|
+
*
|
|
7
|
+
* - `#version 300 es` → removed (1.00 has no version directive)
|
|
8
|
+
* - `out vec4 <name>;` → removed; writes to `<name>` become `gl_FragColor`
|
|
9
|
+
* - `in <type> <name>;` → `varying <type> <name>;`
|
|
10
|
+
* - `texture(s, uv)` → `texture2D(s, uv)`
|
|
11
|
+
*
|
|
12
|
+
* Paired with {@link VERTEX_SHADER_100}. Kept deliberately string-based (no real
|
|
13
|
+
* GLSL parse) — it only needs to cover the shapes in `presentations/`.
|
|
14
|
+
*/
|
|
15
|
+
export declare function transpileTo100(fragment: string): string;
|
|
16
|
+
//# sourceMappingURL=transpile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transpile.d.ts","sourceRoot":"","sources":["../../src/gl/transpile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAavD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mechanically downgrade a GLSL ES 3.00 (`#version 300 es`) fragment shader —
|
|
3
|
+
* the form every Tier B presentation is authored in — to GLSL ES 1.00, so it
|
|
4
|
+
* can run on a WebGL 1 context (e.g. `headless-gl` during server rendering,
|
|
5
|
+
* which has no WebGL2). The presentations follow a single, regular pattern:
|
|
6
|
+
*
|
|
7
|
+
* - `#version 300 es` → removed (1.00 has no version directive)
|
|
8
|
+
* - `out vec4 <name>;` → removed; writes to `<name>` become `gl_FragColor`
|
|
9
|
+
* - `in <type> <name>;` → `varying <type> <name>;`
|
|
10
|
+
* - `texture(s, uv)` → `texture2D(s, uv)`
|
|
11
|
+
*
|
|
12
|
+
* Paired with {@link VERTEX_SHADER_100}. Kept deliberately string-based (no real
|
|
13
|
+
* GLSL parse) — it only needs to cover the shapes in `presentations/`.
|
|
14
|
+
*/
|
|
15
|
+
export function transpileTo100(fragment) {
|
|
16
|
+
// Capture the fragment-output name so its writes can be rewired to gl_FragColor.
|
|
17
|
+
const outMatch = fragment.match(/\bout\s+vec4\s+(\w+)\s*;/);
|
|
18
|
+
const outName = outMatch?.[1];
|
|
19
|
+
let src = fragment
|
|
20
|
+
.replace(/#version\s+300\s+es[^\n]*\n/, "")
|
|
21
|
+
.replace(/\bout\s+vec4\s+\w+\s*;\s*/g, "")
|
|
22
|
+
.replace(/\bin\s+(vec[234]|float|int)\b/g, "varying $1")
|
|
23
|
+
.replace(/\btexture\s*\(/g, "texture2D(");
|
|
24
|
+
if (outName) {
|
|
25
|
+
src = src.replace(new RegExp(`\\b${outName}\\b`, "g"), "gl_FragColor");
|
|
26
|
+
}
|
|
27
|
+
return src;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=transpile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transpile.js","sourceRoot":"","sources":["../../src/gl/transpile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,iFAAiF;IACjF,MAAM,QAAQ,GAAG,QAAQ,CAAC,KAAK,CAAC,0BAA0B,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9B,IAAI,GAAG,GAAG,QAAQ;SACf,OAAO,CAAC,6BAA6B,EAAE,EAAE,CAAC;SAC1C,OAAO,CAAC,4BAA4B,EAAE,EAAE,CAAC;SACzC,OAAO,CAAC,gCAAgC,EAAE,YAAY,CAAC;SACvD,OAAO,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAC;IAC5C,IAAI,OAAO,EAAE,CAAC;QACZ,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,EAAE,GAAG,CAAC,EAAE,cAAc,CAAC,CAAC;IACzE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { GlCompositor, type GlPlatform, getCompositor, setCompositorFactory, } from "./gl/compositor.js";
|
|
2
|
+
export { glTransition } from "./gl/gl-transition.js";
|
|
3
|
+
export { type GlContext, VERTEX_SHADER, VERTEX_SHADER_100 } from "./gl/shared.js";
|
|
4
|
+
export { transpileTo100 } from "./gl/transpile.js";
|
|
5
|
+
export * from "./presentations/index.js";
|
|
6
|
+
export { defaultSpringConfig, type LinearTimingOptions, linearTiming, measureSpring, type SpringConfig, type SpringTimingOptions, spring, springTiming, } from "./timings/index.js";
|
|
7
|
+
export { TransitionSeries, type TransitionSeriesOptions, type TransitionSeriesSceneOptions, type TransitionSeriesTransitionOptions, } from "./transition-series.js";
|
|
8
|
+
export type { GlUniforms, Presentation, PresentationDims, Timing } from "./types.js";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EACZ,KAAK,UAAU,EACf,aAAa,EACb,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,KAAK,SAAS,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,cAAc,0BAA0B,CAAC;AACzC,OAAO,EACL,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,YAAY,EACZ,aAAa,EACb,KAAK,YAAY,EACjB,KAAK,mBAAmB,EACxB,MAAM,EACN,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,EAChB,KAAK,uBAAuB,EAC5B,KAAK,4BAA4B,EACjC,KAAK,iCAAiC,GACvC,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export { GlCompositor, getCompositor, setCompositorFactory, } from "./gl/compositor.js";
|
|
2
|
+
export { glTransition } from "./gl/gl-transition.js";
|
|
3
|
+
export { VERTEX_SHADER, VERTEX_SHADER_100 } from "./gl/shared.js";
|
|
4
|
+
export { transpileTo100 } from "./gl/transpile.js";
|
|
5
|
+
export * from "./presentations/index.js";
|
|
6
|
+
export { defaultSpringConfig, linearTiming, measureSpring, spring, springTiming, } from "./timings/index.js";
|
|
7
|
+
export { TransitionSeries, } from "./transition-series.js";
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAEZ,aAAa,EACb,oBAAoB,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAkB,aAAa,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,cAAc,0BAA0B,CAAC;AACzC,OAAO,EACL,mBAAmB,EAEnB,YAAY,EACZ,aAAa,EAGb,MAAM,EACN,YAAY,GACb,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,gBAAgB,GAIjB,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { Presentation } from "../types.js";
|
|
2
|
+
export type BookFlipDirection = "from-left" | "from-right" | "from-top" | "from-bottom";
|
|
3
|
+
export type BookFlipProps = {
|
|
4
|
+
direction?: BookFlipDirection;
|
|
5
|
+
};
|
|
6
|
+
/** Page-turn / book flip (gl-transitions `BookFlip`). */
|
|
7
|
+
export declare function bookFlip(props?: BookFlipProps): Presentation;
|
|
8
|
+
//# sourceMappingURL=book-flip.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"book-flip.d.ts","sourceRoot":"","sources":["../../src/presentations/book-flip.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAkHhD,MAAM,MAAM,iBAAiB,GAAG,WAAW,GAAG,YAAY,GAAG,UAAU,GAAG,aAAa,CAAC;AAExF,MAAM,MAAM,aAAa,GAAG;IAAE,SAAS,CAAC,EAAE,iBAAiB,CAAA;CAAE,CAAC;AAS9D,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,KAAK,GAAE,aAAkB,GAAG,YAAY,CAGhE"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { glTransition } from "../gl/gl-transition.js";
|
|
2
|
+
// Adapted from https://gl-transitions.com/editor/BookFlip
|
|
3
|
+
// Author: hong · License: MIT
|
|
4
|
+
const FRAGMENT = `#version 300 es
|
|
5
|
+
precision highp float;
|
|
6
|
+
|
|
7
|
+
uniform sampler2D u_prev;
|
|
8
|
+
uniform sampler2D u_next;
|
|
9
|
+
uniform float u_time;
|
|
10
|
+
uniform float u_direction;
|
|
11
|
+
|
|
12
|
+
in vec2 v_uv;
|
|
13
|
+
out vec4 outColor;
|
|
14
|
+
|
|
15
|
+
const float EPSILON = 0.0001;
|
|
16
|
+
|
|
17
|
+
float avoidZero(float value) {
|
|
18
|
+
if (abs(value) < EPSILON) {
|
|
19
|
+
return value < 0.0 ? -EPSILON : EPSILON;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
return value;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
vec2 skewRight(vec2 p, float progress) {
|
|
26
|
+
float skewX = (p.x - progress) / avoidZero(0.5 - progress) * 0.5;
|
|
27
|
+
float skewY =
|
|
28
|
+
(p.y - 0.5) /
|
|
29
|
+
avoidZero(0.5 + progress * (p.x - 0.5) / 0.5) *
|
|
30
|
+
0.5 +
|
|
31
|
+
0.5;
|
|
32
|
+
return vec2(skewX, skewY);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
vec2 skewLeft(vec2 p, float progress) {
|
|
36
|
+
float skewX = (p.x - 0.5) / avoidZero(progress - 0.5) * 0.5 + 0.5;
|
|
37
|
+
float skewY =
|
|
38
|
+
(p.y - 0.5) /
|
|
39
|
+
avoidZero(0.5 + (1.0 - progress) * (0.5 - p.x) / 0.5) *
|
|
40
|
+
0.5 +
|
|
41
|
+
0.5;
|
|
42
|
+
return vec2(skewX, skewY);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
vec4 addShade(float progress) {
|
|
46
|
+
float shadeVal = max(0.7, abs(progress - 0.5) * 2.0);
|
|
47
|
+
return vec4(vec3(shadeVal), 1.0);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
vec2 toCanonicalUv(vec2 p) {
|
|
51
|
+
if (u_direction < 0.5) {
|
|
52
|
+
return p;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
if (u_direction < 1.5) {
|
|
56
|
+
return vec2(1.0 - p.x, p.y);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (u_direction < 2.5) {
|
|
60
|
+
return vec2(p.y, 1.0 - p.x);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return vec2(1.0 - p.y, p.x);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
vec2 fromCanonicalUv(vec2 p) {
|
|
67
|
+
if (u_direction < 0.5) {
|
|
68
|
+
return p;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (u_direction < 1.5) {
|
|
72
|
+
return vec2(1.0 - p.x, p.y);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (u_direction < 2.5) {
|
|
76
|
+
return vec2(1.0 - p.y, p.x);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
return vec2(p.y, 1.0 - p.x);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
vec4 samplePrev(vec2 p) {
|
|
83
|
+
return texture(u_prev, fromCanonicalUv(p));
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
vec4 sampleNext(vec2 p) {
|
|
87
|
+
return texture(u_next, fromCanonicalUv(p));
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
vec4 transition(vec2 p, float progress) {
|
|
91
|
+
float pr = step(1.0 - progress, p.x);
|
|
92
|
+
|
|
93
|
+
if (p.x < 0.5) {
|
|
94
|
+
return mix(
|
|
95
|
+
samplePrev(p),
|
|
96
|
+
sampleNext(skewLeft(p, progress)) * addShade(progress),
|
|
97
|
+
pr
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return mix(
|
|
102
|
+
samplePrev(skewRight(p, progress)) * addShade(progress),
|
|
103
|
+
sampleNext(p),
|
|
104
|
+
pr
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
void main() {
|
|
109
|
+
vec2 p = toCanonicalUv(v_uv);
|
|
110
|
+
float progress = 1.0 - u_time;
|
|
111
|
+
outColor = transition(p, progress);
|
|
112
|
+
}`;
|
|
113
|
+
const DIRECTION_CONSTANT = {
|
|
114
|
+
"from-left": 0,
|
|
115
|
+
"from-right": 1,
|
|
116
|
+
"from-top": 2,
|
|
117
|
+
"from-bottom": 3,
|
|
118
|
+
};
|
|
119
|
+
/** Page-turn / book flip (gl-transitions `BookFlip`). */
|
|
120
|
+
export function bookFlip(props = {}) {
|
|
121
|
+
const direction = props.direction ?? "from-right";
|
|
122
|
+
return glTransition(FRAGMENT, () => ({ u_direction: DIRECTION_CONSTANT[direction] }));
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=book-flip.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"book-flip.js","sourceRoot":"","sources":["../../src/presentations/book-flip.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAGtD,0DAA0D;AAC1D,8BAA8B;AAC9B,MAAM,QAAQ,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EA4Gf,CAAC;AAMH,MAAM,kBAAkB,GAAsC;IAC5D,WAAW,EAAE,CAAC;IACd,YAAY,EAAE,CAAC;IACf,UAAU,EAAE,CAAC;IACb,aAAa,EAAE,CAAC;CACjB,CAAC;AAEF,yDAAyD;AACzD,MAAM,UAAU,QAAQ,CAAC,QAAuB,EAAE;IAChD,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,YAAY,CAAC;IAClD,OAAO,YAAY,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,EAAE,WAAW,EAAE,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC,CAAC;AACxF,CAAC"}
|