@remotion/effects 4.0.541 → 4.0.542
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 +10 -0
- package/dist/esm/lightning.mjs +603 -0
- package/dist/esm/magnify.mjs +403 -0
- package/dist/esm/preview/barrel-distortion.mjs +303 -0
- package/dist/esm/preview/bevel-alpha.mjs +525 -0
- package/dist/esm/preview/blur.mjs +435 -0
- package/dist/esm/preview/brightness.mjs +95 -0
- package/dist/esm/preview/burlap.mjs +481 -0
- package/dist/esm/preview/checkerboard.mjs +8 -0
- package/dist/esm/preview/chromatic-aberration.mjs +308 -0
- package/dist/esm/preview/color-correction.mjs +522 -0
- package/dist/esm/preview/color-key.mjs +440 -0
- package/dist/esm/preview/contour-lines.mjs +608 -0
- package/dist/esm/preview/contrast.mjs +95 -0
- package/dist/esm/preview/corner-pin.mjs +6 -0
- package/dist/esm/preview/curves.mjs +357 -0
- package/dist/esm/preview/cylinder.mjs +273 -0
- package/dist/esm/preview/dot-grid.mjs +333 -0
- package/dist/esm/preview/drop-shadow.mjs +607 -0
- package/dist/esm/preview/duotone.mjs +344 -0
- package/dist/esm/preview/emboss.mjs +479 -0
- package/dist/esm/preview/evolve.mjs +485 -0
- package/dist/esm/preview/exposure.mjs +264 -0
- package/dist/esm/preview/film-burn.mjs +298 -0
- package/dist/esm/preview/fisheye.mjs +422 -0
- package/dist/esm/preview/flannel.mjs +401 -0
- package/dist/esm/preview/fractal-noise.mjs +642 -0
- package/dist/esm/preview/glow.mjs +598 -0
- package/dist/esm/preview/grayscale.mjs +86 -0
- package/dist/esm/preview/gridlines.mjs +8 -0
- package/dist/esm/preview/halftone-linear-gradient.mjs +523 -0
- package/dist/esm/preview/halftone.mjs +552 -0
- package/dist/esm/preview/hue.mjs +83 -0
- package/dist/esm/preview/index-00v3hr66.mjs +299 -0
- package/dist/esm/preview/index-0w4eqht8.mjs +351 -0
- package/dist/esm/preview/index-18y0zcy2.mjs +440 -0
- package/dist/esm/preview/index-1m1b1ad7.mjs +520 -0
- package/dist/esm/preview/index-34fxm3ax.mjs +518 -0
- package/dist/esm/preview/index-4fvp93ps.mjs +32 -0
- package/dist/esm/preview/index-4scpn12x.mjs +224 -0
- package/dist/esm/preview/index-4z6pt3ka.mjs +104 -0
- package/dist/esm/preview/index-618ky75w.mjs +51 -0
- package/dist/esm/preview/index-6agxdrvr.mjs +411 -0
- package/dist/esm/preview/index-6jkps947.mjs +120 -0
- package/dist/esm/preview/index-8agtsbw4.mjs +617 -0
- package/dist/esm/preview/index-8jx11jyn.mjs +29 -0
- package/dist/esm/preview/index-8p04sssx.mjs +123 -0
- package/dist/esm/preview/index-afdtmrh2.mjs +596 -0
- package/dist/esm/preview/index-b86qstcs.mjs +18 -0
- package/dist/esm/preview/index-cb77qg3g.mjs +587 -0
- package/dist/esm/preview/index-cdp7tr8x.mjs +122 -0
- package/dist/esm/preview/index-evy8hyah.mjs +55 -0
- package/dist/esm/preview/index-gnsce796.mjs +6 -0
- package/dist/esm/preview/index-kkvzt8b7.mjs +199 -0
- package/dist/esm/preview/index-r0v18b2n.mjs +425 -0
- package/dist/esm/preview/index-rswpzmm5.mjs +926 -0
- package/dist/esm/preview/index-s9mrx750.mjs +97 -0
- package/dist/esm/preview/index-tvfexb7s.mjs +164 -0
- package/dist/esm/preview/index-vp56k1gj.mjs +215 -0
- package/dist/esm/preview/index-wxhvgv2s.mjs +79 -0
- package/dist/esm/preview/index-wy95a41r.mjs +407 -0
- package/dist/esm/preview/index-ysnwfc4t.mjs +306 -0
- package/dist/esm/preview/index.mjs +51 -0
- package/dist/esm/preview/invert.mjs +84 -0
- package/dist/esm/preview/iris-wipe.mjs +315 -0
- package/dist/esm/preview/lens-blur.mjs +563 -0
- package/dist/esm/preview/levels.mjs +400 -0
- package/dist/esm/preview/light-leak.mjs +8 -0
- package/dist/esm/preview/light-trail.mjs +516 -0
- package/dist/esm/preview/lightning.mjs +603 -0
- package/dist/esm/preview/linear-gradient-tint.mjs +6 -0
- package/dist/esm/preview/linear-gradient.mjs +6 -0
- package/dist/esm/preview/linear-progressive-blur.mjs +516 -0
- package/dist/esm/preview/linear-progressive-pixelate.mjs +176 -0
- package/dist/esm/preview/lines.mjs +536 -0
- package/dist/esm/preview/liquid-contours.mjs +512 -0
- package/dist/esm/preview/long-shadows.mjs +437 -0
- package/dist/esm/preview/lut.mjs +601 -0
- package/dist/esm/preview/magnify.mjs +403 -0
- package/dist/esm/preview/mirror.mjs +341 -0
- package/dist/esm/preview/noise-displacement.mjs +584 -0
- package/dist/esm/preview/noise.mjs +318 -0
- package/dist/esm/preview/outline.mjs +725 -0
- package/dist/esm/preview/page-turn.mjs +302 -0
- package/dist/esm/preview/paper.mjs +1249 -0
- package/dist/esm/preview/pattern.mjs +6 -0
- package/dist/esm/preview/pixel-dissolve.mjs +360 -0
- package/dist/esm/preview/pixelate.mjs +249 -0
- package/dist/esm/preview/radial-progressive-blur.mjs +582 -0
- package/dist/esm/preview/radial-progressive-pixelate.mjs +220 -0
- package/dist/esm/preview/radial-wipe.mjs +224 -0
- package/dist/esm/preview/rain-fall.mjs +114 -0
- package/dist/esm/preview/region-blur.mjs +500 -0
- package/dist/esm/preview/rings.mjs +8 -0
- package/dist/esm/preview/roughen-edges.mjs +590 -0
- package/dist/esm/preview/saturation.mjs +86 -0
- package/dist/esm/preview/scale.mjs +109 -0
- package/dist/esm/preview/scanlines.mjs +362 -0
- package/dist/esm/preview/shadows-highlights.mjs +284 -0
- package/dist/esm/preview/shatter.mjs +868 -0
- package/dist/esm/preview/shine.mjs +368 -0
- package/dist/esm/preview/shrinkwrap.mjs +769 -0
- package/dist/esm/preview/skew.mjs +300 -0
- package/dist/esm/preview/snow-fall.mjs +170 -0
- package/dist/esm/preview/speckle.mjs +356 -0
- package/dist/esm/preview/sphere.mjs +252 -0
- package/dist/esm/preview/starburst.mjs +8 -0
- package/dist/esm/preview/tear.mjs +375 -0
- package/dist/esm/preview/thermal-vision.mjs +387 -0
- package/dist/esm/preview/tile.mjs +7 -0
- package/dist/esm/preview/tint.mjs +125 -0
- package/dist/esm/preview/translate.mjs +151 -0
- package/dist/esm/preview/turbulent-displace.mjs +613 -0
- package/dist/esm/preview/tv-signal-off.mjs +308 -0
- package/dist/esm/preview/venetian-blinds.mjs +341 -0
- package/dist/esm/preview/vibrance.mjs +254 -0
- package/dist/esm/preview/vignette.mjs +458 -0
- package/dist/esm/preview/wave.mjs +384 -0
- package/dist/esm/preview/waves.mjs +599 -0
- package/dist/esm/preview/white-balance.mjs +280 -0
- package/dist/esm/preview/white-noise.mjs +244 -0
- package/dist/esm/preview/zigzag.mjs +8 -0
- package/dist/esm/preview/zoom-blur.mjs +389 -0
- package/dist/lightning/geometry.d.ts +10 -0
- package/dist/lightning/index.d.ts +4 -0
- package/dist/lightning/mask.d.ts +2 -0
- package/dist/lightning/params.d.ts +259 -0
- package/dist/lightning/shaders.d.ts +2 -0
- package/dist/lightning.d.ts +2 -0
- package/dist/magnify/shader.d.ts +1 -0
- package/dist/magnify/webgpu-shader.d.ts +1 -0
- package/dist/magnify.d.ts +28 -0
- package/package.json +30 -6
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import"./index-8p04sssx.mjs";
|
|
2
|
+
import {
|
|
3
|
+
createRectTransformImplementations
|
|
4
|
+
} from "./index-s9mrx750.mjs";
|
|
5
|
+
import {
|
|
6
|
+
assertEffectParamsObject,
|
|
7
|
+
assertRequiredFiniteNumber
|
|
8
|
+
} from "./index-4fvp93ps.mjs";
|
|
9
|
+
|
|
10
|
+
// src/scale/index.ts
|
|
11
|
+
import { Internals } from "remotion";
|
|
12
|
+
var { createEffect } = Internals;
|
|
13
|
+
var scaleSchema = {
|
|
14
|
+
scale: {
|
|
15
|
+
type: "number",
|
|
16
|
+
min: 0.1,
|
|
17
|
+
max: 10,
|
|
18
|
+
step: 0.1,
|
|
19
|
+
default: 1,
|
|
20
|
+
description: "Factor",
|
|
21
|
+
hiddenFromList: false,
|
|
22
|
+
defaultKeyframeOutput: "perceptual-scale"
|
|
23
|
+
},
|
|
24
|
+
horizontal: {
|
|
25
|
+
type: "boolean",
|
|
26
|
+
default: true,
|
|
27
|
+
description: "Horizontal"
|
|
28
|
+
},
|
|
29
|
+
vertical: {
|
|
30
|
+
type: "boolean",
|
|
31
|
+
default: true,
|
|
32
|
+
description: "Vertical"
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var resolve = (p) => ({
|
|
36
|
+
scale: p.scale,
|
|
37
|
+
horizontal: p.horizontal ?? true,
|
|
38
|
+
vertical: p.vertical ?? true
|
|
39
|
+
});
|
|
40
|
+
var validateScaleParams = (params) => {
|
|
41
|
+
assertEffectParamsObject(params, "Scale");
|
|
42
|
+
assertRequiredFiniteNumber(params.scale, "scale");
|
|
43
|
+
if (typeof params.horizontal !== "undefined" && typeof params.horizontal !== "boolean") {
|
|
44
|
+
throw new TypeError(`"horizontal" must be a boolean, but got ${JSON.stringify(params.horizontal)}`);
|
|
45
|
+
}
|
|
46
|
+
if (typeof params.vertical !== "undefined" && typeof params.vertical !== "boolean") {
|
|
47
|
+
throw new TypeError(`"vertical" must be a boolean, but got ${JSON.stringify(params.vertical)}`);
|
|
48
|
+
}
|
|
49
|
+
const resolved = resolve(params);
|
|
50
|
+
if (resolved.scale <= 0) {
|
|
51
|
+
throw new TypeError(`"scale" must be greater than 0, but got ${JSON.stringify(resolved.scale)}`);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
var scale = createEffect({
|
|
55
|
+
type: "dev.remotion.effects.scale",
|
|
56
|
+
label: "scale()",
|
|
57
|
+
documentationLink: "https://www.remotion.dev/docs/effects/scale",
|
|
58
|
+
calculateKey: (params) => {
|
|
59
|
+
const r = resolve(params);
|
|
60
|
+
return `scale-${r.scale}-${r.horizontal}-${r.vertical}`;
|
|
61
|
+
},
|
|
62
|
+
implementations: {
|
|
63
|
+
...createRectTransformImplementations("scale", (params, width, height) => {
|
|
64
|
+
const r = resolve(params);
|
|
65
|
+
const scaledWidth = width * (r.horizontal ? r.scale : 1);
|
|
66
|
+
const scaledHeight = height * (r.vertical ? r.scale : 1);
|
|
67
|
+
return {
|
|
68
|
+
x: (width - scaledWidth) / 2,
|
|
69
|
+
y: (height - scaledHeight) / 2,
|
|
70
|
+
width: scaledWidth,
|
|
71
|
+
height: scaledHeight
|
|
72
|
+
};
|
|
73
|
+
}),
|
|
74
|
+
"2d": Internals.createEffectImplementation({
|
|
75
|
+
setup: () => null,
|
|
76
|
+
apply: ({ source, target, width, height, params }) => {
|
|
77
|
+
const ctx = target.getContext("2d");
|
|
78
|
+
if (!ctx) {
|
|
79
|
+
throw new Error("Failed to acquire 2D context for scale effect. The canvas may have been assigned a different context type.");
|
|
80
|
+
}
|
|
81
|
+
const r = resolve(params);
|
|
82
|
+
const scaleX = r.horizontal ? r.scale : 1;
|
|
83
|
+
const scaleY = r.vertical ? r.scale : 1;
|
|
84
|
+
if (scaleX === 1 && scaleY === 1) {
|
|
85
|
+
ctx.clearRect(0, 0, width, height);
|
|
86
|
+
ctx.drawImage(source, 0, 0, width, height);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
ctx.clearRect(0, 0, width, height);
|
|
90
|
+
ctx.save();
|
|
91
|
+
const centerX = width / 2;
|
|
92
|
+
const centerY = height / 2;
|
|
93
|
+
ctx.translate(centerX, centerY);
|
|
94
|
+
ctx.scale(scaleX, scaleY);
|
|
95
|
+
ctx.translate(-centerX, -centerY);
|
|
96
|
+
ctx.drawImage(source, 0, 0, width, height);
|
|
97
|
+
ctx.restore();
|
|
98
|
+
},
|
|
99
|
+
cleanup: () => {
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
})
|
|
103
|
+
},
|
|
104
|
+
schema: scaleSchema,
|
|
105
|
+
validateParams: validateScaleParams
|
|
106
|
+
});
|
|
107
|
+
export {
|
|
108
|
+
scale
|
|
109
|
+
};
|
|
@@ -0,0 +1,362 @@
|
|
|
1
|
+
import {
|
|
2
|
+
assertOptionalFiniteNumber,
|
|
3
|
+
validateUnitInterval,
|
|
4
|
+
validateNonNegative
|
|
5
|
+
} from "./index-wxhvgv2s.mjs";
|
|
6
|
+
import {
|
|
7
|
+
WEBGPU_SINGLE_PASS_VERTEX,
|
|
8
|
+
setupWebGpuSinglePass,
|
|
9
|
+
cleanupWebGpuSinglePass,
|
|
10
|
+
applyWebGpuSinglePass
|
|
11
|
+
} from "./index-tvfexb7s.mjs";
|
|
12
|
+
import {
|
|
13
|
+
assertEffectParamsObject
|
|
14
|
+
} from "./index-4fvp93ps.mjs";
|
|
15
|
+
|
|
16
|
+
// src/scanlines.ts
|
|
17
|
+
import { Internals } from "remotion";
|
|
18
|
+
var { createEffect, createWebGL2ContextError } = Internals;
|
|
19
|
+
var DEFAULT_AMOUNT = 0.15;
|
|
20
|
+
var DEFAULT_SPACING = 4;
|
|
21
|
+
var DEFAULT_THICKNESS = 1;
|
|
22
|
+
var DEFAULT_OFFSET = 0;
|
|
23
|
+
var DEFAULT_PREMULTIPLY = false;
|
|
24
|
+
var scanlinesSchema = {
|
|
25
|
+
amount: {
|
|
26
|
+
type: "number",
|
|
27
|
+
min: 0,
|
|
28
|
+
max: 1,
|
|
29
|
+
step: 0.01,
|
|
30
|
+
default: DEFAULT_AMOUNT,
|
|
31
|
+
description: "Amount",
|
|
32
|
+
hiddenFromList: false
|
|
33
|
+
},
|
|
34
|
+
spacing: {
|
|
35
|
+
type: "number",
|
|
36
|
+
min: 0.1,
|
|
37
|
+
max: 100,
|
|
38
|
+
step: 0.1,
|
|
39
|
+
default: DEFAULT_SPACING,
|
|
40
|
+
description: "Spacing",
|
|
41
|
+
hiddenFromList: false
|
|
42
|
+
},
|
|
43
|
+
thickness: {
|
|
44
|
+
type: "number",
|
|
45
|
+
min: 0,
|
|
46
|
+
max: 100,
|
|
47
|
+
step: 0.1,
|
|
48
|
+
default: DEFAULT_THICKNESS,
|
|
49
|
+
description: "Thickness",
|
|
50
|
+
hiddenFromList: false
|
|
51
|
+
},
|
|
52
|
+
offset: {
|
|
53
|
+
type: "number",
|
|
54
|
+
step: 0.1,
|
|
55
|
+
default: DEFAULT_OFFSET,
|
|
56
|
+
description: "Offset",
|
|
57
|
+
hiddenFromList: false
|
|
58
|
+
},
|
|
59
|
+
premultiply: {
|
|
60
|
+
type: "boolean",
|
|
61
|
+
default: DEFAULT_PREMULTIPLY,
|
|
62
|
+
description: "Premultiply"
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
var resolve = (p) => ({
|
|
66
|
+
amount: p.amount ?? DEFAULT_AMOUNT,
|
|
67
|
+
spacing: p.spacing ?? DEFAULT_SPACING,
|
|
68
|
+
thickness: p.thickness ?? DEFAULT_THICKNESS,
|
|
69
|
+
offset: p.offset ?? DEFAULT_OFFSET,
|
|
70
|
+
premultiply: p.premultiply ?? DEFAULT_PREMULTIPLY
|
|
71
|
+
});
|
|
72
|
+
var assertOptionalBoolean = (value, name) => {
|
|
73
|
+
if (value === undefined) {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (typeof value !== "boolean") {
|
|
77
|
+
throw new TypeError(`"${name}" must be a boolean, but got ${JSON.stringify(value)}`);
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
var validatePositive = (value, name) => {
|
|
81
|
+
if (value <= 0) {
|
|
82
|
+
throw new TypeError(`"${name}" must be greater than 0, but got ${JSON.stringify(value)}`);
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
var validateScanlinesParams = (params) => {
|
|
86
|
+
assertEffectParamsObject(params, "Scanlines");
|
|
87
|
+
assertOptionalFiniteNumber(params.amount, "amount");
|
|
88
|
+
assertOptionalFiniteNumber(params.spacing, "spacing");
|
|
89
|
+
assertOptionalFiniteNumber(params.thickness, "thickness");
|
|
90
|
+
assertOptionalFiniteNumber(params.offset, "offset");
|
|
91
|
+
assertOptionalBoolean(params.premultiply, "premultiply");
|
|
92
|
+
const r = resolve(params);
|
|
93
|
+
validateUnitInterval(r.amount, "amount");
|
|
94
|
+
validatePositive(r.spacing, "spacing");
|
|
95
|
+
validateNonNegative(r.thickness, "thickness");
|
|
96
|
+
};
|
|
97
|
+
var SCANLINES_VS = `#version 300 es
|
|
98
|
+
in vec2 aPos;
|
|
99
|
+
in vec2 aUv;
|
|
100
|
+
out vec2 vUv;
|
|
101
|
+
|
|
102
|
+
void main() {
|
|
103
|
+
vUv = aUv;
|
|
104
|
+
gl_Position = vec4(aPos, 0.0, 1.0);
|
|
105
|
+
}
|
|
106
|
+
`;
|
|
107
|
+
var SCANLINES_FS = `#version 300 es
|
|
108
|
+
precision highp float;
|
|
109
|
+
|
|
110
|
+
in vec2 vUv;
|
|
111
|
+
out vec4 fragColor;
|
|
112
|
+
|
|
113
|
+
uniform sampler2D uSource;
|
|
114
|
+
uniform float uAmount;
|
|
115
|
+
uniform float uSpacing;
|
|
116
|
+
uniform float uThickness;
|
|
117
|
+
uniform float uOffset;
|
|
118
|
+
uniform bool uPremultiply;
|
|
119
|
+
|
|
120
|
+
void main() {
|
|
121
|
+
vec4 texColor = texture(uSource, vUv);
|
|
122
|
+
float alpha = texColor.a;
|
|
123
|
+
|
|
124
|
+
if (alpha <= 0.001) {
|
|
125
|
+
fragColor = vec4(0.0);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (uAmount <= 0.0 || uThickness <= 0.0) {
|
|
130
|
+
fragColor = texColor;
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
float spacing = max(uSpacing, 0.001);
|
|
135
|
+
float thickness = min(uThickness, spacing);
|
|
136
|
+
float halfThickness = thickness * 0.5;
|
|
137
|
+
float position = mod(gl_FragCoord.y + uOffset, spacing);
|
|
138
|
+
float distanceToLine = min(position, spacing - position);
|
|
139
|
+
float line = 1.0 - smoothstep(halfThickness, halfThickness + 1.0, distanceToLine);
|
|
140
|
+
float dutyCycle = thickness / spacing;
|
|
141
|
+
float signal = line - dutyCycle;
|
|
142
|
+
|
|
143
|
+
vec3 rgb = texColor.rgb / alpha;
|
|
144
|
+
vec3 scanlineLayer = uPremultiply ? rgb * signal : vec3(signal);
|
|
145
|
+
rgb = clamp(rgb + scanlineLayer * uAmount, 0.0, 1.0);
|
|
146
|
+
fragColor = vec4(rgb * alpha, alpha);
|
|
147
|
+
}
|
|
148
|
+
`;
|
|
149
|
+
var compileShader = (gl, type, source) => {
|
|
150
|
+
const shader = gl.createShader(type);
|
|
151
|
+
if (!shader) {
|
|
152
|
+
throw new Error("Failed to create WebGL shader");
|
|
153
|
+
}
|
|
154
|
+
gl.shaderSource(shader, source);
|
|
155
|
+
gl.compileShader(shader);
|
|
156
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
157
|
+
const log = gl.getShaderInfoLog(shader);
|
|
158
|
+
gl.deleteShader(shader);
|
|
159
|
+
throw new Error(`Scanlines shader compile failed: ${log ?? "(no log)"}`);
|
|
160
|
+
}
|
|
161
|
+
return shader;
|
|
162
|
+
};
|
|
163
|
+
var linkProgram = (gl, vs, fs) => {
|
|
164
|
+
const program = gl.createProgram();
|
|
165
|
+
if (!program) {
|
|
166
|
+
throw new Error("Failed to create WebGL program");
|
|
167
|
+
}
|
|
168
|
+
gl.attachShader(program, vs);
|
|
169
|
+
gl.attachShader(program, fs);
|
|
170
|
+
gl.linkProgram(program);
|
|
171
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
172
|
+
const log = gl.getProgramInfoLog(program);
|
|
173
|
+
gl.deleteProgram(program);
|
|
174
|
+
throw new Error(`Scanlines program link failed: ${log ?? "(no log)"}`);
|
|
175
|
+
}
|
|
176
|
+
return program;
|
|
177
|
+
};
|
|
178
|
+
var setupScanlines = (target) => {
|
|
179
|
+
const gl = target.getContext("webgl2", {
|
|
180
|
+
premultipliedAlpha: true,
|
|
181
|
+
alpha: true,
|
|
182
|
+
preserveDrawingBuffer: true
|
|
183
|
+
});
|
|
184
|
+
if (!gl) {
|
|
185
|
+
throw createWebGL2ContextError("scanlines effect");
|
|
186
|
+
}
|
|
187
|
+
gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true);
|
|
188
|
+
const vs = compileShader(gl, gl.VERTEX_SHADER, SCANLINES_VS);
|
|
189
|
+
const fs = compileShader(gl, gl.FRAGMENT_SHADER, SCANLINES_FS);
|
|
190
|
+
const program = linkProgram(gl, vs, fs);
|
|
191
|
+
gl.deleteShader(vs);
|
|
192
|
+
gl.deleteShader(fs);
|
|
193
|
+
const vao = gl.createVertexArray();
|
|
194
|
+
if (!vao) {
|
|
195
|
+
throw new Error("Failed to create WebGL vertex array");
|
|
196
|
+
}
|
|
197
|
+
gl.bindVertexArray(vao);
|
|
198
|
+
const data = new Float32Array([
|
|
199
|
+
-1,
|
|
200
|
+
-1,
|
|
201
|
+
0,
|
|
202
|
+
0,
|
|
203
|
+
1,
|
|
204
|
+
-1,
|
|
205
|
+
1,
|
|
206
|
+
0,
|
|
207
|
+
-1,
|
|
208
|
+
1,
|
|
209
|
+
0,
|
|
210
|
+
1,
|
|
211
|
+
1,
|
|
212
|
+
1,
|
|
213
|
+
1,
|
|
214
|
+
1
|
|
215
|
+
]);
|
|
216
|
+
const vbo = gl.createBuffer();
|
|
217
|
+
if (!vbo) {
|
|
218
|
+
throw new Error("Failed to create WebGL buffer");
|
|
219
|
+
}
|
|
220
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, vbo);
|
|
221
|
+
gl.bufferData(gl.ARRAY_BUFFER, data, gl.STATIC_DRAW);
|
|
222
|
+
const aPos = gl.getAttribLocation(program, "aPos");
|
|
223
|
+
const aUv = gl.getAttribLocation(program, "aUv");
|
|
224
|
+
gl.enableVertexAttribArray(aPos);
|
|
225
|
+
gl.vertexAttribPointer(aPos, 2, gl.FLOAT, false, 16, 0);
|
|
226
|
+
gl.enableVertexAttribArray(aUv);
|
|
227
|
+
gl.vertexAttribPointer(aUv, 2, gl.FLOAT, false, 16, 8);
|
|
228
|
+
gl.bindVertexArray(null);
|
|
229
|
+
const texture = gl.createTexture();
|
|
230
|
+
if (!texture) {
|
|
231
|
+
throw new Error("Failed to create WebGL texture");
|
|
232
|
+
}
|
|
233
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
234
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
|
|
235
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR);
|
|
236
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
|
|
237
|
+
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
|
|
238
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
239
|
+
return {
|
|
240
|
+
gl,
|
|
241
|
+
program,
|
|
242
|
+
vao,
|
|
243
|
+
vbo,
|
|
244
|
+
texture,
|
|
245
|
+
uSource: gl.getUniformLocation(program, "uSource"),
|
|
246
|
+
uAmount: gl.getUniformLocation(program, "uAmount"),
|
|
247
|
+
uSpacing: gl.getUniformLocation(program, "uSpacing"),
|
|
248
|
+
uThickness: gl.getUniformLocation(program, "uThickness"),
|
|
249
|
+
uOffset: gl.getUniformLocation(program, "uOffset"),
|
|
250
|
+
uPremultiply: gl.getUniformLocation(program, "uPremultiply")
|
|
251
|
+
};
|
|
252
|
+
};
|
|
253
|
+
var WEBGPU_SHADER = `
|
|
254
|
+
${WEBGPU_SINGLE_PASS_VERTEX}
|
|
255
|
+
struct Params { controls: vec4f, options: vec4f, }
|
|
256
|
+
@group(0) @binding(0) var source: texture_2d<f32>;
|
|
257
|
+
@group(0) @binding(1) var sourceSampler: sampler;
|
|
258
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
259
|
+
@fragment fn fragment(input: VertexOutput) -> @location(0) vec4f {
|
|
260
|
+
let texColor = textureSampleLevel(source, sourceSampler, input.uv, 0);
|
|
261
|
+
let alpha = texColor.a;
|
|
262
|
+
if (alpha <= 0.001) { return vec4f(0); }
|
|
263
|
+
if (params.controls.x <= 0.0 || params.controls.z <= 0.0) { return texColor; }
|
|
264
|
+
let spacing = max(params.controls.y, 0.001);
|
|
265
|
+
let thickness = min(params.controls.z, spacing);
|
|
266
|
+
let halfThickness = thickness * 0.5;
|
|
267
|
+
// WebGL fragment coordinates run bottom-to-top.
|
|
268
|
+
let rawPosition = params.options.y - input.position.y + params.controls.w;
|
|
269
|
+
let position = rawPosition - spacing * floor(rawPosition / spacing);
|
|
270
|
+
let distanceToLine = min(position, spacing - position);
|
|
271
|
+
let line = 1.0 - smoothstep(halfThickness, halfThickness + 1.0, distanceToLine);
|
|
272
|
+
let dutyCycle = thickness / spacing;
|
|
273
|
+
let signal = line - dutyCycle;
|
|
274
|
+
let rgb = texColor.rgb / alpha;
|
|
275
|
+
let scanlineLayer = select(vec3f(signal), rgb * signal, params.options.x != 0.0);
|
|
276
|
+
let result = clamp(rgb + scanlineLayer * params.controls.x, vec3f(0), vec3f(1));
|
|
277
|
+
return vec4f(result * alpha, alpha);
|
|
278
|
+
}
|
|
279
|
+
`;
|
|
280
|
+
var scanlines = createEffect({
|
|
281
|
+
type: "dev.remotion.effects.scanlines",
|
|
282
|
+
label: "scanlines()",
|
|
283
|
+
documentationLink: "https://www.remotion.dev/docs/effects/scanlines",
|
|
284
|
+
calculateKey: (params) => {
|
|
285
|
+
const r = resolve(params);
|
|
286
|
+
return `scanlines-${r.amount}-${r.spacing}-${r.thickness}-${r.offset}-${r.premultiply ? 1 : 0}`;
|
|
287
|
+
},
|
|
288
|
+
implementations: {
|
|
289
|
+
webgpu: Internals.createEffectImplementation({
|
|
290
|
+
setup: (target) => setupWebGpuSinglePass(target, "scanlines"),
|
|
291
|
+
apply: ({ source, width, height, params, state, gpuDevice }) => {
|
|
292
|
+
if (!gpuDevice) {
|
|
293
|
+
throw new Error("A WebGPU device is required for the scanlines effect");
|
|
294
|
+
}
|
|
295
|
+
const r = resolve(params);
|
|
296
|
+
applyWebGpuSinglePass({
|
|
297
|
+
source,
|
|
298
|
+
width,
|
|
299
|
+
height,
|
|
300
|
+
state,
|
|
301
|
+
device: gpuDevice,
|
|
302
|
+
shader: WEBGPU_SHADER,
|
|
303
|
+
uniformData: new Float32Array([
|
|
304
|
+
r.amount,
|
|
305
|
+
r.spacing,
|
|
306
|
+
r.thickness,
|
|
307
|
+
r.offset,
|
|
308
|
+
r.premultiply ? 1 : 0,
|
|
309
|
+
height,
|
|
310
|
+
0,
|
|
311
|
+
0
|
|
312
|
+
])
|
|
313
|
+
});
|
|
314
|
+
},
|
|
315
|
+
cleanup: cleanupWebGpuSinglePass
|
|
316
|
+
}),
|
|
317
|
+
webgl2: Internals.createEffectImplementation({
|
|
318
|
+
setup: (target) => setupScanlines(target),
|
|
319
|
+
apply: ({ source, width, height, params, state, flipSourceY }) => {
|
|
320
|
+
const r = resolve(params);
|
|
321
|
+
const { gl, program, texture, vao } = state;
|
|
322
|
+
gl.viewport(0, 0, width, height);
|
|
323
|
+
gl.bindFramebuffer(gl.FRAMEBUFFER, null);
|
|
324
|
+
gl.clearColor(0, 0, 0, 0);
|
|
325
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
326
|
+
gl.activeTexture(gl.TEXTURE0);
|
|
327
|
+
gl.bindTexture(gl.TEXTURE_2D, texture);
|
|
328
|
+
gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, flipSourceY);
|
|
329
|
+
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, source);
|
|
330
|
+
gl.useProgram(program);
|
|
331
|
+
if (state.uSource)
|
|
332
|
+
gl.uniform1i(state.uSource, 0);
|
|
333
|
+
if (state.uAmount)
|
|
334
|
+
gl.uniform1f(state.uAmount, r.amount);
|
|
335
|
+
if (state.uSpacing)
|
|
336
|
+
gl.uniform1f(state.uSpacing, r.spacing);
|
|
337
|
+
if (state.uThickness)
|
|
338
|
+
gl.uniform1f(state.uThickness, r.thickness);
|
|
339
|
+
if (state.uOffset)
|
|
340
|
+
gl.uniform1f(state.uOffset, r.offset);
|
|
341
|
+
if (state.uPremultiply)
|
|
342
|
+
gl.uniform1i(state.uPremultiply, r.premultiply ? 1 : 0);
|
|
343
|
+
gl.bindVertexArray(vao);
|
|
344
|
+
gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
|
|
345
|
+
gl.bindVertexArray(null);
|
|
346
|
+
gl.bindTexture(gl.TEXTURE_2D, null);
|
|
347
|
+
gl.useProgram(null);
|
|
348
|
+
},
|
|
349
|
+
cleanup: ({ gl, program, vao, vbo, texture }) => {
|
|
350
|
+
gl.deleteTexture(texture);
|
|
351
|
+
gl.deleteBuffer(vbo);
|
|
352
|
+
gl.deleteProgram(program);
|
|
353
|
+
gl.deleteVertexArray(vao);
|
|
354
|
+
}
|
|
355
|
+
})
|
|
356
|
+
},
|
|
357
|
+
schema: scanlinesSchema,
|
|
358
|
+
validateParams: validateScanlinesParams
|
|
359
|
+
});
|
|
360
|
+
export {
|
|
361
|
+
scanlines
|
|
362
|
+
};
|