@remotion/effects 4.0.473 → 4.0.475

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.
Files changed (45) hide show
  1. package/dist/esm/barrel-distortion.mjs +8 -0
  2. package/dist/esm/blur.mjs +8 -0
  3. package/dist/esm/brightness.mjs +8 -0
  4. package/dist/esm/chromatic-aberration.mjs +8 -0
  5. package/dist/esm/color-key.mjs +8 -0
  6. package/dist/esm/contrast.mjs +8 -0
  7. package/dist/esm/dot-grid.mjs +10 -2
  8. package/dist/esm/drop-shadow.mjs +8 -0
  9. package/dist/esm/duotone.mjs +8 -0
  10. package/dist/esm/evolve.mjs +8 -0
  11. package/dist/esm/fisheye.mjs +8 -0
  12. package/dist/esm/glow.mjs +8 -0
  13. package/dist/esm/grayscale.mjs +8 -0
  14. package/dist/esm/halftone-linear-gradient.mjs +35 -3
  15. package/dist/esm/halftone.mjs +8 -8
  16. package/dist/esm/hue.mjs +8 -0
  17. package/dist/esm/index.mjs +56 -6
  18. package/dist/esm/invert.mjs +8 -0
  19. package/dist/esm/linear-progressive-blur.mjs +8 -0
  20. package/dist/esm/lines.mjs +32 -3
  21. package/dist/esm/mirror.mjs +8 -0
  22. package/dist/esm/noise-displacement.mjs +578 -0
  23. package/dist/esm/noise.mjs +10 -2
  24. package/dist/esm/pixel-dissolve.mjs +8 -0
  25. package/dist/esm/rings.mjs +32 -3
  26. package/dist/esm/saturation.mjs +8 -0
  27. package/dist/esm/scale.mjs +8 -0
  28. package/dist/esm/scanlines.mjs +10 -2
  29. package/dist/esm/shine.mjs +8 -0
  30. package/dist/esm/speckle.mjs +8 -0
  31. package/dist/esm/tint.mjs +8 -0
  32. package/dist/esm/translate.mjs +8 -0
  33. package/dist/esm/vignette.mjs +8 -0
  34. package/dist/esm/wave.mjs +8 -0
  35. package/dist/esm/waves.mjs +32 -3
  36. package/dist/esm/white-noise.mjs +8 -0
  37. package/dist/esm/zigzag.mjs +32 -3
  38. package/dist/halftone-linear-gradient.d.ts +9 -0
  39. package/dist/lines.d.ts +7 -0
  40. package/dist/noise-displacement.d.ts +26 -0
  41. package/dist/rings.d.ts +7 -0
  42. package/dist/validate-effect-param.d.ts +1 -0
  43. package/dist/waves.d.ts +7 -0
  44. package/dist/zigzag.d.ts +7 -0
  45. package/package.json +11 -3
@@ -23,6 +23,14 @@ var assertOptionalColor = (value, name) => {
23
23
  }
24
24
  assertRequiredColor(value, name);
25
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
+ };
26
34
 
27
35
  // src/color-utils.ts
28
36
  var DEFAULT_AMOUNT = 1;
@@ -107,6 +115,7 @@ var DEFAULT_THICKNESS = 40;
107
115
  var DEFAULT_GAP = 0;
108
116
  var DEFAULT_ANGLE = 0;
109
117
  var DEFAULT_OFFSET = 0;
118
+ var DEFAULT_MASK_TO_SOURCE_ALPHA = false;
110
119
  var linesSchema = {
111
120
  direction: {
112
121
  type: "enum",
@@ -147,6 +156,11 @@ var linesSchema = {
147
156
  default: DEFAULT_OFFSET,
148
157
  description: "Offset",
149
158
  hiddenFromList: false
159
+ },
160
+ maskToSourceAlpha: {
161
+ type: "boolean",
162
+ default: DEFAULT_MASK_TO_SOURCE_ALPHA,
163
+ description: "Mask to source alpha"
150
164
  }
151
165
  };
152
166
  var resolve = (p) => {
@@ -158,7 +172,8 @@ var resolve = (p) => {
158
172
  thickness,
159
173
  spacing: thickness + gap,
160
174
  angle: p.angle ?? DEFAULT_ANGLE,
161
- offset: p.offset ?? DEFAULT_OFFSET
175
+ offset: p.offset ?? DEFAULT_OFFSET,
176
+ maskToSourceAlpha: p.maskToSourceAlpha ?? DEFAULT_MASK_TO_SOURCE_ALPHA
162
177
  };
163
178
  };
164
179
  var formatEnum = (variants) => {
@@ -204,6 +219,7 @@ var validateLinesParams = (params) => {
204
219
  assertOptionalFiniteNumber(params.gap, "gap");
205
220
  assertOptionalFiniteNumber(params.angle, "angle");
206
221
  assertOptionalFiniteNumber(params.offset, "offset");
222
+ assertOptionalBoolean(params.maskToSourceAlpha, "maskToSourceAlpha");
207
223
  const thickness = params.thickness ?? DEFAULT_THICKNESS;
208
224
  const gap = params.gap ?? DEFAULT_GAP;
209
225
  validatePositive(thickness, "thickness");
@@ -234,6 +250,7 @@ uniform float uThickness;
234
250
  uniform float uSpacing;
235
251
  uniform float uAngle;
236
252
  uniform float uOffset;
253
+ uniform bool uMaskToSourceAlpha;
237
254
 
238
255
  void main() {
239
256
  vec4 texColor = texture(uSource, vUv);
@@ -265,6 +282,14 @@ float c = cos(uAngle);
265
282
  float lineAlpha = lineColor.a;
266
283
  vec3 premultipliedLine = lineColor.rgb * lineAlpha;
267
284
 
285
+ if (uMaskToSourceAlpha) {
286
+ fragColor = vec4(
287
+ premultipliedLine * texColor.a + texColor.rgb * (1.0 - lineAlpha),
288
+ texColor.a
289
+ );
290
+ return;
291
+ }
292
+
268
293
  fragColor = vec4(
269
294
  premultipliedLine + texColor.rgb * (1.0 - lineAlpha),
270
295
  lineAlpha + texColor.a * (1.0 - lineAlpha)
@@ -392,7 +417,8 @@ var setupLines = (target) => {
392
417
  uThickness: gl.getUniformLocation(program, "uThickness"),
393
418
  uSpacing: gl.getUniformLocation(program, "uSpacing"),
394
419
  uAngle: gl.getUniformLocation(program, "uAngle"),
395
- uOffset: gl.getUniformLocation(program, "uOffset")
420
+ uOffset: gl.getUniformLocation(program, "uOffset"),
421
+ uMaskToSourceAlpha: gl.getUniformLocation(program, "uMaskToSourceAlpha")
396
422
  },
397
423
  cachedPaletteKey: "",
398
424
  palettePixelData: new Uint8Array(0)
@@ -426,7 +452,8 @@ var lines = createEffect({
426
452
  backend: "webgl2",
427
453
  calculateKey: (params) => {
428
454
  const r = resolve(params);
429
- return `lines-${r.colors.join("|")}-${r.direction}-${r.thickness}-${r.spacing}-${r.angle}-${r.offset}`;
455
+ const maskSuffix = r.maskToSourceAlpha ? "-mask-to-source-alpha" : "";
456
+ return `lines-${r.colors.join("|")}-${r.direction}-${r.thickness}-${r.spacing}-${r.angle}-${r.offset}${maskSuffix}`;
430
457
  },
431
458
  setup: (target) => setupLines(target),
432
459
  apply: ({ source, width, height, params, state, flipSourceY }) => {
@@ -469,6 +496,8 @@ var lines = createEffect({
469
496
  gl.uniform1f(uniforms.uAngle, r.angle * Math.PI / 180);
470
497
  if (uniforms.uOffset)
471
498
  gl.uniform1f(uniforms.uOffset, r.offset);
499
+ if (uniforms.uMaskToSourceAlpha)
500
+ gl.uniform1i(uniforms.uMaskToSourceAlpha, r.maskToSourceAlpha ? 1 : 0);
472
501
  gl.bindVertexArray(vao);
473
502
  gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
474
503
  gl.bindVertexArray(null);
@@ -23,6 +23,14 @@ var assertOptionalColor = (value, name) => {
23
23
  }
24
24
  assertRequiredColor(value, name);
25
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
+ };
26
34
 
27
35
  // src/color-utils.ts
28
36
  var DEFAULT_AMOUNT = 1;
@@ -0,0 +1,578 @@
1
+ // src/noise-displacement.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/noise-displacement.ts
110
+ var { createEffect, createWebGL2ContextError } = Internals;
111
+ var DEFAULT_STRENGTH = 36;
112
+ var DEFAULT_SEED = 0;
113
+ var DEFAULT_GRAIN_SIZE = 8;
114
+ var DEFAULT_PASSES = 6;
115
+ var DEFAULT_BLUR = 0;
116
+ var DEFAULT_FEATHER = 0.25;
117
+ var DEFAULT_BIAS_DIRECTION = 0;
118
+ var DEFAULT_BIAS_AMOUNT = 0;
119
+ var MAX_PASSES = 12;
120
+ var noiseDisplacementSchema = {
121
+ center: {
122
+ type: "uv-coordinate",
123
+ step: 0.01,
124
+ default: undefined,
125
+ description: "Center"
126
+ },
127
+ radius: {
128
+ type: "number",
129
+ min: 0.001,
130
+ max: 1,
131
+ step: 0.01,
132
+ default: undefined,
133
+ description: "Radius",
134
+ hiddenFromList: false
135
+ },
136
+ strength: {
137
+ type: "number",
138
+ min: 0,
139
+ max: 200,
140
+ step: 0.1,
141
+ default: DEFAULT_STRENGTH,
142
+ description: "Strength",
143
+ hiddenFromList: false
144
+ },
145
+ seed: {
146
+ type: "number",
147
+ step: 1,
148
+ default: DEFAULT_SEED,
149
+ description: "Seed",
150
+ hiddenFromList: false
151
+ },
152
+ grainSize: {
153
+ type: "number",
154
+ min: 0.1,
155
+ max: 100,
156
+ step: 0.1,
157
+ default: DEFAULT_GRAIN_SIZE,
158
+ description: "Grain size",
159
+ hiddenFromList: false
160
+ },
161
+ passes: {
162
+ type: "number",
163
+ min: 1,
164
+ max: MAX_PASSES,
165
+ step: 1,
166
+ default: DEFAULT_PASSES,
167
+ description: "Passes",
168
+ hiddenFromList: false
169
+ },
170
+ blur: {
171
+ type: "number",
172
+ min: 0,
173
+ max: 100,
174
+ step: 0.1,
175
+ default: DEFAULT_BLUR,
176
+ description: "Blur",
177
+ hiddenFromList: false
178
+ },
179
+ feather: {
180
+ type: "number",
181
+ min: 0,
182
+ max: 1,
183
+ step: 0.01,
184
+ default: DEFAULT_FEATHER,
185
+ description: "Feather",
186
+ hiddenFromList: false
187
+ },
188
+ biasDirection: {
189
+ type: "rotation-degrees",
190
+ step: 1,
191
+ default: DEFAULT_BIAS_DIRECTION,
192
+ description: "Bias direction"
193
+ },
194
+ biasAmount: {
195
+ type: "number",
196
+ min: 0,
197
+ max: 1,
198
+ step: 0.01,
199
+ default: DEFAULT_BIAS_AMOUNT,
200
+ description: "Bias amount",
201
+ hiddenFromList: false
202
+ }
203
+ };
204
+ var resolve = (p) => ({
205
+ center: [...p.center],
206
+ radius: p.radius,
207
+ strength: p.strength ?? DEFAULT_STRENGTH,
208
+ seed: p.seed ?? DEFAULT_SEED,
209
+ grainSize: p.grainSize ?? DEFAULT_GRAIN_SIZE,
210
+ passes: p.passes ?? DEFAULT_PASSES,
211
+ blur: p.blur ?? DEFAULT_BLUR,
212
+ feather: p.feather ?? DEFAULT_FEATHER,
213
+ biasDirection: p.biasDirection ?? DEFAULT_BIAS_DIRECTION,
214
+ biasAmount: p.biasAmount ?? DEFAULT_BIAS_AMOUNT
215
+ });
216
+ var assertRequiredUvCoordinate = (value, name) => {
217
+ if (!Array.isArray(value) || value.length !== 2 || value.some((item) => typeof item !== "number" || !Number.isFinite(item))) {
218
+ throw new TypeError(`"${name}" must be a [number, number] tuple`);
219
+ }
220
+ };
221
+ var assertOptionalIntegerNumber = (value, name) => {
222
+ if (value === undefined) {
223
+ return;
224
+ }
225
+ if (!Number.isInteger(value)) {
226
+ throw new TypeError(`"${name}" must be an integer, but got ${JSON.stringify(value)}`);
227
+ }
228
+ };
229
+ var validatePositive = (value, name) => {
230
+ if (value <= 0) {
231
+ throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
232
+ }
233
+ };
234
+ var validateMax = (value, max, name) => {
235
+ if (value > max) {
236
+ throw new TypeError(`"${name}" must be <= ${max}, but got ${JSON.stringify(value)}`);
237
+ }
238
+ };
239
+ var validateNoiseDisplacementParams = (params) => {
240
+ assertEffectParamsObject(params, "Noise Displacement");
241
+ assertRequiredUvCoordinate(params.center, "center");
242
+ assertRequiredFiniteNumber(params.radius, "radius");
243
+ assertOptionalFiniteNumber(params.strength, "strength");
244
+ assertOptionalFiniteNumber(params.seed, "seed");
245
+ assertOptionalFiniteNumber(params.grainSize, "grainSize");
246
+ assertOptionalFiniteNumber(params.passes, "passes");
247
+ assertOptionalIntegerNumber(params.passes, "passes");
248
+ assertOptionalFiniteNumber(params.blur, "blur");
249
+ assertOptionalFiniteNumber(params.feather, "feather");
250
+ assertOptionalFiniteNumber(params.biasDirection, "biasDirection");
251
+ assertOptionalFiniteNumber(params.biasAmount, "biasAmount");
252
+ const r = resolve(params);
253
+ validateUnitInterval(r.center[0], "center[0]");
254
+ validateUnitInterval(r.center[1], "center[1]");
255
+ validatePositive(r.radius, "radius");
256
+ validateUnitInterval(r.radius, "radius");
257
+ if (r.strength < 0) {
258
+ throw new TypeError(`"strength" must be >= 0, but got ${JSON.stringify(r.strength)}`);
259
+ }
260
+ validatePositive(r.grainSize, "grainSize");
261
+ validatePositive(r.passes, "passes");
262
+ validateMax(r.passes, MAX_PASSES, "passes");
263
+ if (r.blur < 0) {
264
+ throw new TypeError(`"blur" must be >= 0, but got ${JSON.stringify(r.blur)}`);
265
+ }
266
+ validateUnitInterval(r.feather, "feather");
267
+ if (r.biasAmount < 0) {
268
+ throw new TypeError(`"biasAmount" must be >= 0, but got ${JSON.stringify(r.biasAmount)}`);
269
+ }
270
+ };
271
+ var NOISE_DISPLACEMENT_VS = `#version 300 es
272
+ in vec2 aPos;
273
+ in vec2 aUv;
274
+ out vec2 vUv;
275
+
276
+ void main() {
277
+ vUv = aUv;
278
+ gl_Position = vec4(aPos, 0.0, 1.0);
279
+ }
280
+ `;
281
+ var NOISE_DISPLACEMENT_FS = `#version 300 es
282
+ precision highp float;
283
+
284
+ in vec2 vUv;
285
+ out vec4 fragColor;
286
+
287
+ uniform sampler2D uSource;
288
+ uniform vec2 uResolution;
289
+ uniform vec2 uCenter;
290
+ uniform float uRadius;
291
+ uniform float uStrength;
292
+ uniform float uSeed;
293
+ uniform float uGrainSize;
294
+ uniform int uPasses;
295
+ uniform float uBlur;
296
+ uniform float uFeather;
297
+ uniform float uBiasDirection;
298
+ uniform float uBiasAmount;
299
+
300
+ const float PI = 3.141592653589793;
301
+ const vec2 DISC[9] = vec2[9](
302
+ vec2(0.0, 0.0),
303
+ vec2(1.0, 0.0), vec2(-1.0, 0.0), vec2(0.0, 1.0), vec2(0.0, -1.0),
304
+ vec2(0.707, 0.707), vec2(-0.707, 0.707),
305
+ vec2(0.707, -0.707), vec2(-0.707, -0.707)
306
+ );
307
+ const float DISC_W[9] = float[9](1.0, 0.7, 0.7, 0.7, 0.7, 0.5, 0.5, 0.5, 0.5);
308
+
309
+ float hash12(vec2 p) {
310
+ vec3 p3 = fract(vec3(p.xyx) * 0.1031 + uSeed * 0.0973);
311
+ p3 += dot(p3, p3.yzx + 33.33);
312
+ return fract((p3.x + p3.y) * p3.z);
313
+ }
314
+
315
+ float valueNoise(vec2 p) {
316
+ vec2 i = floor(p);
317
+ vec2 f = fract(p);
318
+ vec2 u = f * f * (3.0 - 2.0 * f);
319
+ return mix(
320
+ mix(hash12(i), hash12(i + vec2(1.0, 0.0)), u.x),
321
+ mix(hash12(i + vec2(0.0, 1.0)), hash12(i + vec2(1.0, 1.0)), u.x),
322
+ u.y
323
+ );
324
+ }
325
+
326
+ vec2 noiseVector(vec2 p) {
327
+ return vec2(
328
+ valueNoise(p + vec2(17.13, 71.79)),
329
+ valueNoise(p + vec2(83.41, 29.67))
330
+ ) * 2.0 - 1.0;
331
+ }
332
+
333
+ float effectMask(vec2 pixel) {
334
+ vec2 centerPx = uCenter * uResolution;
335
+ float radiusPx = uRadius * min(uResolution.x, uResolution.y);
336
+ float dist = length(pixel - centerPx);
337
+
338
+ if (dist >= radiusPx) {
339
+ return 0.0;
340
+ }
341
+
342
+ if (uFeather <= 0.0001) {
343
+ return 1.0;
344
+ }
345
+
346
+ float inner = radiusPx * (1.0 - uFeather);
347
+ return 1.0 - smoothstep(inner, radiusPx, dist);
348
+ }
349
+
350
+ vec4 sampleSource(vec2 pixel) {
351
+ vec2 uv = clamp(
352
+ vec2(pixel.x / uResolution.x, 1.0 - pixel.y / uResolution.y),
353
+ vec2(0.0),
354
+ vec2(1.0)
355
+ );
356
+ return texture(uSource, uv);
357
+ }
358
+
359
+ void main() {
360
+ vec2 pixel = vec2(vUv.x, 1.0 - vUv.y) * uResolution;
361
+ float mask = effectMask(pixel);
362
+
363
+ if (mask <= 0.0 || uStrength <= 0.0) {
364
+ fragColor = texture(uSource, vUv);
365
+ return;
366
+ }
367
+
368
+ vec2 noiseCoord = pixel / max(uGrainSize, 0.001);
369
+ vec2 biasDir = vec2(
370
+ cos(uBiasDirection * PI / 180.0),
371
+ sin(uBiasDirection * PI / 180.0)
372
+ );
373
+ vec2 displacement = (noiseVector(noiseCoord) + biasDir * uBiasAmount) * uStrength * mask;
374
+ int passes = max(uPasses, 1);
375
+ float blurRadius = uBlur * mask;
376
+ int blurTaps = blurRadius > 0.5 ? 9 : 1;
377
+
378
+ vec4 color = vec4(0.0);
379
+ float totalWeight = 0.0;
380
+ for (int s = 0; s < 12; s++) {
381
+ if (s >= passes) {
382
+ break;
383
+ }
384
+
385
+ float t = passes == 1 ? 1.0 : float(s) / float(passes - 1);
386
+ vec2 samplePixel = pixel + displacement * t;
387
+ float passWeight = 1.0 - t * 0.6;
388
+
389
+ for (int b = 0; b < 9; b++) {
390
+ if (b >= blurTaps) {
391
+ break;
392
+ }
393
+
394
+ float weight = passWeight * DISC_W[b];
395
+ color += sampleSource(samplePixel + DISC[b] * blurRadius) * weight;
396
+ totalWeight += weight;
397
+ }
398
+ }
399
+
400
+ fragColor = color / totalWeight;
401
+ }
402
+ `;
403
+ var compileShader = (gl, type, source) => {
404
+ const shader = gl.createShader(type);
405
+ if (!shader) {
406
+ throw new Error("Failed to create WebGL shader");
407
+ }
408
+ gl.shaderSource(shader, source);
409
+ gl.compileShader(shader);
410
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
411
+ const log = gl.getShaderInfoLog(shader);
412
+ gl.deleteShader(shader);
413
+ throw new Error(`Noise displacement shader compile failed: ${log ?? "(no log)"}`);
414
+ }
415
+ return shader;
416
+ };
417
+ var linkProgram = (gl, vs, fs) => {
418
+ const program = gl.createProgram();
419
+ if (!program) {
420
+ throw new Error("Failed to create WebGL program");
421
+ }
422
+ gl.attachShader(program, vs);
423
+ gl.attachShader(program, fs);
424
+ gl.linkProgram(program);
425
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
426
+ const log = gl.getProgramInfoLog(program);
427
+ gl.deleteProgram(program);
428
+ throw new Error(`Noise displacement program link failed: ${log ?? "(no log)"}`);
429
+ }
430
+ return program;
431
+ };
432
+ var setupNoiseDisplacement = (target) => {
433
+ const gl = target.getContext("webgl2", {
434
+ premultipliedAlpha: true,
435
+ alpha: true,
436
+ preserveDrawingBuffer: true
437
+ });
438
+ if (!gl) {
439
+ throw createWebGL2ContextError("noise displacement effect");
440
+ }
441
+ gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
442
+ const vs = compileShader(gl, gl.VERTEX_SHADER, NOISE_DISPLACEMENT_VS);
443
+ const fs = compileShader(gl, gl.FRAGMENT_SHADER, NOISE_DISPLACEMENT_FS);
444
+ const program = linkProgram(gl, vs, fs);
445
+ gl.deleteShader(vs);
446
+ gl.deleteShader(fs);
447
+ const vao = gl.createVertexArray();
448
+ if (!vao) {
449
+ throw new Error("Failed to create WebGL vertex array");
450
+ }
451
+ gl.bindVertexArray(vao);
452
+ const data = new Float32Array([
453
+ -1,
454
+ -1,
455
+ 0,
456
+ 0,
457
+ 1,
458
+ -1,
459
+ 1,
460
+ 0,
461
+ -1,
462
+ 1,
463
+ 0,
464
+ 1,
465
+ 1,
466
+ 1,
467
+ 1,
468
+ 1
469
+ ]);
470
+ const vbo = gl.createBuffer();
471
+ if (!vbo) {
472
+ throw new Error("Failed to create WebGL buffer");
473
+ }
474
+ gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
475
+ gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
476
+ const aPos = gl.getAttribLocation(program, "aPos");
477
+ const aUv = gl.getAttribLocation(program, "aUv");
478
+ gl.enableVertexAttribArray(aPos);
479
+ gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
480
+ gl.enableVertexAttribArray(aUv);
481
+ gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
482
+ gl.bindVertexArray(null);
483
+ const texture = gl.createTexture();
484
+ if (!texture) {
485
+ throw new Error("Failed to create WebGL texture");
486
+ }
487
+ gl.bindTexture(gl.TEXTURE_2D, texture);
488
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
489
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
490
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
491
+ gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
492
+ gl.bindTexture(gl.TEXTURE_2D, null);
493
+ return {
494
+ gl,
495
+ program,
496
+ vao,
497
+ vbo,
498
+ texture,
499
+ uniforms: {
500
+ uSource: gl.getUniformLocation(program, "uSource"),
501
+ uResolution: gl.getUniformLocation(program, "uResolution"),
502
+ uCenter: gl.getUniformLocation(program, "uCenter"),
503
+ uRadius: gl.getUniformLocation(program, "uRadius"),
504
+ uStrength: gl.getUniformLocation(program, "uStrength"),
505
+ uSeed: gl.getUniformLocation(program, "uSeed"),
506
+ uGrainSize: gl.getUniformLocation(program, "uGrainSize"),
507
+ uPasses: gl.getUniformLocation(program, "uPasses"),
508
+ uBlur: gl.getUniformLocation(program, "uBlur"),
509
+ uFeather: gl.getUniformLocation(program, "uFeather"),
510
+ uBiasDirection: gl.getUniformLocation(program, "uBiasDirection"),
511
+ uBiasAmount: gl.getUniformLocation(program, "uBiasAmount")
512
+ }
513
+ };
514
+ };
515
+ var noiseDisplacement = createEffect({
516
+ type: "remotion/noise-displacement",
517
+ label: "noiseDisplacement()",
518
+ documentationLink: "https://www.remotion.dev/docs/effects/noise-displacement",
519
+ backend: "webgl2",
520
+ calculateKey: (params) => {
521
+ const r = resolve(params);
522
+ return `noise-displacement-${r.center.join(":")}-${r.radius}-${r.strength}-${r.seed}-${r.grainSize}-${r.passes}-${r.blur}-${r.feather}-${r.biasDirection}-${r.biasAmount}`;
523
+ },
524
+ setup: (target) => setupNoiseDisplacement(target),
525
+ apply: ({ source, width, height, params, state, flipSourceY }) => {
526
+ const r = resolve(params);
527
+ const { gl, program, texture, vao, uniforms } = state;
528
+ gl.viewport(0, 0, width, height);
529
+ gl.bindFramebuffer(gl.FRAMEBUFFER, null);
530
+ gl.clearColor(0, 0, 0, 0);
531
+ gl.clear(gl.COLOR_BUFFER_BIT);
532
+ gl.activeTexture(gl.TEXTURE0);
533
+ gl.bindTexture(gl.TEXTURE_2D, texture);
534
+ gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
535
+ gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
536
+ gl.useProgram(program);
537
+ if (uniforms.uSource)
538
+ gl.uniform1i(uniforms.uSource, 0);
539
+ if (uniforms.uResolution)
540
+ gl.uniform2f(uniforms.uResolution, width, height);
541
+ if (uniforms.uCenter)
542
+ gl.uniform2f(uniforms.uCenter, r.center[0], r.center[1]);
543
+ if (uniforms.uRadius)
544
+ gl.uniform1f(uniforms.uRadius, r.radius);
545
+ if (uniforms.uStrength)
546
+ gl.uniform1f(uniforms.uStrength, r.strength);
547
+ if (uniforms.uSeed)
548
+ gl.uniform1f(uniforms.uSeed, r.seed);
549
+ if (uniforms.uGrainSize)
550
+ gl.uniform1f(uniforms.uGrainSize, r.grainSize);
551
+ if (uniforms.uPasses)
552
+ gl.uniform1i(uniforms.uPasses, r.passes);
553
+ if (uniforms.uBlur)
554
+ gl.uniform1f(uniforms.uBlur, r.blur);
555
+ if (uniforms.uFeather)
556
+ gl.uniform1f(uniforms.uFeather, r.feather);
557
+ if (uniforms.uBiasDirection)
558
+ gl.uniform1f(uniforms.uBiasDirection, r.biasDirection);
559
+ if (uniforms.uBiasAmount)
560
+ gl.uniform1f(uniforms.uBiasAmount, r.biasAmount);
561
+ gl.bindVertexArray(vao);
562
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
563
+ gl.bindVertexArray(null);
564
+ gl.bindTexture(gl.TEXTURE_2D, null);
565
+ gl.useProgram(null);
566
+ },
567
+ cleanup: ({ gl, program, vao, vbo, texture }) => {
568
+ gl.deleteTexture(texture);
569
+ gl.deleteBuffer(vbo);
570
+ gl.deleteProgram(program);
571
+ gl.deleteVertexArray(vao);
572
+ },
573
+ schema: noiseDisplacementSchema,
574
+ validateParams: validateNoiseDisplacementParams
575
+ });
576
+ export {
577
+ noiseDisplacement
578
+ };