@remotion/effects 4.0.473 → 4.0.474
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/esm/barrel-distortion.mjs +8 -0
- package/dist/esm/blur.mjs +8 -0
- package/dist/esm/brightness.mjs +8 -0
- package/dist/esm/chromatic-aberration.mjs +8 -0
- package/dist/esm/color-key.mjs +8 -0
- package/dist/esm/contrast.mjs +8 -0
- package/dist/esm/dot-grid.mjs +10 -2
- package/dist/esm/drop-shadow.mjs +8 -0
- package/dist/esm/duotone.mjs +8 -0
- package/dist/esm/evolve.mjs +8 -0
- package/dist/esm/fisheye.mjs +8 -0
- package/dist/esm/glow.mjs +8 -0
- package/dist/esm/grayscale.mjs +8 -0
- package/dist/esm/halftone-linear-gradient.mjs +35 -3
- package/dist/esm/halftone.mjs +8 -8
- package/dist/esm/hue.mjs +8 -0
- package/dist/esm/index.mjs +56 -6
- package/dist/esm/invert.mjs +8 -0
- package/dist/esm/linear-progressive-blur.mjs +8 -0
- package/dist/esm/lines.mjs +32 -3
- package/dist/esm/mirror.mjs +8 -0
- package/dist/esm/noise-displacement.mjs +578 -0
- package/dist/esm/noise.mjs +10 -2
- package/dist/esm/pixel-dissolve.mjs +8 -0
- package/dist/esm/rings.mjs +32 -3
- package/dist/esm/saturation.mjs +8 -0
- package/dist/esm/scale.mjs +8 -0
- package/dist/esm/scanlines.mjs +10 -2
- package/dist/esm/shine.mjs +8 -0
- package/dist/esm/speckle.mjs +8 -0
- package/dist/esm/tint.mjs +8 -0
- package/dist/esm/translate.mjs +8 -0
- package/dist/esm/vignette.mjs +8 -0
- package/dist/esm/wave.mjs +8 -0
- package/dist/esm/waves.mjs +32 -3
- package/dist/esm/white-noise.mjs +8 -0
- package/dist/esm/zigzag.mjs +32 -3
- package/dist/halftone-linear-gradient.d.ts +9 -0
- package/dist/lines.d.ts +7 -0
- package/dist/noise-displacement.d.ts +26 -0
- package/dist/rings.d.ts +7 -0
- package/dist/validate-effect-param.d.ts +1 -0
- package/dist/waves.d.ts +7 -0
- package/dist/zigzag.d.ts +7 -0
- package/package.json +11 -3
package/dist/esm/lines.mjs
CHANGED
|
@@ -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
|
-
|
|
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);
|
package/dist/esm/mirror.mjs
CHANGED
|
@@ -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
|
+
};
|