@remotion/transitions 4.0.464 → 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/dissolve.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/dissolve.mjs +376 -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/esm/zoom-blur.mjs +4 -4
- package/dist/esm/zoom-in-out.mjs +4 -4
- package/dist/html-in-canvas-presentation.d.ts +4 -4
- package/dist/html-in-canvas-presentation.js +4 -4
- 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/dissolve.d.ts +17 -0
- package/dist/presentations/dissolve.js +193 -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/dist/presentations/zoom-blur.d.ts +2 -2
- package/dist/presentations/zoom-in-out.d.ts +2 -2
- package/dreamy-zoom.js +2 -0
- package/linear-blur.js +2 -0
- package/package.json +71 -8
- package/ripple.js +2 -0
- package/swap.js +2 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.bookFlip = exports.bookFlipShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const DIRECTION_FROM_LEFT = 0;
|
|
6
|
+
const DIRECTION_FROM_RIGHT = 1;
|
|
7
|
+
const DIRECTION_FROM_TOP = 2;
|
|
8
|
+
const DIRECTION_FROM_BOTTOM = 3;
|
|
9
|
+
const DEFAULT_DIRECTION = 'from-right';
|
|
10
|
+
const VERTEX_SHADER = `#version 300 es
|
|
11
|
+
in vec2 a_pos;
|
|
12
|
+
out vec2 v_uv;
|
|
13
|
+
void main() {
|
|
14
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
15
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
16
|
+
}`;
|
|
17
|
+
// Adapted from https://gl-transitions.com/editor/BookFlip
|
|
18
|
+
// Author: hong · License: MIT
|
|
19
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
20
|
+
precision highp float;
|
|
21
|
+
|
|
22
|
+
uniform sampler2D u_prev;
|
|
23
|
+
uniform sampler2D u_next;
|
|
24
|
+
uniform float u_time;
|
|
25
|
+
uniform float u_direction;
|
|
26
|
+
|
|
27
|
+
in vec2 v_uv;
|
|
28
|
+
out vec4 outColor;
|
|
29
|
+
|
|
30
|
+
const float EPSILON = 0.0001;
|
|
31
|
+
|
|
32
|
+
float avoidZero(float value) {
|
|
33
|
+
if (abs(value) < EPSILON) {
|
|
34
|
+
return value < 0.0 ? -EPSILON : EPSILON;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
vec2 skewRight(vec2 p, float progress) {
|
|
41
|
+
float skewX = (p.x - progress) / avoidZero(0.5 - progress) * 0.5;
|
|
42
|
+
float skewY =
|
|
43
|
+
(p.y - 0.5) /
|
|
44
|
+
avoidZero(0.5 + progress * (p.x - 0.5) / 0.5) *
|
|
45
|
+
0.5 +
|
|
46
|
+
0.5;
|
|
47
|
+
return vec2(skewX, skewY);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
vec2 skewLeft(vec2 p, float progress) {
|
|
51
|
+
float skewX = (p.x - 0.5) / avoidZero(progress - 0.5) * 0.5 + 0.5;
|
|
52
|
+
float skewY =
|
|
53
|
+
(p.y - 0.5) /
|
|
54
|
+
avoidZero(0.5 + (1.0 - progress) * (0.5 - p.x) / 0.5) *
|
|
55
|
+
0.5 +
|
|
56
|
+
0.5;
|
|
57
|
+
return vec2(skewX, skewY);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
vec4 addShade(float progress) {
|
|
61
|
+
float shadeVal = max(0.7, abs(progress - 0.5) * 2.0);
|
|
62
|
+
return vec4(vec3(shadeVal), 1.0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
vec2 toCanonicalUv(vec2 p) {
|
|
66
|
+
if (u_direction < 0.5) {
|
|
67
|
+
return p;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (u_direction < 1.5) {
|
|
71
|
+
return vec2(1.0 - p.x, p.y);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if (u_direction < 2.5) {
|
|
75
|
+
return vec2(p.y, 1.0 - p.x);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return vec2(1.0 - p.y, p.x);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
vec2 fromCanonicalUv(vec2 p) {
|
|
82
|
+
if (u_direction < 0.5) {
|
|
83
|
+
return p;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (u_direction < 1.5) {
|
|
87
|
+
return vec2(1.0 - p.x, p.y);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (u_direction < 2.5) {
|
|
91
|
+
return vec2(1.0 - p.y, p.x);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return vec2(p.y, 1.0 - p.x);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
vec4 samplePrev(vec2 p) {
|
|
98
|
+
return texture(u_prev, fromCanonicalUv(p));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
vec4 sampleNext(vec2 p) {
|
|
102
|
+
return texture(u_next, fromCanonicalUv(p));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
vec4 transition(vec2 p, float progress) {
|
|
106
|
+
float pr = step(1.0 - progress, p.x);
|
|
107
|
+
|
|
108
|
+
if (p.x < 0.5) {
|
|
109
|
+
return mix(
|
|
110
|
+
samplePrev(p),
|
|
111
|
+
sampleNext(skewLeft(p, progress)) * addShade(progress),
|
|
112
|
+
pr
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
return mix(
|
|
117
|
+
samplePrev(skewRight(p, progress)) * addShade(progress),
|
|
118
|
+
sampleNext(p),
|
|
119
|
+
pr
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
void main() {
|
|
124
|
+
vec2 p = toCanonicalUv(v_uv);
|
|
125
|
+
float progress = 1.0 - u_time;
|
|
126
|
+
outColor = transition(p, progress);
|
|
127
|
+
}`;
|
|
128
|
+
const compileShader = (gl, source, type) => {
|
|
129
|
+
const shader = gl.createShader(type);
|
|
130
|
+
if (!shader) {
|
|
131
|
+
throw new Error('Failed to create shader');
|
|
132
|
+
}
|
|
133
|
+
gl.shaderSource(shader, source);
|
|
134
|
+
gl.compileShader(shader);
|
|
135
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
136
|
+
const log = gl.getShaderInfoLog(shader);
|
|
137
|
+
gl.deleteShader(shader);
|
|
138
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
139
|
+
}
|
|
140
|
+
return shader;
|
|
141
|
+
};
|
|
142
|
+
const createProgram = (gl) => {
|
|
143
|
+
const program = gl.createProgram();
|
|
144
|
+
if (!program) {
|
|
145
|
+
throw new Error('Failed to create WebGL program');
|
|
146
|
+
}
|
|
147
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
148
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
149
|
+
gl.attachShader(program, vs);
|
|
150
|
+
gl.attachShader(program, fs);
|
|
151
|
+
gl.linkProgram(program);
|
|
152
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
153
|
+
const log = gl.getProgramInfoLog(program);
|
|
154
|
+
gl.deleteProgram(program);
|
|
155
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
156
|
+
}
|
|
157
|
+
return program;
|
|
158
|
+
};
|
|
159
|
+
const createTexture = (gl) => {
|
|
160
|
+
const tex = gl.createTexture();
|
|
161
|
+
if (!tex) {
|
|
162
|
+
throw new Error('Failed to create texture');
|
|
163
|
+
}
|
|
164
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
165
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
166
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
167
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
168
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
169
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
170
|
+
return tex;
|
|
171
|
+
};
|
|
172
|
+
const getDirectionConstant = (direction) => {
|
|
173
|
+
switch (direction) {
|
|
174
|
+
case 'from-left':
|
|
175
|
+
return DIRECTION_FROM_LEFT;
|
|
176
|
+
case 'from-right':
|
|
177
|
+
return DIRECTION_FROM_RIGHT;
|
|
178
|
+
case 'from-top':
|
|
179
|
+
return DIRECTION_FROM_TOP;
|
|
180
|
+
case 'from-bottom':
|
|
181
|
+
return DIRECTION_FROM_BOTTOM;
|
|
182
|
+
default:
|
|
183
|
+
return DIRECTION_FROM_RIGHT;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const bookFlipShader = (canvas) => {
|
|
187
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
188
|
+
if (!gl) {
|
|
189
|
+
throw new Error('Failed to create WebGL2 context');
|
|
190
|
+
}
|
|
191
|
+
const program = createProgram(gl);
|
|
192
|
+
const prevTex = createTexture(gl);
|
|
193
|
+
const nextTex = createTexture(gl);
|
|
194
|
+
const vao = gl.createVertexArray();
|
|
195
|
+
gl.bindVertexArray(vao);
|
|
196
|
+
const buffer = gl.createBuffer();
|
|
197
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
198
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
199
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
200
|
+
gl.enableVertexAttribArray(aPos);
|
|
201
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
202
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
203
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
204
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
205
|
+
const uDirection = gl.getUniformLocation(program, 'u_direction');
|
|
206
|
+
const cleanup = () => {
|
|
207
|
+
gl.deleteProgram(program);
|
|
208
|
+
gl.deleteTexture(prevTex);
|
|
209
|
+
gl.deleteTexture(nextTex);
|
|
210
|
+
};
|
|
211
|
+
const clear = () => {
|
|
212
|
+
gl.clearColor(0, 0, 0, 0);
|
|
213
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
214
|
+
};
|
|
215
|
+
const draw = ({ prevImage, nextImage, width, height, time, passedProps, }) => {
|
|
216
|
+
const { direction = DEFAULT_DIRECTION } = passedProps;
|
|
217
|
+
if (!prevImage && !nextImage) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
227
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
228
|
+
gl.viewport(0, 0, width, height);
|
|
229
|
+
gl.clearColor(0, 0, 0, 0);
|
|
230
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
231
|
+
gl.useProgram(program);
|
|
232
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
233
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
234
|
+
if (prevImage) {
|
|
235
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
236
|
+
}
|
|
237
|
+
gl.uniform1i(uPrev, 0);
|
|
238
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
239
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
240
|
+
if (nextImage) {
|
|
241
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
242
|
+
}
|
|
243
|
+
gl.uniform1i(uNext, 1);
|
|
244
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
245
|
+
gl.uniform1f(uDirection, getDirectionConstant(direction));
|
|
246
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
247
|
+
};
|
|
248
|
+
return {
|
|
249
|
+
clear,
|
|
250
|
+
cleanup,
|
|
251
|
+
draw,
|
|
252
|
+
};
|
|
253
|
+
};
|
|
254
|
+
exports.bookFlipShader = bookFlipShader;
|
|
255
|
+
exports.bookFlip = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.bookFlipShader);
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type CrosswarpProps = Record<string, never>;
|
|
2
|
+
export declare const crosswarpShader: (canvas: OffscreenCanvas) => {
|
|
3
|
+
clear: () => void;
|
|
4
|
+
cleanup: () => void;
|
|
5
|
+
draw: import("..").HtmlInCanvasShaderDraw<CrosswarpProps>;
|
|
6
|
+
};
|
|
7
|
+
export declare const crosswarp: (props: CrosswarpProps & {
|
|
8
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
9
|
+
}) => import("..").TransitionPresentation<CrosswarpProps & {
|
|
10
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
11
|
+
}>;
|
|
@@ -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,17 @@
|
|
|
1
|
+
export type DissolveProps = {
|
|
2
|
+
lineWidth?: number;
|
|
3
|
+
spreadColor?: string;
|
|
4
|
+
hotColor?: string;
|
|
5
|
+
pow?: number;
|
|
6
|
+
intensity?: number;
|
|
7
|
+
};
|
|
8
|
+
export declare const dissolveShader: (canvas: OffscreenCanvas) => {
|
|
9
|
+
clear: () => void;
|
|
10
|
+
cleanup: () => void;
|
|
11
|
+
draw: import("..").HtmlInCanvasShaderDraw<DissolveProps>;
|
|
12
|
+
};
|
|
13
|
+
export declare const dissolve: (props: DissolveProps & {
|
|
14
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
15
|
+
}) => import("..").TransitionPresentation<DissolveProps & {
|
|
16
|
+
effects?: import("remotion").EffectsProp | undefined;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dissolve = exports.dissolveShader = void 0;
|
|
4
|
+
const html_in_canvas_presentation_1 = require("../html-in-canvas-presentation");
|
|
5
|
+
const DEFAULT_LINE_WIDTH = 0.1;
|
|
6
|
+
const DEFAULT_SPREAD_COLOR = '#ff0000';
|
|
7
|
+
const DEFAULT_HOT_COLOR = '#e6e633';
|
|
8
|
+
const DEFAULT_POW = 5.0;
|
|
9
|
+
const DEFAULT_INTENSITY = 1.0;
|
|
10
|
+
const parseHexColor = (hex) => {
|
|
11
|
+
const cleaned = hex.startsWith('#') ? hex.slice(1) : hex;
|
|
12
|
+
if (!/^[0-9a-fA-F]{6}$/.test(cleaned)) {
|
|
13
|
+
throw new Error(`Invalid color "${hex}" passed to dissolve(). Expected a "#rrggbb" hex string.`);
|
|
14
|
+
}
|
|
15
|
+
return [
|
|
16
|
+
parseInt(cleaned.slice(0, 2), 16) / 255,
|
|
17
|
+
parseInt(cleaned.slice(2, 4), 16) / 255,
|
|
18
|
+
parseInt(cleaned.slice(4, 6), 16) / 255,
|
|
19
|
+
];
|
|
20
|
+
};
|
|
21
|
+
const VERTEX_SHADER = `#version 300 es
|
|
22
|
+
in vec2 a_pos;
|
|
23
|
+
out vec2 v_uv;
|
|
24
|
+
void main() {
|
|
25
|
+
v_uv = vec2(a_pos.x * 0.5 + 0.5, 0.5 - a_pos.y * 0.5);
|
|
26
|
+
gl_Position = vec4(a_pos, 0.0, 1.0);
|
|
27
|
+
}`;
|
|
28
|
+
// Adapted from https://gl-transitions.com/editor/dissolve
|
|
29
|
+
// Author: hjm1fb · License: MIT
|
|
30
|
+
const FRAGMENT_SHADER = `#version 300 es
|
|
31
|
+
precision highp float;
|
|
32
|
+
|
|
33
|
+
uniform sampler2D u_prev;
|
|
34
|
+
uniform sampler2D u_next;
|
|
35
|
+
uniform float u_time;
|
|
36
|
+
uniform float u_line_width;
|
|
37
|
+
uniform vec3 u_spread_color;
|
|
38
|
+
uniform vec3 u_hot_color;
|
|
39
|
+
uniform float u_pow;
|
|
40
|
+
uniform float u_intensity;
|
|
41
|
+
|
|
42
|
+
in vec2 v_uv;
|
|
43
|
+
out vec4 outColor;
|
|
44
|
+
|
|
45
|
+
vec4 transition(vec2 uv, float progress) {
|
|
46
|
+
vec4 from = texture(u_next, uv);
|
|
47
|
+
vec4 to = texture(u_prev, uv);
|
|
48
|
+
float burn = 0.5 + 0.5 * (0.299 * from.r + 0.587 * from.g + 0.114 * from.b);
|
|
49
|
+
float show = burn - progress;
|
|
50
|
+
if (show < 0.001) {
|
|
51
|
+
return to;
|
|
52
|
+
}
|
|
53
|
+
float factor = 1.0 - smoothstep(0.0, u_line_width, show);
|
|
54
|
+
vec3 burnColor = mix(u_spread_color, u_hot_color, factor);
|
|
55
|
+
burnColor = pow(burnColor, vec3(u_pow)) * u_intensity;
|
|
56
|
+
vec3 finalRGB = mix(from.rgb, burnColor, factor * step(0.0001, progress));
|
|
57
|
+
return vec4(finalRGB, from.a);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
void main() {
|
|
61
|
+
// In Remotion's HTML-in-canvas convention, u_prev is bound to the incoming
|
|
62
|
+
// scene and u_next is bound to the outgoing scene, so the gl-transitions
|
|
63
|
+
// "from" → u_next and "to" → u_prev. With this binding, progress = u_time
|
|
64
|
+
// (no inversion) maps to the gl-transitions convention where progress = 0
|
|
65
|
+
// shows the outgoing scene and progress = 1 shows the incoming one.
|
|
66
|
+
float progress = u_time;
|
|
67
|
+
outColor = transition(v_uv, progress);
|
|
68
|
+
}`;
|
|
69
|
+
const compileShader = (gl, source, type) => {
|
|
70
|
+
const shader = gl.createShader(type);
|
|
71
|
+
if (!shader) {
|
|
72
|
+
throw new Error('Failed to create shader');
|
|
73
|
+
}
|
|
74
|
+
gl.shaderSource(shader, source);
|
|
75
|
+
gl.compileShader(shader);
|
|
76
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
77
|
+
const log = gl.getShaderInfoLog(shader);
|
|
78
|
+
gl.deleteShader(shader);
|
|
79
|
+
throw new Error(`Failed to compile shader: ${log}`);
|
|
80
|
+
}
|
|
81
|
+
return shader;
|
|
82
|
+
};
|
|
83
|
+
const createProgram = (gl) => {
|
|
84
|
+
const program = gl.createProgram();
|
|
85
|
+
if (!program) {
|
|
86
|
+
throw new Error('Failed to create WebGL program');
|
|
87
|
+
}
|
|
88
|
+
const vs = compileShader(gl, VERTEX_SHADER, gl.VERTEX_SHADER);
|
|
89
|
+
const fs = compileShader(gl, FRAGMENT_SHADER, gl.FRAGMENT_SHADER);
|
|
90
|
+
gl.attachShader(program, vs);
|
|
91
|
+
gl.attachShader(program, fs);
|
|
92
|
+
gl.linkProgram(program);
|
|
93
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
94
|
+
const log = gl.getProgramInfoLog(program);
|
|
95
|
+
gl.deleteProgram(program);
|
|
96
|
+
throw new Error(`Failed to link program: ${log}`);
|
|
97
|
+
}
|
|
98
|
+
return program;
|
|
99
|
+
};
|
|
100
|
+
const createTexture = (gl) => {
|
|
101
|
+
const tex = gl.createTexture();
|
|
102
|
+
if (!tex) {
|
|
103
|
+
throw new Error('Failed to create texture');
|
|
104
|
+
}
|
|
105
|
+
gl.bindTexture(gl.TEXTURE_2D, tex);
|
|
106
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
107
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
108
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
109
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
110
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array([0, 0, 0, 0]));
|
|
111
|
+
return tex;
|
|
112
|
+
};
|
|
113
|
+
const dissolveShader = (canvas) => {
|
|
114
|
+
const gl = canvas.getContext('webgl2', { premultipliedAlpha: true });
|
|
115
|
+
if (!gl) {
|
|
116
|
+
throw new Error('Failed to create WebGL2 context');
|
|
117
|
+
}
|
|
118
|
+
const program = createProgram(gl);
|
|
119
|
+
const prevTex = createTexture(gl);
|
|
120
|
+
const nextTex = createTexture(gl);
|
|
121
|
+
const vao = gl.createVertexArray();
|
|
122
|
+
gl.bindVertexArray(vao);
|
|
123
|
+
const buffer = gl.createBuffer();
|
|
124
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, buffer);
|
|
125
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
126
|
+
const aPos = gl.getAttribLocation(program, 'a_pos');
|
|
127
|
+
gl.enableVertexAttribArray(aPos);
|
|
128
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 0, 0);
|
|
129
|
+
const uTime = gl.getUniformLocation(program, 'u_time');
|
|
130
|
+
const uPrev = gl.getUniformLocation(program, 'u_prev');
|
|
131
|
+
const uNext = gl.getUniformLocation(program, 'u_next');
|
|
132
|
+
const uLineWidth = gl.getUniformLocation(program, 'u_line_width');
|
|
133
|
+
const uSpreadColor = gl.getUniformLocation(program, 'u_spread_color');
|
|
134
|
+
const uHotColor = gl.getUniformLocation(program, 'u_hot_color');
|
|
135
|
+
const uPow = gl.getUniformLocation(program, 'u_pow');
|
|
136
|
+
const uIntensity = gl.getUniformLocation(program, 'u_intensity');
|
|
137
|
+
const cleanup = () => {
|
|
138
|
+
gl.deleteProgram(program);
|
|
139
|
+
gl.deleteTexture(prevTex);
|
|
140
|
+
gl.deleteTexture(nextTex);
|
|
141
|
+
};
|
|
142
|
+
const clear = () => {
|
|
143
|
+
gl.clearColor(0, 0, 0, 0);
|
|
144
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
145
|
+
};
|
|
146
|
+
const draw = ({ prevImage, nextImage, width, height, time, passedProps, }) => {
|
|
147
|
+
const { lineWidth = DEFAULT_LINE_WIDTH, spreadColor = DEFAULT_SPREAD_COLOR, hotColor = DEFAULT_HOT_COLOR, pow = DEFAULT_POW, intensity = DEFAULT_INTENSITY, } = passedProps;
|
|
148
|
+
if (!prevImage && !nextImage) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
if (prevImage && (prevImage.width === 0 || prevImage.height === 0)) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (nextImage && (nextImage.width === 0 || nextImage.height === 0)) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
// When one side is missing, force the mix to fully show the other.
|
|
158
|
+
// At time=0 the shader outputs nextImage. At time=1 the shader outputs prevImage.
|
|
159
|
+
const effectiveTime = !prevImage ? 0 : !nextImage ? 1 : time;
|
|
160
|
+
gl.viewport(0, 0, width, height);
|
|
161
|
+
gl.clearColor(0, 0, 0, 0);
|
|
162
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
163
|
+
gl.useProgram(program);
|
|
164
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
165
|
+
gl.bindTexture(gl.TEXTURE_2D, prevTex);
|
|
166
|
+
if (prevImage) {
|
|
167
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, prevImage);
|
|
168
|
+
}
|
|
169
|
+
gl.uniform1i(uPrev, 0);
|
|
170
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
171
|
+
gl.bindTexture(gl.TEXTURE_2D, nextTex);
|
|
172
|
+
if (nextImage) {
|
|
173
|
+
gl.texElementImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, nextImage);
|
|
174
|
+
}
|
|
175
|
+
gl.uniform1i(uNext, 1);
|
|
176
|
+
const spread = parseHexColor(spreadColor);
|
|
177
|
+
const hot = parseHexColor(hotColor);
|
|
178
|
+
gl.uniform1f(uTime, effectiveTime);
|
|
179
|
+
gl.uniform1f(uLineWidth, lineWidth);
|
|
180
|
+
gl.uniform3f(uSpreadColor, spread[0], spread[1], spread[2]);
|
|
181
|
+
gl.uniform3f(uHotColor, hot[0], hot[1], hot[2]);
|
|
182
|
+
gl.uniform1f(uPow, pow);
|
|
183
|
+
gl.uniform1f(uIntensity, intensity);
|
|
184
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
185
|
+
};
|
|
186
|
+
return {
|
|
187
|
+
clear,
|
|
188
|
+
cleanup,
|
|
189
|
+
draw,
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
exports.dissolveShader = dissolveShader;
|
|
193
|
+
exports.dissolve = (0, html_in_canvas_presentation_1.makeHtmlInCanvasPresentation)(exports.dissolveShader);
|
|
@@ -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
|
+
}>;
|