@remotion/light-leaks 4.0.415

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/README.md ADDED
@@ -0,0 +1,18 @@
1
+ # @remotion/light-leaks
2
+
3
+ Light leak effects for Remotion
4
+
5
+ [![NPM Downloads](https://img.shields.io/npm/dm/@remotion/light-leaks.svg?style=flat&color=black&label=Downloads)](https://npmcharts.com/compare/@remotion/light-leaks?minimal=true)
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @remotion/light-leaks --save-exact
11
+ ```
12
+
13
+ When installing a Remotion package, make sure to align the version of all `remotion` and `@remotion/*` packages to the same version.
14
+ Remove the `^` character from the version number to use the exact version.
15
+
16
+ ## Usage
17
+
18
+ See the [documentation](https://www.remotion.dev/docs/light-leaks) for more information.
@@ -0,0 +1,8 @@
1
+ import React from 'react';
2
+ import { type SequenceProps } from 'remotion';
3
+ export type LightLeakProps = Omit<SequenceProps, 'children' | 'layout' | 'durationInFrames'> & {
4
+ readonly durationInFrames?: number;
5
+ readonly seed?: number;
6
+ readonly hueShift?: number;
7
+ };
8
+ export declare const LightLeak: React.FC<LightLeakProps>;
@@ -0,0 +1,210 @@
1
+ // src/LightLeak.tsx
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ import {
4
+ AbsoluteFill,
5
+ Sequence,
6
+ useCurrentFrame,
7
+ useDelayRender,
8
+ useVideoConfig
9
+ } from "remotion";
10
+ import { jsx } from "react/jsx-runtime";
11
+ var VERTEX_SHADER = `
12
+ attribute vec2 position;
13
+ void main() {
14
+ gl_Position = vec4(position, 0.0, 1.0);
15
+ }
16
+ `;
17
+ var FRAGMENT_SHADER = `
18
+ #ifdef GL_ES
19
+ precision mediump float;
20
+ #endif
21
+
22
+ uniform float evolveProgress;
23
+ uniform float retractProgress;
24
+ uniform float seed;
25
+ uniform float retractSeed;
26
+ uniform float hueShift;
27
+ uniform vec2 resolution;
28
+
29
+ const float Pi = 3.14159;
30
+
31
+ vec3 computePattern(vec2 uv, float s, float t) {
32
+ vec2 p = uv * 0.8;
33
+ p += vec2(sin(s * 1.61803) * 5.0, cos(s * 2.71828) * 5.0);
34
+
35
+ for(int i = 1; i < 5; i++)
36
+ {
37
+ vec2 newp = p;
38
+ float fi = float(i);
39
+ float phase = s * 0.7 * fi;
40
+ newp.x += 0.6 / fi * cos(fi * p.y + t * 0.7 + 0.3 * fi + phase) + 20.0;
41
+ newp.y += 0.6 / fi * cos(fi * p.x + t * 0.7 + 0.3 * float(i + 10) + phase) - 20.0 + 15.0;
42
+ p = newp;
43
+ }
44
+
45
+ float v1 = 0.5 * sin(2.0 * p.x) + 0.5;
46
+ float v2 = 0.5 * sin(2.0 * p.y) + 0.5;
47
+ float blend = sin(p.x + p.y) * 0.5 + 0.5;
48
+ float brightness = v1 * 0.5 + v2 * 0.5;
49
+ float patternValue = brightness * 0.6 + blend * 0.4;
50
+
51
+ return vec3(brightness, blend, patternValue);
52
+ }
53
+
54
+ void main()
55
+ {
56
+ float refScale = 1.92;
57
+ vec2 uv = (gl_FragCoord.xy / resolution) * vec2(refScale, refScale * resolution.y / resolution.x);
58
+
59
+ vec3 patA = computePattern(uv, seed, evolveProgress * Pi);
60
+ float threshA = 1.0 - evolveProgress;
61
+ float revealAlpha = smoothstep(threshA, threshA + 0.3, patA.z);
62
+
63
+ vec2 maxUv = vec2(refScale, refScale * resolution.y / resolution.x);
64
+ vec2 retractUv = maxUv - uv;
65
+ vec3 patB = computePattern(retractUv, retractSeed, retractProgress * Pi);
66
+ float threshB = 1.0 - retractProgress;
67
+ float eraseAlpha = smoothstep(threshB, threshB + 0.3, patB.z);
68
+
69
+ float alpha = revealAlpha * (1.0 - eraseAlpha);
70
+
71
+ vec3 yellow = vec3(1.0, 0.85, 0.2);
72
+ vec3 orange = vec3(1.0, 0.5, 0.05);
73
+ vec3 col = mix(yellow, orange, patA.y);
74
+ col *= 0.6 + 0.6 * patA.x;
75
+
76
+ float angle = hueShift * Pi / 180.0;
77
+ float cosA = cos(angle);
78
+ float sinA = sin(angle);
79
+ mat3 hueRot = mat3(
80
+ cosA + (1.0 - cosA) / 3.0,
81
+ (1.0 - cosA) / 3.0 - sinA * 0.57735,
82
+ (1.0 - cosA) / 3.0 + sinA * 0.57735,
83
+ (1.0 - cosA) / 3.0 + sinA * 0.57735,
84
+ cosA + (1.0 - cosA) / 3.0,
85
+ (1.0 - cosA) / 3.0 - sinA * 0.57735,
86
+ (1.0 - cosA) / 3.0 - sinA * 0.57735,
87
+ (1.0 - cosA) / 3.0 + sinA * 0.57735,
88
+ cosA + (1.0 - cosA) / 3.0
89
+ );
90
+ col = clamp(hueRot * col, 0.0, 1.0);
91
+
92
+ gl_FragColor = vec4(col, alpha);
93
+ }
94
+ `;
95
+ var LightLeakCanvas = ({ seed, hueShift }) => {
96
+ const frame = useCurrentFrame();
97
+ const { width, height, durationInFrames } = useVideoConfig();
98
+ const canvasRef = useRef(null);
99
+ const glRef = useRef(null);
100
+ const { delayRender, continueRender, cancelRender } = useDelayRender();
101
+ const [handle] = useState(() => delayRender());
102
+ const initGl = useCallback((canvas) => {
103
+ const gl = canvas.getContext("webgl", {
104
+ premultipliedAlpha: false,
105
+ alpha: true
106
+ });
107
+ if (!gl) {
108
+ cancelRender(new Error("Failed to get WebGL context. Try rendering with --gl=angle to enable WebGL."));
109
+ return null;
110
+ }
111
+ gl.enable(gl.BLEND);
112
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
113
+ const compile = (type, src) => {
114
+ const s = gl.createShader(type);
115
+ gl.shaderSource(s, src);
116
+ gl.compileShader(s);
117
+ return s;
118
+ };
119
+ const program = gl.createProgram();
120
+ gl.attachShader(program, compile(gl.VERTEX_SHADER, VERTEX_SHADER));
121
+ gl.attachShader(program, compile(gl.FRAGMENT_SHADER, FRAGMENT_SHADER));
122
+ gl.linkProgram(program);
123
+ gl.useProgram(program);
124
+ const buf = gl.createBuffer();
125
+ gl.bindBuffer(gl.ARRAY_BUFFER, buf);
126
+ gl.bufferData(gl.ARRAY_BUFFER, new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]), gl.STATIC_DRAW);
127
+ const pos = gl.getAttribLocation(program, "position");
128
+ gl.enableVertexAttribArray(pos);
129
+ gl.vertexAttribPointer(pos, 2, gl.FLOAT, false, 0, 0);
130
+ continueRender(handle);
131
+ return {
132
+ gl,
133
+ resLoc: gl.getUniformLocation(program, "resolution"),
134
+ evolveProgressLoc: gl.getUniformLocation(program, "evolveProgress"),
135
+ retractProgressLoc: gl.getUniformLocation(program, "retractProgress"),
136
+ seedLoc: gl.getUniformLocation(program, "seed"),
137
+ retractSeedLoc: gl.getUniformLocation(program, "retractSeed"),
138
+ hueShiftLoc: gl.getUniformLocation(program, "hueShift")
139
+ };
140
+ }, [continueRender, handle, cancelRender]);
141
+ useEffect(() => {
142
+ const canvas = canvasRef.current;
143
+ if (!canvas || glRef.current)
144
+ return;
145
+ glRef.current = initGl(canvas);
146
+ }, [initGl]);
147
+ useEffect(() => {
148
+ const ctx = glRef.current;
149
+ if (!ctx)
150
+ return;
151
+ const {
152
+ gl,
153
+ resLoc,
154
+ evolveProgressLoc,
155
+ retractProgressLoc,
156
+ seedLoc,
157
+ retractSeedLoc,
158
+ hueShiftLoc
159
+ } = ctx;
160
+ const normalized = durationInFrames <= 1 ? 0 : frame / (durationInFrames - 1);
161
+ const evolveProgress = Math.min(1, normalized * 2);
162
+ const retractProgress = Math.max(0, normalized * 2 - 1);
163
+ gl.viewport(0, 0, gl.canvas.width, gl.canvas.height);
164
+ gl.clearColor(0, 0, 0, 0);
165
+ gl.clear(gl.COLOR_BUFFER_BIT);
166
+ gl.uniform1f(evolveProgressLoc, evolveProgress);
167
+ gl.uniform1f(retractProgressLoc, retractProgress);
168
+ gl.uniform1f(seedLoc, seed);
169
+ gl.uniform1f(retractSeedLoc, seed + 42);
170
+ gl.uniform1f(hueShiftLoc, hueShift);
171
+ gl.uniform2f(resLoc, gl.canvas.width, gl.canvas.height);
172
+ gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4);
173
+ }, [frame, durationInFrames, seed, hueShift, width, height]);
174
+ return /* @__PURE__ */ jsx(AbsoluteFill, {
175
+ children: /* @__PURE__ */ jsx("canvas", {
176
+ ref: canvasRef,
177
+ width,
178
+ height
179
+ })
180
+ });
181
+ };
182
+ var LightLeak = ({
183
+ seed = 0,
184
+ hueShift = 0,
185
+ durationInFrames,
186
+ ...sequenceProps
187
+ }) => {
188
+ const { durationInFrames: videoDuration } = useVideoConfig();
189
+ const resolvedDuration = durationInFrames ?? videoDuration;
190
+ if (typeof seed !== "number" || !Number.isFinite(seed)) {
191
+ throw new TypeError(`"seed" must be a finite number, but got ${JSON.stringify(seed)}`);
192
+ }
193
+ if (typeof hueShift !== "number" || !Number.isFinite(hueShift)) {
194
+ throw new TypeError(`"hueShift" must be a finite number, but got ${JSON.stringify(hueShift)}`);
195
+ }
196
+ if (hueShift < 0 || hueShift > 360) {
197
+ throw new RangeError(`"hueShift" must be between 0 and 360, but got ${hueShift}`);
198
+ }
199
+ return /* @__PURE__ */ jsx(Sequence, {
200
+ durationInFrames: resolvedDuration,
201
+ ...sequenceProps,
202
+ children: /* @__PURE__ */ jsx(LightLeakCanvas, {
203
+ seed,
204
+ hueShift
205
+ })
206
+ });
207
+ };
208
+ export {
209
+ LightLeak
210
+ };
@@ -0,0 +1,2 @@
1
+ export { LightLeak } from './LightLeak';
2
+ export type { LightLeakProps } from './LightLeak';
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "@remotion/light-leaks",
3
+ "version": "4.0.415",
4
+ "description": "Light leak effects for Remotion",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "module": "dist/esm/index.mjs",
8
+ "repository": {
9
+ "url": "https://github.com/remotion-dev/remotion/tree/main/packages/light-leaks"
10
+ },
11
+ "sideEffects": false,
12
+ "type": "module",
13
+ "scripts": {
14
+ "formatting": "prettier --experimental-cli src --check",
15
+ "lint": "eslint src",
16
+ "watch": "tsgo -w",
17
+ "make": "tsgo && bun --env-file=../.env.bundle bundle.ts"
18
+ },
19
+ "author": "Jonny Burger <jonny@remotion.dev>",
20
+ "contributors": [],
21
+ "license": "Remotion License",
22
+ "bugs": {
23
+ "url": "https://github.com/remotion-dev/remotion/issues"
24
+ },
25
+ "dependencies": {
26
+ "remotion": "4.0.414"
27
+ },
28
+ "peerDependencies": {
29
+ "react": ">=16.8.0",
30
+ "react-dom": ">=16.8.0"
31
+ },
32
+ "exports": {
33
+ ".": {
34
+ "types": "./dist/index.d.ts",
35
+ "module": "./dist/esm/index.mjs",
36
+ "import": "./dist/esm/index.mjs"
37
+ },
38
+ "./package.json": "./package.json"
39
+ },
40
+ "devDependencies": {
41
+ "react": "19.2.3",
42
+ "react-dom": "19.2.3",
43
+ "@remotion/eslint-config-internal": "4.0.414",
44
+ "eslint": "9.19.0",
45
+ "@typescript/native-preview": "7.0.0-dev.20260105.1"
46
+ },
47
+ "keywords": [
48
+ "remotion",
49
+ "light-leaks"
50
+ ],
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "homepage": "https://www.remotion.dev/docs/light-leaks"
55
+ }