@remotion/transitions 4.0.465 → 4.0.466
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/book-flip.js +2 -0
- package/crosswarp.js +2 -0
- package/dist/TransitionSeries.js +16 -6
- package/dist/esm/book-flip.mjs +433 -0
- package/dist/esm/crosswarp.mjs +330 -0
- package/dist/esm/dreamy-zoom.mjs +347 -0
- package/dist/esm/index.mjs +553 -209
- package/dist/esm/linear-blur.mjs +342 -0
- package/dist/esm/ripple.mjs +341 -0
- package/dist/esm/swap.mjs +393 -0
- package/dist/index.d.ts +9 -3
- package/dist/index.js +5 -1
- package/dist/presentations/book-flip.d.ts +14 -0
- package/dist/presentations/book-flip.js +255 -0
- package/dist/presentations/crosswarp.d.ts +11 -0
- package/dist/presentations/crosswarp.js +154 -0
- package/dist/presentations/dreamy-zoom.d.ts +14 -0
- package/dist/presentations/dreamy-zoom.js +169 -0
- package/dist/presentations/linear-blur.d.ts +13 -0
- package/dist/presentations/linear-blur.js +164 -0
- package/dist/presentations/ripple.d.ts +14 -0
- package/dist/presentations/ripple.js +164 -0
- package/dist/presentations/swap.d.ts +15 -0
- package/dist/presentations/swap.js +212 -0
- package/dreamy-zoom.js +2 -0
- package/linear-blur.js +2 -0
- package/package.json +62 -8
- package/ripple.js +2 -0
- package/swap.js +2 -0
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.crosswarp = exports.crosswarpShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const VERTEX_SHADER = `#version 300 es
|
|
6
|
+
in vec2 a_pos;
|
|
7
|
+
out vec2 v_uv;
|
|
8
|
+
void main() {
|
|
9
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
10
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
11
|
+
}`;
|
|
12
|
+
// Adapted from https://gl-transitions.com/editor/crosswarp
|
|
13
|
+
// Author: Eke Péter · License: MIT
|
|
14
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
15
|
+
precision highp float;
|
|
16
|
+
|
|
17
|
+
uniform sampler2D u_prev;
|
|
18
|
+
uniform sampler2D u_next;
|
|
19
|
+
uniform float u_time;
|
|
20
|
+
|
|
21
|
+
in vec2 v_uv;
|
|
22
|
+
out vec4 outColor;
|
|
23
|
+
|
|
24
|
+
vec4 transition(vec2 uv, float progress) {
|
|
25
|
+
float x = progress;
|
|
26
|
+
x = smoothstep(0.0, 1.0, x * 2.0 + uv.x - 1.0);
|
|
27
|
+
return mix(
|
|
28
|
+
texture(u_next, (uv - 0.5) * (1.0 - x) + 0.5),
|
|
29
|
+
texture(u_prev, (uv - 0.5) * x + 0.5),
|
|
30
|
+
x
|
|
31
|
+
);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
void main() {
|
|
35
|
+
// In Remotion's HTML-in-canvas convention, u_prev is bound to the incoming
|
|
36
|
+
// scene and u_next is bound to the outgoing scene, so the gl-transitions
|
|
37
|
+
// "from" → u_next and "to" → u_prev. With this binding, progress = u_time
|
|
38
|
+
// (no inversion) maps to the gl-transitions convention where progress = 0
|
|
39
|
+
// shows the outgoing scene and progress = 1 shows the incoming one.
|
|
40
|
+
float progress = u_time;
|
|
41
|
+
outColor = transition(v_uv, progress);
|
|
42
|
+
}`;
|
|
43
|
+
const compileShader = (gl, source, type) => {
|
|
44
|
+
const shader = gl.createShader(type);
|
|
45
|
+
if (!shader) {
|
|
46
|
+
throw new Error('Failed to create shader');
|
|
47
|
+
}
|
|
48
|
+
gl.shaderSource(shader, source);
|
|
49
|
+
gl.compileShader(shader);
|
|
50
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
51
|
+
const log = gl.getShaderInfoLog(shader);
|
|
52
|
+
gl.deleteShader(shader);
|
|
53
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
54
|
+
}
|
|
55
|
+
return shader;
|
|
56
|
+
};
|
|
57
|
+
const createProgram = (gl) => {
|
|
58
|
+
const program = gl.createProgram();
|
|
59
|
+
if (!program) {
|
|
60
|
+
throw new Error('Failed to create WebGL program');
|
|
61
|
+
}
|
|
62
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
63
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
64
|
+
gl.attachShader(program, vs);
|
|
65
|
+
gl.attachShader(program, fs);
|
|
66
|
+
gl.linkProgram(program);
|
|
67
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
68
|
+
const log = gl.getProgramInfoLog(program);
|
|
69
|
+
gl.deleteProgram(program);
|
|
70
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
71
|
+
}
|
|
72
|
+
return program;
|
|
73
|
+
};
|
|
74
|
+
const createTexture = (gl) => {
|
|
75
|
+
const tex = gl.createTexture();
|
|
76
|
+
if (!tex) {
|
|
77
|
+
throw new Error('Failed to create texture');
|
|
78
|
+
}
|
|
79
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
80
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
81
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
82
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
83
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
84
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
85
|
+
return tex;
|
|
86
|
+
};
|
|
87
|
+
const crosswarpShader = (canvas) => {
|
|
88
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
89
|
+
if (!gl) {
|
|
90
|
+
throw new Error('Failed to create WebGL2 context');
|
|
91
|
+
}
|
|
92
|
+
const program = createProgram(gl);
|
|
93
|
+
const prevTex = createTexture(gl);
|
|
94
|
+
const nextTex = createTexture(gl);
|
|
95
|
+
const vao = gl.createVertexArray();
|
|
96
|
+
gl.bindVertexArray(vao);
|
|
97
|
+
const buffer = gl.createBuffer();
|
|
98
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
99
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
100
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
101
|
+
gl.enableVertexAttribArray(aPos);
|
|
102
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
103
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
104
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
105
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
106
|
+
const cleanup = () => {
|
|
107
|
+
gl.deleteProgram(program);
|
|
108
|
+
gl.deleteTexture(prevTex);
|
|
109
|
+
gl.deleteTexture(nextTex);
|
|
110
|
+
};
|
|
111
|
+
const clear = () => {
|
|
112
|
+
gl.clearColor(0, 0, 0, 0);
|
|
113
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
114
|
+
};
|
|
115
|
+
const draw = ({ prevImage, nextImage, width, height, time, }) => {
|
|
116
|
+
if (!prevImage && !nextImage) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
// When one side is missing, force the mix to fully show the other.
|
|
126
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
127
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
128
|
+
gl.viewport(0, 0, width, height);
|
|
129
|
+
gl.clearColor(0, 0, 0, 0);
|
|
130
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
131
|
+
gl.useProgram(program);
|
|
132
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
133
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
134
|
+
if (prevImage) {
|
|
135
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
136
|
+
}
|
|
137
|
+
gl.uniform1i(uPrev, 0);
|
|
138
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
139
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
140
|
+
if (nextImage) {
|
|
141
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
142
|
+
}
|
|
143
|
+
gl.uniform1i(uNext, 1);
|
|
144
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
145
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
146
|
+
};
|
|
147
|
+
return {
|
|
148
|
+
clear,
|
|
149
|
+
cleanup,
|
|
150
|
+
draw,
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
exports.crosswarpShader = crosswarpShader;
|
|
154
|
+
exports.crosswarp = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.crosswarpShader);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type DreamyZoomProps = {
|
|
2
|
+
rotation?: number;
|
|
3
|
+
scale?: number;
|
|
4
|
+
};
|
|
5
|
+
export declare const dreamyZoomShader: (canvas: OffscreenCanvas) => {
|
|
6
|
+
clear: () => void;
|
|
7
|
+
cleanup: () => void;
|
|
8
|
+
draw: import("..").HtmlInCanvasShaderDraw<DreamyZoomProps>;
|
|
9
|
+
};
|
|
10
|
+
export declare const dreamyZoom: (props: DreamyZoomProps & {
|
|
11
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
12
|
+
}) => import("..").TransitionPresentation<DreamyZoomProps & {
|
|
13
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dreamyZoom = exports.dreamyZoomShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const DEFAULT_ROTATION = 6;
|
|
6
|
+
const DEFAULT_SCALE = 1.2;
|
|
7
|
+
const VERTEX_SHADER = `#version 300 es
|
|
8
|
+
in vec2 a_pos;
|
|
9
|
+
out vec2 v_uv;
|
|
10
|
+
void main() {
|
|
11
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
12
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
13
|
+
}`;
|
|
14
|
+
// Adapted from https://gl-transitions.com/editor/DreamyZoom
|
|
15
|
+
// Author: Zeh Fernando · License: MIT
|
|
16
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
17
|
+
precision highp float;
|
|
18
|
+
|
|
19
|
+
uniform sampler2D u_prev;
|
|
20
|
+
uniform sampler2D u_next;
|
|
21
|
+
uniform float u_time;
|
|
22
|
+
uniform float u_rotation;
|
|
23
|
+
uniform float u_scale;
|
|
24
|
+
uniform float u_ratio;
|
|
25
|
+
|
|
26
|
+
in vec2 v_uv;
|
|
27
|
+
out vec4 outColor;
|
|
28
|
+
|
|
29
|
+
const float DEG2RAD = 0.03926990816987241548078304229099;
|
|
30
|
+
|
|
31
|
+
vec4 transition(vec2 uv, float progress) {
|
|
32
|
+
float phase = progress < 0.5 ? progress * 2.0 : (progress - 0.5) * 2.0;
|
|
33
|
+
float angleOffset = progress < 0.5 ? mix(0.0, u_rotation * DEG2RAD, phase) : mix(-u_rotation * DEG2RAD, 0.0, phase);
|
|
34
|
+
float newScale = progress < 0.5 ? mix(1.0, u_scale, phase) : mix(u_scale, 1.0, phase);
|
|
35
|
+
|
|
36
|
+
vec2 center = vec2(0.0, 0.0);
|
|
37
|
+
vec2 p = (uv.xy - vec2(0.5, 0.5)) / newScale * vec2(u_ratio, 1.0);
|
|
38
|
+
float angle = atan(p.y, p.x) + angleOffset;
|
|
39
|
+
float dist = distance(center, p);
|
|
40
|
+
|
|
41
|
+
p.x = cos(angle) * dist / u_ratio + 0.5;
|
|
42
|
+
p.y = sin(angle) * dist + 0.5;
|
|
43
|
+
|
|
44
|
+
vec4 c = progress < 0.5 ? texture(u_prev, p) : texture(u_next, p);
|
|
45
|
+
return c + (progress < 0.5 ? mix(0.0, 1.0, phase) : mix(1.0, 0.0, phase));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
void main() {
|
|
49
|
+
float progress = 1.0 - u_time;
|
|
50
|
+
outColor = transition(v_uv, progress);
|
|
51
|
+
}`;
|
|
52
|
+
const compileShader = (gl, source, type) => {
|
|
53
|
+
const shader = gl.createShader(type);
|
|
54
|
+
if (!shader) {
|
|
55
|
+
throw new Error('Failed to create shader');
|
|
56
|
+
}
|
|
57
|
+
gl.shaderSource(shader, source);
|
|
58
|
+
gl.compileShader(shader);
|
|
59
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
60
|
+
const log = gl.getShaderInfoLog(shader);
|
|
61
|
+
gl.deleteShader(shader);
|
|
62
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
63
|
+
}
|
|
64
|
+
return shader;
|
|
65
|
+
};
|
|
66
|
+
const createProgram = (gl) => {
|
|
67
|
+
const program = gl.createProgram();
|
|
68
|
+
if (!program) {
|
|
69
|
+
throw new Error('Failed to create WebGL program');
|
|
70
|
+
}
|
|
71
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
72
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
73
|
+
gl.attachShader(program, vs);
|
|
74
|
+
gl.attachShader(program, fs);
|
|
75
|
+
gl.linkProgram(program);
|
|
76
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
77
|
+
const log = gl.getProgramInfoLog(program);
|
|
78
|
+
gl.deleteProgram(program);
|
|
79
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
80
|
+
}
|
|
81
|
+
return program;
|
|
82
|
+
};
|
|
83
|
+
const createTexture = (gl) => {
|
|
84
|
+
const tex = gl.createTexture();
|
|
85
|
+
if (!tex) {
|
|
86
|
+
throw new Error('Failed to create texture');
|
|
87
|
+
}
|
|
88
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
89
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
90
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
91
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
92
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
93
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
94
|
+
return tex;
|
|
95
|
+
};
|
|
96
|
+
const dreamyZoomShader = (canvas) => {
|
|
97
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
98
|
+
if (!gl) {
|
|
99
|
+
throw new Error('Failed to create WebGL2 context');
|
|
100
|
+
}
|
|
101
|
+
const program = createProgram(gl);
|
|
102
|
+
const prevTex = createTexture(gl);
|
|
103
|
+
const nextTex = createTexture(gl);
|
|
104
|
+
const vao = gl.createVertexArray();
|
|
105
|
+
gl.bindVertexArray(vao);
|
|
106
|
+
const buffer = gl.createBuffer();
|
|
107
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
108
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
109
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
110
|
+
gl.enableVertexAttribArray(aPos);
|
|
111
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
112
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
113
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
114
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
115
|
+
const uRotation = gl.getUniformLocation(program, 'u_rotation');
|
|
116
|
+
const uScale = gl.getUniformLocation(program, 'u_scale');
|
|
117
|
+
const uRatio = gl.getUniformLocation(program, 'u_ratio');
|
|
118
|
+
const cleanup = () => {
|
|
119
|
+
gl.deleteProgram(program);
|
|
120
|
+
gl.deleteTexture(prevTex);
|
|
121
|
+
gl.deleteTexture(nextTex);
|
|
122
|
+
};
|
|
123
|
+
const clear = () => {
|
|
124
|
+
gl.clearColor(0, 0, 0, 0);
|
|
125
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
126
|
+
};
|
|
127
|
+
const draw = ({ prevImage, nextImage, width, height, time, passedProps, }) => {
|
|
128
|
+
const { rotation = DEFAULT_ROTATION, scale = DEFAULT_SCALE } = passedProps;
|
|
129
|
+
if (!prevImage && !nextImage) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
139
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
140
|
+
gl.viewport(0, 0, width, height);
|
|
141
|
+
gl.clearColor(0, 0, 0, 0);
|
|
142
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
143
|
+
gl.useProgram(program);
|
|
144
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
145
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
146
|
+
if (prevImage) {
|
|
147
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
148
|
+
}
|
|
149
|
+
gl.uniform1i(uPrev, 0);
|
|
150
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
151
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
152
|
+
if (nextImage) {
|
|
153
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
154
|
+
}
|
|
155
|
+
gl.uniform1i(uNext, 1);
|
|
156
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
157
|
+
gl.uniform1f(uRotation, rotation);
|
|
158
|
+
gl.uniform1f(uScale, scale);
|
|
159
|
+
gl.uniform1f(uRatio, width / height);
|
|
160
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
161
|
+
};
|
|
162
|
+
return {
|
|
163
|
+
clear,
|
|
164
|
+
cleanup,
|
|
165
|
+
draw,
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
exports.dreamyZoomShader = dreamyZoomShader;
|
|
169
|
+
exports.dreamyZoom = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.dreamyZoomShader);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export type LinearBlurProps = {
|
|
2
|
+
intensity?: number;
|
|
3
|
+
};
|
|
4
|
+
export declare const linearBlurShader: (canvas: OffscreenCanvas) => {
|
|
5
|
+
clear: () => void;
|
|
6
|
+
cleanup: () => void;
|
|
7
|
+
draw: import("..").HtmlInCanvasShaderDraw<LinearBlurProps>;
|
|
8
|
+
};
|
|
9
|
+
export declare const linearBlur: (props: LinearBlurProps & {
|
|
10
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
11
|
+
}) => import("..").TransitionPresentation<LinearBlurProps & {
|
|
12
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
13
|
+
}>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.linearBlur = exports.linearBlurShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const VERTEX_SHADER = `#version 300 es
|
|
6
|
+
in vec2 a_pos;
|
|
7
|
+
out vec2 v_uv;
|
|
8
|
+
void main() {
|
|
9
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
10
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
11
|
+
}`;
|
|
12
|
+
// Adapted from https://gl-transitions.com/editor/LinearBlur
|
|
13
|
+
// Author: gre · License: MIT
|
|
14
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
15
|
+
precision highp float;
|
|
16
|
+
|
|
17
|
+
uniform sampler2D u_prev;
|
|
18
|
+
uniform sampler2D u_next;
|
|
19
|
+
uniform float u_time;
|
|
20
|
+
uniform float u_intensity;
|
|
21
|
+
|
|
22
|
+
in vec2 v_uv;
|
|
23
|
+
out vec4 outColor;
|
|
24
|
+
|
|
25
|
+
const int PASSES = 6;
|
|
26
|
+
|
|
27
|
+
vec4 transition(vec2 uv, float progress) {
|
|
28
|
+
vec4 c1 = vec4(0.0);
|
|
29
|
+
vec4 c2 = vec4(0.0);
|
|
30
|
+
|
|
31
|
+
float disp = u_intensity * (0.5 - distance(0.5, progress));
|
|
32
|
+
for (int xi = 0; xi < PASSES; xi++) {
|
|
33
|
+
float x = float(xi) / float(PASSES) - 0.5;
|
|
34
|
+
for (int yi = 0; yi < PASSES; yi++) {
|
|
35
|
+
float y = float(yi) / float(PASSES) - 0.5;
|
|
36
|
+
vec2 v = vec2(x, y);
|
|
37
|
+
c1 += texture(u_prev, uv + disp * v);
|
|
38
|
+
c2 += texture(u_next, uv + disp * v);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
c1 /= float(PASSES * PASSES);
|
|
43
|
+
c2 /= float(PASSES * PASSES);
|
|
44
|
+
return mix(c1, c2, progress);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
void main() {
|
|
48
|
+
float progress = 1.0 - u_time;
|
|
49
|
+
outColor = transition(v_uv, progress);
|
|
50
|
+
}`;
|
|
51
|
+
const compileShader = (gl, source, type) => {
|
|
52
|
+
const shader = gl.createShader(type);
|
|
53
|
+
if (!shader) {
|
|
54
|
+
throw new Error('Failed to create shader');
|
|
55
|
+
}
|
|
56
|
+
gl.shaderSource(shader, source);
|
|
57
|
+
gl.compileShader(shader);
|
|
58
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
59
|
+
const log = gl.getShaderInfoLog(shader);
|
|
60
|
+
gl.deleteShader(shader);
|
|
61
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
62
|
+
}
|
|
63
|
+
return shader;
|
|
64
|
+
};
|
|
65
|
+
const createProgram = (gl) => {
|
|
66
|
+
const program = gl.createProgram();
|
|
67
|
+
if (!program) {
|
|
68
|
+
throw new Error('Failed to create WebGL program');
|
|
69
|
+
}
|
|
70
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
71
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
72
|
+
gl.attachShader(program, vs);
|
|
73
|
+
gl.attachShader(program, fs);
|
|
74
|
+
gl.linkProgram(program);
|
|
75
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
76
|
+
const log = gl.getProgramInfoLog(program);
|
|
77
|
+
gl.deleteProgram(program);
|
|
78
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
79
|
+
}
|
|
80
|
+
return program;
|
|
81
|
+
};
|
|
82
|
+
const createTexture = (gl) => {
|
|
83
|
+
const tex = gl.createTexture();
|
|
84
|
+
if (!tex) {
|
|
85
|
+
throw new Error('Failed to create texture');
|
|
86
|
+
}
|
|
87
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
88
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
89
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
90
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
91
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
92
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
93
|
+
return tex;
|
|
94
|
+
};
|
|
95
|
+
const linearBlurShader = (canvas) => {
|
|
96
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
97
|
+
if (!gl) {
|
|
98
|
+
throw new Error('Failed to create WebGL2 context');
|
|
99
|
+
}
|
|
100
|
+
const program = createProgram(gl);
|
|
101
|
+
const prevTex = createTexture(gl);
|
|
102
|
+
const nextTex = createTexture(gl);
|
|
103
|
+
const vao = gl.createVertexArray();
|
|
104
|
+
gl.bindVertexArray(vao);
|
|
105
|
+
const buffer = gl.createBuffer();
|
|
106
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
107
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
108
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
109
|
+
gl.enableVertexAttribArray(aPos);
|
|
110
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
111
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
112
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
113
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
114
|
+
const uIntensity = gl.getUniformLocation(program, 'u_intensity');
|
|
115
|
+
const cleanup = () => {
|
|
116
|
+
gl.deleteProgram(program);
|
|
117
|
+
gl.deleteTexture(prevTex);
|
|
118
|
+
gl.deleteTexture(nextTex);
|
|
119
|
+
};
|
|
120
|
+
const clear = () => {
|
|
121
|
+
gl.clearColor(0, 0, 0, 0);
|
|
122
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
123
|
+
};
|
|
124
|
+
const draw = ({ prevImage, nextImage, width, height, time, passedProps, }) => {
|
|
125
|
+
const { intensity = 0.1 } = passedProps;
|
|
126
|
+
if (!prevImage && !nextImage) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
136
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
137
|
+
gl.viewport(0, 0, width, height);
|
|
138
|
+
gl.clearColor(0, 0, 0, 0);
|
|
139
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
140
|
+
gl.useProgram(program);
|
|
141
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
142
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
143
|
+
if (prevImage) {
|
|
144
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
145
|
+
}
|
|
146
|
+
gl.uniform1i(uPrev, 0);
|
|
147
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
148
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
149
|
+
if (nextImage) {
|
|
150
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
151
|
+
}
|
|
152
|
+
gl.uniform1i(uNext, 1);
|
|
153
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
154
|
+
gl.uniform1f(uIntensity, intensity);
|
|
155
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
156
|
+
};
|
|
157
|
+
return {
|
|
158
|
+
clear,
|
|
159
|
+
cleanup,
|
|
160
|
+
draw,
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
exports.linearBlurShader = linearBlurShader;
|
|
164
|
+
exports.linearBlur = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.linearBlurShader);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export type RippleProps = {
|
|
2
|
+
amplitude?: number;
|
|
3
|
+
speed?: number;
|
|
4
|
+
};
|
|
5
|
+
export declare const rippleShader: (canvas: OffscreenCanvas) => {
|
|
6
|
+
clear: () => void;
|
|
7
|
+
cleanup: () => void;
|
|
8
|
+
draw: import("..").HtmlInCanvasShaderDraw<RippleProps>;
|
|
9
|
+
};
|
|
10
|
+
export declare const ripple: (props: RippleProps & {
|
|
11
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
12
|
+
}) => import("..").TransitionPresentation<RippleProps & {
|
|
13
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ripple = exports.rippleShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const DEFAULT_AMPLITUDE = 100.0;
|
|
6
|
+
const DEFAULT_SPEED = 50.0;
|
|
7
|
+
const VERTEX_SHADER = `#version 300 es
|
|
8
|
+
in vec2 a_pos;
|
|
9
|
+
out vec2 v_uv;
|
|
10
|
+
void main() {
|
|
11
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
12
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
13
|
+
}`;
|
|
14
|
+
// Adapted from https://gl-transitions.com/editor/ripple
|
|
15
|
+
// Author: gre · License: MIT
|
|
16
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
17
|
+
precision highp float;
|
|
18
|
+
|
|
19
|
+
uniform sampler2D u_prev;
|
|
20
|
+
uniform sampler2D u_next;
|
|
21
|
+
uniform float u_time;
|
|
22
|
+
uniform float u_amplitude;
|
|
23
|
+
uniform float u_speed;
|
|
24
|
+
|
|
25
|
+
in vec2 v_uv;
|
|
26
|
+
out vec4 outColor;
|
|
27
|
+
|
|
28
|
+
vec4 transition(vec2 uv, float progress) {
|
|
29
|
+
vec2 dir = uv - vec2(0.5);
|
|
30
|
+
float dist = length(dir);
|
|
31
|
+
vec2 offset = dir * (sin(progress * dist * u_amplitude - progress * u_speed) + 0.5) / 30.0 * progress;
|
|
32
|
+
return mix(
|
|
33
|
+
texture(u_next, uv + offset),
|
|
34
|
+
texture(u_prev, uv),
|
|
35
|
+
smoothstep(0.2, 1.0, progress)
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
void main() {
|
|
40
|
+
// In Remotion's HTML-in-canvas convention, u_prev is bound to the incoming
|
|
41
|
+
// scene and u_next is bound to the outgoing scene, so the gl-transitions
|
|
42
|
+
// "from" → u_next and "to" → u_prev. With this binding, progress = u_time
|
|
43
|
+
// (no inversion) maps to the gl-transitions convention where progress = 0
|
|
44
|
+
// shows the outgoing scene and progress = 1 shows the incoming one.
|
|
45
|
+
float progress = u_time;
|
|
46
|
+
outColor = transition(v_uv, progress);
|
|
47
|
+
}`;
|
|
48
|
+
const compileShader = (gl, source, type) => {
|
|
49
|
+
const shader = gl.createShader(type);
|
|
50
|
+
if (!shader) {
|
|
51
|
+
throw new Error('Failed to create shader');
|
|
52
|
+
}
|
|
53
|
+
gl.shaderSource(shader, source);
|
|
54
|
+
gl.compileShader(shader);
|
|
55
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
56
|
+
const log = gl.getShaderInfoLog(shader);
|
|
57
|
+
gl.deleteShader(shader);
|
|
58
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
59
|
+
}
|
|
60
|
+
return shader;
|
|
61
|
+
};
|
|
62
|
+
const createProgram = (gl) => {
|
|
63
|
+
const program = gl.createProgram();
|
|
64
|
+
if (!program) {
|
|
65
|
+
throw new Error('Failed to create WebGL program');
|
|
66
|
+
}
|
|
67
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
68
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
69
|
+
gl.attachShader(program, vs);
|
|
70
|
+
gl.attachShader(program, fs);
|
|
71
|
+
gl.linkProgram(program);
|
|
72
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
73
|
+
const log = gl.getProgramInfoLog(program);
|
|
74
|
+
gl.deleteProgram(program);
|
|
75
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
76
|
+
}
|
|
77
|
+
return program;
|
|
78
|
+
};
|
|
79
|
+
const createTexture = (gl) => {
|
|
80
|
+
const tex = gl.createTexture();
|
|
81
|
+
if (!tex) {
|
|
82
|
+
throw new Error('Failed to create texture');
|
|
83
|
+
}
|
|
84
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
85
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
86
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
87
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
88
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
89
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
90
|
+
return tex;
|
|
91
|
+
};
|
|
92
|
+
const rippleShader = (canvas) => {
|
|
93
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
94
|
+
if (!gl) {
|
|
95
|
+
throw new Error('Failed to create WebGL2 context');
|
|
96
|
+
}
|
|
97
|
+
const program = createProgram(gl);
|
|
98
|
+
const prevTex = createTexture(gl);
|
|
99
|
+
const nextTex = createTexture(gl);
|
|
100
|
+
const vao = gl.createVertexArray();
|
|
101
|
+
gl.bindVertexArray(vao);
|
|
102
|
+
const buffer = gl.createBuffer();
|
|
103
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
104
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
105
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
106
|
+
gl.enableVertexAttribArray(aPos);
|
|
107
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
108
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
109
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
110
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
111
|
+
const uAmplitude = gl.getUniformLocation(program, 'u_amplitude');
|
|
112
|
+
const uSpeed = gl.getUniformLocation(program, 'u_speed');
|
|
113
|
+
const cleanup = () => {
|
|
114
|
+
gl.deleteProgram(program);
|
|
115
|
+
gl.deleteTexture(prevTex);
|
|
116
|
+
gl.deleteTexture(nextTex);
|
|
117
|
+
};
|
|
118
|
+
const clear = () => {
|
|
119
|
+
gl.clearColor(0, 0, 0, 0);
|
|
120
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
121
|
+
};
|
|
122
|
+
const draw = ({ prevImage, nextImage, width, height, time, passedProps, }) => {
|
|
123
|
+
const { amplitude = DEFAULT_AMPLITUDE, speed = DEFAULT_SPEED } = passedProps;
|
|
124
|
+
if (!prevImage && !nextImage) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
// When one side is missing, force the mix to fully show the other.
|
|
134
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
135
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
136
|
+
gl.viewport(0, 0, width, height);
|
|
137
|
+
gl.clearColor(0, 0, 0, 0);
|
|
138
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
139
|
+
gl.useProgram(program);
|
|
140
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
141
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
142
|
+
if (prevImage) {
|
|
143
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
144
|
+
}
|
|
145
|
+
gl.uniform1i(uPrev, 0);
|
|
146
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
147
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
148
|
+
if (nextImage) {
|
|
149
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
150
|
+
}
|
|
151
|
+
gl.uniform1i(uNext, 1);
|
|
152
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
153
|
+
gl.uniform1f(uAmplitude, amplitude);
|
|
154
|
+
gl.uniform1f(uSpeed, speed);
|
|
155
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
156
|
+
};
|
|
157
|
+
return {
|
|
158
|
+
clear,
|
|
159
|
+
cleanup,
|
|
160
|
+
draw,
|
|
161
|
+
};
|
|
162
|
+
};
|
|
163
|
+
exports.rippleShader = rippleShader;
|
|
164
|
+
exports.ripple = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.rippleShader);
|