@remotion/effects 4.0.477 → 4.0.478

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.
@@ -0,0 +1,114 @@
1
+ export declare const contourLinesSchema: {
2
+ readonly lineColor: {
3
+ readonly type: "color";
4
+ readonly default: "#ffffff";
5
+ readonly description: "Line color";
6
+ };
7
+ readonly lineWidth: {
8
+ readonly type: "number";
9
+ readonly min: 0.1;
10
+ readonly max: 20;
11
+ readonly step: 0.1;
12
+ readonly default: 1.5;
13
+ readonly description: "Line width";
14
+ readonly hiddenFromList: false;
15
+ };
16
+ readonly spacing: {
17
+ readonly type: "number";
18
+ readonly min: 1;
19
+ readonly max: 200;
20
+ readonly step: 1;
21
+ readonly default: 36;
22
+ readonly description: "Spacing";
23
+ readonly hiddenFromList: false;
24
+ };
25
+ readonly scale: {
26
+ readonly type: "number";
27
+ readonly min: 20;
28
+ readonly max: 1000;
29
+ readonly step: 1;
30
+ readonly default: 220;
31
+ readonly description: "Scale";
32
+ readonly hiddenFromList: false;
33
+ };
34
+ readonly complexity: {
35
+ readonly type: "number";
36
+ readonly min: 0;
37
+ readonly max: 1;
38
+ readonly step: 0.01;
39
+ readonly default: 0.65;
40
+ readonly description: "Complexity";
41
+ readonly hiddenFromList: false;
42
+ };
43
+ readonly smoothness: {
44
+ readonly type: "number";
45
+ readonly min: 0;
46
+ readonly max: 1;
47
+ readonly step: 0.01;
48
+ readonly default: 0.55;
49
+ readonly description: "Smoothness";
50
+ readonly hiddenFromList: false;
51
+ };
52
+ readonly seed: {
53
+ readonly type: "number";
54
+ readonly step: 1;
55
+ readonly default: 0;
56
+ readonly description: "Seed";
57
+ readonly hiddenFromList: false;
58
+ };
59
+ readonly offsetX: {
60
+ readonly type: "number";
61
+ readonly step: 0.1;
62
+ readonly default: 0;
63
+ readonly description: "Offset X";
64
+ readonly hiddenFromList: false;
65
+ };
66
+ readonly offsetY: {
67
+ readonly type: "number";
68
+ readonly step: 0.1;
69
+ readonly default: 0;
70
+ readonly description: "Offset Y";
71
+ readonly hiddenFromList: false;
72
+ };
73
+ readonly opacity: {
74
+ readonly type: "number";
75
+ readonly min: 0;
76
+ readonly max: 1;
77
+ readonly step: 0.01;
78
+ readonly default: 1;
79
+ readonly description: "Opacity";
80
+ readonly hiddenFromList: false;
81
+ };
82
+ readonly maskToSourceAlpha: {
83
+ readonly type: "boolean";
84
+ readonly default: false;
85
+ readonly description: "Mask to source alpha";
86
+ };
87
+ };
88
+ export type ContourLinesParams = {
89
+ /** Color of the contour lines. Defaults to `#ffffff`. */
90
+ readonly lineColor?: string;
91
+ /** Width of each contour line in pixels. Defaults to `1.5`. */
92
+ readonly lineWidth?: number;
93
+ /** Distance between contour height levels in pixels. Defaults to `36`. */
94
+ readonly spacing?: number;
95
+ /** Size of the generated terrain features in pixels. Defaults to `220`. */
96
+ readonly scale?: number;
97
+ /** Amount of terrain detail from `0` to `1`. Defaults to `0.65`. */
98
+ readonly complexity?: number;
99
+ /** Smooths the contour curves from `0` to `1`. Defaults to `0.55`. */
100
+ readonly smoothness?: number;
101
+ /** Deterministic seed for the contour field. Defaults to `0`. */
102
+ readonly seed?: number;
103
+ /** Horizontal offset in pixels. Defaults to `0`. */
104
+ readonly offsetX?: number;
105
+ /** Vertical offset in pixels. Defaults to `0`. */
106
+ readonly offsetY?: number;
107
+ /** Multiplies the alpha channel of `lineColor`. Defaults to `1`. */
108
+ readonly opacity?: number;
109
+ /** Masks the generated contour lines to the source alpha channel. Defaults to `false`. */
110
+ readonly maskToSourceAlpha?: boolean;
111
+ };
112
+ export declare const contourLines: (params?: (ContourLinesParams & {
113
+ readonly disabled?: boolean | undefined;
114
+ }) | undefined) => import("remotion").EffectDescriptor<unknown>;
@@ -0,0 +1,567 @@
1
+ // src/contour-lines.ts
2
+ import { Internals } from "remotion";
3
+
4
+ // src/validate-effect-param.ts
5
+ var assertEffectParamsObject = (params, effectLabel) => {
6
+ if (params === null || typeof params !== "object") {
7
+ throw new TypeError(`${effectLabel} effect requires a parameters object, but got ${JSON.stringify(params)}`);
8
+ }
9
+ };
10
+ var assertRequiredFiniteNumber = (value, name) => {
11
+ if (typeof value !== "number" || !Number.isFinite(value)) {
12
+ throw new TypeError(`"${name}" must be a finite number, but got ${JSON.stringify(value)}`);
13
+ }
14
+ };
15
+ var assertRequiredColor = (value, name) => {
16
+ if (typeof value !== "string" || value.length === 0) {
17
+ throw new TypeError(`"${name}" must be a non-empty string, but got ${JSON.stringify(value)}`);
18
+ }
19
+ };
20
+ var assertOptionalColor = (value, name) => {
21
+ if (value === undefined) {
22
+ return;
23
+ }
24
+ assertRequiredColor(value, name);
25
+ };
26
+ var assertOptionalBoolean = (value, name) => {
27
+ if (value === undefined) {
28
+ return;
29
+ }
30
+ if (typeof value !== "boolean") {
31
+ throw new TypeError(`"${name}" must be a boolean, but got ${JSON.stringify(value)}`);
32
+ }
33
+ };
34
+
35
+ // src/color-utils.ts
36
+ var DEFAULT_AMOUNT = 1;
37
+ var DEFAULT_BRIGHTNESS_AMOUNT = 0;
38
+ var DEFAULT_HUE_DEGREES = 0;
39
+ var colorAmountSchema = {
40
+ type: "number",
41
+ min: 0,
42
+ max: 1,
43
+ step: 0.01,
44
+ default: DEFAULT_AMOUNT,
45
+ description: "Amount",
46
+ hiddenFromList: false
47
+ };
48
+ var colorMultiplierSchema = {
49
+ type: "number",
50
+ min: 0,
51
+ step: 0.01,
52
+ default: DEFAULT_AMOUNT,
53
+ description: "Amount",
54
+ hiddenFromList: false
55
+ };
56
+ var brightnessAmountSchema = {
57
+ type: "number",
58
+ min: -1,
59
+ max: 1,
60
+ step: 0.01,
61
+ default: DEFAULT_BRIGHTNESS_AMOUNT,
62
+ description: "Amount",
63
+ hiddenFromList: false
64
+ };
65
+ var hueDegreesSchema = {
66
+ type: "rotation-degrees",
67
+ step: 1,
68
+ default: DEFAULT_HUE_DEGREES,
69
+ description: "Degrees"
70
+ };
71
+ var assertOptionalFiniteNumber = (value, name) => {
72
+ if (value === undefined) {
73
+ return;
74
+ }
75
+ assertRequiredFiniteNumber(value, name);
76
+ };
77
+ var validateUnitInterval = (value, name) => {
78
+ if (value < 0) {
79
+ throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
80
+ }
81
+ if (value > 1) {
82
+ throw new TypeError(`"${name}" must be <= 1, but got ${JSON.stringify(value)}`);
83
+ }
84
+ };
85
+ var validateNonNegative = (value, name) => {
86
+ if (value < 0) {
87
+ throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
88
+ }
89
+ };
90
+ var validateSignedUnitInterval = (value, name) => {
91
+ if (value < -1) {
92
+ throw new TypeError(`"${name}" must be >= -1, but got ${JSON.stringify(value)}`);
93
+ }
94
+ if (value > 1) {
95
+ throw new TypeError(`"${name}" must be <= 1, but got ${JSON.stringify(value)}`);
96
+ }
97
+ };
98
+ var clampColorChannel = (value) => {
99
+ return Math.max(0, Math.min(255, value));
100
+ };
101
+ var parseColorRgba = (ctx, color) => {
102
+ ctx.clearRect(0, 0, 1, 1);
103
+ ctx.fillStyle = color;
104
+ ctx.fillRect(0, 0, 1, 1);
105
+ const { data } = ctx.getImageData(0, 0, 1, 1);
106
+ return [data[0], data[1], data[2], data[3]];
107
+ };
108
+
109
+ // src/contour-lines.ts
110
+ var { createEffect, createWebGL2ContextError } = Internals;
111
+ var DEFAULT_LINE_COLOR = "#ffffff";
112
+ var DEFAULT_LINE_WIDTH = 1.5;
113
+ var DEFAULT_SPACING = 36;
114
+ var DEFAULT_SCALE = 220;
115
+ var DEFAULT_COMPLEXITY = 0.65;
116
+ var DEFAULT_SMOOTHNESS = 0.55;
117
+ var DEFAULT_SEED = 0;
118
+ var DEFAULT_OFFSET_X = 0;
119
+ var DEFAULT_OFFSET_Y = 0;
120
+ var DEFAULT_OPACITY = 1;
121
+ var DEFAULT_MASK_TO_SOURCE_ALPHA = false;
122
+ var contourLinesSchema = {
123
+ lineColor: {
124
+ type: "color",
125
+ default: DEFAULT_LINE_COLOR,
126
+ description: "Line color"
127
+ },
128
+ lineWidth: {
129
+ type: "number",
130
+ min: 0.1,
131
+ max: 20,
132
+ step: 0.1,
133
+ default: DEFAULT_LINE_WIDTH,
134
+ description: "Line width",
135
+ hiddenFromList: false
136
+ },
137
+ spacing: {
138
+ type: "number",
139
+ min: 1,
140
+ max: 200,
141
+ step: 1,
142
+ default: DEFAULT_SPACING,
143
+ description: "Spacing",
144
+ hiddenFromList: false
145
+ },
146
+ scale: {
147
+ type: "number",
148
+ min: 20,
149
+ max: 1000,
150
+ step: 1,
151
+ default: DEFAULT_SCALE,
152
+ description: "Scale",
153
+ hiddenFromList: false
154
+ },
155
+ complexity: {
156
+ type: "number",
157
+ min: 0,
158
+ max: 1,
159
+ step: 0.01,
160
+ default: DEFAULT_COMPLEXITY,
161
+ description: "Complexity",
162
+ hiddenFromList: false
163
+ },
164
+ smoothness: {
165
+ type: "number",
166
+ min: 0,
167
+ max: 1,
168
+ step: 0.01,
169
+ default: DEFAULT_SMOOTHNESS,
170
+ description: "Smoothness",
171
+ hiddenFromList: false
172
+ },
173
+ seed: {
174
+ type: "number",
175
+ step: 1,
176
+ default: DEFAULT_SEED,
177
+ description: "Seed",
178
+ hiddenFromList: false
179
+ },
180
+ offsetX: {
181
+ type: "number",
182
+ step: 0.1,
183
+ default: DEFAULT_OFFSET_X,
184
+ description: "Offset X",
185
+ hiddenFromList: false
186
+ },
187
+ offsetY: {
188
+ type: "number",
189
+ step: 0.1,
190
+ default: DEFAULT_OFFSET_Y,
191
+ description: "Offset Y",
192
+ hiddenFromList: false
193
+ },
194
+ opacity: {
195
+ type: "number",
196
+ min: 0,
197
+ max: 1,
198
+ step: 0.01,
199
+ default: DEFAULT_OPACITY,
200
+ description: "Opacity",
201
+ hiddenFromList: false
202
+ },
203
+ maskToSourceAlpha: {
204
+ type: "boolean",
205
+ default: DEFAULT_MASK_TO_SOURCE_ALPHA,
206
+ description: "Mask to source alpha"
207
+ }
208
+ };
209
+ var resolve = (p) => ({
210
+ lineColor: p.lineColor ?? DEFAULT_LINE_COLOR,
211
+ lineWidth: p.lineWidth ?? DEFAULT_LINE_WIDTH,
212
+ spacing: p.spacing ?? DEFAULT_SPACING,
213
+ scale: p.scale ?? DEFAULT_SCALE,
214
+ complexity: p.complexity ?? DEFAULT_COMPLEXITY,
215
+ smoothness: p.smoothness ?? DEFAULT_SMOOTHNESS,
216
+ seed: p.seed ?? DEFAULT_SEED,
217
+ offsetX: p.offsetX ?? DEFAULT_OFFSET_X,
218
+ offsetY: p.offsetY ?? DEFAULT_OFFSET_Y,
219
+ opacity: p.opacity ?? DEFAULT_OPACITY,
220
+ maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA
221
+ });
222
+ var validatePositive = (value, name) => {
223
+ if (value <= 0) {
224
+ throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
225
+ }
226
+ };
227
+ var validateContourLinesParams = (params) => {
228
+ assertEffectParamsObject(params, "Contour lines");
229
+ assertOptionalColor(params.lineColor, "lineColor");
230
+ assertOptionalFiniteNumber(params.lineWidth, "lineWidth");
231
+ assertOptionalFiniteNumber(params.spacing, "spacing");
232
+ assertOptionalFiniteNumber(params.scale, "scale");
233
+ assertOptionalFiniteNumber(params.complexity, "complexity");
234
+ assertOptionalFiniteNumber(params.smoothness, "smoothness");
235
+ assertOptionalFiniteNumber(params.seed, "seed");
236
+ assertOptionalFiniteNumber(params.offsetX, "offsetX");
237
+ assertOptionalFiniteNumber(params.offsetY, "offsetY");
238
+ assertOptionalFiniteNumber(params.opacity, "opacity");
239
+ assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
240
+ const r = resolve(params);
241
+ validatePositive(r.lineWidth, "lineWidth");
242
+ validatePositive(r.spacing, "spacing");
243
+ validatePositive(r.scale, "scale");
244
+ validateUnitInterval(r.complexity, "complexity");
245
+ validateUnitInterval(r.smoothness, "smoothness");
246
+ validateUnitInterval(r.opacity, "opacity");
247
+ };
248
+ var CONTOUR_LINES_VS = `#version 300 es
249
+ in vec2 aPos;
250
+ in vec2 aUv;
251
+ out vec2 vUv;
252
+
253
+ void main() {
254
+ vUv = aUv;
255
+ gl_Position = vec4(aPos, 0.0, 1.0);
256
+ }
257
+ `;
258
+ var CONTOUR_LINES_FS = `#version 300 es
259
+ precision highp float;
260
+
261
+ in vec2 vUv;
262
+ out vec4 fragColor;
263
+
264
+ uniform sampler2D uSource;
265
+ uniform vec2 uResolution;
266
+ uniform vec4 uLineColor;
267
+ uniform float uLineWidth;
268
+ uniform float uSpacing;
269
+ uniform float uScale;
270
+ uniform float uComplexity;
271
+ uniform float uSmoothness;
272
+ uniform float uSeed;
273
+ uniform vec2 uOffset;
274
+ uniform float uOpacity;
275
+ uniform bool uMaskToSourceAlpha;
276
+
277
+ float hash(vec2 p) {
278
+ vec3 p3 = fract(vec3(p.xyx) * 0.1031);
279
+ p3 += dot(p3, p3.yzx + 33.33 + uSeed * 0.013);
280
+ return fract((p3.x + p3.y) * p3.z);
281
+ }
282
+
283
+ float valueNoise(vec2 p) {
284
+ vec2 i = floor(p);
285
+ vec2 f = fract(p);
286
+ vec2 u = f * f * f * (f * (f * 6.0 - 15.0) + 10.0);
287
+
288
+ float a = hash(i);
289
+ float b = hash(i + vec2(1.0, 0.0));
290
+ float c = hash(i + vec2(0.0, 1.0));
291
+ float d = hash(i + vec2(1.0, 1.0));
292
+
293
+ return mix(mix(a, b, u.x), mix(c, d, u.x), u.y);
294
+ }
295
+
296
+ float fbm(vec2 p) {
297
+ float value = 0.0;
298
+ float amplitude = 0.5;
299
+ float totalAmplitude = 0.0;
300
+ float persistence = mix(0.18, 0.58, clamp(uComplexity, 0.0, 1.0));
301
+ float smoothness = clamp(uSmoothness, 0.0, 1.0);
302
+ mat2 rotate = mat2(0.80, 0.60, -0.60, 0.80);
303
+
304
+ for (int i = 0; i < 5; i++) {
305
+ float octave = float(i) / 4.0;
306
+ float detailWeight = mix(
307
+ 1.0,
308
+ 1.0 - smoothstep(0.15, 1.0, octave),
309
+ smoothness
310
+ );
311
+ value += amplitude * detailWeight * valueNoise(p);
312
+ totalAmplitude += amplitude * detailWeight;
313
+ p = rotate * p * 2.04 + vec2(13.17, 7.31);
314
+ amplitude *= persistence;
315
+ }
316
+
317
+ return value / totalAmplitude;
318
+ }
319
+
320
+ void main() {
321
+ vec4 texColor = texture(uSource, vUv);
322
+ vec2 pixelPosition = vUv * uResolution + uOffset;
323
+ float scale = max(uScale, 0.001);
324
+ vec2 p = pixelPosition / scale + vec2(uSeed * 0.137, uSeed * 0.193);
325
+
326
+ float complexity = clamp(uComplexity, 0.0, 1.0);
327
+ float smoothness = clamp(uSmoothness, 0.0, 1.0);
328
+ vec2 warp = vec2(
329
+ fbm(p + vec2(5.2, 1.3)),
330
+ fbm(p + vec2(1.7, 9.2))
331
+ ) - 0.5;
332
+ float terrain = fbm(p + warp * complexity * mix(2.8, 1.2, smoothness));
333
+
334
+ float levels = max(
335
+ max(uResolution.x, uResolution.y) / (max(uSpacing, 0.001) * 2.0),
336
+ 1.0
337
+ );
338
+ float contourPosition = terrain * levels;
339
+ float contourFraction = fract(contourPosition);
340
+ float distanceToContour = min(contourFraction, 1.0 - contourFraction);
341
+ float derivative = max(fwidth(contourPosition), 0.0001);
342
+ float halfLineWidth = max(uLineWidth, 0.001) * 0.5 * derivative;
343
+ float coverage = 1.0 - smoothstep(
344
+ halfLineWidth,
345
+ halfLineWidth + derivative,
346
+ distanceToContour
347
+ );
348
+
349
+ float lineAlpha = uLineColor.a * uOpacity * coverage;
350
+ vec3 premultipliedLine = uLineColor.rgb * lineAlpha;
351
+
352
+ if (uMaskToSourceAlpha) {
353
+ fragColor = vec4(
354
+ premultipliedLine * texColor.a + texColor.rgb * (1.0 - lineAlpha),
355
+ texColor.a
356
+ );
357
+ return;
358
+ }
359
+
360
+ fragColor = vec4(
361
+ premultipliedLine + texColor.rgb * (1.0 - lineAlpha),
362
+ lineAlpha + texColor.a * (1.0 - lineAlpha)
363
+ );
364
+ }
365
+ `;
366
+ var compileShader = (gl, type, source) => {
367
+ const shader = gl.createShader(type);
368
+ if (!shader) {
369
+ throw new Error("Failed to create WebGL shader");
370
+ }
371
+ gl.shaderSource(shader, source);
372
+ gl.compileShader(shader);
373
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
374
+ const log = gl.getShaderInfoLog(shader);
375
+ gl.deleteShader(shader);
376
+ throw new Error(`Contour lines shader compile failed: ${log ?? "(no log)"}`);
377
+ }
378
+ return shader;
379
+ };
380
+ var linkProgram = (gl, vs, fs) => {
381
+ const program = gl.createProgram();
382
+ if (!program) {
383
+ throw new Error("Failed to create WebGL program");
384
+ }
385
+ gl.attachShader(program, vs);
386
+ gl.attachShader(program, fs);
387
+ gl.linkProgram(program);
388
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
389
+ const log = gl.getProgramInfoLog(program);
390
+ gl.deleteProgram(program);
391
+ throw new Error(`Contour lines program link failed: ${log ?? "(no log)"}`);
392
+ }
393
+ return program;
394
+ };
395
+ var createProgram = (gl, vertexSource, fragmentSource) => {
396
+ const vs = compileShader(gl, gl.VERTEX_SHADER, vertexSource);
397
+ const fs = compileShader(gl, gl.FRAGMENT_SHADER, fragmentSource);
398
+ const program = linkProgram(gl, vs, fs);
399
+ gl.deleteShader(vs);
400
+ gl.deleteShader(fs);
401
+ return program;
402
+ };
403
+ var createTexture = (gl) => {
404
+ const texture = gl.createTexture();
405
+ if (!texture) {
406
+ throw new Error("Failed to create WebGL texture");
407
+ }
408
+ gl.bindTexture(gl.TEXTURE_2D, texture);
409
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
410
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
411
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
412
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
413
+ gl.bindTexture(gl.TEXTURE_2D, null);
414
+ return texture;
415
+ };
416
+ var setupContourLines = (target) => {
417
+ const gl = target.getContext("webgl2", {
418
+ premultipliedAlpha: true,
419
+ alpha: true,
420
+ preserveDrawingBuffer: true
421
+ });
422
+ if (!gl) {
423
+ throw createWebGL2ContextError("contour lines effect");
424
+ }
425
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
426
+ const program = createProgram(gl, CONTOUR_LINES_VS, CONTOUR_LINES_FS);
427
+ const vao = gl.createVertexArray();
428
+ if (!vao) {
429
+ throw new Error("Failed to create WebGL vertex array");
430
+ }
431
+ gl.bindVertexArray(vao);
432
+ const data = new Float32Array([
433
+ -1,
434
+ -1,
435
+ 0,
436
+ 0,
437
+ 1,
438
+ -1,
439
+ 1,
440
+ 0,
441
+ -1,
442
+ 1,
443
+ 0,
444
+ 1,
445
+ 1,
446
+ 1,
447
+ 1,
448
+ 1
449
+ ]);
450
+ const vbo = gl.createBuffer();
451
+ if (!vbo) {
452
+ throw new Error("Failed to create WebGL buffer");
453
+ }
454
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
455
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
456
+ const aPos = gl.getAttribLocation(program, "aPos");
457
+ const aUv = gl.getAttribLocation(program, "aUv");
458
+ gl.enableVertexAttribArray(aPos);
459
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
460
+ gl.enableVertexAttribArray(aUv);
461
+ gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
462
+ gl.bindVertexArray(null);
463
+ const colorCanvas = document.createElement("canvas");
464
+ colorCanvas.width = 1;
465
+ colorCanvas.height = 1;
466
+ const colorCtx = colorCanvas.getContext("2d", { willReadFrequently: true });
467
+ if (!colorCtx) {
468
+ throw new Error("Failed to acquire 2D context for color parsing");
469
+ }
470
+ return {
471
+ gl,
472
+ program,
473
+ vao,
474
+ vbo,
475
+ sourceTexture: createTexture(gl),
476
+ colorCtx,
477
+ uniforms: {
478
+ uSource: gl.getUniformLocation(program, "uSource"),
479
+ uResolution: gl.getUniformLocation(program, "uResolution"),
480
+ uLineColor: gl.getUniformLocation(program, "uLineColor"),
481
+ uLineWidth: gl.getUniformLocation(program, "uLineWidth"),
482
+ uSpacing: gl.getUniformLocation(program, "uSpacing"),
483
+ uScale: gl.getUniformLocation(program, "uScale"),
484
+ uComplexity: gl.getUniformLocation(program, "uComplexity"),
485
+ uSmoothness: gl.getUniformLocation(program, "uSmoothness"),
486
+ uSeed: gl.getUniformLocation(program, "uSeed"),
487
+ uOffset: gl.getUniformLocation(program, "uOffset"),
488
+ uOpacity: gl.getUniformLocation(program, "uOpacity"),
489
+ uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
490
+ },
491
+ cachedLineColor: "",
492
+ cachedLineColorRgba: [255, 255, 255, 255]
493
+ };
494
+ };
495
+ var contourLines = createEffect({
496
+ type: "remotion/contour-lines",
497
+ label: "contourLines()",
498
+ documentationLink: "https://www.remotion.dev/docs/effects/contour-lines",
499
+ backend: "webgl2",
500
+ calculateKey: (params) => {
501
+ const r = resolve(params);
502
+ const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
503
+ return `contour-lines-${r.lineColor}-${r.lineWidth}-${r.spacing}-${r.scale}-${r.complexity}-${r.smoothness}-${r.seed}-${r.offsetX}-${r.offsetY}-${r.opacity}${maskSuffix}`;
504
+ },
505
+ setup: (target) => setupContourLines(target),
506
+ apply: ({ source, width, height, params, state, flipSourceY }) => {
507
+ const r = resolve(params);
508
+ const { gl, program, sourceTexture, uniforms, vao } = state;
509
+ if (state.cachedLineColor !== r.lineColor) {
510
+ state.cachedLineColor = r.lineColor;
511
+ state.cachedLineColorRgba = parseColorRgba(state.colorCtx, r.lineColor);
512
+ }
513
+ const [cr, cg, cb, ca] = state.cachedLineColorRgba;
514
+ gl.viewport(0, 0, width, height);
515
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
516
+ gl.clearColor(0, 0, 0, 0);
517
+ gl.clear(gl.COLOR_BUFFER_BIT);
518
+ gl.activeTexture(gl.TEXTURE0);
519
+ gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
520
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
521
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
522
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
523
+ gl.useProgram(program);
524
+ if (uniforms.uSource)
525
+ gl.uniform1i(uniforms.uSource, 0);
526
+ if (uniforms.uResolution)
527
+ gl.uniform2f(uniforms.uResolution, width, height);
528
+ if (uniforms.uLineColor) {
529
+ gl.uniform4f(uniforms.uLineColor, cr / 255, cg / 255, cb / 255, ca / 255);
530
+ }
531
+ if (uniforms.uLineWidth)
532
+ gl.uniform1f(uniforms.uLineWidth, r.lineWidth);
533
+ if (uniforms.uSpacing)
534
+ gl.uniform1f(uniforms.uSpacing, r.spacing);
535
+ if (uniforms.uScale)
536
+ gl.uniform1f(uniforms.uScale, r.scale);
537
+ if (uniforms.uComplexity)
538
+ gl.uniform1f(uniforms.uComplexity, r.complexity);
539
+ if (uniforms.uSmoothness)
540
+ gl.uniform1f(uniforms.uSmoothness, r.smoothness);
541
+ if (uniforms.uSeed)
542
+ gl.uniform1f(uniforms.uSeed, r.seed);
543
+ if (uniforms.uOffset)
544
+ gl.uniform2f(uniforms.uOffset, r.offsetX, r.offsetY);
545
+ if (uniforms.uOpacity)
546
+ gl.uniform1f(uniforms.uOpacity, r.opacity);
547
+ if (uniforms.uMaskToSourceAlpha)
548
+ gl.uniform1i(uniforms.uMaskToSourceAlpha, r.maskToSourceAlpha ? 1 : 0);
549
+ gl.bindVertexArray(vao);
550
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
551
+ gl.bindVertexArray(null);
552
+ gl.bindTexture(gl.TEXTURE_2D, null);
553
+ gl.useProgram(null);
554
+ },
555
+ cleanup: ({ gl, program, vao, vbo, sourceTexture }) => {
556
+ gl.deleteTexture(sourceTexture);
557
+ gl.deleteBuffer(vbo);
558
+ gl.deleteProgram(program);
559
+ gl.deleteVertexArray(vao);
560
+ },
561
+ schema: contourLinesSchema,
562
+ validateParams: validateContourLinesParams
563
+ });
564
+ export {
565
+ contourLinesSchema,
566
+ contourLines
567
+ };
@@ -268,11 +268,6 @@ var validateAtLeast = (value, min, name) => {
268
268
  throw new TypeError(`"${name}" must be >= ${min}, but got ${JSON.stringify(value)}`);
269
269
  }
270
270
  };
271
- var validateNonNegative2 = (value, name) => {
272
- if (value < 0) {
273
- throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
274
- }
275
- };
276
271
  var validatePatternParams = (params) => {
277
272
  assertEffectParamsObject(params, "Pattern");
278
273
  assertOptionalFiniteNumber(params.scale, "scale");
@@ -294,8 +289,6 @@ var validatePatternParams = (params) => {
294
289
  assertOptionalInteger(params.columnOffsetEvery, "columnOffsetEvery");
295
290
  const r = resolve(params);
296
291
  validatePositive(r.scale, "scale");
297
- validateNonNegative2(r.gapX, "gapX");
298
- validateNonNegative2(r.gapY, "gapY");
299
292
  validateAtLeast(r.rowOffsetEvery, 0, "rowOffsetEvery");
300
293
  validateAtLeast(r.columnOffsetEvery, 0, "columnOffsetEvery");
301
294
  validateUnitInterval(r.origin[0], "origin[0]");
@@ -655,7 +648,7 @@ var validatePositive2 = (value, name) => {
655
648
  throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
656
649
  }
657
650
  };
658
- var validateNonNegative3 = (value, name) => {
651
+ var validateNonNegative2 = (value, name) => {
659
652
  if (value < 0) {
660
653
  throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
661
654
  }
@@ -692,7 +685,7 @@ var validateRingsParams = (params) => {
692
685
  const thickness = params.thickness ?? DEFAULT_THICKNESS;
693
686
  const gap = params.gap ?? DEFAULT_GAP2;
694
687
  validatePositive2(thickness, "thickness");
695
- validateNonNegative3(gap, "gap");
688
+ validateNonNegative2(gap, "gap");
696
689
  };
697
690
  var RINGS_VS = `#version 300 es
698
691
  in vec2 aPos;
@@ -1092,7 +1085,7 @@ var validatePositive3 = (value, name) => {
1092
1085
  throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
1093
1086
  }
1094
1087
  };
1095
- var validateNonNegative4 = (value, name) => {
1088
+ var validateNonNegative3 = (value, name) => {
1096
1089
  if (value < 0) {
1097
1090
  throw new TypeError(`"${name}" must be greater than or equal to 0, but got ${JSON.stringify(value)}`);
1098
1091
  }
@@ -1132,8 +1125,8 @@ var validateZigzagParams = (params) => {
1132
1125
  const amplitude = params.amplitude ?? DEFAULT_AMPLITUDE;
1133
1126
  const wavelength = params.wavelength ?? DEFAULT_WAVELENGTH;
1134
1127
  validatePositive3(thickness, "thickness");
1135
- validateNonNegative4(gap, "gap");
1136
- validateNonNegative4(amplitude, "amplitude");
1128
+ validateNonNegative3(gap, "gap");
1129
+ validateNonNegative3(amplitude, "amplitude");
1137
1130
  validatePositive3(wavelength, "wavelength");
1138
1131
  };
1139
1132
  var ZIGZAG_VS = `#version 300 es
@@ -268,11 +268,6 @@ var validateAtLeast = (value, min, name) => {
268
268
  throw new TypeError(`"${name}" must be >= ${min}, but got ${JSON.stringify(value)}`);
269
269
  }
270
270
  };
271
- var validateNonNegative2 = (value, name) => {
272
- if (value < 0) {
273
- throw new TypeError(`"${name}" must be >= 0, but got ${JSON.stringify(value)}`);
274
- }
275
- };
276
271
  var validatePatternParams = (params) => {
277
272
  assertEffectParamsObject(params, "Pattern");
278
273
  assertOptionalFiniteNumber(params.scale, "scale");
@@ -294,8 +289,6 @@ var validatePatternParams = (params) => {
294
289
  assertOptionalInteger(params.columnOffsetEvery, "columnOffsetEvery");
295
290
  const r = resolve(params);
296
291
  validatePositive(r.scale, "scale");
297
- validateNonNegative2(r.gapX, "gapX");
298
- validateNonNegative2(r.gapY, "gapY");
299
292
  validateAtLeast(r.rowOffsetEvery, 0, "rowOffsetEvery");
300
293
  validateAtLeast(r.columnOffsetEvery, 0, "columnOffsetEvery");
301
294
  validateUnitInterval(r.origin[0], "origin[0]");
@@ -221,13 +221,15 @@ float hash21(vec2 p) {
221
221
  return fract((p3.x + p3.y) * p3.z);
222
222
  }
223
223
 
224
- float dissolveMask(float noise, float threshold, float feather) {
224
+ float dissolveMask(float noise, float progress, float feather) {
225
225
  float edge = max(feather, 0.0);
226
+ float threshold = 1.0 - clamp(progress, 0.0, 1.0) * (1.0 + edge);
227
+
226
228
  if (edge <= 0.0001) {
227
- return step(noise, threshold);
229
+ return 1.0 - step(threshold, noise);
228
230
  }
229
231
 
230
- return 1.0 - smoothstep(threshold, min(threshold + edge, 1.0), noise);
232
+ return 1.0 - smoothstep(threshold, threshold + edge, noise);
231
233
  }
232
234
 
233
235
  void main() {
@@ -236,9 +238,8 @@ void main() {
236
238
  vec2 cell = floor(gridUv * divisions);
237
239
  vec4 color = texture(uSource, vUv);
238
240
 
239
- float threshold = 1.0 - clamp(uProgress, 0.0, 1.0);
240
241
  float noise = hash21(cell + vec2(uSeed, uSeed * 1.618));
241
- float mask = dissolveMask(noise, threshold, uFeather);
242
+ float mask = dissolveMask(noise, uProgress, uFeather);
242
243
 
243
244
  fragColor = vec4(color.rgb * mask, color.a * mask);
244
245
  }
@@ -6,6 +6,11 @@ export declare const testImage: ({ blob, testId, threshold, allowedMismatchedPix
6
6
  allowedMismatchedPixelRatio?: number | undefined;
7
7
  }) => Promise<void>;
8
8
  export declare const descriptorsToMemoizedEffects: (effects: EffectDescriptor<unknown>[]) => EffectDefinitionAndStack<unknown>[];
9
+ export declare const renderEffectChainToCanvas: ({ effects, width, height, }: {
10
+ effects: EffectDefinitionAndStack<unknown>[];
11
+ width?: number | undefined;
12
+ height?: number | undefined;
13
+ }) => Promise<HTMLCanvasElement>;
9
14
  export declare const renderEffectChainToBlob: ({ effects, width, height, }: {
10
15
  effects: EffectDefinitionAndStack<unknown>[];
11
16
  width?: number | undefined;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remotion/effects",
3
- "version": "4.0.477",
3
+ "version": "4.0.478",
4
4
  "description": "Effects that can be applied to Remotion-based canvas components",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -26,7 +26,7 @@
26
26
  "url": "https://github.com/remotion-dev/remotion/issues"
27
27
  },
28
28
  "dependencies": {
29
- "remotion": "4.0.477"
29
+ "remotion": "4.0.478"
30
30
  },
31
31
  "exports": {
32
32
  ".": {
@@ -64,6 +64,11 @@
64
64
  "module": "./dist/esm/contrast.mjs",
65
65
  "import": "./dist/esm/contrast.mjs"
66
66
  },
67
+ "./contour-lines": {
68
+ "types": "./dist/contour-lines.d.ts",
69
+ "module": "./dist/esm/contour-lines.mjs",
70
+ "import": "./dist/esm/contour-lines.mjs"
71
+ },
67
72
  "./drop-shadow": {
68
73
  "types": "./dist/drop-shadow.d.ts",
69
74
  "module": "./dist/esm/drop-shadow.mjs",
@@ -246,6 +251,9 @@
246
251
  "contrast": [
247
252
  "dist/contrast.d.ts"
248
253
  ],
254
+ "contour-lines": [
255
+ "dist/contour-lines.d.ts"
256
+ ],
249
257
  "drop-shadow": [
250
258
  "dist/drop-shadow.d.ts"
251
259
  ],
@@ -346,7 +354,7 @@
346
354
  },
347
355
  "homepage": "https://www.remotion.dev/docs/effects/api",
348
356
  "devDependencies": {
349
- "@remotion/eslint-config-internal": "4.0.477",
357
+ "@remotion/eslint-config-internal": "4.0.478",
350
358
  "@vitest/browser-playwright": "4.0.9",
351
359
  "eslint": "9.19.0",
352
360
  "vitest": "4.0.9",
@@ -1,8 +0,0 @@
1
- export declare const EffectInternals: {
2
- readonly halftone: (params?: (import("./halftone.js").HalftoneParams & {
3
- readonly disabled?: boolean | undefined;
4
- }) | undefined) => import("remotion").EffectDescriptor<unknown>;
5
- readonly tint: (params: import("./tint.js").TintParams & {
6
- readonly disabled?: boolean | undefined;
7
- }) => import("remotion").EffectDescriptor<unknown>;
8
- };
@@ -1,6 +0,0 @@
1
- import * as blurExports from '../blur/index.js';
2
- export type { BlurParams } from '../blur/index.js';
3
- declare const blur: (params: blurExports.BlurParams & {
4
- readonly disabled?: boolean | undefined;
5
- }) => import("remotion").EffectDescriptor<unknown>;
6
- export { blur };