gl-transitions 1.70.0 → 1.71.0

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gl-transitions",
3
- "version": "1.70.0",
3
+ "version": "1.71.0",
4
4
  "description": "The open collection of GL Transitions",
5
5
  "main": "index.js",
6
6
  "license": "MIT",
@@ -0,0 +1,184 @@
1
+ // Author: bread
2
+ // License: MIT
3
+
4
+ uniform float strength; // = 1.0
5
+ uniform float horizontalBars; // = 42.0
6
+ uniform float verticalSlits; // = 18.0
7
+ uniform float tear; // = 0.18
8
+ uniform float chroma; // = 0.032
9
+ uniform float residue; // = 0.62
10
+ uniform float noiseAmount; // = 0.16
11
+ uniform float scanAmount; // = 0.13
12
+ uniform float flashAmount; // = 0.20
13
+
14
+ const float PI = 3.141592653589793;
15
+
16
+ float hash(float n) {
17
+ return fract(sin(n) * 43758.5453123);
18
+ }
19
+
20
+ float hash(vec2 p) {
21
+ return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453123);
22
+ }
23
+
24
+ float sat(float v) {
25
+ return clamp(v, 0.0, 1.0);
26
+ }
27
+
28
+ float burst() {
29
+ return pow(max(0.0, sin(progress * PI)), 0.42) * strength;
30
+ }
31
+
32
+ vec2 safeUv(vec2 uv) {
33
+ return clamp(uv, vec2(0.0), vec2(1.0));
34
+ }
35
+
36
+ float stripeY(vec2 uv, float density, float seed, float minWidth, float maxWidth) {
37
+ float y = uv.y * density + seed * 0.137;
38
+ float id = floor(y);
39
+ float f = fract(y);
40
+ float c = hash(vec2(id, seed));
41
+ float w = mix(minWidth, maxWidth, hash(vec2(id + 9.17, seed + 2.31)));
42
+ return 1.0 - smoothstep(w, w + 0.018, abs(f - c));
43
+ }
44
+
45
+ float stripeX(vec2 uv, float density, float seed, float minWidth, float maxWidth) {
46
+ float x = uv.x * density + seed * 0.091;
47
+ float id = floor(x);
48
+ float f = fract(x);
49
+ float c = hash(vec2(id, seed + 41.0));
50
+ float w = mix(minWidth, maxWidth, hash(vec2(id + 4.7, seed + 8.9)));
51
+ return 1.0 - smoothstep(w, w + 0.012, abs(f - c));
52
+ }
53
+
54
+ float brokenGate(vec2 uv, float row, float rnd, float frame) {
55
+ float segs = mix(1.0, 9.0, hash(vec2(row, frame + 44.0)));
56
+ float seg = floor(uv.x * segs);
57
+ return step(0.16, hash(vec2(seg, row + frame * 3.0 + rnd)));
58
+ }
59
+
60
+ float horizontalMask(vec2 uv, float frame) {
61
+ float r1 = floor((uv.y + hash(frame) * 0.031) * horizontalBars * 0.38);
62
+ float r2 = floor((uv.y + hash(frame + 2.0) * 0.013) * horizontalBars);
63
+ float r3 = floor((uv.y + hash(frame + 7.0) * 0.006) * horizontalBars * 3.4);
64
+
65
+ float thick = stripeY(uv, horizontalBars * 0.38, frame + 1.0, 0.035, 0.22);
66
+ float mid = stripeY(uv, horizontalBars, frame + 4.0, 0.014, 0.11);
67
+ float hair = stripeY(uv, horizontalBars * 3.4, frame + 9.0, 0.004, 0.035);
68
+
69
+ thick *= step(0.42, hash(vec2(r1, frame + 10.0)));
70
+ mid *= step(0.48, hash(vec2(r2, frame + 20.0)));
71
+ hair *= step(0.62, hash(vec2(r3, frame + 30.0)));
72
+
73
+ thick *= brokenGate(uv, r1, hash(vec2(r1, frame)), frame);
74
+ mid *= brokenGate(uv, r2, hash(vec2(r2, frame)), frame + 3.0);
75
+
76
+ return sat(max(thick, max(mid, hair)));
77
+ }
78
+
79
+ float verticalMask(vec2 uv, float frame) {
80
+ float col = floor((uv.x + hash(frame + 12.0) * 0.017) * verticalSlits);
81
+ float slit = stripeX(uv, verticalSlits, frame + 13.0, 0.01, 0.075);
82
+ slit *= step(0.66, hash(vec2(col, frame + 19.0)));
83
+ return sat(slit);
84
+ }
85
+
86
+ vec4 chromaFrom(vec2 uv, vec2 s) {
87
+ uv = safeUv(uv);
88
+ return vec4(
89
+ getFromColor(safeUv(uv + s)).r,
90
+ getFromColor(uv).g,
91
+ getFromColor(safeUv(uv - s)).b,
92
+ 1.0
93
+ );
94
+ }
95
+
96
+ vec4 chromaTo(vec2 uv, vec2 s) {
97
+ uv = safeUv(uv);
98
+ return vec4(
99
+ getToColor(safeUv(uv - s)).r,
100
+ getToColor(uv).g,
101
+ getToColor(safeUv(uv + s)).b,
102
+ 1.0
103
+ );
104
+ }
105
+
106
+ vec2 distortUv(vec2 uv, float dir, float b, float h, float v, float frame) {
107
+ float row = floor(uv.y * horizontalBars);
108
+ float col = floor(uv.x * verticalSlits);
109
+
110
+ float rowRnd = hash(vec2(row, frame));
111
+ float colRnd = hash(vec2(col, frame + 27.0));
112
+
113
+ float xTear = (rowRnd - 0.5) * 2.0 * tear * b * h;
114
+ xTear += sin(uv.y * 120.0 + progress * 95.0) * 0.006 * b;
115
+
116
+ float yDrag = (colRnd - 0.5) * 0.13 * b * v;
117
+ float micro = (hash(vec2(row, col + frame)) - 0.5) * 0.018 * b * max(h, v);
118
+
119
+ return uv + vec2(xTear * dir + micro, yDrag);
120
+ }
121
+
122
+ vec4 transition(vec2 uv) {
123
+ if (progress <= 0.0) return getFromColor(uv);
124
+ if (progress >= 1.0) return getToColor(uv);
125
+
126
+ float b = burst();
127
+ float frame = floor(progress * 30.0);
128
+
129
+ float h = horizontalMask(uv, frame);
130
+ float v = verticalMask(uv, frame);
131
+ float glitch = sat(max(h, v * 0.75));
132
+
133
+ float row = floor(uv.y * horizontalBars);
134
+ float rowRnd = hash(vec2(row, frame + 5.0));
135
+
136
+ float bandDelay = (rowRnd - 0.5) * 0.30 * h;
137
+ float reveal = smoothstep(0.18, 0.84, progress + bandDelay);
138
+
139
+ vec2 split = vec2(chroma * b * (1.0 + 1.7 * glitch), chroma * 0.22 * b * v);
140
+
141
+ vec2 fromUv = distortUv(uv, 1.0, b, h, v, frame);
142
+ vec2 toUv = distortUv(uv, -1.0, b, h, v, frame);
143
+
144
+ vec4 color = mix(
145
+ chromaFrom(fromUv, split),
146
+ chromaTo(toUv, split),
147
+ reveal
148
+ );
149
+
150
+ // Horizontal time-slice residue: old/new frames dragged through uneven scan bands.
151
+ vec2 smearUv = uv;
152
+ smearUv.x += (rowRnd - 0.5) * 0.46 * b * h;
153
+ smearUv.y += (hash(vec2(row, frame + 31.0)) - 0.5) * 0.045 * b * h;
154
+
155
+ float sliceReveal = smoothstep(0.28, 0.78, progress + (rowRnd - 0.5) * 0.22);
156
+ vec4 sliceColor = mix(
157
+ chromaFrom(smearUv, split * 1.65),
158
+ chromaTo(smearUv - vec2((rowRnd - 0.5) * 0.18 * b, 0.0), split * 1.65),
159
+ sliceReveal
160
+ );
161
+
162
+ color = mix(color, sliceColor, h * b * residue);
163
+
164
+ // Thin scan sparks and broken white lines, like the reference clip's bright horizontal noise.
165
+ float hairLine = stripeY(uv, 190.0, frame + 55.0, 0.002, 0.012);
166
+ hairLine *= step(0.70, hash(vec2(floor(uv.y * 190.0), frame + 56.0)));
167
+ color.rgb += vec3(0.72, 0.90, 1.0) * hairLine * b * 0.28;
168
+
169
+ float scan = 0.5 + 0.5 * sin(uv.y * 980.0 + progress * 130.0);
170
+ color.rgb *= 1.0 - scanAmount * b * scan;
171
+
172
+ vec2 nCell = floor(uv * vec2(360.0 * ratio, 210.0));
173
+ float n = hash(nCell + vec2(frame * 7.0, frame * 13.0));
174
+ color.rgb += (n - 0.5) * noiseAmount * b * (0.55 + glitch);
175
+
176
+ // Slight desaturation during the damage peak makes it feel more like broadcast/video signal corruption.
177
+ float luma = dot(color.rgb, vec3(0.299, 0.587, 0.114));
178
+ color.rgb = mix(color.rgb, vec3(luma), 0.18 * b * glitch);
179
+
180
+ float strobe = step(0.78, hash(vec2(frame, 3.14))) * pow(b, 1.65);
181
+ color.rgb += vec3(strobe * flashAmount);
182
+
183
+ return vec4(clamp(color.rgb, vec3(0.0), vec3(1.0)), 1.0);
184
+ }