@remotion/effects 4.0.479 → 4.0.482
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/dist/checkerboard.d.ts +75 -0
- package/dist/corner-pin/corner-pin-runtime.d.ts +27 -0
- package/dist/corner-pin/corner-pin-shaders.d.ts +2 -0
- package/dist/corner-pin/index.d.ts +14 -0
- package/dist/corner-pin.d.ts +1 -0
- package/dist/emboss.d.ts +76 -0
- package/dist/esm/blur.mjs +1 -1
- package/dist/esm/checkerboard.mjs +516 -0
- package/dist/esm/corner-pin.mjs +389 -0
- package/dist/esm/emboss.mjs +477 -0
- package/dist/esm/gridlines.mjs +577 -0
- package/dist/esm/index.mjs +1902 -676
- package/dist/esm/light-trail.mjs +519 -0
- package/dist/esm/pixelate.mjs +3 -3
- package/dist/esm/vignette.mjs +5 -10
- package/dist/esm/zoom-blur.mjs +419 -0
- package/dist/gridlines.d.ts +113 -0
- package/dist/index.d.ts +3 -0
- package/dist/light-trail/index.d.ts +19 -0
- package/dist/light-trail/light-trail-runtime.d.ts +38 -0
- package/dist/light-trail/light-trail-shaders.d.ts +2 -0
- package/dist/light-trail.d.ts +1 -0
- package/dist/visual-test/visual-utils.d.ts +4 -2
- package/dist/zoom-blur/index.d.ts +12 -0
- package/dist/zoom-blur/zoom-blur-runtime.d.ts +26 -0
- package/dist/zoom-blur/zoom-blur-shaders.d.ts +2 -0
- package/dist/zoom-blur.d.ts +1 -0
- package/package.json +51 -3
package/dist/esm/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// src/
|
|
1
|
+
// src/checkerboard.ts
|
|
2
2
|
import { Internals } from "remotion";
|
|
3
3
|
|
|
4
4
|
// src/validate-effect-param.ts
|
|
@@ -106,195 +106,120 @@ var parseColorRgba = (ctx, color) => {
|
|
|
106
106
|
return [data[0], data[1], data[2], data[3]];
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
// src/
|
|
109
|
+
// src/checkerboard.ts
|
|
110
110
|
var { createEffect, createWebGL2ContextError } = Internals;
|
|
111
|
-
var
|
|
112
|
-
var
|
|
111
|
+
var DEFAULT_COLORS = ["#dff4ff", "#7cc6ff"];
|
|
112
|
+
var DEFAULT_CELL_SIZE = 80;
|
|
113
113
|
var DEFAULT_GAP = 0;
|
|
114
|
-
var
|
|
115
|
-
var
|
|
116
|
-
var
|
|
117
|
-
var
|
|
118
|
-
var
|
|
119
|
-
|
|
120
|
-
type: "
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
default:
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
type: "number",
|
|
130
|
-
step: 1,
|
|
131
|
-
default: DEFAULT_CROP,
|
|
132
|
-
description: "Crop left",
|
|
133
|
-
hiddenFromList: false
|
|
134
|
-
},
|
|
135
|
-
cropTop: {
|
|
136
|
-
type: "number",
|
|
137
|
-
step: 1,
|
|
138
|
-
default: DEFAULT_CROP,
|
|
139
|
-
description: "Crop top",
|
|
140
|
-
hiddenFromList: false
|
|
141
|
-
},
|
|
142
|
-
cropRight: {
|
|
143
|
-
type: "number",
|
|
144
|
-
step: 1,
|
|
145
|
-
default: DEFAULT_CROP,
|
|
146
|
-
description: "Crop right",
|
|
147
|
-
hiddenFromList: false
|
|
148
|
-
},
|
|
149
|
-
cropBottom: {
|
|
150
|
-
type: "number",
|
|
151
|
-
step: 1,
|
|
152
|
-
default: DEFAULT_CROP,
|
|
153
|
-
description: "Crop bottom",
|
|
154
|
-
hiddenFromList: false
|
|
114
|
+
var DEFAULT_ANGLE = 0;
|
|
115
|
+
var DEFAULT_OFFSET_X = 0;
|
|
116
|
+
var DEFAULT_OFFSET_Y = 0;
|
|
117
|
+
var DEFAULT_MASK_TO_SOURCE_ALPHA = false;
|
|
118
|
+
var checkerboardSchema = {
|
|
119
|
+
colors: {
|
|
120
|
+
type: "array",
|
|
121
|
+
item: {
|
|
122
|
+
type: "color"
|
|
123
|
+
},
|
|
124
|
+
default: DEFAULT_COLORS,
|
|
125
|
+
minLength: 2,
|
|
126
|
+
newItemDefault: "#ff0000",
|
|
127
|
+
description: "Colors",
|
|
128
|
+
keyframable: false
|
|
155
129
|
},
|
|
156
|
-
|
|
130
|
+
cellSize: {
|
|
157
131
|
type: "number",
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
132
|
+
min: 0.1,
|
|
133
|
+
max: 800,
|
|
134
|
+
step: 0.1,
|
|
135
|
+
default: DEFAULT_CELL_SIZE,
|
|
136
|
+
description: "Cell size",
|
|
161
137
|
hiddenFromList: false
|
|
162
138
|
},
|
|
163
|
-
|
|
139
|
+
gap: {
|
|
164
140
|
type: "number",
|
|
165
|
-
|
|
141
|
+
min: 0,
|
|
142
|
+
max: 400,
|
|
143
|
+
step: 0.1,
|
|
166
144
|
default: DEFAULT_GAP,
|
|
167
|
-
description: "Gap
|
|
168
|
-
hiddenFromList: false
|
|
169
|
-
},
|
|
170
|
-
offsetU: {
|
|
171
|
-
type: "number",
|
|
172
|
-
step: 0.01,
|
|
173
|
-
default: DEFAULT_OFFSET,
|
|
174
|
-
description: "Offset U",
|
|
175
|
-
hiddenFromList: false
|
|
176
|
-
},
|
|
177
|
-
offsetV: {
|
|
178
|
-
type: "number",
|
|
179
|
-
step: 0.01,
|
|
180
|
-
default: DEFAULT_OFFSET,
|
|
181
|
-
description: "Offset V",
|
|
182
|
-
hiddenFromList: false
|
|
183
|
-
},
|
|
184
|
-
rowOffset: {
|
|
185
|
-
type: "number",
|
|
186
|
-
step: 1,
|
|
187
|
-
default: DEFAULT_OFFSET,
|
|
188
|
-
description: "Row offset",
|
|
145
|
+
description: "Gap",
|
|
189
146
|
hiddenFromList: false
|
|
190
147
|
},
|
|
191
|
-
|
|
192
|
-
type: "
|
|
193
|
-
min: 0,
|
|
148
|
+
angle: {
|
|
149
|
+
type: "rotation-degrees",
|
|
194
150
|
step: 1,
|
|
195
|
-
default:
|
|
196
|
-
description: "
|
|
197
|
-
hiddenFromList: false
|
|
151
|
+
default: DEFAULT_ANGLE,
|
|
152
|
+
description: "Angle"
|
|
198
153
|
},
|
|
199
|
-
|
|
154
|
+
offsetX: {
|
|
200
155
|
type: "number",
|
|
201
|
-
step: 1,
|
|
202
|
-
default:
|
|
203
|
-
description: "
|
|
156
|
+
step: 0.1,
|
|
157
|
+
default: DEFAULT_OFFSET_X,
|
|
158
|
+
description: "Offset X",
|
|
204
159
|
hiddenFromList: false
|
|
205
160
|
},
|
|
206
|
-
|
|
161
|
+
offsetY: {
|
|
207
162
|
type: "number",
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
description: "Column offset every",
|
|
163
|
+
step: 0.1,
|
|
164
|
+
default: DEFAULT_OFFSET_Y,
|
|
165
|
+
description: "Offset Y",
|
|
212
166
|
hiddenFromList: false
|
|
213
167
|
},
|
|
214
|
-
|
|
215
|
-
type: "uv-coordinate",
|
|
216
|
-
min: 0,
|
|
217
|
-
max: 1,
|
|
218
|
-
step: 0.01,
|
|
219
|
-
default: DEFAULT_ORIGIN,
|
|
220
|
-
description: "Origin"
|
|
221
|
-
},
|
|
222
|
-
wrap: {
|
|
168
|
+
maskToSourceAlpha: {
|
|
223
169
|
type: "boolean",
|
|
224
|
-
default:
|
|
225
|
-
description: "
|
|
170
|
+
default: DEFAULT_MASK_TO_SOURCE_ALPHA,
|
|
171
|
+
description: "Mask to source alpha"
|
|
226
172
|
}
|
|
227
173
|
};
|
|
228
|
-
var resolve = (p) =>
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
});
|
|
245
|
-
var assertOptionalUvCoordinate = (value, name) => {
|
|
246
|
-
if (value === undefined) {
|
|
247
|
-
return;
|
|
174
|
+
var resolve = (p) => {
|
|
175
|
+
const cellSize = p.cellSize ?? DEFAULT_CELL_SIZE;
|
|
176
|
+
const gap = p.gap ?? DEFAULT_GAP;
|
|
177
|
+
return {
|
|
178
|
+
colors: p.colors ?? DEFAULT_COLORS,
|
|
179
|
+
cellSize,
|
|
180
|
+
spacing: cellSize + gap,
|
|
181
|
+
angle: p.angle ?? DEFAULT_ANGLE,
|
|
182
|
+
offsetX: p.offsetX ?? DEFAULT_OFFSET_X,
|
|
183
|
+
offsetY: p.offsetY ?? DEFAULT_OFFSET_Y,
|
|
184
|
+
maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA
|
|
185
|
+
};
|
|
186
|
+
};
|
|
187
|
+
var validatePositive = (value, name) => {
|
|
188
|
+
if (value <= 0) {
|
|
189
|
+
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
248
190
|
}
|
|
249
|
-
|
|
250
|
-
|
|
191
|
+
};
|
|
192
|
+
var validateNonNegative2 = (value, name) => {
|
|
193
|
+
if (value < 0) {
|
|
194
|
+
throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
|
|
251
195
|
}
|
|
252
196
|
};
|
|
253
|
-
var
|
|
254
|
-
if (
|
|
197
|
+
var validateColors = (colors) => {
|
|
198
|
+
if (colors === undefined) {
|
|
255
199
|
return;
|
|
256
200
|
}
|
|
257
|
-
if (!
|
|
258
|
-
throw new TypeError(`"
|
|
259
|
-
}
|
|
260
|
-
};
|
|
261
|
-
var validatePositive = (value, name) => {
|
|
262
|
-
if (value <= 0) {
|
|
263
|
-
throw new TypeError(`"${name}" must be > 0`);
|
|
201
|
+
if (!Array.isArray(colors) || colors.length < 2) {
|
|
202
|
+
throw new TypeError(`"colors" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`);
|
|
264
203
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
if (value < min) {
|
|
268
|
-
throw new TypeError(`"${name}" must be >= ${min}, but got ${JSON.stringify(value)}`);
|
|
204
|
+
for (let i = 0;i < colors.length; i++) {
|
|
205
|
+
assertRequiredColor(colors[i], `colors[${i}]`);
|
|
269
206
|
}
|
|
270
207
|
};
|
|
271
|
-
var
|
|
272
|
-
assertEffectParamsObject(params, "
|
|
273
|
-
|
|
274
|
-
assertOptionalFiniteNumber(params.
|
|
275
|
-
assertOptionalFiniteNumber(params.
|
|
276
|
-
assertOptionalFiniteNumber(params.
|
|
277
|
-
assertOptionalFiniteNumber(params.
|
|
278
|
-
assertOptionalFiniteNumber(params.
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
assertOptionalFiniteNumber(params.columnOffset, "columnOffset");
|
|
285
|
-
assertOptionalFiniteNumber(params.columnOffsetEvery, "columnOffsetEvery");
|
|
286
|
-
assertOptionalUvCoordinate(params.origin, "origin");
|
|
287
|
-
assertOptionalBoolean(params.wrap, "wrap");
|
|
288
|
-
assertOptionalInteger(params.rowOffsetEvery, "rowOffsetEvery");
|
|
289
|
-
assertOptionalInteger(params.columnOffsetEvery, "columnOffsetEvery");
|
|
290
|
-
const r = resolve(params);
|
|
291
|
-
validatePositive(r.scale, "scale");
|
|
292
|
-
validateAtLeast(r.rowOffsetEvery, 0, "rowOffsetEvery");
|
|
293
|
-
validateAtLeast(r.columnOffsetEvery, 0, "columnOffsetEvery");
|
|
294
|
-
validateUnitInterval(r.origin[0], "origin[0]");
|
|
295
|
-
validateUnitInterval(r.origin[1], "origin[1]");
|
|
208
|
+
var validateCheckerboardParams = (params) => {
|
|
209
|
+
assertEffectParamsObject(params, "Checkerboard");
|
|
210
|
+
validateColors(params.colors);
|
|
211
|
+
assertOptionalFiniteNumber(params.cellSize, "cellSize");
|
|
212
|
+
assertOptionalFiniteNumber(params.gap, "gap");
|
|
213
|
+
assertOptionalFiniteNumber(params.angle, "angle");
|
|
214
|
+
assertOptionalFiniteNumber(params.offsetX, "offsetX");
|
|
215
|
+
assertOptionalFiniteNumber(params.offsetY, "offsetY");
|
|
216
|
+
assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
|
|
217
|
+
const cellSize = params.cellSize ?? DEFAULT_CELL_SIZE;
|
|
218
|
+
const gap = params.gap ?? DEFAULT_GAP;
|
|
219
|
+
validatePositive(cellSize, "cellSize");
|
|
220
|
+
validateNonNegative2(gap, "gap");
|
|
296
221
|
};
|
|
297
|
-
var
|
|
222
|
+
var CHECKERBOARD_VS = `#version 300 es
|
|
298
223
|
in vec2 aPos;
|
|
299
224
|
in vec2 aUv;
|
|
300
225
|
out vec2 vUv;
|
|
@@ -304,101 +229,936 @@ void main() {
|
|
|
304
229
|
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
305
230
|
}
|
|
306
231
|
`;
|
|
307
|
-
var
|
|
232
|
+
var CHECKERBOARD_FS = `#version 300 es
|
|
308
233
|
precision highp float;
|
|
309
234
|
|
|
310
235
|
in vec2 vUv;
|
|
311
236
|
out vec4 fragColor;
|
|
312
237
|
|
|
313
238
|
uniform sampler2D uSource;
|
|
239
|
+
uniform sampler2D uPalette;
|
|
314
240
|
uniform vec2 uResolution;
|
|
315
|
-
uniform float
|
|
316
|
-
uniform
|
|
317
|
-
uniform
|
|
241
|
+
uniform float uNumColors;
|
|
242
|
+
uniform float uCellSize;
|
|
243
|
+
uniform float uSpacing;
|
|
244
|
+
uniform float uAngle;
|
|
318
245
|
uniform vec2 uOffset;
|
|
319
|
-
uniform
|
|
320
|
-
uniform vec2 uColumnOffset;
|
|
321
|
-
uniform vec2 uOrigin;
|
|
322
|
-
uniform bool uWrap;
|
|
323
|
-
|
|
324
|
-
float positiveModulo(float value, float modulo) {
|
|
325
|
-
return mod(mod(value, modulo) + modulo, modulo);
|
|
326
|
-
}
|
|
246
|
+
uniform bool uMaskToSourceAlpha;
|
|
327
247
|
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
248
|
+
void main() {
|
|
249
|
+
vec4 texColor = texture(uSource, vUv);
|
|
250
|
+
float cellSize = max(uCellSize, 0.001);
|
|
251
|
+
float spacing = max(uSpacing, 0.001);
|
|
252
|
+
vec2 centered = vUv * uResolution - uResolution * 0.5;
|
|
253
|
+
float s = sin(uAngle);
|
|
254
|
+
float c = cos(uAngle);
|
|
255
|
+
vec2 rotated = vec2(
|
|
256
|
+
centered.x * c - centered.y * s,
|
|
257
|
+
centered.x * s + centered.y * c
|
|
258
|
+
);
|
|
259
|
+
vec2 position = rotated + uOffset;
|
|
260
|
+
vec2 localPosition = mod(position, spacing);
|
|
261
|
+
if (localPosition.x < 0.0) {
|
|
262
|
+
localPosition.x += spacing;
|
|
331
263
|
}
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
}
|
|
335
|
-
|
|
336
|
-
bool sampleCell(vec2 cell, vec2 fragPx, vec2 cropStart, vec2 tileSize, vec2 pitch, vec2 originPx, out vec4 color) {
|
|
337
|
-
if (!uWrap && (cell.x < 0.0 || cell.y < 0.0)) {
|
|
338
|
-
return false;
|
|
264
|
+
if (localPosition.y < 0.0) {
|
|
265
|
+
localPosition.y += spacing;
|
|
339
266
|
}
|
|
340
267
|
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
268
|
+
if (localPosition.x > cellSize || localPosition.y > cellSize) {
|
|
269
|
+
fragColor = texColor;
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
345
272
|
|
|
346
|
-
|
|
347
|
-
|
|
273
|
+
vec2 cell = floor(position / spacing);
|
|
274
|
+
float colorIndex = mod(cell.x + cell.y, uNumColors);
|
|
275
|
+
if (colorIndex < 0.0) {
|
|
276
|
+
colorIndex += uNumColors;
|
|
348
277
|
}
|
|
349
278
|
|
|
350
|
-
|
|
351
|
-
|
|
279
|
+
float texCoord = (colorIndex + 0.5) / uNumColors;
|
|
280
|
+
vec4 checkerColor = texture(uPalette, vec2(texCoord, 0.5));
|
|
281
|
+
float checkerAlpha = checkerColor.a;
|
|
282
|
+
vec3 premultipliedChecker = checkerColor.rgb * checkerAlpha;
|
|
283
|
+
|
|
284
|
+
if (uMaskToSourceAlpha) {
|
|
285
|
+
fragColor = vec4(
|
|
286
|
+
premultipliedChecker * texColor.a + texColor.rgb * (1.0 - checkerAlpha),
|
|
287
|
+
texColor.a
|
|
288
|
+
);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
fragColor = vec4(
|
|
293
|
+
premultipliedChecker + texColor.rgb * (1.0 - checkerAlpha),
|
|
294
|
+
checkerAlpha + texColor.a * (1.0 - checkerAlpha)
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
`;
|
|
298
|
+
var compileShader = (gl, type, source) => {
|
|
299
|
+
const shader = gl.createShader(type);
|
|
300
|
+
if (!shader) {
|
|
301
|
+
throw new Error("Failed to create WebGL shader");
|
|
302
|
+
}
|
|
303
|
+
gl.shaderSource(shader, source);
|
|
304
|
+
gl.compileShader(shader);
|
|
305
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
306
|
+
const log = gl.getShaderInfoLog(shader);
|
|
307
|
+
gl.deleteShader(shader);
|
|
308
|
+
throw new Error(`Checkerboard shader compile failed: ${log ?? "(no log)"}`);
|
|
309
|
+
}
|
|
310
|
+
return shader;
|
|
311
|
+
};
|
|
312
|
+
var linkProgram = (gl, vs, fs) => {
|
|
313
|
+
const program = gl.createProgram();
|
|
314
|
+
if (!program) {
|
|
315
|
+
throw new Error("Failed to create WebGL program");
|
|
316
|
+
}
|
|
317
|
+
gl.attachShader(program, vs);
|
|
318
|
+
gl.attachShader(program, fs);
|
|
319
|
+
gl.linkProgram(program);
|
|
320
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
321
|
+
const log = gl.getProgramInfoLog(program);
|
|
322
|
+
gl.deleteProgram(program);
|
|
323
|
+
throw new Error(`Checkerboard program link failed: ${log ?? "(no log)"}`);
|
|
324
|
+
}
|
|
325
|
+
return program;
|
|
326
|
+
};
|
|
327
|
+
var createProgram = (gl, vertexSource, fragmentSource) => {
|
|
328
|
+
const vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);
|
|
329
|
+
const fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
330
|
+
const program = linkProgram(gl, vs, fs);
|
|
331
|
+
gl.deleteShader(vs);
|
|
332
|
+
gl.deleteShader(fs);
|
|
333
|
+
return program;
|
|
334
|
+
};
|
|
335
|
+
var createTexture = (gl, filter) => {
|
|
336
|
+
const texture = gl.createTexture();
|
|
337
|
+
if (!texture) {
|
|
338
|
+
throw new Error("Failed to create WebGL texture");
|
|
339
|
+
}
|
|
340
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
341
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
342
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
343
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
344
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
345
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
346
|
+
return texture;
|
|
347
|
+
};
|
|
348
|
+
var setupCheckerboard = (target) => {
|
|
349
|
+
const gl = target.getContext("webgl2", {
|
|
350
|
+
premultipliedAlpha: true,
|
|
351
|
+
alpha: true,
|
|
352
|
+
preserveDrawingBuffer: true
|
|
353
|
+
});
|
|
354
|
+
if (!gl) {
|
|
355
|
+
throw createWebGL2ContextError("checkerboard effect");
|
|
356
|
+
}
|
|
357
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
358
|
+
const program = createProgram(gl, CHECKERBOARD_VS, CHECKERBOARD_FS);
|
|
359
|
+
const vao = gl.createVertexArray();
|
|
360
|
+
if (!vao) {
|
|
361
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
362
|
+
}
|
|
363
|
+
gl.bindVertexArray(vao);
|
|
364
|
+
const data = new Float32Array([
|
|
365
|
+
-1,
|
|
366
|
+
-1,
|
|
367
|
+
0,
|
|
368
|
+
0,
|
|
369
|
+
1,
|
|
370
|
+
-1,
|
|
371
|
+
1,
|
|
372
|
+
0,
|
|
373
|
+
-1,
|
|
374
|
+
1,
|
|
375
|
+
0,
|
|
376
|
+
1,
|
|
377
|
+
1,
|
|
378
|
+
1,
|
|
379
|
+
1,
|
|
380
|
+
1
|
|
381
|
+
]);
|
|
382
|
+
const vbo = gl.createBuffer();
|
|
383
|
+
if (!vbo) {
|
|
384
|
+
throw new Error("Failed to create WebGL buffer");
|
|
385
|
+
}
|
|
386
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
387
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
388
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
389
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
390
|
+
gl.enableVertexAttribArray(aPos);
|
|
391
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
392
|
+
gl.enableVertexAttribArray(aUv);
|
|
393
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
394
|
+
gl.bindVertexArray(null);
|
|
395
|
+
const colorCanvas = document.createElement("canvas");
|
|
396
|
+
colorCanvas.width = 1;
|
|
397
|
+
colorCanvas.height = 1;
|
|
398
|
+
const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
|
|
399
|
+
if (!colorCtx) {
|
|
400
|
+
throw new Error("Failed to acquire 2D context for color parsing");
|
|
401
|
+
}
|
|
402
|
+
return {
|
|
403
|
+
gl,
|
|
404
|
+
program,
|
|
405
|
+
vao,
|
|
406
|
+
vbo,
|
|
407
|
+
sourceTexture: createTexture(gl, gl.LINEAR),
|
|
408
|
+
paletteTexture: createTexture(gl, gl.NEAREST),
|
|
409
|
+
colorCtx,
|
|
410
|
+
uniforms: {
|
|
411
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
412
|
+
uPalette: gl.getUniformLocation(program, "uPalette"),
|
|
413
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
414
|
+
uNumColors: gl.getUniformLocation(program, "uNumColors"),
|
|
415
|
+
uCellSize: gl.getUniformLocation(program, "uCellSize"),
|
|
416
|
+
uSpacing: gl.getUniformLocation(program, "uSpacing"),
|
|
417
|
+
uAngle: gl.getUniformLocation(program, "uAngle"),
|
|
418
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
419
|
+
uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
|
|
420
|
+
},
|
|
421
|
+
cachedPaletteKey: "",
|
|
422
|
+
palettePixelData: new Uint8Array(0)
|
|
423
|
+
};
|
|
424
|
+
};
|
|
425
|
+
var updatePalette = (state, colors) => {
|
|
426
|
+
const paletteKey = colors.join("|");
|
|
427
|
+
const paletteDirty = state.cachedPaletteKey !== paletteKey;
|
|
428
|
+
if (!paletteDirty) {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
state.cachedPaletteKey = paletteKey;
|
|
432
|
+
const len = colors.length * 4;
|
|
433
|
+
if (state.palettePixelData.length !== len) {
|
|
434
|
+
state.palettePixelData = new Uint8Array(len);
|
|
435
|
+
}
|
|
436
|
+
const { palettePixelData } = state;
|
|
437
|
+
for (let i = 0;i < colors.length; i++) {
|
|
438
|
+
const color = parseColorRgba(state.colorCtx, colors[i]);
|
|
439
|
+
palettePixelData[i * 4] = color[0];
|
|
440
|
+
palettePixelData[i * 4 + 1] = color[1];
|
|
441
|
+
palettePixelData[i * 4 + 2] = color[2];
|
|
442
|
+
palettePixelData[i * 4 + 3] = color[3];
|
|
443
|
+
}
|
|
444
|
+
return true;
|
|
445
|
+
};
|
|
446
|
+
var checkerboard = createEffect({
|
|
447
|
+
type: "remotion/checkerboard",
|
|
448
|
+
label: "checkerboard()",
|
|
449
|
+
documentationLink: "https://www.remotion.dev/docs/effects/checkerboard",
|
|
450
|
+
backend: "webgl2",
|
|
451
|
+
calculateKey: (params) => {
|
|
452
|
+
const r = resolve(params);
|
|
453
|
+
const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
|
|
454
|
+
return `checkerboard-${r.colors.join("|")}-${r.cellSize}-${r.spacing}-${r.angle}-${r.offsetX}-${r.offsetY}${maskSuffix}`;
|
|
455
|
+
},
|
|
456
|
+
setup: (target) => setupCheckerboard(target),
|
|
457
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
458
|
+
const r = resolve(params);
|
|
459
|
+
const paletteDirty = updatePalette(state, r.colors);
|
|
460
|
+
const { gl, program, sourceTexture, paletteTexture, uniforms, vao } = state;
|
|
461
|
+
gl.viewport(0, 0, width, height);
|
|
462
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
463
|
+
gl.clearColor(0, 0, 0, 0);
|
|
464
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
465
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
466
|
+
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
|
|
467
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
468
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
469
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
470
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
471
|
+
gl.bindTexture(gl.TEXTURE_2D, paletteTexture);
|
|
472
|
+
if (paletteDirty) {
|
|
473
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
474
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
475
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, r.colors.length, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, state.palettePixelData);
|
|
476
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
477
|
+
}
|
|
478
|
+
gl.useProgram(program);
|
|
479
|
+
if (uniforms.uSource)
|
|
480
|
+
gl.uniform1i(uniforms.uSource, 0);
|
|
481
|
+
if (uniforms.uPalette)
|
|
482
|
+
gl.uniform1i(uniforms.uPalette, 1);
|
|
483
|
+
if (uniforms.uResolution)
|
|
484
|
+
gl.uniform2f(uniforms.uResolution, width, height);
|
|
485
|
+
if (uniforms.uNumColors)
|
|
486
|
+
gl.uniform1f(uniforms.uNumColors, r.colors.length);
|
|
487
|
+
if (uniforms.uCellSize)
|
|
488
|
+
gl.uniform1f(uniforms.uCellSize, r.cellSize);
|
|
489
|
+
if (uniforms.uSpacing)
|
|
490
|
+
gl.uniform1f(uniforms.uSpacing, r.spacing);
|
|
491
|
+
if (uniforms.uAngle)
|
|
492
|
+
gl.uniform1f(uniforms.uAngle, r.angle * Math.PI / 180);
|
|
493
|
+
if (uniforms.uOffset)
|
|
494
|
+
gl.uniform2f(uniforms.uOffset, r.offsetX, r.offsetY);
|
|
495
|
+
if (uniforms.uMaskToSourceAlpha)
|
|
496
|
+
gl.uniform1i(uniforms.uMaskToSourceAlpha, r.maskToSourceAlpha ? 1 : 0);
|
|
497
|
+
gl.bindVertexArray(vao);
|
|
498
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
499
|
+
gl.bindVertexArray(null);
|
|
500
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
501
|
+
gl.useProgram(null);
|
|
502
|
+
},
|
|
503
|
+
cleanup: ({ gl, program, vao, vbo, sourceTexture, paletteTexture }) => {
|
|
504
|
+
gl.deleteTexture(sourceTexture);
|
|
505
|
+
gl.deleteTexture(paletteTexture);
|
|
506
|
+
gl.deleteBuffer(vbo);
|
|
507
|
+
gl.deleteProgram(program);
|
|
508
|
+
gl.deleteVertexArray(vao);
|
|
509
|
+
},
|
|
510
|
+
schema: checkerboardSchema,
|
|
511
|
+
validateParams: validateCheckerboardParams
|
|
512
|
+
});
|
|
513
|
+
|
|
514
|
+
// src/pattern.ts
|
|
515
|
+
import { Internals as Internals2 } from "remotion";
|
|
516
|
+
var { createEffect: createEffect2, createWebGL2ContextError: createWebGL2ContextError2 } = Internals2;
|
|
517
|
+
var DEFAULT_SCALE = 0.1;
|
|
518
|
+
var DEFAULT_CROP = 0;
|
|
519
|
+
var DEFAULT_GAP2 = 0;
|
|
520
|
+
var DEFAULT_OFFSET = 0;
|
|
521
|
+
var DEFAULT_OFFSET_EVERY = 0;
|
|
522
|
+
var DEFAULT_ORIGIN = [0, 0];
|
|
523
|
+
var DEFAULT_WRAP = true;
|
|
524
|
+
var patternSchema = {
|
|
525
|
+
scale: {
|
|
526
|
+
type: "number",
|
|
527
|
+
min: 0.001,
|
|
528
|
+
max: 2,
|
|
529
|
+
step: 0.01,
|
|
530
|
+
default: DEFAULT_SCALE,
|
|
531
|
+
description: "Scale",
|
|
532
|
+
hiddenFromList: false
|
|
533
|
+
},
|
|
534
|
+
cropLeft: {
|
|
535
|
+
type: "number",
|
|
536
|
+
step: 1,
|
|
537
|
+
default: DEFAULT_CROP,
|
|
538
|
+
description: "Crop left",
|
|
539
|
+
hiddenFromList: false
|
|
540
|
+
},
|
|
541
|
+
cropTop: {
|
|
542
|
+
type: "number",
|
|
543
|
+
step: 1,
|
|
544
|
+
default: DEFAULT_CROP,
|
|
545
|
+
description: "Crop top",
|
|
546
|
+
hiddenFromList: false
|
|
547
|
+
},
|
|
548
|
+
cropRight: {
|
|
549
|
+
type: "number",
|
|
550
|
+
step: 1,
|
|
551
|
+
default: DEFAULT_CROP,
|
|
552
|
+
description: "Crop right",
|
|
553
|
+
hiddenFromList: false
|
|
554
|
+
},
|
|
555
|
+
cropBottom: {
|
|
556
|
+
type: "number",
|
|
557
|
+
step: 1,
|
|
558
|
+
default: DEFAULT_CROP,
|
|
559
|
+
description: "Crop bottom",
|
|
560
|
+
hiddenFromList: false
|
|
561
|
+
},
|
|
562
|
+
gapX: {
|
|
563
|
+
type: "number",
|
|
564
|
+
step: 1,
|
|
565
|
+
default: DEFAULT_GAP2,
|
|
566
|
+
description: "Gap X",
|
|
567
|
+
hiddenFromList: false
|
|
568
|
+
},
|
|
569
|
+
gapY: {
|
|
570
|
+
type: "number",
|
|
571
|
+
step: 1,
|
|
572
|
+
default: DEFAULT_GAP2,
|
|
573
|
+
description: "Gap Y",
|
|
574
|
+
hiddenFromList: false
|
|
575
|
+
},
|
|
576
|
+
offsetU: {
|
|
577
|
+
type: "number",
|
|
578
|
+
step: 0.01,
|
|
579
|
+
default: DEFAULT_OFFSET,
|
|
580
|
+
description: "Offset U",
|
|
581
|
+
hiddenFromList: false
|
|
582
|
+
},
|
|
583
|
+
offsetV: {
|
|
584
|
+
type: "number",
|
|
585
|
+
step: 0.01,
|
|
586
|
+
default: DEFAULT_OFFSET,
|
|
587
|
+
description: "Offset V",
|
|
588
|
+
hiddenFromList: false
|
|
589
|
+
},
|
|
590
|
+
rowOffset: {
|
|
591
|
+
type: "number",
|
|
592
|
+
step: 1,
|
|
593
|
+
default: DEFAULT_OFFSET,
|
|
594
|
+
description: "Row offset",
|
|
595
|
+
hiddenFromList: false
|
|
596
|
+
},
|
|
597
|
+
rowOffsetEvery: {
|
|
598
|
+
type: "number",
|
|
599
|
+
min: 0,
|
|
600
|
+
step: 1,
|
|
601
|
+
default: DEFAULT_OFFSET_EVERY,
|
|
602
|
+
description: "Row offset every",
|
|
603
|
+
hiddenFromList: false
|
|
604
|
+
},
|
|
605
|
+
columnOffset: {
|
|
606
|
+
type: "number",
|
|
607
|
+
step: 1,
|
|
608
|
+
default: DEFAULT_OFFSET,
|
|
609
|
+
description: "Column offset",
|
|
610
|
+
hiddenFromList: false
|
|
611
|
+
},
|
|
612
|
+
columnOffsetEvery: {
|
|
613
|
+
type: "number",
|
|
614
|
+
min: 0,
|
|
615
|
+
step: 1,
|
|
616
|
+
default: DEFAULT_OFFSET_EVERY,
|
|
617
|
+
description: "Column offset every",
|
|
618
|
+
hiddenFromList: false
|
|
619
|
+
},
|
|
620
|
+
origin: {
|
|
621
|
+
type: "uv-coordinate",
|
|
622
|
+
min: 0,
|
|
623
|
+
max: 1,
|
|
624
|
+
step: 0.01,
|
|
625
|
+
default: DEFAULT_ORIGIN,
|
|
626
|
+
description: "Origin"
|
|
627
|
+
},
|
|
628
|
+
wrap: {
|
|
629
|
+
type: "boolean",
|
|
630
|
+
default: DEFAULT_WRAP,
|
|
631
|
+
description: "Wrap"
|
|
632
|
+
}
|
|
633
|
+
};
|
|
634
|
+
var resolve2 = (p) => ({
|
|
635
|
+
scale: p.scale ?? DEFAULT_SCALE,
|
|
636
|
+
cropLeft: p.cropLeft ?? DEFAULT_CROP,
|
|
637
|
+
cropTop: p.cropTop ?? DEFAULT_CROP,
|
|
638
|
+
cropRight: p.cropRight ?? DEFAULT_CROP,
|
|
639
|
+
cropBottom: p.cropBottom ?? DEFAULT_CROP,
|
|
640
|
+
gapX: p.gapX ?? DEFAULT_GAP2,
|
|
641
|
+
gapY: p.gapY ?? DEFAULT_GAP2,
|
|
642
|
+
offsetU: p.offsetU ?? DEFAULT_OFFSET,
|
|
643
|
+
offsetV: p.offsetV ?? DEFAULT_OFFSET,
|
|
644
|
+
rowOffset: p.rowOffset ?? DEFAULT_OFFSET,
|
|
645
|
+
rowOffsetEvery: p.rowOffsetEvery ?? DEFAULT_OFFSET_EVERY,
|
|
646
|
+
columnOffset: p.columnOffset ?? DEFAULT_OFFSET,
|
|
647
|
+
columnOffsetEvery: p.columnOffsetEvery ?? DEFAULT_OFFSET_EVERY,
|
|
648
|
+
origin: [...p.origin ?? DEFAULT_ORIGIN],
|
|
649
|
+
wrap: p.wrap ?? DEFAULT_WRAP
|
|
650
|
+
});
|
|
651
|
+
var assertOptionalUvCoordinate = (value, name) => {
|
|
652
|
+
if (value === undefined) {
|
|
653
|
+
return;
|
|
654
|
+
}
|
|
655
|
+
if (!Array.isArray(value) || value.length !== 2 || value.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
|
|
656
|
+
throw new TypeError(`"${name}" must be a [number, number] tuple`);
|
|
657
|
+
}
|
|
658
|
+
};
|
|
659
|
+
var assertOptionalInteger = (value, name) => {
|
|
660
|
+
if (value === undefined) {
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
663
|
+
if (!Number.isInteger(value)) {
|
|
664
|
+
throw new TypeError(`"${name}" must be an integer, but got ${JSON.stringify(value)}`);
|
|
665
|
+
}
|
|
666
|
+
};
|
|
667
|
+
var validatePositive2 = (value, name) => {
|
|
668
|
+
if (value <= 0) {
|
|
669
|
+
throw new TypeError(`"${name}" must be > 0`);
|
|
670
|
+
}
|
|
671
|
+
};
|
|
672
|
+
var validateAtLeast = (value, min, name) => {
|
|
673
|
+
if (value < min) {
|
|
674
|
+
throw new TypeError(`"${name}" must be >= ${min}, but got ${JSON.stringify(value)}`);
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
var validatePatternParams = (params) => {
|
|
678
|
+
assertEffectParamsObject(params, "Pattern");
|
|
679
|
+
assertOptionalFiniteNumber(params.scale, "scale");
|
|
680
|
+
assertOptionalFiniteNumber(params.cropLeft, "cropLeft");
|
|
681
|
+
assertOptionalFiniteNumber(params.cropTop, "cropTop");
|
|
682
|
+
assertOptionalFiniteNumber(params.cropRight, "cropRight");
|
|
683
|
+
assertOptionalFiniteNumber(params.cropBottom, "cropBottom");
|
|
684
|
+
assertOptionalFiniteNumber(params.gapX, "gapX");
|
|
685
|
+
assertOptionalFiniteNumber(params.gapY, "gapY");
|
|
686
|
+
assertOptionalFiniteNumber(params.offsetU, "offsetU");
|
|
687
|
+
assertOptionalFiniteNumber(params.offsetV, "offsetV");
|
|
688
|
+
assertOptionalFiniteNumber(params.rowOffset, "rowOffset");
|
|
689
|
+
assertOptionalFiniteNumber(params.rowOffsetEvery, "rowOffsetEvery");
|
|
690
|
+
assertOptionalFiniteNumber(params.columnOffset, "columnOffset");
|
|
691
|
+
assertOptionalFiniteNumber(params.columnOffsetEvery, "columnOffsetEvery");
|
|
692
|
+
assertOptionalUvCoordinate(params.origin, "origin");
|
|
693
|
+
assertOptionalBoolean(params.wrap, "wrap");
|
|
694
|
+
assertOptionalInteger(params.rowOffsetEvery, "rowOffsetEvery");
|
|
695
|
+
assertOptionalInteger(params.columnOffsetEvery, "columnOffsetEvery");
|
|
696
|
+
const r = resolve2(params);
|
|
697
|
+
validatePositive2(r.scale, "scale");
|
|
698
|
+
validateAtLeast(r.rowOffsetEvery, 0, "rowOffsetEvery");
|
|
699
|
+
validateAtLeast(r.columnOffsetEvery, 0, "columnOffsetEvery");
|
|
700
|
+
validateUnitInterval(r.origin[0], "origin[0]");
|
|
701
|
+
validateUnitInterval(r.origin[1], "origin[1]");
|
|
702
|
+
};
|
|
703
|
+
var PATTERN_VS = `#version 300 es
|
|
704
|
+
in vec2 aPos;
|
|
705
|
+
in vec2 aUv;
|
|
706
|
+
out vec2 vUv;
|
|
707
|
+
|
|
708
|
+
void main() {
|
|
709
|
+
vUv = aUv;
|
|
710
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
711
|
+
}
|
|
712
|
+
`;
|
|
713
|
+
var PATTERN_FS = `#version 300 es
|
|
714
|
+
precision highp float;
|
|
715
|
+
|
|
716
|
+
in vec2 vUv;
|
|
717
|
+
out vec4 fragColor;
|
|
718
|
+
|
|
719
|
+
uniform sampler2D uSource;
|
|
720
|
+
uniform vec2 uResolution;
|
|
721
|
+
uniform float uScale;
|
|
722
|
+
uniform vec4 uCrop;
|
|
723
|
+
uniform vec2 uGap;
|
|
724
|
+
uniform vec2 uOffset;
|
|
725
|
+
uniform vec2 uRowOffset;
|
|
726
|
+
uniform vec2 uColumnOffset;
|
|
727
|
+
uniform vec2 uOrigin;
|
|
728
|
+
uniform bool uWrap;
|
|
729
|
+
|
|
730
|
+
float positiveModulo(float value, float modulo) {
|
|
731
|
+
return mod(mod(value, modulo) + modulo, modulo);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
float getPhase(float index, float every) {
|
|
735
|
+
if (every == 0.0) {
|
|
736
|
+
return index;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
return positiveModulo(index, every);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
bool sampleCell(vec2 cell, vec2 fragPx, vec2 cropStart, vec2 tileSize, vec2 pitch, vec2 originPx, out vec4 color) {
|
|
743
|
+
if (!uWrap && (cell.x < 0.0 || cell.y < 0.0)) {
|
|
744
|
+
return false;
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
float rowPhase = getPhase(cell.y, uRowOffset.y);
|
|
748
|
+
float columnPhase = getPhase(cell.x, uColumnOffset.y);
|
|
749
|
+
vec2 stagger = vec2(rowPhase * uRowOffset.x, columnPhase * uColumnOffset.x);
|
|
750
|
+
vec2 localPx = fragPx - originPx - stagger - cell * pitch;
|
|
751
|
+
|
|
752
|
+
if (localPx.x < 0.0 || localPx.y < 0.0 || localPx.x >= tileSize.x || localPx.y >= tileSize.y) {
|
|
753
|
+
return false;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
vec2 sourcePx = cropStart + localPx / uScale;
|
|
757
|
+
vec2 sourceUv = vec2(sourcePx.x / uResolution.x, 1.0 - sourcePx.y / uResolution.y);
|
|
758
|
+
|
|
759
|
+
if (sourceUv.x < 0.0 || sourceUv.y < 0.0 || sourceUv.x > 1.0 || sourceUv.y > 1.0) {
|
|
760
|
+
return false;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
color = texture(uSource, sourceUv);
|
|
764
|
+
return true;
|
|
765
|
+
}
|
|
766
|
+
|
|
767
|
+
void main() {
|
|
768
|
+
vec2 cropStart = uCrop.xy;
|
|
769
|
+
vec2 cropEnd = uResolution - uCrop.zw;
|
|
770
|
+
vec2 cropSize = max(cropEnd - cropStart, vec2(0.001));
|
|
771
|
+
vec2 tileSize = max(cropSize * uScale, vec2(0.001));
|
|
772
|
+
vec2 pitch = max(tileSize + uGap, vec2(0.001));
|
|
773
|
+
vec2 patternUv = vec2(vUv.x, 1.0 - vUv.y);
|
|
774
|
+
vec2 originPx = (uOrigin + uOffset) * uResolution;
|
|
775
|
+
vec2 fragPx = patternUv * uResolution;
|
|
776
|
+
|
|
777
|
+
vec2 gridPx = fragPx - originPx;
|
|
778
|
+
vec2 cell = floor(gridPx / pitch);
|
|
779
|
+
|
|
780
|
+
for (int i = 0; i < 4; i++) {
|
|
781
|
+
float rowPhase = getPhase(cell.y, uRowOffset.y);
|
|
782
|
+
float columnPhase = getPhase(cell.x, uColumnOffset.y);
|
|
783
|
+
vec2 stagger = vec2(rowPhase * uRowOffset.x, columnPhase * uColumnOffset.x);
|
|
784
|
+
vec2 adjustedGridPx = fragPx - originPx - stagger;
|
|
785
|
+
vec2 nextCell = floor(adjustedGridPx / pitch);
|
|
352
786
|
|
|
353
|
-
|
|
354
|
-
|
|
787
|
+
if (all(equal(nextCell, cell))) {
|
|
788
|
+
break;
|
|
789
|
+
}
|
|
790
|
+
|
|
791
|
+
cell = nextCell;
|
|
355
792
|
}
|
|
356
793
|
|
|
357
|
-
color =
|
|
358
|
-
|
|
794
|
+
vec4 color = vec4(0.0);
|
|
795
|
+
for (int y = -4; y <= 4; y++) {
|
|
796
|
+
for (int x = -4; x <= 4; x++) {
|
|
797
|
+
if (sampleCell(cell + vec2(float(x), float(y)), fragPx, cropStart, tileSize, pitch, originPx, color)) {
|
|
798
|
+
fragColor = color;
|
|
799
|
+
return;
|
|
800
|
+
}
|
|
801
|
+
}
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
fragColor = vec4(0.0);
|
|
359
805
|
}
|
|
806
|
+
`;
|
|
807
|
+
var compileShader2 = (gl, type, source) => {
|
|
808
|
+
const shader = gl.createShader(type);
|
|
809
|
+
if (!shader) {
|
|
810
|
+
throw new Error("Failed to create WebGL shader");
|
|
811
|
+
}
|
|
812
|
+
gl.shaderSource(shader, source);
|
|
813
|
+
gl.compileShader(shader);
|
|
814
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
815
|
+
const log = gl.getShaderInfoLog(shader);
|
|
816
|
+
gl.deleteShader(shader);
|
|
817
|
+
throw new Error(`Pattern shader compile failed: ${log ?? "(no log)"}`);
|
|
818
|
+
}
|
|
819
|
+
return shader;
|
|
820
|
+
};
|
|
821
|
+
var linkProgram2 = (gl, vs, fs) => {
|
|
822
|
+
const program = gl.createProgram();
|
|
823
|
+
if (!program) {
|
|
824
|
+
throw new Error("Failed to create WebGL program");
|
|
825
|
+
}
|
|
826
|
+
gl.attachShader(program, vs);
|
|
827
|
+
gl.attachShader(program, fs);
|
|
828
|
+
gl.linkProgram(program);
|
|
829
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
830
|
+
const log = gl.getProgramInfoLog(program);
|
|
831
|
+
gl.deleteProgram(program);
|
|
832
|
+
throw new Error(`Pattern program link failed: ${log ?? "(no log)"}`);
|
|
833
|
+
}
|
|
834
|
+
return program;
|
|
835
|
+
};
|
|
836
|
+
var pattern = createEffect2({
|
|
837
|
+
type: "dev.remotion.effects.pattern",
|
|
838
|
+
label: "pattern()",
|
|
839
|
+
documentationLink: "https://www.remotion.dev/docs/effects/pattern",
|
|
840
|
+
backend: "webgl2",
|
|
841
|
+
calculateKey: (params) => {
|
|
842
|
+
const r = resolve2(params);
|
|
843
|
+
return `pattern-${r.scale}-${r.cropLeft}-${r.cropTop}-${r.cropRight}-${r.cropBottom}-${r.gapX}-${r.gapY}-${r.offsetU}-${r.offsetV}-${r.rowOffset}-${r.rowOffsetEvery}-${r.columnOffset}-${r.columnOffsetEvery}-${r.origin[0]}-${r.origin[1]}-${r.wrap ? 1 : 0}`;
|
|
844
|
+
},
|
|
845
|
+
setup: (target) => {
|
|
846
|
+
const gl = target.getContext("webgl2", {
|
|
847
|
+
premultipliedAlpha: true,
|
|
848
|
+
alpha: true,
|
|
849
|
+
preserveDrawingBuffer: true
|
|
850
|
+
});
|
|
851
|
+
if (!gl) {
|
|
852
|
+
throw createWebGL2ContextError2("pattern effect");
|
|
853
|
+
}
|
|
854
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
855
|
+
const vs = compileShader2(gl, gl.VERTEX_SHADER, PATTERN_VS);
|
|
856
|
+
const fs = compileShader2(gl, gl.FRAGMENT_SHADER, PATTERN_FS);
|
|
857
|
+
const program = linkProgram2(gl, vs, fs);
|
|
858
|
+
gl.deleteShader(vs);
|
|
859
|
+
gl.deleteShader(fs);
|
|
860
|
+
const vao = gl.createVertexArray();
|
|
861
|
+
if (!vao) {
|
|
862
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
863
|
+
}
|
|
864
|
+
gl.bindVertexArray(vao);
|
|
865
|
+
const data = new Float32Array([
|
|
866
|
+
-1,
|
|
867
|
+
-1,
|
|
868
|
+
0,
|
|
869
|
+
0,
|
|
870
|
+
1,
|
|
871
|
+
-1,
|
|
872
|
+
1,
|
|
873
|
+
0,
|
|
874
|
+
-1,
|
|
875
|
+
1,
|
|
876
|
+
0,
|
|
877
|
+
1,
|
|
878
|
+
1,
|
|
879
|
+
1,
|
|
880
|
+
1,
|
|
881
|
+
1
|
|
882
|
+
]);
|
|
883
|
+
const vbo = gl.createBuffer();
|
|
884
|
+
if (!vbo) {
|
|
885
|
+
throw new Error("Failed to create WebGL buffer");
|
|
886
|
+
}
|
|
887
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
888
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
889
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
890
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
891
|
+
gl.enableVertexAttribArray(aPos);
|
|
892
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
893
|
+
gl.enableVertexAttribArray(aUv);
|
|
894
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
895
|
+
gl.bindVertexArray(null);
|
|
896
|
+
const texture = gl.createTexture();
|
|
897
|
+
if (!texture) {
|
|
898
|
+
throw new Error("Failed to create WebGL texture");
|
|
899
|
+
}
|
|
900
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
901
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
902
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
903
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
904
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
905
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
906
|
+
return {
|
|
907
|
+
gl,
|
|
908
|
+
program,
|
|
909
|
+
vao,
|
|
910
|
+
vbo,
|
|
911
|
+
texture,
|
|
912
|
+
uniforms: {
|
|
913
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
914
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
915
|
+
uScale: gl.getUniformLocation(program, "uScale"),
|
|
916
|
+
uCrop: gl.getUniformLocation(program, "uCrop"),
|
|
917
|
+
uGap: gl.getUniformLocation(program, "uGap"),
|
|
918
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
919
|
+
uRowOffset: gl.getUniformLocation(program, "uRowOffset"),
|
|
920
|
+
uColumnOffset: gl.getUniformLocation(program, "uColumnOffset"),
|
|
921
|
+
uOrigin: gl.getUniformLocation(program, "uOrigin"),
|
|
922
|
+
uWrap: gl.getUniformLocation(program, "uWrap")
|
|
923
|
+
}
|
|
924
|
+
};
|
|
925
|
+
},
|
|
926
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
927
|
+
const r = resolve2(params);
|
|
928
|
+
const { gl, program, vao, texture, uniforms } = state;
|
|
929
|
+
gl.viewport(0, 0, width, height);
|
|
930
|
+
gl.clearColor(0, 0, 0, 0);
|
|
931
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
932
|
+
gl.useProgram(program);
|
|
933
|
+
gl.bindVertexArray(vao);
|
|
934
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
935
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
936
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
937
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
938
|
+
if (uniforms.uSource)
|
|
939
|
+
gl.uniform1i(uniforms.uSource, 0);
|
|
940
|
+
if (uniforms.uResolution)
|
|
941
|
+
gl.uniform2f(uniforms.uResolution, width, height);
|
|
942
|
+
if (uniforms.uScale)
|
|
943
|
+
gl.uniform1f(uniforms.uScale, r.scale);
|
|
944
|
+
if (uniforms.uCrop)
|
|
945
|
+
gl.uniform4f(uniforms.uCrop, r.cropLeft, r.cropTop, r.cropRight, r.cropBottom);
|
|
946
|
+
if (uniforms.uGap)
|
|
947
|
+
gl.uniform2f(uniforms.uGap, r.gapX, r.gapY);
|
|
948
|
+
if (uniforms.uOffset)
|
|
949
|
+
gl.uniform2f(uniforms.uOffset, r.offsetU, r.offsetV);
|
|
950
|
+
if (uniforms.uRowOffset)
|
|
951
|
+
gl.uniform2f(uniforms.uRowOffset, r.rowOffset, r.rowOffsetEvery);
|
|
952
|
+
if (uniforms.uColumnOffset)
|
|
953
|
+
gl.uniform2f(uniforms.uColumnOffset, r.columnOffset, r.columnOffsetEvery);
|
|
954
|
+
if (uniforms.uOrigin)
|
|
955
|
+
gl.uniform2f(uniforms.uOrigin, r.origin[0], r.origin[1]);
|
|
956
|
+
if (uniforms.uWrap)
|
|
957
|
+
gl.uniform1i(uniforms.uWrap, r.wrap ? 1 : 0);
|
|
958
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
959
|
+
gl.bindVertexArray(null);
|
|
960
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
961
|
+
gl.useProgram(null);
|
|
962
|
+
},
|
|
963
|
+
cleanup: ({ gl, program, vao, vbo, texture }) => {
|
|
964
|
+
gl.deleteBuffer(vbo);
|
|
965
|
+
gl.deleteProgram(program);
|
|
966
|
+
gl.deleteVertexArray(vao);
|
|
967
|
+
gl.deleteTexture(texture);
|
|
968
|
+
},
|
|
969
|
+
schema: patternSchema,
|
|
970
|
+
validateParams: validatePatternParams
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
// src/rings.ts
|
|
974
|
+
import { Internals as Internals3 } from "remotion";
|
|
975
|
+
|
|
976
|
+
// src/uv-coordinate.ts
|
|
977
|
+
var publicUvToShaderUv = (uv) => {
|
|
978
|
+
return [uv[0], 1 - uv[1]];
|
|
979
|
+
};
|
|
980
|
+
|
|
981
|
+
// src/rings.ts
|
|
982
|
+
var { createEffect: createEffect3, createWebGL2ContextError: createWebGL2ContextError3 } = Internals3;
|
|
983
|
+
var DEFAULT_COLORS2 = ["#dff4ff", "#7cc6ff"];
|
|
984
|
+
var DEFAULT_CENTER = [0.5, 0.5];
|
|
985
|
+
var DEFAULT_THICKNESS = 40;
|
|
986
|
+
var DEFAULT_GAP3 = 0;
|
|
987
|
+
var DEFAULT_OFFSET2 = 0;
|
|
988
|
+
var DEFAULT_MASK_TO_SOURCE_ALPHA2 = false;
|
|
989
|
+
var ringsSchema = {
|
|
990
|
+
colors: {
|
|
991
|
+
type: "array",
|
|
992
|
+
item: {
|
|
993
|
+
type: "color"
|
|
994
|
+
},
|
|
995
|
+
default: DEFAULT_COLORS2,
|
|
996
|
+
minLength: 2,
|
|
997
|
+
newItemDefault: "#ff0000",
|
|
998
|
+
description: "Colors",
|
|
999
|
+
keyframable: false
|
|
1000
|
+
},
|
|
1001
|
+
center: {
|
|
1002
|
+
type: "uv-coordinate",
|
|
1003
|
+
min: 0,
|
|
1004
|
+
max: 1,
|
|
1005
|
+
step: 0.01,
|
|
1006
|
+
default: DEFAULT_CENTER,
|
|
1007
|
+
description: "Center"
|
|
1008
|
+
},
|
|
1009
|
+
thickness: {
|
|
1010
|
+
type: "number",
|
|
1011
|
+
min: 0.1,
|
|
1012
|
+
max: 400,
|
|
1013
|
+
step: 0.1,
|
|
1014
|
+
default: DEFAULT_THICKNESS,
|
|
1015
|
+
description: "Thickness",
|
|
1016
|
+
hiddenFromList: false
|
|
1017
|
+
},
|
|
1018
|
+
gap: {
|
|
1019
|
+
type: "number",
|
|
1020
|
+
min: 0,
|
|
1021
|
+
max: 400,
|
|
1022
|
+
step: 0.1,
|
|
1023
|
+
default: DEFAULT_GAP3,
|
|
1024
|
+
description: "Gap",
|
|
1025
|
+
hiddenFromList: false
|
|
1026
|
+
},
|
|
1027
|
+
offset: {
|
|
1028
|
+
type: "number",
|
|
1029
|
+
step: 0.1,
|
|
1030
|
+
default: DEFAULT_OFFSET2,
|
|
1031
|
+
description: "Offset",
|
|
1032
|
+
hiddenFromList: false
|
|
1033
|
+
},
|
|
1034
|
+
maskToSourceAlpha: {
|
|
1035
|
+
type: "boolean",
|
|
1036
|
+
default: DEFAULT_MASK_TO_SOURCE_ALPHA2,
|
|
1037
|
+
description: "Mask to source alpha"
|
|
1038
|
+
}
|
|
1039
|
+
};
|
|
1040
|
+
var resolve3 = (p) => {
|
|
1041
|
+
const thickness = p.thickness ?? DEFAULT_THICKNESS;
|
|
1042
|
+
const gap = p.gap ?? DEFAULT_GAP3;
|
|
1043
|
+
return {
|
|
1044
|
+
colors: p.colors ?? DEFAULT_COLORS2,
|
|
1045
|
+
center: [...p.center ?? DEFAULT_CENTER],
|
|
1046
|
+
thickness,
|
|
1047
|
+
spacing: thickness + gap,
|
|
1048
|
+
offset: p.offset ?? DEFAULT_OFFSET2,
|
|
1049
|
+
maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA2
|
|
1050
|
+
};
|
|
1051
|
+
};
|
|
1052
|
+
var validatePositive3 = (value, name) => {
|
|
1053
|
+
if (value <= 0) {
|
|
1054
|
+
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
1055
|
+
}
|
|
1056
|
+
};
|
|
1057
|
+
var validateNonNegative3 = (value, name) => {
|
|
1058
|
+
if (value < 0) {
|
|
1059
|
+
throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
|
|
1060
|
+
}
|
|
1061
|
+
};
|
|
1062
|
+
var validateColors2 = (colors) => {
|
|
1063
|
+
if (colors === undefined) {
|
|
1064
|
+
return;
|
|
1065
|
+
}
|
|
1066
|
+
if (!Array.isArray(colors) || colors.length < 2) {
|
|
1067
|
+
throw new TypeError(`"colors" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`);
|
|
1068
|
+
}
|
|
1069
|
+
for (let i = 0;i < colors.length; i++) {
|
|
1070
|
+
assertRequiredColor(colors[i], `colors[${i}]`);
|
|
1071
|
+
}
|
|
1072
|
+
};
|
|
1073
|
+
var assertOptionalCenter = (value, name) => {
|
|
1074
|
+
if (value === undefined) {
|
|
1075
|
+
return;
|
|
1076
|
+
}
|
|
1077
|
+
if (!Array.isArray(value) || value.length !== 2 || value.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
|
|
1078
|
+
throw new TypeError(`"${name}" must be a [number, number] tuple`);
|
|
1079
|
+
}
|
|
1080
|
+
validateUnitInterval(value[0], `${name}[0]`);
|
|
1081
|
+
validateUnitInterval(value[1], `${name}[1]`);
|
|
1082
|
+
};
|
|
1083
|
+
var validateRingsParams = (params) => {
|
|
1084
|
+
assertEffectParamsObject(params, "Rings");
|
|
1085
|
+
validateColors2(params.colors);
|
|
1086
|
+
assertOptionalCenter(params.center, "center");
|
|
1087
|
+
assertOptionalFiniteNumber(params.thickness, "thickness");
|
|
1088
|
+
assertOptionalFiniteNumber(params.gap, "gap");
|
|
1089
|
+
assertOptionalFiniteNumber(params.offset, "offset");
|
|
1090
|
+
assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
|
|
1091
|
+
const thickness = params.thickness ?? DEFAULT_THICKNESS;
|
|
1092
|
+
const gap = params.gap ?? DEFAULT_GAP3;
|
|
1093
|
+
validatePositive3(thickness, "thickness");
|
|
1094
|
+
validateNonNegative3(gap, "gap");
|
|
1095
|
+
};
|
|
1096
|
+
var RINGS_VS = `#version 300 es
|
|
1097
|
+
in vec2 aPos;
|
|
1098
|
+
in vec2 aUv;
|
|
1099
|
+
out vec2 vUv;
|
|
360
1100
|
|
|
361
1101
|
void main() {
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
vec2 originPx = (uOrigin + uOffset) * uResolution;
|
|
369
|
-
vec2 fragPx = patternUv * uResolution;
|
|
1102
|
+
vUv = aUv;
|
|
1103
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
1104
|
+
}
|
|
1105
|
+
`;
|
|
1106
|
+
var RINGS_FS = `#version 300 es
|
|
1107
|
+
precision highp float;
|
|
370
1108
|
|
|
371
|
-
|
|
372
|
-
|
|
1109
|
+
in vec2 vUv;
|
|
1110
|
+
out vec4 fragColor;
|
|
373
1111
|
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
1112
|
+
uniform sampler2D uSource;
|
|
1113
|
+
uniform sampler2D uPalette;
|
|
1114
|
+
uniform vec2 uResolution;
|
|
1115
|
+
uniform float uNumColors;
|
|
1116
|
+
uniform vec2 uCenter;
|
|
1117
|
+
uniform float uThickness;
|
|
1118
|
+
uniform float uSpacing;
|
|
1119
|
+
uniform float uOffset;
|
|
1120
|
+
uniform bool uMaskToSourceAlpha;
|
|
380
1121
|
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
1122
|
+
void main() {
|
|
1123
|
+
vec4 texColor = texture(uSource, vUv);
|
|
1124
|
+
float thickness = max(uThickness, 0.001);
|
|
1125
|
+
float spacing = max(uSpacing, 0.001);
|
|
1126
|
+
float cycle = spacing * uNumColors;
|
|
1127
|
+
vec2 pixelPosition = vUv * uResolution;
|
|
1128
|
+
vec2 centerPosition = uCenter * uResolution;
|
|
1129
|
+
float radius = length(pixelPosition - centerPosition);
|
|
1130
|
+
float position = mod(radius + uOffset, cycle);
|
|
1131
|
+
if (position < 0.0) {
|
|
1132
|
+
position += cycle;
|
|
1133
|
+
}
|
|
384
1134
|
|
|
385
|
-
|
|
1135
|
+
float colorIndex = floor(position / spacing);
|
|
1136
|
+
float inStripe = mod(position, spacing);
|
|
1137
|
+
if (inStripe > thickness) {
|
|
1138
|
+
fragColor = texColor;
|
|
1139
|
+
return;
|
|
386
1140
|
}
|
|
387
1141
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
1142
|
+
float texCoord = (colorIndex + 0.5) / uNumColors;
|
|
1143
|
+
vec4 ringColor = texture(uPalette, vec2(texCoord, 0.5));
|
|
1144
|
+
float ringAlpha = ringColor.a;
|
|
1145
|
+
vec3 premultipliedRing = ringColor.rgb * ringAlpha;
|
|
1146
|
+
|
|
1147
|
+
if (uMaskToSourceAlpha) {
|
|
1148
|
+
fragColor = vec4(
|
|
1149
|
+
premultipliedRing * texColor.a + texColor.rgb * (1.0 - ringAlpha),
|
|
1150
|
+
texColor.a
|
|
1151
|
+
);
|
|
1152
|
+
return;
|
|
396
1153
|
}
|
|
397
1154
|
|
|
398
|
-
fragColor = vec4(
|
|
1155
|
+
fragColor = vec4(
|
|
1156
|
+
premultipliedRing + texColor.rgb * (1.0 - ringAlpha),
|
|
1157
|
+
ringAlpha + texColor.a * (1.0 - ringAlpha)
|
|
1158
|
+
);
|
|
399
1159
|
}
|
|
400
1160
|
`;
|
|
401
|
-
var
|
|
1161
|
+
var compileShader3 = (gl, type, source) => {
|
|
402
1162
|
const shader = gl.createShader(type);
|
|
403
1163
|
if (!shader) {
|
|
404
1164
|
throw new Error("Failed to create WebGL shader");
|
|
@@ -408,11 +1168,11 @@ var compileShader = (gl, type, source) => {
|
|
|
408
1168
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
409
1169
|
const log = gl.getShaderInfoLog(shader);
|
|
410
1170
|
gl.deleteShader(shader);
|
|
411
|
-
throw new Error(`
|
|
1171
|
+
throw new Error(`Rings shader compile failed: ${log ?? "(no log)"}`);
|
|
412
1172
|
}
|
|
413
1173
|
return shader;
|
|
414
1174
|
};
|
|
415
|
-
var
|
|
1175
|
+
var linkProgram3 = (gl, vs, fs) => {
|
|
416
1176
|
const program = gl.createProgram();
|
|
417
1177
|
if (!program) {
|
|
418
1178
|
throw new Error("Failed to create WebGL program");
|
|
@@ -423,271 +1183,340 @@ var linkProgram = (gl, vs, fs) => {
|
|
|
423
1183
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
424
1184
|
const log = gl.getProgramInfoLog(program);
|
|
425
1185
|
gl.deleteProgram(program);
|
|
426
|
-
throw new Error(`
|
|
1186
|
+
throw new Error(`Rings program link failed: ${log ?? "(no log)"}`);
|
|
1187
|
+
}
|
|
1188
|
+
return program;
|
|
1189
|
+
};
|
|
1190
|
+
var createProgram2 = (gl, vertexSource, fragmentSource) => {
|
|
1191
|
+
const vs = compileShader3(gl, gl.VERTEX_SHADER, vertexSource);
|
|
1192
|
+
const fs = compileShader3(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
1193
|
+
const program = linkProgram3(gl, vs, fs);
|
|
1194
|
+
gl.deleteShader(vs);
|
|
1195
|
+
gl.deleteShader(fs);
|
|
1196
|
+
return program;
|
|
1197
|
+
};
|
|
1198
|
+
var createTexture2 = (gl, filter) => {
|
|
1199
|
+
const texture = gl.createTexture();
|
|
1200
|
+
if (!texture) {
|
|
1201
|
+
throw new Error("Failed to create WebGL texture");
|
|
1202
|
+
}
|
|
1203
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
1204
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
1205
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
1206
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
1207
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1208
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
1209
|
+
return texture;
|
|
1210
|
+
};
|
|
1211
|
+
var setupRings = (target) => {
|
|
1212
|
+
const gl = target.getContext("webgl2", {
|
|
1213
|
+
premultipliedAlpha: true,
|
|
1214
|
+
alpha: true,
|
|
1215
|
+
preserveDrawingBuffer: true
|
|
1216
|
+
});
|
|
1217
|
+
if (!gl) {
|
|
1218
|
+
throw createWebGL2ContextError3("rings effect");
|
|
1219
|
+
}
|
|
1220
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
1221
|
+
const program = createProgram2(gl, RINGS_VS, RINGS_FS);
|
|
1222
|
+
const vao = gl.createVertexArray();
|
|
1223
|
+
if (!vao) {
|
|
1224
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
1225
|
+
}
|
|
1226
|
+
gl.bindVertexArray(vao);
|
|
1227
|
+
const data = new Float32Array([
|
|
1228
|
+
-1,
|
|
1229
|
+
-1,
|
|
1230
|
+
0,
|
|
1231
|
+
0,
|
|
1232
|
+
1,
|
|
1233
|
+
-1,
|
|
1234
|
+
1,
|
|
1235
|
+
0,
|
|
1236
|
+
-1,
|
|
1237
|
+
1,
|
|
1238
|
+
0,
|
|
1239
|
+
1,
|
|
1240
|
+
1,
|
|
1241
|
+
1,
|
|
1242
|
+
1,
|
|
1243
|
+
1
|
|
1244
|
+
]);
|
|
1245
|
+
const vbo = gl.createBuffer();
|
|
1246
|
+
if (!vbo) {
|
|
1247
|
+
throw new Error("Failed to create WebGL buffer");
|
|
1248
|
+
}
|
|
1249
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
1250
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
1251
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
1252
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
1253
|
+
gl.enableVertexAttribArray(aPos);
|
|
1254
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
1255
|
+
gl.enableVertexAttribArray(aUv);
|
|
1256
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
1257
|
+
gl.bindVertexArray(null);
|
|
1258
|
+
const colorCanvas = document.createElement("canvas");
|
|
1259
|
+
colorCanvas.width = 1;
|
|
1260
|
+
colorCanvas.height = 1;
|
|
1261
|
+
const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
|
|
1262
|
+
if (!colorCtx) {
|
|
1263
|
+
throw new Error("Failed to acquire 2D context for color parsing");
|
|
1264
|
+
}
|
|
1265
|
+
return {
|
|
1266
|
+
gl,
|
|
1267
|
+
program,
|
|
1268
|
+
vao,
|
|
1269
|
+
vbo,
|
|
1270
|
+
sourceTexture: createTexture2(gl, gl.LINEAR),
|
|
1271
|
+
paletteTexture: createTexture2(gl, gl.NEAREST),
|
|
1272
|
+
colorCtx,
|
|
1273
|
+
uniforms: {
|
|
1274
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
1275
|
+
uPalette: gl.getUniformLocation(program, "uPalette"),
|
|
1276
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
1277
|
+
uNumColors: gl.getUniformLocation(program, "uNumColors"),
|
|
1278
|
+
uCenter: gl.getUniformLocation(program, "uCenter"),
|
|
1279
|
+
uThickness: gl.getUniformLocation(program, "uThickness"),
|
|
1280
|
+
uSpacing: gl.getUniformLocation(program, "uSpacing"),
|
|
1281
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
1282
|
+
uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
|
|
1283
|
+
},
|
|
1284
|
+
cachedPaletteKey: "",
|
|
1285
|
+
palettePixelData: new Uint8Array(0)
|
|
1286
|
+
};
|
|
1287
|
+
};
|
|
1288
|
+
var updatePalette2 = (state, colors) => {
|
|
1289
|
+
const paletteKey = colors.join("|");
|
|
1290
|
+
const paletteDirty = state.cachedPaletteKey !== paletteKey;
|
|
1291
|
+
if (!paletteDirty) {
|
|
1292
|
+
return false;
|
|
1293
|
+
}
|
|
1294
|
+
state.cachedPaletteKey = paletteKey;
|
|
1295
|
+
const len = colors.length * 4;
|
|
1296
|
+
if (state.palettePixelData.length !== len) {
|
|
1297
|
+
state.palettePixelData = new Uint8Array(len);
|
|
1298
|
+
}
|
|
1299
|
+
const { palettePixelData } = state;
|
|
1300
|
+
for (let i = 0;i < colors.length; i++) {
|
|
1301
|
+
const color = parseColorRgba(state.colorCtx, colors[i]);
|
|
1302
|
+
palettePixelData[i * 4] = color[0];
|
|
1303
|
+
palettePixelData[i * 4 + 1] = color[1];
|
|
1304
|
+
palettePixelData[i * 4 + 2] = color[2];
|
|
1305
|
+
palettePixelData[i * 4 + 3] = color[3];
|
|
427
1306
|
}
|
|
428
|
-
return
|
|
1307
|
+
return true;
|
|
429
1308
|
};
|
|
430
|
-
var
|
|
431
|
-
type: "dev.remotion.effects.
|
|
432
|
-
label: "
|
|
433
|
-
documentationLink: "https://www.remotion.dev/docs/effects/
|
|
1309
|
+
var rings = createEffect3({
|
|
1310
|
+
type: "dev.remotion.effects.rings",
|
|
1311
|
+
label: "rings()",
|
|
1312
|
+
documentationLink: "https://www.remotion.dev/docs/effects/rings",
|
|
434
1313
|
backend: "webgl2",
|
|
435
1314
|
calculateKey: (params) => {
|
|
436
|
-
const r =
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
setup: (target) => {
|
|
440
|
-
const gl = target.getContext("webgl2", {
|
|
441
|
-
premultipliedAlpha: true,
|
|
442
|
-
alpha: true,
|
|
443
|
-
preserveDrawingBuffer: true
|
|
444
|
-
});
|
|
445
|
-
if (!gl) {
|
|
446
|
-
throw createWebGL2ContextError("pattern effect");
|
|
447
|
-
}
|
|
448
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
449
|
-
const vs = compileShader(gl, gl.VERTEX_SHADER, PATTERN_VS);
|
|
450
|
-
const fs = compileShader(gl, gl.FRAGMENT_SHADER, PATTERN_FS);
|
|
451
|
-
const program = linkProgram(gl, vs, fs);
|
|
452
|
-
gl.deleteShader(vs);
|
|
453
|
-
gl.deleteShader(fs);
|
|
454
|
-
const vao = gl.createVertexArray();
|
|
455
|
-
if (!vao) {
|
|
456
|
-
throw new Error("Failed to create WebGL vertex array");
|
|
457
|
-
}
|
|
458
|
-
gl.bindVertexArray(vao);
|
|
459
|
-
const data = new Float32Array([
|
|
460
|
-
-1,
|
|
461
|
-
-1,
|
|
462
|
-
0,
|
|
463
|
-
0,
|
|
464
|
-
1,
|
|
465
|
-
-1,
|
|
466
|
-
1,
|
|
467
|
-
0,
|
|
468
|
-
-1,
|
|
469
|
-
1,
|
|
470
|
-
0,
|
|
471
|
-
1,
|
|
472
|
-
1,
|
|
473
|
-
1,
|
|
474
|
-
1,
|
|
475
|
-
1
|
|
476
|
-
]);
|
|
477
|
-
const vbo = gl.createBuffer();
|
|
478
|
-
if (!vbo) {
|
|
479
|
-
throw new Error("Failed to create WebGL buffer");
|
|
480
|
-
}
|
|
481
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
482
|
-
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
483
|
-
const aPos = gl.getAttribLocation(program, "aPos");
|
|
484
|
-
const aUv = gl.getAttribLocation(program, "aUv");
|
|
485
|
-
gl.enableVertexAttribArray(aPos);
|
|
486
|
-
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
487
|
-
gl.enableVertexAttribArray(aUv);
|
|
488
|
-
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
489
|
-
gl.bindVertexArray(null);
|
|
490
|
-
const texture = gl.createTexture();
|
|
491
|
-
if (!texture) {
|
|
492
|
-
throw new Error("Failed to create WebGL texture");
|
|
493
|
-
}
|
|
494
|
-
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
495
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
496
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
497
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
498
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
499
|
-
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
500
|
-
return {
|
|
501
|
-
gl,
|
|
502
|
-
program,
|
|
503
|
-
vao,
|
|
504
|
-
vbo,
|
|
505
|
-
texture,
|
|
506
|
-
uniforms: {
|
|
507
|
-
uSource: gl.getUniformLocation(program, "uSource"),
|
|
508
|
-
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
509
|
-
uScale: gl.getUniformLocation(program, "uScale"),
|
|
510
|
-
uCrop: gl.getUniformLocation(program, "uCrop"),
|
|
511
|
-
uGap: gl.getUniformLocation(program, "uGap"),
|
|
512
|
-
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
513
|
-
uRowOffset: gl.getUniformLocation(program, "uRowOffset"),
|
|
514
|
-
uColumnOffset: gl.getUniformLocation(program, "uColumnOffset"),
|
|
515
|
-
uOrigin: gl.getUniformLocation(program, "uOrigin"),
|
|
516
|
-
uWrap: gl.getUniformLocation(program, "uWrap")
|
|
517
|
-
}
|
|
518
|
-
};
|
|
1315
|
+
const r = resolve3(params);
|
|
1316
|
+
const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
|
|
1317
|
+
return `rings-${r.colors.join("|")}-${r.center.join(":")}-${r.thickness}-${r.spacing}-${r.offset}${maskSuffix}`;
|
|
519
1318
|
},
|
|
1319
|
+
setup: (target) => setupRings(target),
|
|
520
1320
|
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
521
|
-
const r =
|
|
522
|
-
const
|
|
1321
|
+
const r = resolve3(params);
|
|
1322
|
+
const paletteDirty = updatePalette2(state, r.colors);
|
|
1323
|
+
const { gl, program, sourceTexture, paletteTexture, uniforms, vao } = state;
|
|
523
1324
|
gl.viewport(0, 0, width, height);
|
|
1325
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
524
1326
|
gl.clearColor(0, 0, 0, 0);
|
|
525
1327
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
526
|
-
gl.useProgram(program);
|
|
527
|
-
gl.bindVertexArray(vao);
|
|
528
1328
|
gl.activeTexture(gl.TEXTURE0);
|
|
529
|
-
gl.bindTexture(gl.TEXTURE_2D,
|
|
1329
|
+
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
|
|
1330
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
530
1331
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
531
1332
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
1333
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
1334
|
+
gl.bindTexture(gl.TEXTURE_2D, paletteTexture);
|
|
1335
|
+
if (paletteDirty) {
|
|
1336
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
1337
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
1338
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, r.colors.length, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, state.palettePixelData);
|
|
1339
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
1340
|
+
}
|
|
1341
|
+
gl.useProgram(program);
|
|
532
1342
|
if (uniforms.uSource)
|
|
533
1343
|
gl.uniform1i(uniforms.uSource, 0);
|
|
1344
|
+
if (uniforms.uPalette)
|
|
1345
|
+
gl.uniform1i(uniforms.uPalette, 1);
|
|
534
1346
|
if (uniforms.uResolution)
|
|
535
1347
|
gl.uniform2f(uniforms.uResolution, width, height);
|
|
536
|
-
if (uniforms.
|
|
537
|
-
gl.uniform1f(uniforms.
|
|
538
|
-
if (uniforms.
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
1348
|
+
if (uniforms.uNumColors)
|
|
1349
|
+
gl.uniform1f(uniforms.uNumColors, r.colors.length);
|
|
1350
|
+
if (uniforms.uCenter) {
|
|
1351
|
+
const shaderCenter = publicUvToShaderUv(r.center);
|
|
1352
|
+
gl.uniform2f(uniforms.uCenter, shaderCenter[0], shaderCenter[1]);
|
|
1353
|
+
}
|
|
1354
|
+
if (uniforms.uThickness)
|
|
1355
|
+
gl.uniform1f(uniforms.uThickness, r.thickness);
|
|
1356
|
+
if (uniforms.uSpacing)
|
|
1357
|
+
gl.uniform1f(uniforms.uSpacing, r.spacing);
|
|
542
1358
|
if (uniforms.uOffset)
|
|
543
|
-
gl.
|
|
544
|
-
if (uniforms.
|
|
545
|
-
gl.
|
|
546
|
-
|
|
547
|
-
gl.uniform2f(uniforms.uColumnOffset, r.columnOffset, r.columnOffsetEvery);
|
|
548
|
-
if (uniforms.uOrigin)
|
|
549
|
-
gl.uniform2f(uniforms.uOrigin, r.origin[0], r.origin[1]);
|
|
550
|
-
if (uniforms.uWrap)
|
|
551
|
-
gl.uniform1i(uniforms.uWrap, r.wrap ? 1 : 0);
|
|
1359
|
+
gl.uniform1f(uniforms.uOffset, r.offset);
|
|
1360
|
+
if (uniforms.uMaskToSourceAlpha)
|
|
1361
|
+
gl.uniform1i(uniforms.uMaskToSourceAlpha, r.maskToSourceAlpha ? 1 : 0);
|
|
1362
|
+
gl.bindVertexArray(vao);
|
|
552
1363
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
553
1364
|
gl.bindVertexArray(null);
|
|
554
1365
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
555
1366
|
gl.useProgram(null);
|
|
556
1367
|
},
|
|
557
|
-
cleanup: ({ gl, program, vao, vbo,
|
|
1368
|
+
cleanup: ({ gl, program, vao, vbo, sourceTexture, paletteTexture }) => {
|
|
1369
|
+
gl.deleteTexture(sourceTexture);
|
|
1370
|
+
gl.deleteTexture(paletteTexture);
|
|
558
1371
|
gl.deleteBuffer(vbo);
|
|
559
1372
|
gl.deleteProgram(program);
|
|
560
1373
|
gl.deleteVertexArray(vao);
|
|
561
|
-
gl.deleteTexture(texture);
|
|
562
1374
|
},
|
|
563
|
-
schema:
|
|
564
|
-
validateParams:
|
|
1375
|
+
schema: ringsSchema,
|
|
1376
|
+
validateParams: validateRingsParams
|
|
565
1377
|
});
|
|
566
1378
|
|
|
567
|
-
// src/
|
|
568
|
-
import { Internals as
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
var
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
var
|
|
577
|
-
var
|
|
578
|
-
var
|
|
579
|
-
var
|
|
580
|
-
var
|
|
581
|
-
var
|
|
582
|
-
|
|
583
|
-
var ringsSchema = {
|
|
584
|
-
colors: {
|
|
585
|
-
type: "array",
|
|
586
|
-
item: {
|
|
587
|
-
type: "color"
|
|
588
|
-
},
|
|
589
|
-
default: DEFAULT_COLORS,
|
|
590
|
-
minLength: 2,
|
|
591
|
-
newItemDefault: "#ff0000",
|
|
592
|
-
description: "Colors",
|
|
593
|
-
keyframable: false
|
|
594
|
-
},
|
|
595
|
-
center: {
|
|
596
|
-
type: "uv-coordinate",
|
|
597
|
-
min: 0,
|
|
598
|
-
max: 1,
|
|
599
|
-
step: 0.01,
|
|
600
|
-
default: DEFAULT_CENTER,
|
|
601
|
-
description: "Center"
|
|
602
|
-
},
|
|
603
|
-
thickness: {
|
|
1379
|
+
// src/gridlines.ts
|
|
1380
|
+
import { Internals as Internals4 } from "remotion";
|
|
1381
|
+
var { createEffect: createEffect4, createWebGL2ContextError: createWebGL2ContextError4 } = Internals4;
|
|
1382
|
+
var DEFAULT_GRID_SIZE = 64;
|
|
1383
|
+
var DEFAULT_LINE_WIDTH = 2;
|
|
1384
|
+
var DEFAULT_LINE_COLOR = "#ffffff";
|
|
1385
|
+
var DEFAULT_BACKGROUND_COLOR = "transparent";
|
|
1386
|
+
var DEFAULT_ROTATION = 0;
|
|
1387
|
+
var DEFAULT_ROTATION_X = 0;
|
|
1388
|
+
var DEFAULT_ROTATION_Y = 0;
|
|
1389
|
+
var DEFAULT_PERSPECTIVE = 0;
|
|
1390
|
+
var DEFAULT_OFFSET_X2 = 0;
|
|
1391
|
+
var DEFAULT_OFFSET_Y2 = 0;
|
|
1392
|
+
var DEFAULT_MASK_TO_SOURCE_ALPHA3 = false;
|
|
1393
|
+
var gridlinesSchema = {
|
|
1394
|
+
gridSize: {
|
|
604
1395
|
type: "number",
|
|
605
|
-
min:
|
|
1396
|
+
min: 1,
|
|
606
1397
|
max: 400,
|
|
1398
|
+
step: 1,
|
|
1399
|
+
default: DEFAULT_GRID_SIZE,
|
|
1400
|
+
description: "Grid size",
|
|
1401
|
+
hiddenFromList: false
|
|
1402
|
+
},
|
|
1403
|
+
lineWidth: {
|
|
1404
|
+
type: "number",
|
|
1405
|
+
min: 0,
|
|
1406
|
+
max: 100,
|
|
607
1407
|
step: 0.1,
|
|
608
|
-
default:
|
|
609
|
-
description: "
|
|
1408
|
+
default: DEFAULT_LINE_WIDTH,
|
|
1409
|
+
description: "Line width",
|
|
610
1410
|
hiddenFromList: false
|
|
611
1411
|
},
|
|
612
|
-
|
|
1412
|
+
lineColor: {
|
|
1413
|
+
type: "color",
|
|
1414
|
+
default: DEFAULT_LINE_COLOR,
|
|
1415
|
+
description: "Line color"
|
|
1416
|
+
},
|
|
1417
|
+
backgroundColor: {
|
|
1418
|
+
type: "color",
|
|
1419
|
+
default: DEFAULT_BACKGROUND_COLOR,
|
|
1420
|
+
description: "Background color"
|
|
1421
|
+
},
|
|
1422
|
+
rotation: {
|
|
1423
|
+
type: "rotation-degrees",
|
|
1424
|
+
min: -180,
|
|
1425
|
+
max: 180,
|
|
1426
|
+
step: 1,
|
|
1427
|
+
default: DEFAULT_ROTATION,
|
|
1428
|
+
description: "Rotation"
|
|
1429
|
+
},
|
|
1430
|
+
rotationX: {
|
|
1431
|
+
type: "rotation-degrees",
|
|
1432
|
+
min: -180,
|
|
1433
|
+
max: 180,
|
|
1434
|
+
step: 0.1,
|
|
1435
|
+
default: DEFAULT_ROTATION_X,
|
|
1436
|
+
description: "Rotation X"
|
|
1437
|
+
},
|
|
1438
|
+
rotationY: {
|
|
1439
|
+
type: "rotation-degrees",
|
|
1440
|
+
min: -180,
|
|
1441
|
+
max: 180,
|
|
1442
|
+
step: 0.1,
|
|
1443
|
+
default: DEFAULT_ROTATION_Y,
|
|
1444
|
+
description: "Rotation Y"
|
|
1445
|
+
},
|
|
1446
|
+
perspective: {
|
|
613
1447
|
type: "number",
|
|
614
1448
|
min: 0,
|
|
1449
|
+
max: 4000,
|
|
1450
|
+
step: 1,
|
|
1451
|
+
default: DEFAULT_PERSPECTIVE,
|
|
1452
|
+
description: "Perspective",
|
|
1453
|
+
hiddenFromList: false
|
|
1454
|
+
},
|
|
1455
|
+
offsetX: {
|
|
1456
|
+
type: "number",
|
|
1457
|
+
min: -400,
|
|
615
1458
|
max: 400,
|
|
616
1459
|
step: 0.1,
|
|
617
|
-
default:
|
|
618
|
-
description: "
|
|
1460
|
+
default: DEFAULT_OFFSET_X2,
|
|
1461
|
+
description: "Offset X",
|
|
619
1462
|
hiddenFromList: false
|
|
620
1463
|
},
|
|
621
|
-
|
|
1464
|
+
offsetY: {
|
|
622
1465
|
type: "number",
|
|
1466
|
+
min: -400,
|
|
1467
|
+
max: 400,
|
|
623
1468
|
step: 0.1,
|
|
624
|
-
default:
|
|
625
|
-
description: "Offset",
|
|
1469
|
+
default: DEFAULT_OFFSET_Y2,
|
|
1470
|
+
description: "Offset Y",
|
|
626
1471
|
hiddenFromList: false
|
|
627
1472
|
},
|
|
628
1473
|
maskToSourceAlpha: {
|
|
629
1474
|
type: "boolean",
|
|
630
|
-
default:
|
|
631
|
-
description: "Mask to source alpha"
|
|
632
|
-
}
|
|
633
|
-
};
|
|
634
|
-
var resolve2 = (p) => {
|
|
635
|
-
const thickness = p.thickness ?? DEFAULT_THICKNESS;
|
|
636
|
-
const gap = p.gap ?? DEFAULT_GAP2;
|
|
637
|
-
return {
|
|
638
|
-
colors: p.colors ?? DEFAULT_COLORS,
|
|
639
|
-
center: [...p.center ?? DEFAULT_CENTER],
|
|
640
|
-
thickness,
|
|
641
|
-
spacing: thickness + gap,
|
|
642
|
-
offset: p.offset ?? DEFAULT_OFFSET2,
|
|
643
|
-
maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA
|
|
644
|
-
};
|
|
645
|
-
};
|
|
646
|
-
var validatePositive2 = (value, name) => {
|
|
647
|
-
if (value <= 0) {
|
|
648
|
-
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
649
|
-
}
|
|
650
|
-
};
|
|
651
|
-
var validateNonNegative2 = (value, name) => {
|
|
652
|
-
if (value < 0) {
|
|
653
|
-
throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
|
|
654
|
-
}
|
|
655
|
-
};
|
|
656
|
-
var validateColors = (colors) => {
|
|
657
|
-
if (colors === undefined) {
|
|
658
|
-
return;
|
|
659
|
-
}
|
|
660
|
-
if (!Array.isArray(colors) || colors.length < 2) {
|
|
661
|
-
throw new TypeError(`"colors" must be an array with at least 2 colors, but got ${JSON.stringify(colors)}`);
|
|
662
|
-
}
|
|
663
|
-
for (let i = 0;i < colors.length; i++) {
|
|
664
|
-
assertRequiredColor(colors[i], `colors[${i}]`);
|
|
1475
|
+
default: DEFAULT_MASK_TO_SOURCE_ALPHA3,
|
|
1476
|
+
description: "Mask to source alpha"
|
|
665
1477
|
}
|
|
666
1478
|
};
|
|
667
|
-
var
|
|
668
|
-
|
|
669
|
-
|
|
1479
|
+
var resolve4 = (p) => ({
|
|
1480
|
+
gridSize: p.gridSize ?? DEFAULT_GRID_SIZE,
|
|
1481
|
+
lineWidth: p.lineWidth ?? DEFAULT_LINE_WIDTH,
|
|
1482
|
+
lineColor: p.lineColor ?? DEFAULT_LINE_COLOR,
|
|
1483
|
+
backgroundColor: p.backgroundColor ?? DEFAULT_BACKGROUND_COLOR,
|
|
1484
|
+
rotation: p.rotation ?? DEFAULT_ROTATION,
|
|
1485
|
+
rotationX: p.rotationX ?? DEFAULT_ROTATION_X,
|
|
1486
|
+
rotationY: p.rotationY ?? DEFAULT_ROTATION_Y,
|
|
1487
|
+
perspective: p.perspective ?? DEFAULT_PERSPECTIVE,
|
|
1488
|
+
offsetX: p.offsetX ?? DEFAULT_OFFSET_X2,
|
|
1489
|
+
offsetY: p.offsetY ?? DEFAULT_OFFSET_Y2,
|
|
1490
|
+
maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA3
|
|
1491
|
+
});
|
|
1492
|
+
var validatePositive4 = (value, name) => {
|
|
1493
|
+
if (value <= 0) {
|
|
1494
|
+
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
670
1495
|
}
|
|
671
|
-
|
|
672
|
-
|
|
1496
|
+
};
|
|
1497
|
+
var validateNonNegative4 = (value, name) => {
|
|
1498
|
+
if (value < 0) {
|
|
1499
|
+
throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
|
|
673
1500
|
}
|
|
674
|
-
validateUnitInterval(value[0], `${name}[0]`);
|
|
675
|
-
validateUnitInterval(value[1], `${name}[1]`);
|
|
676
1501
|
};
|
|
677
|
-
var
|
|
678
|
-
assertEffectParamsObject(params, "
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
assertOptionalFiniteNumber(params.
|
|
682
|
-
assertOptionalFiniteNumber(params.
|
|
683
|
-
assertOptionalFiniteNumber(params.
|
|
1502
|
+
var validateGridlinesParams = (params) => {
|
|
1503
|
+
assertEffectParamsObject(params, "Gridlines");
|
|
1504
|
+
assertOptionalFiniteNumber(params.gridSize, "gridSize");
|
|
1505
|
+
assertOptionalFiniteNumber(params.lineWidth, "lineWidth");
|
|
1506
|
+
assertOptionalFiniteNumber(params.rotation, "rotation");
|
|
1507
|
+
assertOptionalFiniteNumber(params.rotationX, "rotationX");
|
|
1508
|
+
assertOptionalFiniteNumber(params.rotationY, "rotationY");
|
|
1509
|
+
assertOptionalFiniteNumber(params.perspective, "perspective");
|
|
1510
|
+
assertOptionalFiniteNumber(params.offsetX, "offsetX");
|
|
1511
|
+
assertOptionalFiniteNumber(params.offsetY, "offsetY");
|
|
1512
|
+
assertOptionalColor(params.lineColor, "lineColor");
|
|
1513
|
+
assertOptionalColor(params.backgroundColor, "backgroundColor");
|
|
684
1514
|
assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
validateNonNegative2(gap, "gap");
|
|
1515
|
+
validatePositive4(params.gridSize ?? DEFAULT_GRID_SIZE, "gridSize");
|
|
1516
|
+
validateNonNegative4(params.lineWidth ?? DEFAULT_LINE_WIDTH, "lineWidth");
|
|
1517
|
+
validateNonNegative4(params.perspective ?? DEFAULT_PERSPECTIVE, "perspective");
|
|
689
1518
|
};
|
|
690
|
-
var
|
|
1519
|
+
var GRIDLINES_VS = `#version 300 es
|
|
691
1520
|
in vec2 aPos;
|
|
692
1521
|
in vec2 aUv;
|
|
693
1522
|
out vec2 vUv;
|
|
@@ -697,62 +1526,123 @@ void main() {
|
|
|
697
1526
|
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
698
1527
|
}
|
|
699
1528
|
`;
|
|
700
|
-
var
|
|
1529
|
+
var GRIDLINES_FS = `#version 300 es
|
|
701
1530
|
precision highp float;
|
|
702
1531
|
|
|
703
1532
|
in vec2 vUv;
|
|
704
1533
|
out vec4 fragColor;
|
|
705
1534
|
|
|
706
1535
|
uniform sampler2D uSource;
|
|
707
|
-
uniform sampler2D uPalette;
|
|
708
1536
|
uniform vec2 uResolution;
|
|
709
|
-
uniform float
|
|
710
|
-
uniform
|
|
711
|
-
uniform
|
|
712
|
-
uniform
|
|
713
|
-
uniform float
|
|
1537
|
+
uniform float uGridSize;
|
|
1538
|
+
uniform float uLineWidth;
|
|
1539
|
+
uniform vec4 uLineColor;
|
|
1540
|
+
uniform vec4 uBackgroundColor;
|
|
1541
|
+
uniform float uRotation;
|
|
1542
|
+
uniform float uRotationX;
|
|
1543
|
+
uniform float uRotationY;
|
|
1544
|
+
uniform float uPerspective;
|
|
1545
|
+
uniform vec2 uOffset;
|
|
714
1546
|
uniform bool uMaskToSourceAlpha;
|
|
715
1547
|
|
|
1548
|
+
vec4 sourceOver(vec4 backdrop, vec4 overlay) {
|
|
1549
|
+
return overlay + backdrop * (1.0 - overlay.a);
|
|
1550
|
+
}
|
|
1551
|
+
|
|
1552
|
+
vec4 sourceAtop(vec4 backdrop, vec4 overlay) {
|
|
1553
|
+
return vec4(
|
|
1554
|
+
overlay.rgb * backdrop.a + backdrop.rgb * (1.0 - overlay.a),
|
|
1555
|
+
backdrop.a
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
|
|
1559
|
+
mat3 rotationMatrix(float rotationX, float rotationY, float rotationZ) {
|
|
1560
|
+
float sx = sin(rotationX);
|
|
1561
|
+
float cx = cos(rotationX);
|
|
1562
|
+
float sy = sin(rotationY);
|
|
1563
|
+
float cy = cos(rotationY);
|
|
1564
|
+
float sz = sin(rotationZ);
|
|
1565
|
+
float cz = cos(rotationZ);
|
|
1566
|
+
|
|
1567
|
+
mat3 rx = mat3(
|
|
1568
|
+
1.0, 0.0, 0.0,
|
|
1569
|
+
0.0, cx, sx,
|
|
1570
|
+
0.0, -sx, cx
|
|
1571
|
+
);
|
|
1572
|
+
mat3 ry = mat3(
|
|
1573
|
+
cy, 0.0, -sy,
|
|
1574
|
+
0.0, 1.0, 0.0,
|
|
1575
|
+
sy, 0.0, cy
|
|
1576
|
+
);
|
|
1577
|
+
mat3 rz = mat3(
|
|
1578
|
+
cz, sz, 0.0,
|
|
1579
|
+
-sz, cz, 0.0,
|
|
1580
|
+
0.0, 0.0, 1.0
|
|
1581
|
+
);
|
|
1582
|
+
|
|
1583
|
+
return rz * ry * rx;
|
|
1584
|
+
}
|
|
1585
|
+
|
|
716
1586
|
void main() {
|
|
717
1587
|
vec4 texColor = texture(uSource, vUv);
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
vec2 pixelPosition = vUv * uResolution;
|
|
722
|
-
vec2 centerPosition = uCenter * uResolution;
|
|
723
|
-
float radius = length(pixelPosition - centerPosition);
|
|
724
|
-
float position = mod(radius + uOffset, cycle);
|
|
725
|
-
if (position < 0.0) {
|
|
726
|
-
position += cycle;
|
|
727
|
-
}
|
|
1588
|
+
vec2 centered = vUv * uResolution - uResolution * 0.5;
|
|
1589
|
+
mat3 rotation = rotationMatrix(uRotationX, uRotationY, uRotation);
|
|
1590
|
+
vec2 gridCoord;
|
|
728
1591
|
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
1592
|
+
if (uPerspective <= 0.0) {
|
|
1593
|
+
vec3 rotated = rotation * vec3(centered, 0.0);
|
|
1594
|
+
gridCoord = rotated.xy + uOffset;
|
|
1595
|
+
} else {
|
|
1596
|
+
vec3 camera = vec3(0.0, 0.0, uPerspective);
|
|
1597
|
+
vec3 ray = normalize(vec3(centered, -uPerspective));
|
|
1598
|
+
vec3 normal = rotation * vec3(0.0, 0.0, 1.0);
|
|
1599
|
+
float denominator = dot(ray, normal);
|
|
1600
|
+
float t = -dot(camera, normal) / denominator;
|
|
1601
|
+
|
|
1602
|
+
if (abs(denominator) < 0.0001 || t <= 0.0) {
|
|
1603
|
+
fragColor = sourceOver(texColor, uBackgroundColor);
|
|
1604
|
+
return;
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
vec3 worldPosition = camera + ray * t;
|
|
1608
|
+
vec3 localPosition = transpose(rotation) * worldPosition;
|
|
1609
|
+
gridCoord = localPosition.xy + uOffset;
|
|
734
1610
|
}
|
|
735
1611
|
|
|
736
|
-
float
|
|
737
|
-
|
|
738
|
-
float
|
|
739
|
-
|
|
1612
|
+
float gridSize = max(uGridSize, 0.001);
|
|
1613
|
+
vec2 cell = abs(fract(gridCoord / gridSize + 0.5) - 0.5) * gridSize;
|
|
1614
|
+
float halfLineWidth = uLineWidth * 0.5;
|
|
1615
|
+
vec2 gridUnitsPerPixel = max(fwidth(gridCoord), vec2(0.001));
|
|
1616
|
+
vec2 halfWidthInGridUnits = halfLineWidth * gridUnitsPerPixel;
|
|
1617
|
+
vec2 antialiasInGridUnits = gridUnitsPerPixel;
|
|
1618
|
+
vec2 projectedCellSize = gridSize / gridUnitsPerPixel;
|
|
1619
|
+
vec2 densityFade = smoothstep(
|
|
1620
|
+
vec2(max(uLineWidth * 1.5, 1.0)),
|
|
1621
|
+
vec2(max(uLineWidth * 4.0, 2.0)),
|
|
1622
|
+
projectedCellSize
|
|
1623
|
+
);
|
|
1624
|
+
vec2 lineCoverage = halfLineWidth <= 0.001
|
|
1625
|
+
? vec2(0.0)
|
|
1626
|
+
: 1.0 - smoothstep(
|
|
1627
|
+
halfWidthInGridUnits - antialiasInGridUnits,
|
|
1628
|
+
halfWidthInGridUnits + antialiasInGridUnits,
|
|
1629
|
+
cell
|
|
1630
|
+
);
|
|
1631
|
+
lineCoverage *= densityFade;
|
|
1632
|
+
float coverage = max(lineCoverage.x, lineCoverage.y);
|
|
1633
|
+
|
|
1634
|
+
vec4 background = uBackgroundColor;
|
|
1635
|
+
vec4 line = uLineColor * coverage;
|
|
740
1636
|
|
|
741
1637
|
if (uMaskToSourceAlpha) {
|
|
742
|
-
fragColor =
|
|
743
|
-
premultipliedRing * texColor.a + texColor.rgb * (1.0 - ringAlpha),
|
|
744
|
-
texColor.a
|
|
745
|
-
);
|
|
1638
|
+
fragColor = sourceAtop(sourceAtop(texColor, background), line);
|
|
746
1639
|
return;
|
|
747
1640
|
}
|
|
748
1641
|
|
|
749
|
-
fragColor =
|
|
750
|
-
premultipliedRing + texColor.rgb * (1.0 - ringAlpha),
|
|
751
|
-
ringAlpha + texColor.a * (1.0 - ringAlpha)
|
|
752
|
-
);
|
|
1642
|
+
fragColor = sourceOver(sourceOver(texColor, background), line);
|
|
753
1643
|
}
|
|
754
1644
|
`;
|
|
755
|
-
var
|
|
1645
|
+
var compileShader4 = (gl, type, source) => {
|
|
756
1646
|
const shader = gl.createShader(type);
|
|
757
1647
|
if (!shader) {
|
|
758
1648
|
throw new Error("Failed to create WebGL shader");
|
|
@@ -762,11 +1652,11 @@ var compileShader2 = (gl, type, source) => {
|
|
|
762
1652
|
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
763
1653
|
const log = gl.getShaderInfoLog(shader);
|
|
764
1654
|
gl.deleteShader(shader);
|
|
765
|
-
throw new Error(`
|
|
1655
|
+
throw new Error(`Gridlines shader compile failed: ${log ?? "(no log)"}`);
|
|
766
1656
|
}
|
|
767
1657
|
return shader;
|
|
768
1658
|
};
|
|
769
|
-
var
|
|
1659
|
+
var linkProgram4 = (gl, vs, fs) => {
|
|
770
1660
|
const program = gl.createProgram();
|
|
771
1661
|
if (!program) {
|
|
772
1662
|
throw new Error("Failed to create WebGL program");
|
|
@@ -777,219 +1667,202 @@ var linkProgram2 = (gl, vs, fs) => {
|
|
|
777
1667
|
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
778
1668
|
const log = gl.getProgramInfoLog(program);
|
|
779
1669
|
gl.deleteProgram(program);
|
|
780
|
-
throw new Error(`
|
|
1670
|
+
throw new Error(`Gridlines program link failed: ${log ?? "(no log)"}`);
|
|
781
1671
|
}
|
|
782
1672
|
return program;
|
|
783
1673
|
};
|
|
784
|
-
var
|
|
785
|
-
const
|
|
786
|
-
const
|
|
787
|
-
|
|
788
|
-
gl.deleteShader(vs);
|
|
789
|
-
gl.deleteShader(fs);
|
|
790
|
-
return program;
|
|
791
|
-
};
|
|
792
|
-
var createTexture = (gl, filter) => {
|
|
793
|
-
const texture = gl.createTexture();
|
|
794
|
-
if (!texture) {
|
|
795
|
-
throw new Error("Failed to create WebGL texture");
|
|
796
|
-
}
|
|
797
|
-
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
798
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
799
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
800
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
801
|
-
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
802
|
-
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
803
|
-
return texture;
|
|
804
|
-
};
|
|
805
|
-
var setupRings = (target) => {
|
|
806
|
-
const gl = target.getContext("webgl2", {
|
|
807
|
-
premultipliedAlpha: true,
|
|
808
|
-
alpha: true,
|
|
809
|
-
preserveDrawingBuffer: true
|
|
810
|
-
});
|
|
811
|
-
if (!gl) {
|
|
812
|
-
throw createWebGL2ContextError2("rings effect");
|
|
813
|
-
}
|
|
814
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
815
|
-
const program = createProgram(gl, RINGS_VS, RINGS_FS);
|
|
816
|
-
const vao = gl.createVertexArray();
|
|
817
|
-
if (!vao) {
|
|
818
|
-
throw new Error("Failed to create WebGL vertex array");
|
|
819
|
-
}
|
|
820
|
-
gl.bindVertexArray(vao);
|
|
821
|
-
const data = new Float32Array([
|
|
822
|
-
-1,
|
|
823
|
-
-1,
|
|
824
|
-
0,
|
|
825
|
-
0,
|
|
826
|
-
1,
|
|
827
|
-
-1,
|
|
828
|
-
1,
|
|
829
|
-
0,
|
|
830
|
-
-1,
|
|
831
|
-
1,
|
|
832
|
-
0,
|
|
833
|
-
1,
|
|
834
|
-
1,
|
|
835
|
-
1,
|
|
836
|
-
1,
|
|
837
|
-
1
|
|
838
|
-
]);
|
|
839
|
-
const vbo = gl.createBuffer();
|
|
840
|
-
if (!vbo) {
|
|
841
|
-
throw new Error("Failed to create WebGL buffer");
|
|
842
|
-
}
|
|
843
|
-
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
844
|
-
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
845
|
-
const aPos = gl.getAttribLocation(program, "aPos");
|
|
846
|
-
const aUv = gl.getAttribLocation(program, "aUv");
|
|
847
|
-
gl.enableVertexAttribArray(aPos);
|
|
848
|
-
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
849
|
-
gl.enableVertexAttribArray(aUv);
|
|
850
|
-
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
851
|
-
gl.bindVertexArray(null);
|
|
852
|
-
const colorCanvas = document.createElement("canvas");
|
|
853
|
-
colorCanvas.width = 1;
|
|
854
|
-
colorCanvas.height = 1;
|
|
855
|
-
const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
|
|
856
|
-
if (!colorCtx) {
|
|
857
|
-
throw new Error("Failed to acquire 2D context for color parsing");
|
|
858
|
-
}
|
|
859
|
-
return {
|
|
860
|
-
gl,
|
|
861
|
-
program,
|
|
862
|
-
vao,
|
|
863
|
-
vbo,
|
|
864
|
-
sourceTexture: createTexture(gl, gl.LINEAR),
|
|
865
|
-
paletteTexture: createTexture(gl, gl.NEAREST),
|
|
866
|
-
colorCtx,
|
|
867
|
-
uniforms: {
|
|
868
|
-
uSource: gl.getUniformLocation(program, "uSource"),
|
|
869
|
-
uPalette: gl.getUniformLocation(program, "uPalette"),
|
|
870
|
-
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
871
|
-
uNumColors: gl.getUniformLocation(program, "uNumColors"),
|
|
872
|
-
uCenter: gl.getUniformLocation(program, "uCenter"),
|
|
873
|
-
uThickness: gl.getUniformLocation(program, "uThickness"),
|
|
874
|
-
uSpacing: gl.getUniformLocation(program, "uSpacing"),
|
|
875
|
-
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
876
|
-
uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
|
|
877
|
-
},
|
|
878
|
-
cachedPaletteKey: "",
|
|
879
|
-
palettePixelData: new Uint8Array(0)
|
|
880
|
-
};
|
|
881
|
-
};
|
|
882
|
-
var updatePalette = (state, colors) => {
|
|
883
|
-
const paletteKey = colors.join("|");
|
|
884
|
-
const paletteDirty = state.cachedPaletteKey !== paletteKey;
|
|
885
|
-
if (!paletteDirty) {
|
|
886
|
-
return false;
|
|
887
|
-
}
|
|
888
|
-
state.cachedPaletteKey = paletteKey;
|
|
889
|
-
const len = colors.length * 4;
|
|
890
|
-
if (state.palettePixelData.length !== len) {
|
|
891
|
-
state.palettePixelData = new Uint8Array(len);
|
|
892
|
-
}
|
|
893
|
-
const { palettePixelData } = state;
|
|
894
|
-
for (let i = 0;i < colors.length; i++) {
|
|
895
|
-
const color = parseColorRgba(state.colorCtx, colors[i]);
|
|
896
|
-
palettePixelData[i * 4] = color[0];
|
|
897
|
-
palettePixelData[i * 4 + 1] = color[1];
|
|
898
|
-
palettePixelData[i * 4 + 2] = color[2];
|
|
899
|
-
palettePixelData[i * 4 + 3] = color[3];
|
|
900
|
-
}
|
|
901
|
-
return true;
|
|
1674
|
+
var rgbaToUniform = (rgba) => {
|
|
1675
|
+
const [r, g, b, a] = rgba;
|
|
1676
|
+
const alpha = a / 255;
|
|
1677
|
+
return [r / 255 * alpha, g / 255 * alpha, b / 255 * alpha, alpha];
|
|
902
1678
|
};
|
|
903
|
-
var
|
|
904
|
-
type: "
|
|
905
|
-
label: "
|
|
906
|
-
documentationLink: "https://www.remotion.dev/docs/effects/
|
|
1679
|
+
var gridlines = createEffect4({
|
|
1680
|
+
type: "remotion/gridlines",
|
|
1681
|
+
label: "gridlines()",
|
|
1682
|
+
documentationLink: "https://www.remotion.dev/docs/effects/gridlines",
|
|
907
1683
|
backend: "webgl2",
|
|
908
1684
|
calculateKey: (params) => {
|
|
909
|
-
const r =
|
|
1685
|
+
const r = resolve4(params);
|
|
910
1686
|
const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
|
|
911
|
-
return `
|
|
1687
|
+
return `gridlines-${r.gridSize}-${r.lineWidth}-${r.lineColor}-${r.backgroundColor}-${r.rotation}-${r.rotationX}-${r.rotationY}-${r.perspective}-${r.offsetX}-${r.offsetY}${maskSuffix}`;
|
|
1688
|
+
},
|
|
1689
|
+
setup: (target) => {
|
|
1690
|
+
const gl = target.getContext("webgl2", {
|
|
1691
|
+
premultipliedAlpha: true,
|
|
1692
|
+
alpha: true,
|
|
1693
|
+
preserveDrawingBuffer: true
|
|
1694
|
+
});
|
|
1695
|
+
if (!gl) {
|
|
1696
|
+
throw createWebGL2ContextError4("gridlines effect");
|
|
1697
|
+
}
|
|
1698
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
1699
|
+
const vs = compileShader4(gl, gl.VERTEX_SHADER, GRIDLINES_VS);
|
|
1700
|
+
const fs = compileShader4(gl, gl.FRAGMENT_SHADER, GRIDLINES_FS);
|
|
1701
|
+
const program = linkProgram4(gl, vs, fs);
|
|
1702
|
+
gl.deleteShader(vs);
|
|
1703
|
+
gl.deleteShader(fs);
|
|
1704
|
+
const vao = gl.createVertexArray();
|
|
1705
|
+
if (!vao) {
|
|
1706
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
1707
|
+
}
|
|
1708
|
+
gl.bindVertexArray(vao);
|
|
1709
|
+
const data = new Float32Array([
|
|
1710
|
+
-1,
|
|
1711
|
+
-1,
|
|
1712
|
+
0,
|
|
1713
|
+
0,
|
|
1714
|
+
1,
|
|
1715
|
+
-1,
|
|
1716
|
+
1,
|
|
1717
|
+
0,
|
|
1718
|
+
-1,
|
|
1719
|
+
1,
|
|
1720
|
+
0,
|
|
1721
|
+
1,
|
|
1722
|
+
1,
|
|
1723
|
+
1,
|
|
1724
|
+
1,
|
|
1725
|
+
1
|
|
1726
|
+
]);
|
|
1727
|
+
const vbo = gl.createBuffer();
|
|
1728
|
+
if (!vbo) {
|
|
1729
|
+
throw new Error("Failed to create WebGL buffer");
|
|
1730
|
+
}
|
|
1731
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
1732
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
1733
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
1734
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
1735
|
+
gl.enableVertexAttribArray(aPos);
|
|
1736
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
1737
|
+
gl.enableVertexAttribArray(aUv);
|
|
1738
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
1739
|
+
gl.bindVertexArray(null);
|
|
1740
|
+
const texture = gl.createTexture();
|
|
1741
|
+
if (!texture) {
|
|
1742
|
+
throw new Error("Failed to create WebGL texture");
|
|
1743
|
+
}
|
|
1744
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
1745
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
1746
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
1747
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
1748
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
1749
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
1750
|
+
const colorCanvas = document.createElement("canvas");
|
|
1751
|
+
colorCanvas.width = 1;
|
|
1752
|
+
colorCanvas.height = 1;
|
|
1753
|
+
const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
|
|
1754
|
+
if (!colorCtx) {
|
|
1755
|
+
throw new Error("Failed to acquire 2D context for color parsing");
|
|
1756
|
+
}
|
|
1757
|
+
return {
|
|
1758
|
+
gl,
|
|
1759
|
+
program,
|
|
1760
|
+
vao,
|
|
1761
|
+
vbo,
|
|
1762
|
+
texture,
|
|
1763
|
+
uniforms: {
|
|
1764
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
1765
|
+
uResolution: gl.getUniformLocation(program, "uResolution"),
|
|
1766
|
+
uGridSize: gl.getUniformLocation(program, "uGridSize"),
|
|
1767
|
+
uLineWidth: gl.getUniformLocation(program, "uLineWidth"),
|
|
1768
|
+
uLineColor: gl.getUniformLocation(program, "uLineColor"),
|
|
1769
|
+
uBackgroundColor: gl.getUniformLocation(program, "uBackgroundColor"),
|
|
1770
|
+
uRotation: gl.getUniformLocation(program, "uRotation"),
|
|
1771
|
+
uRotationX: gl.getUniformLocation(program, "uRotationX"),
|
|
1772
|
+
uRotationY: gl.getUniformLocation(program, "uRotationY"),
|
|
1773
|
+
uPerspective: gl.getUniformLocation(program, "uPerspective"),
|
|
1774
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
1775
|
+
uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
|
|
1776
|
+
},
|
|
1777
|
+
colorCtx,
|
|
1778
|
+
cachedLineColorStr: "",
|
|
1779
|
+
cachedLineColorRgba: [255, 255, 255, 255],
|
|
1780
|
+
cachedBackgroundColorStr: "",
|
|
1781
|
+
cachedBackgroundColorRgba: [0, 0, 0, 0]
|
|
1782
|
+
};
|
|
912
1783
|
},
|
|
913
|
-
setup: (target) => setupRings(target),
|
|
914
1784
|
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
915
|
-
const r =
|
|
916
|
-
const
|
|
917
|
-
|
|
1785
|
+
const r = resolve4(params);
|
|
1786
|
+
const { gl, program, vao, texture, uniforms } = state;
|
|
1787
|
+
if (state.cachedLineColorStr !== r.lineColor) {
|
|
1788
|
+
state.cachedLineColorStr = r.lineColor;
|
|
1789
|
+
state.cachedLineColorRgba = parseColorRgba(state.colorCtx, r.lineColor);
|
|
1790
|
+
}
|
|
1791
|
+
if (state.cachedBackgroundColorStr !== r.backgroundColor) {
|
|
1792
|
+
state.cachedBackgroundColorStr = r.backgroundColor;
|
|
1793
|
+
state.cachedBackgroundColorRgba = parseColorRgba(state.colorCtx, r.backgroundColor);
|
|
1794
|
+
}
|
|
1795
|
+
const [lineR, lineG, lineB, lineA] = rgbaToUniform(state.cachedLineColorRgba);
|
|
1796
|
+
const [bgR, bgG, bgB, bgA] = rgbaToUniform(state.cachedBackgroundColorRgba);
|
|
918
1797
|
gl.viewport(0, 0, width, height);
|
|
919
1798
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
920
1799
|
gl.clearColor(0, 0, 0, 0);
|
|
921
1800
|
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
1801
|
+
gl.useProgram(program);
|
|
1802
|
+
gl.bindVertexArray(vao);
|
|
922
1803
|
gl.activeTexture(gl.TEXTURE0);
|
|
923
|
-
gl.bindTexture(gl.TEXTURE_2D,
|
|
924
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
1804
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
925
1805
|
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
926
1806
|
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
927
|
-
gl.activeTexture(gl.TEXTURE1);
|
|
928
|
-
gl.bindTexture(gl.TEXTURE_2D, paletteTexture);
|
|
929
|
-
if (paletteDirty) {
|
|
930
|
-
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
931
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
932
|
-
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, r.colors.length, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, state.palettePixelData);
|
|
933
|
-
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
934
|
-
}
|
|
935
|
-
gl.useProgram(program);
|
|
936
1807
|
if (uniforms.uSource)
|
|
937
1808
|
gl.uniform1i(uniforms.uSource, 0);
|
|
938
|
-
if (uniforms.uPalette)
|
|
939
|
-
gl.uniform1i(uniforms.uPalette, 1);
|
|
940
1809
|
if (uniforms.uResolution)
|
|
941
1810
|
gl.uniform2f(uniforms.uResolution, width, height);
|
|
942
|
-
if (uniforms.
|
|
943
|
-
gl.uniform1f(uniforms.
|
|
944
|
-
if (uniforms.
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
if (uniforms.
|
|
949
|
-
gl.
|
|
950
|
-
if (uniforms.
|
|
951
|
-
gl.uniform1f(uniforms.
|
|
1811
|
+
if (uniforms.uGridSize)
|
|
1812
|
+
gl.uniform1f(uniforms.uGridSize, r.gridSize);
|
|
1813
|
+
if (uniforms.uLineWidth)
|
|
1814
|
+
gl.uniform1f(uniforms.uLineWidth, r.lineWidth);
|
|
1815
|
+
if (uniforms.uLineColor)
|
|
1816
|
+
gl.uniform4f(uniforms.uLineColor, lineR, lineG, lineB, lineA);
|
|
1817
|
+
if (uniforms.uBackgroundColor)
|
|
1818
|
+
gl.uniform4f(uniforms.uBackgroundColor, bgR, bgG, bgB, bgA);
|
|
1819
|
+
if (uniforms.uRotation)
|
|
1820
|
+
gl.uniform1f(uniforms.uRotation, r.rotation * Math.PI / 180);
|
|
1821
|
+
if (uniforms.uRotationX)
|
|
1822
|
+
gl.uniform1f(uniforms.uRotationX, r.rotationX * Math.PI / 180);
|
|
1823
|
+
if (uniforms.uRotationY)
|
|
1824
|
+
gl.uniform1f(uniforms.uRotationY, r.rotationY * Math.PI / 180);
|
|
1825
|
+
if (uniforms.uPerspective)
|
|
1826
|
+
gl.uniform1f(uniforms.uPerspective, r.perspective);
|
|
952
1827
|
if (uniforms.uOffset)
|
|
953
|
-
gl.
|
|
1828
|
+
gl.uniform2f(uniforms.uOffset, r.offsetX, r.offsetY);
|
|
954
1829
|
if (uniforms.uMaskToSourceAlpha)
|
|
955
1830
|
gl.uniform1i(uniforms.uMaskToSourceAlpha, r.maskToSourceAlpha ? 1 : 0);
|
|
956
|
-
gl.bindVertexArray(vao);
|
|
957
1831
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
958
1832
|
gl.bindVertexArray(null);
|
|
959
1833
|
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
960
1834
|
gl.useProgram(null);
|
|
961
1835
|
},
|
|
962
|
-
cleanup: ({ gl, program, vao, vbo,
|
|
963
|
-
gl.deleteTexture(sourceTexture);
|
|
964
|
-
gl.deleteTexture(paletteTexture);
|
|
1836
|
+
cleanup: ({ gl, program, vao, vbo, texture }) => {
|
|
965
1837
|
gl.deleteBuffer(vbo);
|
|
966
1838
|
gl.deleteProgram(program);
|
|
967
1839
|
gl.deleteVertexArray(vao);
|
|
1840
|
+
gl.deleteTexture(texture);
|
|
968
1841
|
},
|
|
969
|
-
schema:
|
|
970
|
-
validateParams:
|
|
1842
|
+
schema: gridlinesSchema,
|
|
1843
|
+
validateParams: validateGridlinesParams
|
|
971
1844
|
});
|
|
972
1845
|
|
|
973
1846
|
// src/zigzag.ts
|
|
974
|
-
import { Internals as
|
|
975
|
-
var { createEffect:
|
|
1847
|
+
import { Internals as Internals5 } from "remotion";
|
|
1848
|
+
var { createEffect: createEffect5, createWebGL2ContextError: createWebGL2ContextError5 } = Internals5;
|
|
976
1849
|
var ZIGZAG_DIRECTIONS = ["horizontal", "vertical"];
|
|
977
|
-
var
|
|
1850
|
+
var DEFAULT_COLORS3 = ["#dff4ff", "#7cc6ff"];
|
|
978
1851
|
var DEFAULT_DIRECTION = "horizontal";
|
|
979
1852
|
var DEFAULT_THICKNESS2 = 40;
|
|
980
|
-
var
|
|
981
|
-
var
|
|
1853
|
+
var DEFAULT_GAP4 = 0;
|
|
1854
|
+
var DEFAULT_ANGLE2 = 0;
|
|
982
1855
|
var DEFAULT_OFFSET3 = 0;
|
|
983
1856
|
var DEFAULT_AMPLITUDE = 40;
|
|
984
1857
|
var DEFAULT_WAVELENGTH = 160;
|
|
985
|
-
var
|
|
1858
|
+
var DEFAULT_MASK_TO_SOURCE_ALPHA4 = false;
|
|
986
1859
|
var zigzagSchema = {
|
|
987
1860
|
colors: {
|
|
988
1861
|
type: "array",
|
|
989
1862
|
item: {
|
|
990
1863
|
type: "color"
|
|
991
1864
|
},
|
|
992
|
-
default:
|
|
1865
|
+
default: DEFAULT_COLORS3,
|
|
993
1866
|
minLength: 2,
|
|
994
1867
|
newItemDefault: "#ff0000",
|
|
995
1868
|
description: "Colors",
|
|
@@ -1018,14 +1891,14 @@ var zigzagSchema = {
|
|
|
1018
1891
|
min: 0,
|
|
1019
1892
|
max: 400,
|
|
1020
1893
|
step: 0.1,
|
|
1021
|
-
default:
|
|
1894
|
+
default: DEFAULT_GAP4,
|
|
1022
1895
|
description: "Gap",
|
|
1023
1896
|
hiddenFromList: false
|
|
1024
1897
|
},
|
|
1025
1898
|
angle: {
|
|
1026
1899
|
type: "rotation-degrees",
|
|
1027
1900
|
step: 1,
|
|
1028
|
-
default:
|
|
1901
|
+
default: DEFAULT_ANGLE2,
|
|
1029
1902
|
description: "Angle"
|
|
1030
1903
|
},
|
|
1031
1904
|
offset: {
|
|
@@ -1055,23 +1928,23 @@ var zigzagSchema = {
|
|
|
1055
1928
|
},
|
|
1056
1929
|
maskToSourceAlpha: {
|
|
1057
1930
|
type: "boolean",
|
|
1058
|
-
default:
|
|
1931
|
+
default: DEFAULT_MASK_TO_SOURCE_ALPHA4,
|
|
1059
1932
|
description: "Mask to source alpha"
|
|
1060
1933
|
}
|
|
1061
1934
|
};
|
|
1062
|
-
var
|
|
1935
|
+
var resolve5 = (p) => {
|
|
1063
1936
|
const thickness = p.thickness ?? DEFAULT_THICKNESS2;
|
|
1064
|
-
const gap = p.gap ??
|
|
1937
|
+
const gap = p.gap ?? DEFAULT_GAP4;
|
|
1065
1938
|
return {
|
|
1066
|
-
colors: p.colors ??
|
|
1939
|
+
colors: p.colors ?? DEFAULT_COLORS3,
|
|
1067
1940
|
direction: p.direction ?? DEFAULT_DIRECTION,
|
|
1068
1941
|
thickness,
|
|
1069
1942
|
spacing: thickness + gap,
|
|
1070
|
-
angle: p.angle ??
|
|
1943
|
+
angle: p.angle ?? DEFAULT_ANGLE2,
|
|
1071
1944
|
offset: p.offset ?? DEFAULT_OFFSET3,
|
|
1072
1945
|
amplitude: p.amplitude ?? DEFAULT_AMPLITUDE,
|
|
1073
1946
|
wavelength: p.wavelength ?? DEFAULT_WAVELENGTH,
|
|
1074
|
-
maskToSourceAlpha: p.maskToSourceAlpha ??
|
|
1947
|
+
maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA4
|
|
1075
1948
|
};
|
|
1076
1949
|
};
|
|
1077
1950
|
var formatEnum = (variants) => {
|
|
@@ -1080,17 +1953,17 @@ var formatEnum = (variants) => {
|
|
|
1080
1953
|
}
|
|
1081
1954
|
return `${variants.slice(0, -1).map((variant) => `"${variant}"`).join(", ")} or "${variants[variants.length - 1]}"`;
|
|
1082
1955
|
};
|
|
1083
|
-
var
|
|
1956
|
+
var validatePositive5 = (value, name) => {
|
|
1084
1957
|
if (value <= 0) {
|
|
1085
1958
|
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
1086
1959
|
}
|
|
1087
1960
|
};
|
|
1088
|
-
var
|
|
1961
|
+
var validateNonNegative5 = (value, name) => {
|
|
1089
1962
|
if (value < 0) {
|
|
1090
1963
|
throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
|
|
1091
1964
|
}
|
|
1092
1965
|
};
|
|
1093
|
-
var
|
|
1966
|
+
var validateColors3 = (colors) => {
|
|
1094
1967
|
if (colors === undefined) {
|
|
1095
1968
|
return;
|
|
1096
1969
|
}
|
|
@@ -1111,7 +1984,7 @@ var validateDirection = (direction) => {
|
|
|
1111
1984
|
};
|
|
1112
1985
|
var validateZigzagParams = (params) => {
|
|
1113
1986
|
assertEffectParamsObject(params, "Zigzag");
|
|
1114
|
-
|
|
1987
|
+
validateColors3(params.colors);
|
|
1115
1988
|
validateDirection(params.direction);
|
|
1116
1989
|
assertOptionalFiniteNumber(params.thickness, "thickness");
|
|
1117
1990
|
assertOptionalFiniteNumber(params.gap, "gap");
|
|
@@ -1121,13 +1994,13 @@ var validateZigzagParams = (params) => {
|
|
|
1121
1994
|
assertOptionalFiniteNumber(params.wavelength, "wavelength");
|
|
1122
1995
|
assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
|
|
1123
1996
|
const thickness = params.thickness ?? DEFAULT_THICKNESS2;
|
|
1124
|
-
const gap = params.gap ??
|
|
1997
|
+
const gap = params.gap ?? DEFAULT_GAP4;
|
|
1125
1998
|
const amplitude = params.amplitude ?? DEFAULT_AMPLITUDE;
|
|
1126
1999
|
const wavelength = params.wavelength ?? DEFAULT_WAVELENGTH;
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
2000
|
+
validatePositive5(thickness, "thickness");
|
|
2001
|
+
validateNonNegative5(gap, "gap");
|
|
2002
|
+
validateNonNegative5(amplitude, "amplitude");
|
|
2003
|
+
validatePositive5(wavelength, "wavelength");
|
|
1131
2004
|
};
|
|
1132
2005
|
var ZIGZAG_VS = `#version 300 es
|
|
1133
2006
|
in vec2 aPos;
|
|
@@ -1205,7 +2078,7 @@ void main() {
|
|
|
1205
2078
|
);
|
|
1206
2079
|
}
|
|
1207
2080
|
`;
|
|
1208
|
-
var
|
|
2081
|
+
var compileShader5 = (gl, type, source) => {
|
|
1209
2082
|
const shader = gl.createShader(type);
|
|
1210
2083
|
if (!shader) {
|
|
1211
2084
|
throw new Error("Failed to create WebGL shader");
|
|
@@ -1219,7 +2092,7 @@ var compileShader3 = (gl, type, source) => {
|
|
|
1219
2092
|
}
|
|
1220
2093
|
return shader;
|
|
1221
2094
|
};
|
|
1222
|
-
var
|
|
2095
|
+
var linkProgram5 = (gl, vs, fs) => {
|
|
1223
2096
|
const program = gl.createProgram();
|
|
1224
2097
|
if (!program) {
|
|
1225
2098
|
throw new Error("Failed to create WebGL program");
|
|
@@ -1234,15 +2107,15 @@ var linkProgram3 = (gl, vs, fs) => {
|
|
|
1234
2107
|
}
|
|
1235
2108
|
return program;
|
|
1236
2109
|
};
|
|
1237
|
-
var
|
|
1238
|
-
const vs =
|
|
1239
|
-
const fs =
|
|
1240
|
-
const program =
|
|
2110
|
+
var createProgram3 = (gl, vertexSource, fragmentSource) => {
|
|
2111
|
+
const vs = compileShader5(gl, gl.VERTEX_SHADER, vertexSource);
|
|
2112
|
+
const fs = compileShader5(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
2113
|
+
const program = linkProgram5(gl, vs, fs);
|
|
1241
2114
|
gl.deleteShader(vs);
|
|
1242
2115
|
gl.deleteShader(fs);
|
|
1243
2116
|
return program;
|
|
1244
2117
|
};
|
|
1245
|
-
var
|
|
2118
|
+
var createTexture3 = (gl, filter) => {
|
|
1246
2119
|
const texture = gl.createTexture();
|
|
1247
2120
|
if (!texture) {
|
|
1248
2121
|
throw new Error("Failed to create WebGL texture");
|
|
@@ -1262,10 +2135,10 @@ var setupZigzag = (target) => {
|
|
|
1262
2135
|
preserveDrawingBuffer: true
|
|
1263
2136
|
});
|
|
1264
2137
|
if (!gl) {
|
|
1265
|
-
throw
|
|
2138
|
+
throw createWebGL2ContextError5("zigzag effect");
|
|
1266
2139
|
}
|
|
1267
2140
|
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
1268
|
-
const program =
|
|
2141
|
+
const program = createProgram3(gl, ZIGZAG_VS, ZIGZAG_FS);
|
|
1269
2142
|
const vao = gl.createVertexArray();
|
|
1270
2143
|
if (!vao) {
|
|
1271
2144
|
throw new Error("Failed to create WebGL vertex array");
|
|
@@ -1314,8 +2187,8 @@ var setupZigzag = (target) => {
|
|
|
1314
2187
|
program,
|
|
1315
2188
|
vao,
|
|
1316
2189
|
vbo,
|
|
1317
|
-
sourceTexture:
|
|
1318
|
-
paletteTexture:
|
|
2190
|
+
sourceTexture: createTexture3(gl, gl.LINEAR),
|
|
2191
|
+
paletteTexture: createTexture3(gl, gl.NEAREST),
|
|
1319
2192
|
colorCtx,
|
|
1320
2193
|
uniforms: {
|
|
1321
2194
|
uSource: gl.getUniformLocation(program, "uSource"),
|
|
@@ -1335,7 +2208,7 @@ var setupZigzag = (target) => {
|
|
|
1335
2208
|
palettePixelData: new Uint8Array(0)
|
|
1336
2209
|
};
|
|
1337
2210
|
};
|
|
1338
|
-
var
|
|
2211
|
+
var updatePalette3 = (state, colors) => {
|
|
1339
2212
|
const paletteKey = colors.join("|");
|
|
1340
2213
|
const paletteDirty = state.cachedPaletteKey !== paletteKey;
|
|
1341
2214
|
if (!paletteDirty) {
|
|
@@ -1356,20 +2229,20 @@ var updatePalette2 = (state, colors) => {
|
|
|
1356
2229
|
}
|
|
1357
2230
|
return true;
|
|
1358
2231
|
};
|
|
1359
|
-
var zigzag =
|
|
2232
|
+
var zigzag = createEffect5({
|
|
1360
2233
|
type: "dev.remotion.effects.zigzag",
|
|
1361
2234
|
label: "zigzag()",
|
|
1362
2235
|
documentationLink: "https://www.remotion.dev/docs/effects/zigzag",
|
|
1363
2236
|
backend: "webgl2",
|
|
1364
2237
|
calculateKey: (params) => {
|
|
1365
|
-
const r =
|
|
2238
|
+
const r = resolve5(params);
|
|
1366
2239
|
const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
|
|
1367
2240
|
return `zigzag-${r.colors.join("|")}-${r.direction}-${r.thickness}-${r.spacing}-${r.angle}-${r.offset}-${r.amplitude}-${r.wavelength}${maskSuffix}`;
|
|
1368
2241
|
},
|
|
1369
2242
|
setup: (target) => setupZigzag(target),
|
|
1370
2243
|
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
1371
|
-
const r =
|
|
1372
|
-
const paletteDirty =
|
|
2244
|
+
const r = resolve5(params);
|
|
2245
|
+
const paletteDirty = updatePalette3(state, r.colors);
|
|
1373
2246
|
const { gl, program, sourceTexture, paletteTexture, uniforms, vao } = state;
|
|
1374
2247
|
gl.viewport(0, 0, width, height);
|
|
1375
2248
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
@@ -1436,8 +2309,361 @@ var zigzag = createEffect3({
|
|
|
1436
2309
|
schema: zigzagSchema,
|
|
1437
2310
|
validateParams: validateZigzagParams
|
|
1438
2311
|
});
|
|
2312
|
+
// src/corner-pin/index.ts
|
|
2313
|
+
import { Internals as Internals7 } from "remotion";
|
|
2314
|
+
|
|
2315
|
+
// src/corner-pin/corner-pin-runtime.ts
|
|
2316
|
+
import { Internals as Internals6 } from "remotion";
|
|
2317
|
+
|
|
2318
|
+
// src/corner-pin/corner-pin-shaders.ts
|
|
2319
|
+
var CORNER_PIN_VS = `#version 300 es
|
|
2320
|
+
layout(location = 0) in vec2 aPos;
|
|
2321
|
+
layout(location = 1) in vec2 aUv;
|
|
2322
|
+
out vec2 vUv;
|
|
2323
|
+
|
|
2324
|
+
void main() {
|
|
2325
|
+
vUv = aUv;
|
|
2326
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
2327
|
+
}
|
|
2328
|
+
`;
|
|
2329
|
+
var CORNER_PIN_FS = `#version 300 es
|
|
2330
|
+
precision highp float;
|
|
2331
|
+
|
|
2332
|
+
in vec2 vUv;
|
|
2333
|
+
out vec4 fragColor;
|
|
2334
|
+
|
|
2335
|
+
uniform sampler2D uSource;
|
|
2336
|
+
uniform vec2 uTopLeft;
|
|
2337
|
+
uniform vec2 uTopRight;
|
|
2338
|
+
uniform vec2 uBottomRight;
|
|
2339
|
+
uniform vec2 uBottomLeft;
|
|
2340
|
+
|
|
2341
|
+
float cross2(vec2 a, vec2 b) {
|
|
2342
|
+
return a.x * b.y - a.y * b.x;
|
|
2343
|
+
}
|
|
2344
|
+
|
|
2345
|
+
bool solveBilinearInverse(vec2 p, out vec2 uv) {
|
|
2346
|
+
vec2 a = uBottomLeft;
|
|
2347
|
+
vec2 b = uBottomRight - uBottomLeft;
|
|
2348
|
+
vec2 c = uTopLeft - uBottomLeft;
|
|
2349
|
+
vec2 d = uBottomLeft - uBottomRight + uTopRight - uTopLeft;
|
|
2350
|
+
vec2 q = p - a;
|
|
2351
|
+
|
|
2352
|
+
float linearDenominator = cross2(b, c);
|
|
2353
|
+
if (abs(cross2(b, d)) < 0.000001) {
|
|
2354
|
+
if (abs(linearDenominator) < 0.000001) {
|
|
2355
|
+
return false;
|
|
2356
|
+
}
|
|
2357
|
+
|
|
2358
|
+
uv.x = cross2(q, c) / linearDenominator;
|
|
2359
|
+
uv.y = cross2(q, b) / cross2(c, b);
|
|
2360
|
+
return true;
|
|
2361
|
+
}
|
|
2362
|
+
|
|
2363
|
+
float qa = -cross2(b, d);
|
|
2364
|
+
float qb = cross2(q, d) - cross2(b, c);
|
|
2365
|
+
float qc = cross2(q, c);
|
|
2366
|
+
float discriminant = qb * qb - 4.0 * qa * qc;
|
|
2367
|
+
|
|
2368
|
+
if (discriminant < 0.0) {
|
|
2369
|
+
return false;
|
|
2370
|
+
}
|
|
2371
|
+
|
|
2372
|
+
float sqrtDiscriminant = sqrt(discriminant);
|
|
2373
|
+
float u1 = (-qb + sqrtDiscriminant) / (2.0 * qa);
|
|
2374
|
+
float u2 = (-qb - sqrtDiscriminant) / (2.0 * qa);
|
|
2375
|
+
float u = u1;
|
|
2376
|
+
if (u1 < -0.001 || u1 > 1.001) {
|
|
2377
|
+
u = u2;
|
|
2378
|
+
}
|
|
2379
|
+
|
|
2380
|
+
vec2 denominator = c + d * u;
|
|
2381
|
+
float v = abs(denominator.x) > abs(denominator.y)
|
|
2382
|
+
? (q.x - b.x * u) / denominator.x
|
|
2383
|
+
: (q.y - b.y * u) / denominator.y;
|
|
2384
|
+
|
|
2385
|
+
uv = vec2(u, v);
|
|
2386
|
+
return true;
|
|
2387
|
+
}
|
|
2388
|
+
|
|
2389
|
+
void main() {
|
|
2390
|
+
vec2 sourceUv;
|
|
2391
|
+
if (!solveBilinearInverse(vUv, sourceUv)) {
|
|
2392
|
+
fragColor = vec4(0.0);
|
|
2393
|
+
return;
|
|
2394
|
+
}
|
|
2395
|
+
|
|
2396
|
+
if (
|
|
2397
|
+
sourceUv.x < 0.0 ||
|
|
2398
|
+
sourceUv.x > 1.0 ||
|
|
2399
|
+
sourceUv.y < 0.0 ||
|
|
2400
|
+
sourceUv.y > 1.0
|
|
2401
|
+
) {
|
|
2402
|
+
fragColor = vec4(0.0);
|
|
2403
|
+
return;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
fragColor = texture(uSource, sourceUv);
|
|
2407
|
+
}
|
|
2408
|
+
`;
|
|
2409
|
+
|
|
2410
|
+
// src/corner-pin/corner-pin-runtime.ts
|
|
2411
|
+
var { createWebGL2ContextError: createWebGL2ContextError6 } = Internals6;
|
|
2412
|
+
var compileShader6 = (gl, type, source) => {
|
|
2413
|
+
const shader = gl.createShader(type);
|
|
2414
|
+
if (!shader) {
|
|
2415
|
+
throw new Error("Failed to create WebGL shader");
|
|
2416
|
+
}
|
|
2417
|
+
gl.shaderSource(shader, source);
|
|
2418
|
+
gl.compileShader(shader);
|
|
2419
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
2420
|
+
const log = gl.getShaderInfoLog(shader);
|
|
2421
|
+
gl.deleteShader(shader);
|
|
2422
|
+
throw new Error(`Shader compile failed: ${log ?? "(no log)"}`);
|
|
2423
|
+
}
|
|
2424
|
+
return shader;
|
|
2425
|
+
};
|
|
2426
|
+
var linkProgram6 = (gl, vs, fs) => {
|
|
2427
|
+
const program = gl.createProgram();
|
|
2428
|
+
if (!program) {
|
|
2429
|
+
throw new Error("Failed to create WebGL program");
|
|
2430
|
+
}
|
|
2431
|
+
gl.attachShader(program, vs);
|
|
2432
|
+
gl.attachShader(program, fs);
|
|
2433
|
+
gl.linkProgram(program);
|
|
2434
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
2435
|
+
const log = gl.getProgramInfoLog(program);
|
|
2436
|
+
gl.deleteProgram(program);
|
|
2437
|
+
throw new Error(`Program link failed: ${log ?? "(no log)"}`);
|
|
2438
|
+
}
|
|
2439
|
+
return program;
|
|
2440
|
+
};
|
|
2441
|
+
var createProgram4 = (gl, vertexSource, fragmentSource) => {
|
|
2442
|
+
const vs = compileShader6(gl, gl.VERTEX_SHADER, vertexSource);
|
|
2443
|
+
const fs = compileShader6(gl, gl.FRAGMENT_SHADER, fragmentSource);
|
|
2444
|
+
const program = linkProgram6(gl, vs, fs);
|
|
2445
|
+
gl.deleteShader(vs);
|
|
2446
|
+
gl.deleteShader(fs);
|
|
2447
|
+
return program;
|
|
2448
|
+
};
|
|
2449
|
+
var createRgbaTexture = (gl) => {
|
|
2450
|
+
const texture = gl.createTexture();
|
|
2451
|
+
if (!texture) {
|
|
2452
|
+
throw new Error("Failed to create WebGL texture");
|
|
2453
|
+
}
|
|
2454
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
2455
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
2456
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
2457
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
2458
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
2459
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2460
|
+
return texture;
|
|
2461
|
+
};
|
|
2462
|
+
var setupCornerPin = (target) => {
|
|
2463
|
+
const gl = target.getContext("webgl2", {
|
|
2464
|
+
premultipliedAlpha: true,
|
|
2465
|
+
alpha: true,
|
|
2466
|
+
preserveDrawingBuffer: true
|
|
2467
|
+
});
|
|
2468
|
+
if (!gl) {
|
|
2469
|
+
throw createWebGL2ContextError6("corner pin effect");
|
|
2470
|
+
}
|
|
2471
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
2472
|
+
const program = createProgram4(gl, CORNER_PIN_VS, CORNER_PIN_FS);
|
|
2473
|
+
const vao = gl.createVertexArray();
|
|
2474
|
+
if (!vao) {
|
|
2475
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
2476
|
+
}
|
|
2477
|
+
gl.bindVertexArray(vao);
|
|
2478
|
+
const data = new Float32Array([
|
|
2479
|
+
-1,
|
|
2480
|
+
-1,
|
|
2481
|
+
0,
|
|
2482
|
+
0,
|
|
2483
|
+
1,
|
|
2484
|
+
-1,
|
|
2485
|
+
1,
|
|
2486
|
+
0,
|
|
2487
|
+
-1,
|
|
2488
|
+
1,
|
|
2489
|
+
0,
|
|
2490
|
+
1,
|
|
2491
|
+
1,
|
|
2492
|
+
1,
|
|
2493
|
+
1,
|
|
2494
|
+
1
|
|
2495
|
+
]);
|
|
2496
|
+
const vbo = gl.createBuffer();
|
|
2497
|
+
if (!vbo) {
|
|
2498
|
+
throw new Error("Failed to create WebGL buffer");
|
|
2499
|
+
}
|
|
2500
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
2501
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
2502
|
+
gl.enableVertexAttribArray(0);
|
|
2503
|
+
gl.vertexAttribPointer(0, 2, gl.FLOAT, false, 16, 0);
|
|
2504
|
+
gl.enableVertexAttribArray(1);
|
|
2505
|
+
gl.vertexAttribPointer(1, 2, gl.FLOAT, false, 16, 8);
|
|
2506
|
+
gl.bindVertexArray(null);
|
|
2507
|
+
const textureSource = createRgbaTexture(gl);
|
|
2508
|
+
return {
|
|
2509
|
+
gl,
|
|
2510
|
+
program,
|
|
2511
|
+
vao,
|
|
2512
|
+
vbo,
|
|
2513
|
+
textureSource,
|
|
2514
|
+
uniforms: {
|
|
2515
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
2516
|
+
uTopLeft: gl.getUniformLocation(program, "uTopLeft"),
|
|
2517
|
+
uTopRight: gl.getUniformLocation(program, "uTopRight"),
|
|
2518
|
+
uBottomRight: gl.getUniformLocation(program, "uBottomRight"),
|
|
2519
|
+
uBottomLeft: gl.getUniformLocation(program, "uBottomLeft")
|
|
2520
|
+
}
|
|
2521
|
+
};
|
|
2522
|
+
};
|
|
2523
|
+
var cleanupCornerPin = (state) => {
|
|
2524
|
+
const { gl, program, vao, vbo, textureSource } = state;
|
|
2525
|
+
gl.deleteTexture(textureSource);
|
|
2526
|
+
gl.deleteBuffer(vbo);
|
|
2527
|
+
gl.deleteProgram(program);
|
|
2528
|
+
gl.deleteVertexArray(vao);
|
|
2529
|
+
};
|
|
2530
|
+
var drawFullscreenQuad = (state) => {
|
|
2531
|
+
const { gl, vao } = state;
|
|
2532
|
+
gl.bindVertexArray(vao);
|
|
2533
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
2534
|
+
gl.bindVertexArray(null);
|
|
2535
|
+
};
|
|
2536
|
+
var setUvUniform = (gl, location, uv) => {
|
|
2537
|
+
if (!location) {
|
|
2538
|
+
return;
|
|
2539
|
+
}
|
|
2540
|
+
const shaderUv = publicUvToShaderUv(uv);
|
|
2541
|
+
gl.uniform2f(location, shaderUv[0], shaderUv[1]);
|
|
2542
|
+
};
|
|
2543
|
+
var applyCornerPin = ({
|
|
2544
|
+
state,
|
|
2545
|
+
source,
|
|
2546
|
+
width,
|
|
2547
|
+
height,
|
|
2548
|
+
topLeft,
|
|
2549
|
+
topRight,
|
|
2550
|
+
bottomRight,
|
|
2551
|
+
bottomLeft,
|
|
2552
|
+
flipSourceY
|
|
2553
|
+
}) => {
|
|
2554
|
+
const { gl, program, textureSource, uniforms } = state;
|
|
2555
|
+
gl.viewport(0, 0, width, height);
|
|
2556
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
2557
|
+
gl.bindTexture(gl.TEXTURE_2D, textureSource);
|
|
2558
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
2559
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2560
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
2561
|
+
gl.clearColor(0, 0, 0, 0);
|
|
2562
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
2563
|
+
gl.useProgram(program);
|
|
2564
|
+
if (uniforms.uSource)
|
|
2565
|
+
gl.uniform1i(uniforms.uSource, 0);
|
|
2566
|
+
setUvUniform(gl, uniforms.uTopLeft, topLeft);
|
|
2567
|
+
setUvUniform(gl, uniforms.uTopRight, topRight);
|
|
2568
|
+
setUvUniform(gl, uniforms.uBottomRight, bottomRight);
|
|
2569
|
+
setUvUniform(gl, uniforms.uBottomLeft, bottomLeft);
|
|
2570
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
2571
|
+
gl.bindTexture(gl.TEXTURE_2D, textureSource);
|
|
2572
|
+
drawFullscreenQuad(state);
|
|
2573
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
2574
|
+
gl.useProgram(null);
|
|
2575
|
+
};
|
|
2576
|
+
|
|
2577
|
+
// src/corner-pin/index.ts
|
|
2578
|
+
var { createEffect: createEffect6 } = Internals7;
|
|
2579
|
+
var DEFAULT_TOP_LEFT = [0, 0];
|
|
2580
|
+
var DEFAULT_TOP_RIGHT = [1, 0];
|
|
2581
|
+
var DEFAULT_BOTTOM_RIGHT = [1, 1];
|
|
2582
|
+
var DEFAULT_BOTTOM_LEFT = [0, 1];
|
|
2583
|
+
var cornerSchema = (defaultValue) => ({
|
|
2584
|
+
type: "uv-coordinate",
|
|
2585
|
+
min: -1,
|
|
2586
|
+
max: 2,
|
|
2587
|
+
step: 0.01,
|
|
2588
|
+
default: defaultValue,
|
|
2589
|
+
description: "Corner"
|
|
2590
|
+
});
|
|
2591
|
+
var cornerPinSchema = {
|
|
2592
|
+
topLeft: {
|
|
2593
|
+
...cornerSchema(DEFAULT_TOP_LEFT),
|
|
2594
|
+
description: "Top left"
|
|
2595
|
+
},
|
|
2596
|
+
topRight: {
|
|
2597
|
+
...cornerSchema(DEFAULT_TOP_RIGHT),
|
|
2598
|
+
description: "Top right"
|
|
2599
|
+
},
|
|
2600
|
+
bottomRight: {
|
|
2601
|
+
...cornerSchema(DEFAULT_BOTTOM_RIGHT),
|
|
2602
|
+
description: "Bottom right"
|
|
2603
|
+
},
|
|
2604
|
+
bottomLeft: {
|
|
2605
|
+
...cornerSchema(DEFAULT_BOTTOM_LEFT),
|
|
2606
|
+
description: "Bottom left"
|
|
2607
|
+
}
|
|
2608
|
+
};
|
|
2609
|
+
var resolve6 = (p) => ({
|
|
2610
|
+
topLeft: [...p.topLeft ?? DEFAULT_TOP_LEFT],
|
|
2611
|
+
topRight: [...p.topRight ?? DEFAULT_TOP_RIGHT],
|
|
2612
|
+
bottomRight: [
|
|
2613
|
+
...p.bottomRight ?? DEFAULT_BOTTOM_RIGHT
|
|
2614
|
+
],
|
|
2615
|
+
bottomLeft: [
|
|
2616
|
+
...p.bottomLeft ?? DEFAULT_BOTTOM_LEFT
|
|
2617
|
+
]
|
|
2618
|
+
});
|
|
2619
|
+
var assertOptionalUvCoordinate2 = (value, name) => {
|
|
2620
|
+
if (value === undefined) {
|
|
2621
|
+
return;
|
|
2622
|
+
}
|
|
2623
|
+
if (!Array.isArray(value) || value.length !== 2 || value.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
|
|
2624
|
+
throw new TypeError(`"${name}" must be a [number, number] tuple`);
|
|
2625
|
+
}
|
|
2626
|
+
};
|
|
2627
|
+
var validateCornerPinParams = (params) => {
|
|
2628
|
+
assertEffectParamsObject(params, "Corner pin");
|
|
2629
|
+
assertOptionalUvCoordinate2(params.topLeft, "topLeft");
|
|
2630
|
+
assertOptionalUvCoordinate2(params.topRight, "topRight");
|
|
2631
|
+
assertOptionalUvCoordinate2(params.bottomRight, "bottomRight");
|
|
2632
|
+
assertOptionalUvCoordinate2(params.bottomLeft, "bottomLeft");
|
|
2633
|
+
};
|
|
2634
|
+
var cornerPin = createEffect6({
|
|
2635
|
+
type: "dev.remotion.effects.cornerPin",
|
|
2636
|
+
label: "cornerPin()",
|
|
2637
|
+
documentationLink: "https://www.remotion.dev/docs/effects/corner-pin",
|
|
2638
|
+
backend: "webgl2",
|
|
2639
|
+
calculateKey: (params) => {
|
|
2640
|
+
const r = resolve6(params);
|
|
2641
|
+
return `corner-pin-${r.topLeft.join(":")}-${r.topRight.join(":")}-${r.bottomRight.join(":")}-${r.bottomLeft.join(":")}`;
|
|
2642
|
+
},
|
|
2643
|
+
setup: (target) => setupCornerPin(target),
|
|
2644
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
2645
|
+
const r = resolve6(params);
|
|
2646
|
+
applyCornerPin({
|
|
2647
|
+
state,
|
|
2648
|
+
source,
|
|
2649
|
+
width,
|
|
2650
|
+
height,
|
|
2651
|
+
topLeft: r.topLeft,
|
|
2652
|
+
topRight: r.topRight,
|
|
2653
|
+
bottomRight: r.bottomRight,
|
|
2654
|
+
bottomLeft: r.bottomLeft,
|
|
2655
|
+
flipSourceY
|
|
2656
|
+
});
|
|
2657
|
+
},
|
|
2658
|
+
cleanup: (state) => cleanupCornerPin(state),
|
|
2659
|
+
schema: cornerPinSchema,
|
|
2660
|
+
validateParams: validateCornerPinParams
|
|
2661
|
+
});
|
|
1439
2662
|
export {
|
|
1440
2663
|
zigzag,
|
|
1441
2664
|
rings,
|
|
1442
|
-
pattern
|
|
2665
|
+
pattern,
|
|
2666
|
+
gridlines,
|
|
2667
|
+
cornerPin,
|
|
2668
|
+
checkerboard
|
|
1443
2669
|
};
|