@remotion/effects 4.0.535 → 4.0.537
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 +30 -0
- package/dist/bevel-alpha/index.d.ts +13 -0
- package/dist/bevel-alpha/shaders.d.ts +3 -0
- package/dist/bevel-alpha.d.ts +1 -0
- package/dist/cylinder/index.d.ts +20 -0
- package/dist/cylinder/shader.d.ts +1 -0
- package/dist/cylinder.d.ts +1 -0
- package/dist/esm/bevel-alpha.mjs +474 -0
- package/dist/esm/cylinder.mjs +390 -0
- package/dist/esm/fractal-noise.mjs +688 -0
- package/dist/esm/lens-blur.mjs +550 -0
- package/dist/esm/page-turn.mjs +405 -0
- package/dist/esm/sphere.mjs +376 -0
- package/dist/esm/turbulent-displace.mjs +652 -0
- package/dist/fractal-noise/index.d.ts +40 -0
- package/dist/fractal-noise/shader.d.ts +1 -0
- package/dist/fractal-noise.d.ts +1 -0
- package/dist/lens-blur/index.d.ts +30 -0
- package/dist/lens-blur/shader.d.ts +1 -0
- package/dist/lens-blur.d.ts +1 -0
- package/dist/page-turn/index.d.ts +20 -0
- package/dist/page-turn/shader.d.ts +1 -0
- package/dist/page-turn.d.ts +1 -0
- package/dist/sphere/index.d.ts +18 -0
- package/dist/sphere/shader.d.ts +1 -0
- package/dist/sphere.d.ts +1 -0
- package/dist/turbulent-displace/index.d.ts +28 -0
- package/dist/turbulent-displace/shader.d.ts +1 -0
- package/dist/turbulent-displace.d.ts +1 -0
- package/dist/value-noise-shader.d.ts +1 -0
- package/dist/webgpu-projection-runtime.d.ts +24 -0
- package/package.json +62 -5
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
// src/sphere/index.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/webgpu-projection-runtime.ts
|
|
110
|
+
var cleanupWebGpuProjection = (state) => {
|
|
111
|
+
state.resources?.texture.destroy();
|
|
112
|
+
state.resources?.uniforms.destroy();
|
|
113
|
+
state.resources = null;
|
|
114
|
+
state.context.unconfigure();
|
|
115
|
+
};
|
|
116
|
+
var setupWebGpuProjection = (target, label) => {
|
|
117
|
+
const context = target.getContext("webgpu");
|
|
118
|
+
if (!context) {
|
|
119
|
+
throw new Error(`WebGPU is not available for the ${label} effect`);
|
|
120
|
+
}
|
|
121
|
+
return { context, resources: null };
|
|
122
|
+
};
|
|
123
|
+
var applyWebGpuProjection = ({
|
|
124
|
+
state,
|
|
125
|
+
source,
|
|
126
|
+
width,
|
|
127
|
+
height,
|
|
128
|
+
device,
|
|
129
|
+
shader,
|
|
130
|
+
uniformData
|
|
131
|
+
}) => {
|
|
132
|
+
if (state.resources && (state.resources.device !== device || state.resources.width !== width || state.resources.height !== height)) {
|
|
133
|
+
cleanupWebGpuProjection(state);
|
|
134
|
+
}
|
|
135
|
+
if (!state.resources) {
|
|
136
|
+
const format = navigator.gpu.getPreferredCanvasFormat();
|
|
137
|
+
state.context.configure({ device, format, alphaMode: "premultiplied" });
|
|
138
|
+
const module = device.createShaderModule({ code: shader });
|
|
139
|
+
const pipeline = device.createRenderPipeline({
|
|
140
|
+
layout: "auto",
|
|
141
|
+
vertex: { module, entryPoint: "vertex" },
|
|
142
|
+
fragment: { module, entryPoint: "fragment", targets: [{ format }] },
|
|
143
|
+
primitive: { topology: "triangle-list" }
|
|
144
|
+
});
|
|
145
|
+
const uniforms = device.createBuffer({
|
|
146
|
+
size: uniformData.byteLength,
|
|
147
|
+
usage: GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST
|
|
148
|
+
});
|
|
149
|
+
const sampler = device.createSampler({
|
|
150
|
+
addressModeU: "repeat",
|
|
151
|
+
magFilter: "linear",
|
|
152
|
+
minFilter: "linear"
|
|
153
|
+
});
|
|
154
|
+
const texture = device.createTexture({
|
|
155
|
+
size: [width, height],
|
|
156
|
+
format: "rgba8unorm",
|
|
157
|
+
usage: GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.RENDER_ATTACHMENT
|
|
158
|
+
});
|
|
159
|
+
const bindGroup = device.createBindGroup({
|
|
160
|
+
layout: pipeline.getBindGroupLayout(0),
|
|
161
|
+
entries: [
|
|
162
|
+
{ binding: 0, resource: texture.createView() },
|
|
163
|
+
{ binding: 1, resource: sampler },
|
|
164
|
+
{ binding: 2, resource: { buffer: uniforms } }
|
|
165
|
+
]
|
|
166
|
+
});
|
|
167
|
+
state.resources = {
|
|
168
|
+
device,
|
|
169
|
+
pipeline,
|
|
170
|
+
uniforms,
|
|
171
|
+
sampler,
|
|
172
|
+
texture,
|
|
173
|
+
bindGroup,
|
|
174
|
+
width,
|
|
175
|
+
height
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
const { resources } = state;
|
|
179
|
+
device.queue.copyExternalImageToTexture({ source }, { texture: resources.texture, premultipliedAlpha: true }, [width, height]);
|
|
180
|
+
device.queue.writeBuffer(resources.uniforms, 0, uniformData);
|
|
181
|
+
const encoder = device.createCommandEncoder();
|
|
182
|
+
const pass = encoder.beginRenderPass({
|
|
183
|
+
colorAttachments: [
|
|
184
|
+
{
|
|
185
|
+
view: state.context.getCurrentTexture().createView(),
|
|
186
|
+
clearValue: { r: 0, g: 0, b: 0, a: 0 },
|
|
187
|
+
loadOp: "clear",
|
|
188
|
+
storeOp: "store"
|
|
189
|
+
}
|
|
190
|
+
]
|
|
191
|
+
});
|
|
192
|
+
pass.setPipeline(resources.pipeline);
|
|
193
|
+
pass.setBindGroup(0, resources.bindGroup);
|
|
194
|
+
pass.draw(3);
|
|
195
|
+
pass.end();
|
|
196
|
+
device.queue.submit([encoder.finish()]);
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
// src/sphere/shader.ts
|
|
200
|
+
var SPHERE_SHADER = `
|
|
201
|
+
struct Params {
|
|
202
|
+
resolution: vec2f,
|
|
203
|
+
center: vec2f,
|
|
204
|
+
radius: f32,
|
|
205
|
+
padding: f32,
|
|
206
|
+
shading: f32,
|
|
207
|
+
faces: f32,
|
|
208
|
+
rotation: vec4f,
|
|
209
|
+
}
|
|
210
|
+
@group(0) @binding(0) var source: texture_2d<f32>;
|
|
211
|
+
@group(0) @binding(1) var sourceSampler: sampler;
|
|
212
|
+
@group(0) @binding(2) var<uniform> params: Params;
|
|
213
|
+
|
|
214
|
+
@vertex fn vertex(@builtin(vertex_index) index: u32) -> @builtin(position) vec4f {
|
|
215
|
+
let positions = array<vec2f, 3>(vec2f(-1, -1), vec2f(3, -1), vec2f(-1, 3));
|
|
216
|
+
return vec4f(positions[index], 0, 1);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
fn sampleFace(normal: vec3f, inverse: mat3x3f) -> vec4f {
|
|
220
|
+
let local = inverse * normal;
|
|
221
|
+
// Longitude wraps at the seam; latitude spans the complete image height.
|
|
222
|
+
let uv = vec2f(fract(atan2(local.x, local.z) / 6.28318530718 + 0.5), asin(clamp(local.y, -1.0, 1.0)) / 3.14159265359 + 0.5);
|
|
223
|
+
let color = textureSampleLevel(source, sourceSampler, uv, 0);
|
|
224
|
+
let shade = mix(1.0, abs(normal.z), params.shading);
|
|
225
|
+
return vec4f(color.rgb * shade, color.a);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
@fragment fn fragment(@builtin(position) position: vec4f) -> @location(0) vec4f {
|
|
229
|
+
let p = (position.xy - params.center) / params.radius;
|
|
230
|
+
let distanceSquared = dot(p, p);
|
|
231
|
+
let coverage = 1.0 - smoothstep(1.0 - fwidth(distanceSquared), 1.0, distanceSquared);
|
|
232
|
+
if (distanceSquared >= 1.0) { return vec4f(0); }
|
|
233
|
+
let z = sqrt(1.0 - distanceSquared);
|
|
234
|
+
let s = sin(params.rotation.xyz);
|
|
235
|
+
let c = cos(params.rotation.xyz);
|
|
236
|
+
let rx = mat3x3f(vec3f(1, 0, 0), vec3f(0, c.x, s.x), vec3f(0, -s.x, c.x));
|
|
237
|
+
let ry = mat3x3f(vec3f(c.y, 0, -s.y), vec3f(0, 1, 0), vec3f(s.y, 0, c.y));
|
|
238
|
+
let rz = mat3x3f(vec3f(c.z, s.z, 0), vec3f(-s.z, c.z, 0), vec3f(0, 0, 1));
|
|
239
|
+
let inverse = transpose(rz * ry * rx);
|
|
240
|
+
let front = sampleFace(vec3f(p, z), inverse);
|
|
241
|
+
let back = sampleFace(vec3f(p, -z), inverse);
|
|
242
|
+
if (params.faces == 1) { return front * coverage; }
|
|
243
|
+
if (params.faces == 2) { return back * coverage; }
|
|
244
|
+
return (front + back * (1.0 - front.a)) * coverage;
|
|
245
|
+
}
|
|
246
|
+
`;
|
|
247
|
+
|
|
248
|
+
// src/sphere/index.ts
|
|
249
|
+
var DEFAULT_RADIUS = 250;
|
|
250
|
+
var DEFAULT_ROTATION = 0;
|
|
251
|
+
var DEFAULT_POSITION = [0.5, 0.5];
|
|
252
|
+
var DEFAULT_RENDER = "both";
|
|
253
|
+
var DEFAULT_SHADING = 0.35;
|
|
254
|
+
var sphereSchema = {
|
|
255
|
+
radius: {
|
|
256
|
+
type: "number",
|
|
257
|
+
min: 1,
|
|
258
|
+
max: 1000,
|
|
259
|
+
step: 1,
|
|
260
|
+
default: DEFAULT_RADIUS,
|
|
261
|
+
description: "Radius",
|
|
262
|
+
hiddenFromList: false
|
|
263
|
+
},
|
|
264
|
+
rotationX: {
|
|
265
|
+
type: "rotation-degrees",
|
|
266
|
+
default: DEFAULT_ROTATION,
|
|
267
|
+
description: "X rotation"
|
|
268
|
+
},
|
|
269
|
+
rotationY: {
|
|
270
|
+
type: "rotation-degrees",
|
|
271
|
+
default: DEFAULT_ROTATION,
|
|
272
|
+
description: "Y rotation"
|
|
273
|
+
},
|
|
274
|
+
rotationZ: {
|
|
275
|
+
type: "rotation-degrees",
|
|
276
|
+
default: DEFAULT_ROTATION,
|
|
277
|
+
description: "Z rotation"
|
|
278
|
+
},
|
|
279
|
+
position: {
|
|
280
|
+
type: "uv-coordinate",
|
|
281
|
+
default: DEFAULT_POSITION,
|
|
282
|
+
description: "Position"
|
|
283
|
+
},
|
|
284
|
+
render: {
|
|
285
|
+
type: "enum",
|
|
286
|
+
variants: { both: {}, front: {}, back: {} },
|
|
287
|
+
default: DEFAULT_RENDER,
|
|
288
|
+
description: "Faces"
|
|
289
|
+
},
|
|
290
|
+
shading: {
|
|
291
|
+
type: "number",
|
|
292
|
+
min: 0,
|
|
293
|
+
max: 1,
|
|
294
|
+
step: 0.01,
|
|
295
|
+
default: DEFAULT_SHADING,
|
|
296
|
+
description: "Shading",
|
|
297
|
+
hiddenFromList: false
|
|
298
|
+
}
|
|
299
|
+
};
|
|
300
|
+
var resolve = (params) => ({
|
|
301
|
+
radius: params.radius ?? DEFAULT_RADIUS,
|
|
302
|
+
rotationX: params.rotationX ?? DEFAULT_ROTATION,
|
|
303
|
+
rotationY: params.rotationY ?? DEFAULT_ROTATION,
|
|
304
|
+
rotationZ: params.rotationZ ?? DEFAULT_ROTATION,
|
|
305
|
+
position: params.position ?? DEFAULT_POSITION,
|
|
306
|
+
render: params.render ?? DEFAULT_RENDER,
|
|
307
|
+
shading: params.shading ?? DEFAULT_SHADING
|
|
308
|
+
});
|
|
309
|
+
var sphere = Internals.createEffect({
|
|
310
|
+
type: "remotion/sphere",
|
|
311
|
+
label: "sphere()",
|
|
312
|
+
documentationLink: "https://www.remotion.dev/docs/effects/sphere",
|
|
313
|
+
backend: "webgpu",
|
|
314
|
+
schema: sphereSchema,
|
|
315
|
+
validateParams: (params) => {
|
|
316
|
+
assertEffectParamsObject(params, "Sphere");
|
|
317
|
+
for (const key of [
|
|
318
|
+
"radius",
|
|
319
|
+
"rotationX",
|
|
320
|
+
"rotationY",
|
|
321
|
+
"rotationZ",
|
|
322
|
+
"shading"
|
|
323
|
+
]) {
|
|
324
|
+
assertOptionalFiniteNumber(params[key], key);
|
|
325
|
+
}
|
|
326
|
+
const r = resolve(params);
|
|
327
|
+
if (r.radius <= 0) {
|
|
328
|
+
throw new TypeError('"radius" must be greater than 0');
|
|
329
|
+
}
|
|
330
|
+
validateUnitInterval(r.shading, "shading");
|
|
331
|
+
if (params.position !== undefined && (!Array.isArray(params.position) || params.position.length !== 2 || !Number.isFinite(params.position[0]) || !Number.isFinite(params.position[1]))) {
|
|
332
|
+
throw new TypeError('"position" must contain two finite numbers');
|
|
333
|
+
}
|
|
334
|
+
if (params.render !== undefined && params.render !== "both" && params.render !== "front" && params.render !== "back") {
|
|
335
|
+
throw new TypeError('"render" must be "both", "front", or "back"');
|
|
336
|
+
}
|
|
337
|
+
},
|
|
338
|
+
calculateKey: (params) => {
|
|
339
|
+
const r = resolve(params);
|
|
340
|
+
return `sphere-${r.radius}-${r.rotationX}-${r.rotationY}-${r.rotationZ}-${r.position.join(",")}-${r.render}-${r.shading}`;
|
|
341
|
+
},
|
|
342
|
+
setup: (target) => setupWebGpuProjection(target, "sphere"),
|
|
343
|
+
apply: ({ source, width, height, params, state, gpuDevice }) => {
|
|
344
|
+
if (!gpuDevice) {
|
|
345
|
+
throw new Error("A WebGPU device is required for the sphere effect");
|
|
346
|
+
}
|
|
347
|
+
const r = resolve(params);
|
|
348
|
+
const radians = Math.PI / 180;
|
|
349
|
+
applyWebGpuProjection({
|
|
350
|
+
source,
|
|
351
|
+
width,
|
|
352
|
+
height,
|
|
353
|
+
state,
|
|
354
|
+
device: gpuDevice,
|
|
355
|
+
shader: SPHERE_SHADER,
|
|
356
|
+
uniformData: new Float32Array([
|
|
357
|
+
width,
|
|
358
|
+
height,
|
|
359
|
+
r.position[0] * width,
|
|
360
|
+
r.position[1] * height,
|
|
361
|
+
r.radius,
|
|
362
|
+
0,
|
|
363
|
+
r.shading,
|
|
364
|
+
r.render === "front" ? 1 : r.render === "back" ? 2 : 0,
|
|
365
|
+
r.rotationX % 360 * radians,
|
|
366
|
+
r.rotationY % 360 * radians,
|
|
367
|
+
r.rotationZ % 360 * radians,
|
|
368
|
+
0
|
|
369
|
+
])
|
|
370
|
+
});
|
|
371
|
+
},
|
|
372
|
+
cleanup: cleanupWebGpuProjection
|
|
373
|
+
});
|
|
374
|
+
export {
|
|
375
|
+
sphere
|
|
376
|
+
};
|