@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 +18 -0
- package/dist/LightLeak.d.ts +8 -0
- package/dist/esm/index.mjs +210 -0
- package/dist/index.d.ts +2 -0
- package/package.json +55 -0
package/README.md
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# @remotion/light-leaks
|
|
2
|
+
|
|
3
|
+
Light leak effects for Remotion
|
|
4
|
+
|
|
5
|
+
[](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
|
+
};
|
package/dist/index.d.ts
ADDED
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
|
+
}
|