@remotion/effects 4.0.537 → 4.0.539
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/THIRD_PARTY_LICENSES.md +4 -0
- package/dist/barrel-distortion/index.d.ts +1 -1
- package/dist/bevel-alpha/index.d.ts +1 -1
- package/dist/bevel-alpha/shaders.d.ts +1 -1
- package/dist/blur/index.d.ts +1 -1
- package/dist/brightness.d.ts +1 -1
- package/dist/burlap.d.ts +1 -1
- package/dist/checkerboard.d.ts +17 -17
- package/dist/chromatic-aberration/index.d.ts +1 -1
- package/dist/color-correction.d.ts +1 -1
- package/dist/color-key.d.ts +9 -9
- package/dist/color-utils.d.ts +8 -8
- package/dist/contour-lines.d.ts +23 -23
- package/dist/contrast.d.ts +1 -1
- package/dist/corner-pin/index.d.ts +1 -1
- package/dist/curves.d.ts +65 -0
- package/dist/cylinder/index.d.ts +1 -1
- package/dist/dot-grid.d.ts +7 -7
- package/dist/drop-shadow/index.d.ts +1 -1
- package/dist/duotone.d.ts +7 -7
- package/dist/emboss.d.ts +15 -15
- package/dist/esm/curves.mjs +373 -0
- package/dist/esm/levels.mjs +80 -10
- package/dist/esm/long-shadows.mjs +410 -0
- package/dist/esm/shatter.mjs +888 -0
- package/dist/evolve.d.ts +8 -8
- package/dist/exposure.d.ts +1 -1
- package/dist/fisheye/index.d.ts +1 -1
- package/dist/flannel.d.ts +1 -1
- package/dist/fractal-noise/index.d.ts +3 -3
- package/dist/gaussian-blur-shader.d.ts +1 -1
- package/dist/glow/index.d.ts +1 -1
- package/dist/grayscale.d.ts +1 -1
- package/dist/gridlines.d.ts +23 -23
- package/dist/halftone-linear-gradient.d.ts +21 -21
- package/dist/halftone.d.ts +25 -25
- package/dist/hue.d.ts +1 -1
- package/dist/invert.d.ts +1 -1
- package/dist/lens-blur/index.d.ts +2 -2
- package/dist/levels.d.ts +70 -3
- package/dist/light-leak.d.ts +7 -7
- package/dist/light-trail/index.d.ts +1 -1
- package/dist/linear-gradient-tint.d.ts +1 -1
- package/dist/linear-gradient.d.ts +1 -1
- package/dist/linear-progressive-blur/index.d.ts +1 -1
- package/dist/linear-progressive-blur/linear-progressive-blur-shaders.d.ts +1 -1
- package/dist/linear-progressive-pixelate/index.d.ts +1 -1
- package/dist/lines.d.ts +18 -18
- package/dist/liquid-contours.d.ts +21 -21
- package/dist/long-shadows.d.ts +13 -0
- package/dist/lut/index.d.ts +3 -3
- package/dist/mirror/index.d.ts +1 -1
- package/dist/noise-displacement.d.ts +1 -1
- package/dist/noise.d.ts +1 -1
- package/dist/outline/polygonize-alpha.d.ts +1 -1
- package/dist/outline.d.ts +11 -11
- package/dist/page-turn/index.d.ts +1 -1
- package/dist/paper.d.ts +1 -1
- package/dist/pattern.d.ts +1 -1
- package/dist/pixel-dissolve.d.ts +1 -1
- package/dist/pixelate.d.ts +1 -1
- package/dist/radial-progressive-blur/index.d.ts +1 -1
- package/dist/radial-progressive-blur/radial-progressive-blur-shaders.d.ts +1 -1
- package/dist/radial-progressive-pixelate/index.d.ts +1 -1
- package/dist/region-blur/index.d.ts +11 -11
- package/dist/rings.d.ts +15 -15
- package/dist/roughen-edges.d.ts +1 -1
- package/dist/saturation.d.ts +1 -1
- package/dist/scale/index.d.ts +1 -1
- package/dist/scanlines.d.ts +1 -1
- package/dist/shadows-highlights.d.ts +1 -1
- package/dist/shatter/geometry.d.ts +19 -0
- package/dist/shatter/index.d.ts +39 -0
- package/dist/shatter/runtime.d.ts +19 -0
- package/dist/shatter.d.ts +1 -0
- package/dist/shine.d.ts +1 -1
- package/dist/shrinkwrap.d.ts +1 -1
- package/dist/skew.d.ts +1 -1
- package/dist/speckle.d.ts +1 -1
- package/dist/sphere/index.d.ts +1 -1
- package/dist/starburst.d.ts +13 -13
- package/dist/tear.d.ts +1 -1
- package/dist/thermal-vision.d.ts +7 -7
- package/dist/tile.d.ts +1 -1
- package/dist/tint.d.ts +5 -5
- package/dist/translate/index.d.ts +2 -2
- package/dist/turbulent-displace/index.d.ts +3 -3
- package/dist/tv-signal-off.d.ts +1 -1
- package/dist/venetian-blinds.d.ts +8 -8
- package/dist/vibrance.d.ts +1 -1
- package/dist/vignette.d.ts +16 -16
- package/dist/visual-test/visual-utils.d.ts +8 -8
- package/dist/wave/index.d.ts +1 -1
- package/dist/waves.d.ts +24 -24
- package/dist/white-balance.d.ts +1 -1
- package/dist/white-noise.d.ts +1 -1
- package/dist/zigzag.d.ts +22 -22
- package/dist/zoom-blur/index.d.ts +1 -1
- package/package.json +31 -7
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
// src/curves.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/curves.ts
|
|
110
|
+
var { createEffect, createCurveSampler, createWebGL2ContextError } = Internals;
|
|
111
|
+
var DEFAULT_POINTS = [
|
|
112
|
+
[0, 0],
|
|
113
|
+
[1, 1]
|
|
114
|
+
];
|
|
115
|
+
var DEFAULT_CHANNEL = "rgb";
|
|
116
|
+
var DEFAULT_INTERPOLATION = "smooth";
|
|
117
|
+
var DEFAULT_AMOUNT2 = 1;
|
|
118
|
+
var MAX_POINTS = 32;
|
|
119
|
+
var LUT_SIZE = 1024;
|
|
120
|
+
var CURVES_CHANNELS = ["rgb", "red", "green", "blue"];
|
|
121
|
+
var CURVES_INTERPOLATIONS = ["smooth", "linear"];
|
|
122
|
+
var curvesSchema = {
|
|
123
|
+
channel: {
|
|
124
|
+
type: "enum",
|
|
125
|
+
variants: { rgb: {}, red: {}, green: {}, blue: {} },
|
|
126
|
+
default: DEFAULT_CHANNEL,
|
|
127
|
+
description: "Channel"
|
|
128
|
+
},
|
|
129
|
+
points: {
|
|
130
|
+
type: "array",
|
|
131
|
+
item: { type: "uv-coordinate", min: 0, max: 1, step: 0.001 },
|
|
132
|
+
default: DEFAULT_POINTS,
|
|
133
|
+
minLength: 2,
|
|
134
|
+
maxLength: MAX_POINTS,
|
|
135
|
+
newItemDefault: [0.5, 0.5],
|
|
136
|
+
description: "Points",
|
|
137
|
+
keyframable: false
|
|
138
|
+
},
|
|
139
|
+
interpolation: {
|
|
140
|
+
type: "enum",
|
|
141
|
+
variants: { smooth: {}, linear: {} },
|
|
142
|
+
default: DEFAULT_INTERPOLATION,
|
|
143
|
+
description: "Interpolation"
|
|
144
|
+
},
|
|
145
|
+
amount: colorAmountSchema
|
|
146
|
+
};
|
|
147
|
+
var resolve = (params) => ({
|
|
148
|
+
points: params.points ?? DEFAULT_POINTS,
|
|
149
|
+
channel: params.channel ?? DEFAULT_CHANNEL,
|
|
150
|
+
interpolation: params.interpolation ?? DEFAULT_INTERPOLATION,
|
|
151
|
+
amount: params.amount ?? DEFAULT_AMOUNT2
|
|
152
|
+
});
|
|
153
|
+
var validateCurvesParams = (params) => {
|
|
154
|
+
assertEffectParamsObject(params, "Curves");
|
|
155
|
+
assertOptionalFiniteNumber(params.amount, "amount");
|
|
156
|
+
validateUnitInterval(params.amount ?? DEFAULT_AMOUNT2, "amount");
|
|
157
|
+
if (params.channel !== undefined && !CURVES_CHANNELS.includes(params.channel)) {
|
|
158
|
+
throw new TypeError(`"channel" must be "rgb", "red", "green" or "blue", but got ${JSON.stringify(params.channel)}`);
|
|
159
|
+
}
|
|
160
|
+
if (params.interpolation !== undefined && !CURVES_INTERPOLATIONS.includes(params.interpolation)) {
|
|
161
|
+
throw new TypeError(`"interpolation" must be "smooth" or "linear", but got ${JSON.stringify(params.interpolation)}`);
|
|
162
|
+
}
|
|
163
|
+
if (params.points === undefined)
|
|
164
|
+
return;
|
|
165
|
+
if (!Array.isArray(params.points) || params.points.length < 2 || params.points.length > MAX_POINTS) {
|
|
166
|
+
throw new TypeError(`"points" must be an array of 2 to ${MAX_POINTS} input/output pairs`);
|
|
167
|
+
}
|
|
168
|
+
for (let index = 0;index < params.points.length; index++) {
|
|
169
|
+
const point = params.points[index];
|
|
170
|
+
if (!Array.isArray(point) || point.length !== 2) {
|
|
171
|
+
throw new TypeError(`"points[${index}]" must be an [input, output] pair`);
|
|
172
|
+
}
|
|
173
|
+
assertRequiredFiniteNumber(point[0], `points[${index}][0]`);
|
|
174
|
+
assertRequiredFiniteNumber(point[1], `points[${index}][1]`);
|
|
175
|
+
validateUnitInterval(point[0], `points[${index}][0]`);
|
|
176
|
+
validateUnitInterval(point[1], `points[${index}][1]`);
|
|
177
|
+
if (index > 0 && point[0] <= params.points[index - 1][0]) {
|
|
178
|
+
throw new TypeError('"points" must have strictly increasing input values');
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
var VERTEX_SHADER = `#version 300 es
|
|
183
|
+
in vec2 aPos;
|
|
184
|
+
in vec2 aUv;
|
|
185
|
+
out vec2 vUv;
|
|
186
|
+
|
|
187
|
+
void main() {
|
|
188
|
+
vUv = aUv;
|
|
189
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
190
|
+
}
|
|
191
|
+
`;
|
|
192
|
+
var FRAGMENT_SHADER = `#version 300 es
|
|
193
|
+
precision highp float;
|
|
194
|
+
|
|
195
|
+
in vec2 vUv;
|
|
196
|
+
out vec4 fragColor;
|
|
197
|
+
|
|
198
|
+
uniform sampler2D uSource;
|
|
199
|
+
uniform highp sampler2D uCurve;
|
|
200
|
+
uniform int uChannel;
|
|
201
|
+
uniform float uAmount;
|
|
202
|
+
|
|
203
|
+
float sampleCurve(float inputValue) {
|
|
204
|
+
float position = clamp(inputValue, 0.0, 1.0) * float(${LUT_SIZE - 1});
|
|
205
|
+
int lower = int(floor(position));
|
|
206
|
+
int upper = min(lower + 1, ${LUT_SIZE - 1});
|
|
207
|
+
return mix(
|
|
208
|
+
texelFetch(uCurve, ivec2(lower, 0), 0).r,
|
|
209
|
+
texelFetch(uCurve, ivec2(upper, 0), 0).r,
|
|
210
|
+
fract(position)
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
void main() {
|
|
215
|
+
vec4 sourceColor = texture(uSource, vUv);
|
|
216
|
+
float alpha = sourceColor.a;
|
|
217
|
+
if (alpha <= 0.0) {
|
|
218
|
+
fragColor = vec4(0.0);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
vec3 color = sourceColor.rgb / alpha;
|
|
223
|
+
vec3 corrected = color;
|
|
224
|
+
if (uChannel == 0 || uChannel == 1) corrected.r = sampleCurve(color.r);
|
|
225
|
+
if (uChannel == 0 || uChannel == 2) corrected.g = sampleCurve(color.g);
|
|
226
|
+
if (uChannel == 0 || uChannel == 3) corrected.b = sampleCurve(color.b);
|
|
227
|
+
fragColor = vec4(mix(color, corrected, uAmount) * alpha, alpha);
|
|
228
|
+
}
|
|
229
|
+
`;
|
|
230
|
+
var compileShader = (gl, type, source) => {
|
|
231
|
+
const shader = gl.createShader(type);
|
|
232
|
+
if (!shader)
|
|
233
|
+
throw new Error("Failed to create curves shader");
|
|
234
|
+
gl.shaderSource(shader, source);
|
|
235
|
+
gl.compileShader(shader);
|
|
236
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
237
|
+
const log = gl.getShaderInfoLog(shader);
|
|
238
|
+
gl.deleteShader(shader);
|
|
239
|
+
throw new Error(`Curves shader compile failed: ${log ?? "(no log)"}`);
|
|
240
|
+
}
|
|
241
|
+
return shader;
|
|
242
|
+
};
|
|
243
|
+
var createTexture = (gl, filter) => {
|
|
244
|
+
const texture = gl.createTexture();
|
|
245
|
+
if (!texture)
|
|
246
|
+
throw new Error("Failed to create curves texture");
|
|
247
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
248
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, filter);
|
|
249
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, filter);
|
|
250
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
251
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
252
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
253
|
+
return texture;
|
|
254
|
+
};
|
|
255
|
+
var curves = createEffect({
|
|
256
|
+
type: "remotion/curves",
|
|
257
|
+
label: "curves()",
|
|
258
|
+
documentationLink: "https://www.remotion.dev/docs/effects/curves",
|
|
259
|
+
backend: "webgl2",
|
|
260
|
+
calculateKey: (params) => {
|
|
261
|
+
const { points, channel, interpolation, amount } = resolve(params);
|
|
262
|
+
return `curves-${JSON.stringify(points)}-${channel}-${interpolation}-${amount}`;
|
|
263
|
+
},
|
|
264
|
+
setup: (target) => {
|
|
265
|
+
const gl = target.getContext("webgl2", {
|
|
266
|
+
premultipliedAlpha: true,
|
|
267
|
+
alpha: true,
|
|
268
|
+
preserveDrawingBuffer: true
|
|
269
|
+
});
|
|
270
|
+
if (!gl)
|
|
271
|
+
throw createWebGL2ContextError("curves effect");
|
|
272
|
+
const vertexShader = compileShader(gl, gl.VERTEX_SHADER, VERTEX_SHADER);
|
|
273
|
+
const fragmentShader = compileShader(gl, gl.FRAGMENT_SHADER, FRAGMENT_SHADER);
|
|
274
|
+
const program = gl.createProgram();
|
|
275
|
+
if (!program)
|
|
276
|
+
throw new Error("Failed to create curves shader program");
|
|
277
|
+
gl.attachShader(program, vertexShader);
|
|
278
|
+
gl.attachShader(program, fragmentShader);
|
|
279
|
+
gl.linkProgram(program);
|
|
280
|
+
gl.deleteShader(vertexShader);
|
|
281
|
+
gl.deleteShader(fragmentShader);
|
|
282
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
283
|
+
const log = gl.getProgramInfoLog(program);
|
|
284
|
+
gl.deleteProgram(program);
|
|
285
|
+
throw new Error(`Curves shader link failed: ${log ?? "(no log)"}`);
|
|
286
|
+
}
|
|
287
|
+
const vao = gl.createVertexArray();
|
|
288
|
+
if (!vao)
|
|
289
|
+
throw new Error("Failed to create curves vertex array");
|
|
290
|
+
const vbo = gl.createBuffer();
|
|
291
|
+
if (!vbo)
|
|
292
|
+
throw new Error("Failed to create curves vertex buffer");
|
|
293
|
+
gl.bindVertexArray(vao);
|
|
294
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
295
|
+
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 0, 0, 1, -1, 1, 0, -1, 1, 0, 1, 1, 1, 1, 1]), gl.STATIC_DRAW);
|
|
296
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
297
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
298
|
+
gl.enableVertexAttribArray(aPos);
|
|
299
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
300
|
+
gl.enableVertexAttribArray(aUv);
|
|
301
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
302
|
+
gl.bindVertexArray(null);
|
|
303
|
+
return {
|
|
304
|
+
gl,
|
|
305
|
+
program,
|
|
306
|
+
vao,
|
|
307
|
+
vbo,
|
|
308
|
+
sourceTexture: createTexture(gl, gl.LINEAR),
|
|
309
|
+
curveTexture: createTexture(gl, gl.NEAREST),
|
|
310
|
+
uniforms: {
|
|
311
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
312
|
+
uCurve: gl.getUniformLocation(program, "uCurve"),
|
|
313
|
+
uChannel: gl.getUniformLocation(program, "uChannel"),
|
|
314
|
+
uAmount: gl.getUniformLocation(program, "uAmount")
|
|
315
|
+
},
|
|
316
|
+
cachedCurveKey: null
|
|
317
|
+
};
|
|
318
|
+
},
|
|
319
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
320
|
+
const { points, channel, interpolation, amount } = resolve(params);
|
|
321
|
+
const { gl, program, sourceTexture, curveTexture, uniforms, vao } = state;
|
|
322
|
+
const curveKey = `${interpolation}-${JSON.stringify(points)}`;
|
|
323
|
+
gl.activeTexture(gl.TEXTURE1);
|
|
324
|
+
gl.bindTexture(gl.TEXTURE_2D, curveTexture);
|
|
325
|
+
if (state.cachedCurveKey !== curveKey) {
|
|
326
|
+
const sample = createCurveSampler(points, interpolation);
|
|
327
|
+
const data = new Float32Array(LUT_SIZE);
|
|
328
|
+
for (let index = 0;index < LUT_SIZE; index++) {
|
|
329
|
+
data[index] = sample(index / (LUT_SIZE - 1));
|
|
330
|
+
}
|
|
331
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, false);
|
|
332
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);
|
|
333
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.R32F, LUT_SIZE, 1, 0, gl.RED, gl.FLOAT, data);
|
|
334
|
+
state.cachedCurveKey = curveKey;
|
|
335
|
+
}
|
|
336
|
+
gl.viewport(0, 0, width, height);
|
|
337
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
338
|
+
gl.clearColor(0, 0, 0, 0);
|
|
339
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
340
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
341
|
+
gl.bindTexture(gl.TEXTURE_2D, sourceTexture);
|
|
342
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
343
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
344
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
345
|
+
gl.useProgram(program);
|
|
346
|
+
if (uniforms.uSource)
|
|
347
|
+
gl.uniform1i(uniforms.uSource, 0);
|
|
348
|
+
if (uniforms.uCurve)
|
|
349
|
+
gl.uniform1i(uniforms.uCurve, 1);
|
|
350
|
+
if (uniforms.uChannel)
|
|
351
|
+
gl.uniform1i(uniforms.uChannel, CURVES_CHANNELS.indexOf(channel));
|
|
352
|
+
if (uniforms.uAmount)
|
|
353
|
+
gl.uniform1f(uniforms.uAmount, amount);
|
|
354
|
+
gl.bindVertexArray(vao);
|
|
355
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
356
|
+
gl.bindVertexArray(null);
|
|
357
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
358
|
+
gl.useProgram(null);
|
|
359
|
+
},
|
|
360
|
+
cleanup: ({ gl, program, vao, vbo, sourceTexture, curveTexture }) => {
|
|
361
|
+
gl.deleteTexture(sourceTexture);
|
|
362
|
+
gl.deleteTexture(curveTexture);
|
|
363
|
+
gl.deleteBuffer(vbo);
|
|
364
|
+
gl.deleteProgram(program);
|
|
365
|
+
gl.deleteVertexArray(vao);
|
|
366
|
+
},
|
|
367
|
+
schema: curvesSchema,
|
|
368
|
+
validateParams: validateCurvesParams
|
|
369
|
+
});
|
|
370
|
+
export {
|
|
371
|
+
curves,
|
|
372
|
+
curvesSchema
|
|
373
|
+
};
|
package/dist/esm/levels.mjs
CHANGED
|
@@ -111,16 +111,31 @@ var { createEffect, createWebGL2ContextError } = Internals;
|
|
|
111
111
|
var DEFAULT_BLACK_POINT = 0;
|
|
112
112
|
var DEFAULT_WHITE_POINT = 1;
|
|
113
113
|
var DEFAULT_GAMMA = 1;
|
|
114
|
+
var DEFAULT_OUTPUT_BLACK = 0;
|
|
115
|
+
var DEFAULT_OUTPUT_WHITE = 1;
|
|
116
|
+
var DEFAULT_CHANNEL = "rgb";
|
|
117
|
+
var LEVELS_CHANNELS = ["rgb", "red", "green", "blue"];
|
|
114
118
|
var MIN_GAMMA = 0.01;
|
|
115
119
|
var MAX_GAMMA = 10;
|
|
116
120
|
var levelsSchema = {
|
|
121
|
+
channel: {
|
|
122
|
+
type: "enum",
|
|
123
|
+
variants: {
|
|
124
|
+
rgb: {},
|
|
125
|
+
red: {},
|
|
126
|
+
green: {},
|
|
127
|
+
blue: {}
|
|
128
|
+
},
|
|
129
|
+
default: DEFAULT_CHANNEL,
|
|
130
|
+
description: "Channel"
|
|
131
|
+
},
|
|
117
132
|
blackPoint: {
|
|
118
133
|
type: "number",
|
|
119
134
|
min: 0,
|
|
120
135
|
max: 1,
|
|
121
136
|
step: 0.01,
|
|
122
137
|
default: DEFAULT_BLACK_POINT,
|
|
123
|
-
description: "
|
|
138
|
+
description: "Input black",
|
|
124
139
|
hiddenFromList: false
|
|
125
140
|
},
|
|
126
141
|
whitePoint: {
|
|
@@ -129,7 +144,7 @@ var levelsSchema = {
|
|
|
129
144
|
max: 1,
|
|
130
145
|
step: 0.01,
|
|
131
146
|
default: DEFAULT_WHITE_POINT,
|
|
132
|
-
description: "
|
|
147
|
+
description: "Input white",
|
|
133
148
|
hiddenFromList: false
|
|
134
149
|
},
|
|
135
150
|
gamma: {
|
|
@@ -140,21 +155,49 @@ var levelsSchema = {
|
|
|
140
155
|
default: DEFAULT_GAMMA,
|
|
141
156
|
description: "Gamma",
|
|
142
157
|
hiddenFromList: false
|
|
158
|
+
},
|
|
159
|
+
outputBlack: {
|
|
160
|
+
type: "number",
|
|
161
|
+
min: 0,
|
|
162
|
+
max: 1,
|
|
163
|
+
step: 0.01,
|
|
164
|
+
default: DEFAULT_OUTPUT_BLACK,
|
|
165
|
+
description: "Output black",
|
|
166
|
+
hiddenFromList: false
|
|
167
|
+
},
|
|
168
|
+
outputWhite: {
|
|
169
|
+
type: "number",
|
|
170
|
+
min: 0,
|
|
171
|
+
max: 1,
|
|
172
|
+
step: 0.01,
|
|
173
|
+
default: DEFAULT_OUTPUT_WHITE,
|
|
174
|
+
description: "Output white",
|
|
175
|
+
hiddenFromList: false
|
|
143
176
|
}
|
|
144
177
|
};
|
|
145
178
|
var resolve = (params) => ({
|
|
179
|
+
channel: params.channel ?? DEFAULT_CHANNEL,
|
|
146
180
|
blackPoint: params.blackPoint ?? DEFAULT_BLACK_POINT,
|
|
147
181
|
whitePoint: params.whitePoint ?? DEFAULT_WHITE_POINT,
|
|
148
|
-
gamma: params.gamma ?? DEFAULT_GAMMA
|
|
182
|
+
gamma: params.gamma ?? DEFAULT_GAMMA,
|
|
183
|
+
outputBlack: params.outputBlack ?? DEFAULT_OUTPUT_BLACK,
|
|
184
|
+
outputWhite: params.outputWhite ?? DEFAULT_OUTPUT_WHITE
|
|
149
185
|
});
|
|
150
186
|
var validateLevelsParams = (params) => {
|
|
151
187
|
assertEffectParamsObject(params, "Levels");
|
|
152
188
|
assertOptionalFiniteNumber(params.blackPoint, "blackPoint");
|
|
153
189
|
assertOptionalFiniteNumber(params.whitePoint, "whitePoint");
|
|
154
190
|
assertOptionalFiniteNumber(params.gamma, "gamma");
|
|
155
|
-
|
|
191
|
+
assertOptionalFiniteNumber(params.outputBlack, "outputBlack");
|
|
192
|
+
assertOptionalFiniteNumber(params.outputWhite, "outputWhite");
|
|
193
|
+
if (params.channel !== undefined && !LEVELS_CHANNELS.includes(params.channel)) {
|
|
194
|
+
throw new TypeError(`"channel" must be "rgb", "red", "green" or "blue", but got ${JSON.stringify(params.channel)}`);
|
|
195
|
+
}
|
|
196
|
+
const { blackPoint, whitePoint, gamma, outputBlack, outputWhite } = resolve(params);
|
|
156
197
|
validateUnitInterval(blackPoint, "blackPoint");
|
|
157
198
|
validateUnitInterval(whitePoint, "whitePoint");
|
|
199
|
+
validateUnitInterval(outputBlack, "outputBlack");
|
|
200
|
+
validateUnitInterval(outputWhite, "outputWhite");
|
|
158
201
|
if (blackPoint >= whitePoint) {
|
|
159
202
|
throw new TypeError(`"blackPoint" must be less than "whitePoint", but got ${JSON.stringify(blackPoint)} and ${JSON.stringify(whitePoint)}`);
|
|
160
203
|
}
|
|
@@ -185,6 +228,9 @@ uniform sampler2D uSource;
|
|
|
185
228
|
uniform float uBlackPoint;
|
|
186
229
|
uniform float uWhitePoint;
|
|
187
230
|
uniform float uGamma;
|
|
231
|
+
uniform float uOutputBlack;
|
|
232
|
+
uniform float uOutputWhite;
|
|
233
|
+
uniform int uChannel;
|
|
188
234
|
|
|
189
235
|
void main() {
|
|
190
236
|
vec4 sourceColor = texture(uSource, vUv);
|
|
@@ -202,8 +248,19 @@ void main() {
|
|
|
202
248
|
1.0
|
|
203
249
|
);
|
|
204
250
|
vec3 corrected = pow(normalized, vec3(1.0 / uGamma));
|
|
251
|
+
vec3 outputColor = mix(vec3(uOutputBlack), vec3(uOutputWhite), corrected);
|
|
205
252
|
|
|
206
|
-
|
|
253
|
+
if (uChannel == 1) {
|
|
254
|
+
color.r = outputColor.r;
|
|
255
|
+
} else if (uChannel == 2) {
|
|
256
|
+
color.g = outputColor.g;
|
|
257
|
+
} else if (uChannel == 3) {
|
|
258
|
+
color.b = outputColor.b;
|
|
259
|
+
} else {
|
|
260
|
+
color = outputColor;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
fragColor = vec4(color * alpha, alpha);
|
|
207
264
|
}
|
|
208
265
|
`;
|
|
209
266
|
var compileShader = (gl, type, source) => {
|
|
@@ -291,7 +348,10 @@ var setupLevels = (target) => {
|
|
|
291
348
|
uSource: gl.getUniformLocation(program, "uSource"),
|
|
292
349
|
uBlackPoint: gl.getUniformLocation(program, "uBlackPoint"),
|
|
293
350
|
uWhitePoint: gl.getUniformLocation(program, "uWhitePoint"),
|
|
294
|
-
uGamma: gl.getUniformLocation(program, "uGamma")
|
|
351
|
+
uGamma: gl.getUniformLocation(program, "uGamma"),
|
|
352
|
+
uOutputBlack: gl.getUniformLocation(program, "uOutputBlack"),
|
|
353
|
+
uOutputWhite: gl.getUniformLocation(program, "uOutputWhite"),
|
|
354
|
+
uChannel: gl.getUniformLocation(program, "uChannel")
|
|
295
355
|
}
|
|
296
356
|
};
|
|
297
357
|
};
|
|
@@ -301,12 +361,12 @@ var levels = createEffect({
|
|
|
301
361
|
documentationLink: "https://www.remotion.dev/docs/effects/levels",
|
|
302
362
|
backend: "webgl2",
|
|
303
363
|
calculateKey: (params) => {
|
|
304
|
-
const { blackPoint, whitePoint, gamma } = resolve(params);
|
|
305
|
-
return `levels-${blackPoint}-${whitePoint}-${gamma}`;
|
|
364
|
+
const { channel, blackPoint, whitePoint, gamma, outputBlack, outputWhite } = resolve(params);
|
|
365
|
+
return `levels-${channel}-${blackPoint}-${whitePoint}-${gamma}-${outputBlack}-${outputWhite}`;
|
|
306
366
|
},
|
|
307
367
|
setup: setupLevels,
|
|
308
368
|
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
309
|
-
const { blackPoint, whitePoint, gamma } = resolve(params);
|
|
369
|
+
const { channel, blackPoint, whitePoint, gamma, outputBlack, outputWhite } = resolve(params);
|
|
310
370
|
const { gl, program, textureSource, uniforms, vao } = state;
|
|
311
371
|
gl.viewport(0, 0, width, height);
|
|
312
372
|
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
@@ -327,6 +387,15 @@ var levels = createEffect({
|
|
|
327
387
|
}
|
|
328
388
|
if (uniforms.uGamma)
|
|
329
389
|
gl.uniform1f(uniforms.uGamma, gamma);
|
|
390
|
+
if (uniforms.uOutputBlack) {
|
|
391
|
+
gl.uniform1f(uniforms.uOutputBlack, outputBlack);
|
|
392
|
+
}
|
|
393
|
+
if (uniforms.uOutputWhite) {
|
|
394
|
+
gl.uniform1f(uniforms.uOutputWhite, outputWhite);
|
|
395
|
+
}
|
|
396
|
+
if (uniforms.uChannel) {
|
|
397
|
+
gl.uniform1i(uniforms.uChannel, LEVELS_CHANNELS.indexOf(channel));
|
|
398
|
+
}
|
|
330
399
|
gl.bindVertexArray(vao);
|
|
331
400
|
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
332
401
|
gl.bindVertexArray(null);
|
|
@@ -343,5 +412,6 @@ var levels = createEffect({
|
|
|
343
412
|
validateParams: validateLevelsParams
|
|
344
413
|
});
|
|
345
414
|
export {
|
|
346
|
-
levels
|
|
415
|
+
levels,
|
|
416
|
+
levelsSchema
|
|
347
417
|
};
|