react-native-effects 0.0.1 → 0.1.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/LICENSE +20 -0
- package/README.md +251 -0
- package/lib/module/components/Aurora.js +184 -0
- package/lib/module/components/Aurora.js.map +1 -0
- package/lib/module/components/CalicoSwirl.js +155 -0
- package/lib/module/components/CalicoSwirl.js.map +1 -0
- package/lib/module/components/Campfire.js +225 -0
- package/lib/module/components/Campfire.js.map +1 -0
- package/lib/module/components/CircularGradient.js +52 -0
- package/lib/module/components/CircularGradient.js.map +1 -0
- package/lib/module/components/Iridescence.js +57 -0
- package/lib/module/components/Iridescence.js.map +1 -0
- package/lib/module/components/LinearGradient.js +48 -0
- package/lib/module/components/LinearGradient.js.map +1 -0
- package/lib/module/components/LiquidChrome.js +75 -0
- package/lib/module/components/LiquidChrome.js.map +1 -0
- package/lib/module/components/ShaderView/index.js +224 -0
- package/lib/module/components/ShaderView/index.js.map +1 -0
- package/lib/module/components/ShaderView/types.js +4 -0
- package/lib/module/components/ShaderView/types.js.map +1 -0
- package/lib/module/components/Silk.js +83 -0
- package/lib/module/components/Silk.js.map +1 -0
- package/lib/module/consts.js +154 -0
- package/lib/module/consts.js.map +1 -0
- package/lib/module/hooks/useClock.js +15 -0
- package/lib/module/hooks/useClock.js.map +1 -0
- package/lib/module/hooks/useWGPUSetup.js +54 -0
- package/lib/module/hooks/useWGPUSetup.js.map +1 -0
- package/lib/module/index.js +13 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/shaders/TRIANGLE_VERTEX_SHADER.js +20 -0
- package/lib/module/shaders/TRIANGLE_VERTEX_SHADER.js.map +1 -0
- package/lib/module/shaders/uniforms.js +20 -0
- package/lib/module/shaders/uniforms.js.map +1 -0
- package/lib/module/utils/backgroundRuntime.js +12 -0
- package/lib/module/utils/backgroundRuntime.js.map +1 -0
- package/lib/module/utils/colors.js +94 -0
- package/lib/module/utils/colors.js.map +1 -0
- package/lib/module/utils/initWebGPU.js +40 -0
- package/lib/module/utils/initWebGPU.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/components/Aurora.d.ts +17 -0
- package/lib/typescript/src/components/Aurora.d.ts.map +1 -0
- package/lib/typescript/src/components/CalicoSwirl.d.ts +13 -0
- package/lib/typescript/src/components/CalicoSwirl.d.ts.map +1 -0
- package/lib/typescript/src/components/Campfire.d.ts +17 -0
- package/lib/typescript/src/components/Campfire.d.ts.map +1 -0
- package/lib/typescript/src/components/CircularGradient.d.ts +19 -0
- package/lib/typescript/src/components/CircularGradient.d.ts.map +1 -0
- package/lib/typescript/src/components/Iridescence.d.ts +11 -0
- package/lib/typescript/src/components/Iridescence.d.ts.map +1 -0
- package/lib/typescript/src/components/LinearGradient.d.ts +15 -0
- package/lib/typescript/src/components/LinearGradient.d.ts.map +1 -0
- package/lib/typescript/src/components/LiquidChrome.d.ts +17 -0
- package/lib/typescript/src/components/LiquidChrome.d.ts.map +1 -0
- package/lib/typescript/src/components/ShaderView/index.d.ts +3 -0
- package/lib/typescript/src/components/ShaderView/index.d.ts.map +1 -0
- package/lib/typescript/src/components/ShaderView/types.d.ts +15 -0
- package/lib/typescript/src/components/ShaderView/types.d.ts.map +1 -0
- package/lib/typescript/src/components/Silk.d.ts +17 -0
- package/lib/typescript/src/components/Silk.d.ts.map +1 -0
- package/lib/typescript/src/consts.d.ts +2 -0
- package/lib/typescript/src/consts.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useClock.d.ts +3 -0
- package/lib/typescript/src/hooks/useClock.d.ts.map +1 -0
- package/lib/typescript/src/hooks/useWGPUSetup.d.ts +15 -0
- package/lib/typescript/src/hooks/useWGPUSetup.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +12 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/shaders/TRIANGLE_VERTEX_SHADER.d.ts +2 -0
- package/lib/typescript/src/shaders/TRIANGLE_VERTEX_SHADER.d.ts.map +1 -0
- package/lib/typescript/src/shaders/uniforms.d.ts +6 -0
- package/lib/typescript/src/shaders/uniforms.d.ts.map +1 -0
- package/lib/typescript/src/utils/backgroundRuntime.d.ts +3 -0
- package/lib/typescript/src/utils/backgroundRuntime.d.ts.map +1 -0
- package/lib/typescript/src/utils/colors.d.ts +22 -0
- package/lib/typescript/src/utils/colors.d.ts.map +1 -0
- package/lib/typescript/src/utils/initWebGPU.d.ts +23 -0
- package/lib/typescript/src/utils/initWebGPU.d.ts.map +1 -0
- package/package.json +174 -7
- package/src/components/Aurora.tsx +203 -0
- package/src/components/CalicoSwirl.tsx +167 -0
- package/src/components/Campfire.tsx +244 -0
- package/src/components/CircularGradient.tsx +76 -0
- package/src/components/Iridescence.tsx +67 -0
- package/src/components/LinearGradient.tsx +62 -0
- package/src/components/LiquidChrome.tsx +94 -0
- package/src/components/ShaderView/index.tsx +225 -0
- package/src/components/ShaderView/types.ts +15 -0
- package/src/components/Silk.tsx +102 -0
- package/src/consts.ts +152 -0
- package/src/hooks/useClock.ts +20 -0
- package/src/hooks/useWGPUSetup.tsx +73 -0
- package/src/index.tsx +23 -0
- package/src/shaders/TRIANGLE_VERTEX_SHADER.ts +17 -0
- package/src/shaders/uniforms.ts +17 -0
- package/src/utils/backgroundRuntime.ts +10 -0
- package/src/utils/colors.ts +117 -0
- package/src/utils/initWebGPU.ts +47 -0
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { ColorInput } from '../utils/colors';
|
|
4
|
+
import ShaderView from './ShaderView';
|
|
5
|
+
|
|
6
|
+
type Props = ViewProps & {
|
|
7
|
+
/** The color tint for the fire effect. */
|
|
8
|
+
color?: ColorInput;
|
|
9
|
+
/** Animation speed multiplier. Default: 1.0 */
|
|
10
|
+
speed?: number;
|
|
11
|
+
/** Size of the sparks. Default: 1.0 */
|
|
12
|
+
sparkSize?: number;
|
|
13
|
+
/** Intensity of the fire. Default: 1.0 */
|
|
14
|
+
fireIntensity?: number;
|
|
15
|
+
/** Intensity of the smoke. Default: 1.0 */
|
|
16
|
+
smokeIntensity?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function Campfire({
|
|
20
|
+
color = '#ffffff',
|
|
21
|
+
speed = 1.0,
|
|
22
|
+
sparkSize = 1.0,
|
|
23
|
+
fireIntensity = 1.0,
|
|
24
|
+
smokeIntensity = 1.0,
|
|
25
|
+
...viewProps
|
|
26
|
+
}: Props) {
|
|
27
|
+
const colors = useMemo(() => [color], [color]);
|
|
28
|
+
const params = useMemo(
|
|
29
|
+
() => [sparkSize, fireIntensity, smokeIntensity],
|
|
30
|
+
[sparkSize, fireIntensity, smokeIntensity]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ShaderView
|
|
35
|
+
fragmentShader={CAMPFIRE_SHADER}
|
|
36
|
+
colors={colors}
|
|
37
|
+
params={params}
|
|
38
|
+
speed={speed}
|
|
39
|
+
isStatic={false}
|
|
40
|
+
{...viewProps}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const CAMPFIRE_SHADER = /* wgsl */ `
|
|
46
|
+
struct Uniforms {
|
|
47
|
+
resolution: vec4<f32>,
|
|
48
|
+
time: vec4<f32>,
|
|
49
|
+
color0: vec4<f32>,
|
|
50
|
+
color1: vec4<f32>,
|
|
51
|
+
params0: vec4<f32>,
|
|
52
|
+
params1: vec4<f32>,
|
|
53
|
+
};
|
|
54
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
55
|
+
|
|
56
|
+
fn mod289_3(x: vec3<f32>) -> vec3<f32> {
|
|
57
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
fn mod289_4(x: vec4<f32>) -> vec4<f32> {
|
|
61
|
+
return x - floor(x * (1.0 / 289.0)) * 289.0;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
fn permute(x: vec4<f32>) -> vec4<f32> {
|
|
65
|
+
return mod289_4(((x * 34.0) + 1.0) * x);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
fn taylorInvSqrt(r: vec4<f32>) -> vec4<f32> {
|
|
69
|
+
return 1.79284291400159 - 0.85373472095314 * r;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
fn snoise(v: vec3<f32>) -> f32 {
|
|
73
|
+
let C = vec2<f32>(1.0 / 6.0, 1.0 / 3.0);
|
|
74
|
+
let D = vec4<f32>(0.0, 0.5, 1.0, 2.0);
|
|
75
|
+
|
|
76
|
+
var i = floor(v + dot(v, vec3<f32>(C.y, C.y, C.y)));
|
|
77
|
+
let x0 = v - i + dot(i, vec3<f32>(C.x, C.x, C.x));
|
|
78
|
+
|
|
79
|
+
let g = step(vec3<f32>(x0.y, x0.z, x0.x), x0);
|
|
80
|
+
let l = 1.0 - g;
|
|
81
|
+
let i1 = min(g, vec3<f32>(l.z, l.x, l.y));
|
|
82
|
+
let i2 = max(g, vec3<f32>(l.z, l.x, l.y));
|
|
83
|
+
|
|
84
|
+
let x1 = x0 - i1 + vec3<f32>(C.x, C.x, C.x);
|
|
85
|
+
let x2 = x0 - i2 + vec3<f32>(C.y, C.y, C.y);
|
|
86
|
+
let x3 = x0 - vec3<f32>(D.y, D.y, D.y);
|
|
87
|
+
|
|
88
|
+
i = mod289_3(i);
|
|
89
|
+
let p = permute(permute(permute(
|
|
90
|
+
i.z + vec4<f32>(0.0, i1.z, i2.z, 1.0))
|
|
91
|
+
+ i.y + vec4<f32>(0.0, i1.y, i2.y, 1.0))
|
|
92
|
+
+ i.x + vec4<f32>(0.0, i1.x, i2.x, 1.0));
|
|
93
|
+
|
|
94
|
+
let n_ = 0.142857142857;
|
|
95
|
+
let ns = n_ * vec3<f32>(D.w, D.y, D.z) - vec3<f32>(D.x, D.z, D.x);
|
|
96
|
+
|
|
97
|
+
let j = p - 49.0 * floor(p * ns.z * ns.z);
|
|
98
|
+
|
|
99
|
+
let x_ = floor(j * ns.z);
|
|
100
|
+
let y_ = floor(j - 7.0 * x_);
|
|
101
|
+
|
|
102
|
+
let x = x_ * ns.x + vec4<f32>(ns.y, ns.y, ns.y, ns.y);
|
|
103
|
+
let y = y_ * ns.x + vec4<f32>(ns.y, ns.y, ns.y, ns.y);
|
|
104
|
+
let h = 1.0 - abs(x) - abs(y);
|
|
105
|
+
|
|
106
|
+
let b0 = vec4<f32>(x.x, x.y, y.x, y.y);
|
|
107
|
+
let b1 = vec4<f32>(x.z, x.w, y.z, y.w);
|
|
108
|
+
|
|
109
|
+
let s0 = floor(b0) * 2.0 + 1.0;
|
|
110
|
+
let s1 = floor(b1) * 2.0 + 1.0;
|
|
111
|
+
let sh = -step(h, vec4<f32>(0.0));
|
|
112
|
+
|
|
113
|
+
let a0 = vec4<f32>(b0.x, b0.z, b0.y, b0.w) + vec4<f32>(s0.x, s0.z, s0.y, s0.w) * vec4<f32>(sh.x, sh.x, sh.y, sh.y);
|
|
114
|
+
let a1 = vec4<f32>(b1.x, b1.z, b1.y, b1.w) + vec4<f32>(s1.x, s1.z, s1.y, s1.w) * vec4<f32>(sh.z, sh.z, sh.w, sh.w);
|
|
115
|
+
|
|
116
|
+
let p0 = vec3<f32>(a0.x, a0.y, h.x);
|
|
117
|
+
let p1 = vec3<f32>(a0.z, a0.w, h.y);
|
|
118
|
+
let p2 = vec3<f32>(a1.x, a1.y, h.z);
|
|
119
|
+
let p3 = vec3<f32>(a1.z, a1.w, h.w);
|
|
120
|
+
|
|
121
|
+
let norm = inverseSqrt(vec4<f32>(dot(p0, p0), dot(p1, p1), dot(p2, p2), dot(p3, p3)));
|
|
122
|
+
let p0n = p0 * norm.x;
|
|
123
|
+
let p1n = p1 * norm.y;
|
|
124
|
+
let p2n = p2 * norm.z;
|
|
125
|
+
let p3n = p3 * norm.w;
|
|
126
|
+
|
|
127
|
+
var m = max(0.6 - vec4<f32>(dot(x0, x0), dot(x1, x1), dot(x2, x2), dot(x3, x3)), vec4<f32>(0.0));
|
|
128
|
+
m = m * m;
|
|
129
|
+
return 42.0 * dot(m * m, vec4<f32>(dot(p0n, x0), dot(p1n, x1), dot(p2n, x2), dot(p3n, x3)));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
fn prng(seed: vec2<f32>) -> f32 {
|
|
133
|
+
var s = fract(seed * vec2<f32>(5.3983, 5.4427));
|
|
134
|
+
s = s + dot(vec2<f32>(s.y, s.x), s + vec2<f32>(21.5351, 14.3137));
|
|
135
|
+
return fract(s.x * s.y * 95.4337);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
const PI = 3.1415926535897932384626433832795;
|
|
139
|
+
|
|
140
|
+
fn noiseStack(pos: vec3<f32>, octaves: i32, falloff: f32) -> f32 {
|
|
141
|
+
var noise = snoise(pos);
|
|
142
|
+
var off = 1.0;
|
|
143
|
+
var p = pos;
|
|
144
|
+
|
|
145
|
+
if (octaves > 1) {
|
|
146
|
+
p = p * 2.0;
|
|
147
|
+
off = off * falloff;
|
|
148
|
+
noise = (1.0 - off) * noise + off * snoise(p);
|
|
149
|
+
}
|
|
150
|
+
if (octaves > 2) {
|
|
151
|
+
p = p * 2.0;
|
|
152
|
+
off = off * falloff;
|
|
153
|
+
noise = (1.0 - off) * noise + off * snoise(p);
|
|
154
|
+
}
|
|
155
|
+
if (octaves > 3) {
|
|
156
|
+
p = p * 2.0;
|
|
157
|
+
off = off * falloff;
|
|
158
|
+
noise = (1.0 - off) * noise + off * snoise(p);
|
|
159
|
+
}
|
|
160
|
+
return (1.0 + noise) / 2.0;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
fn noiseStackUV(pos: vec3<f32>, octaves: i32, falloff: f32) -> vec2<f32> {
|
|
164
|
+
let displaceA = noiseStack(pos, octaves, falloff);
|
|
165
|
+
let displaceB = noiseStack(pos + vec3<f32>(3984.293, 423.21, 5235.19), octaves, falloff);
|
|
166
|
+
return vec2<f32>(displaceA, displaceB);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
@fragment
|
|
170
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
171
|
+
let time = u.time.x;
|
|
172
|
+
let sparkSize = u.params0.x;
|
|
173
|
+
let fireIntensity = u.params0.y;
|
|
174
|
+
let smokeIntensity = u.params0.z;
|
|
175
|
+
|
|
176
|
+
let resolution = u.resolution.xy;
|
|
177
|
+
let vUv = ndc * 0.5 + vec2<f32>(0.5, 0.5);
|
|
178
|
+
let fragCoord = vUv * resolution;
|
|
179
|
+
|
|
180
|
+
let xpart = fragCoord.x / resolution.x;
|
|
181
|
+
let ypart = fragCoord.y / resolution.y;
|
|
182
|
+
|
|
183
|
+
let clip = 210.0;
|
|
184
|
+
let ypartClip = fragCoord.y / clip;
|
|
185
|
+
let ypartClippedFalloff = clamp(2.0 - ypartClip, 0.0, 1.0);
|
|
186
|
+
let ypartClipped = min(ypartClip, 1.0);
|
|
187
|
+
let ypartClippedn = 1.0 - ypartClipped;
|
|
188
|
+
|
|
189
|
+
let xfuel = 1.0 - abs(2.0 * xpart - 1.0);
|
|
190
|
+
|
|
191
|
+
let timeSpeed = 0.5;
|
|
192
|
+
let realTime = timeSpeed * time;
|
|
193
|
+
|
|
194
|
+
let coordScaled = 0.01 * fragCoord;
|
|
195
|
+
let position = vec3<f32>(coordScaled, 0.0) + vec3<f32>(1223.0, 6434.0, 8425.0);
|
|
196
|
+
let flow = vec3<f32>(4.1 * (0.5 - xpart) * pow(ypartClippedn, 4.0), -2.0 * xfuel * pow(ypartClippedn, 64.0), 0.0);
|
|
197
|
+
let timing = realTime * vec3<f32>(0.0, -1.7, 1.1) + flow;
|
|
198
|
+
|
|
199
|
+
let displacePos = vec3<f32>(1.0, 0.5, 1.0) * 2.4 * position + realTime * vec3<f32>(0.01, -0.7, 1.3);
|
|
200
|
+
let displace3 = vec3<f32>(noiseStackUV(displacePos, 2, 0.4), 0.0);
|
|
201
|
+
|
|
202
|
+
let noiseCoord = (vec3<f32>(2.0, 1.0, 1.0) * position + timing + 0.4 * displace3) / 1.0;
|
|
203
|
+
let noise = noiseStack(noiseCoord, 3, 0.4);
|
|
204
|
+
|
|
205
|
+
let flames = pow(ypartClipped, 0.3 * xfuel) * pow(noise, 0.3 * xfuel);
|
|
206
|
+
|
|
207
|
+
let f = ypartClippedFalloff * pow(1.0 - flames * flames * flames, 8.0);
|
|
208
|
+
let fff = f * f * f;
|
|
209
|
+
var fire = 1.5 * vec3<f32>(f, fff, fff * fff) * fireIntensity;
|
|
210
|
+
|
|
211
|
+
let smokeNoise = 0.5 + snoise(0.4 * position + timing * vec3<f32>(1.0, 1.0, 0.2)) / 2.0;
|
|
212
|
+
let smoke = vec3<f32>(0.3 * pow(xfuel, 3.0) * pow(ypart, 2.0) * (smokeNoise + 0.4 * (1.0 - noise))) * smokeIntensity;
|
|
213
|
+
|
|
214
|
+
let sparkGridSize = 30.0;
|
|
215
|
+
var sparkCoord = fragCoord - vec2<f32>(0.0, 190.0 * realTime);
|
|
216
|
+
sparkCoord = sparkCoord - 30.0 * noiseStackUV(0.01 * vec3<f32>(sparkCoord, 30.0 * time), 1, 0.4);
|
|
217
|
+
sparkCoord = sparkCoord + 100.0 * flow.xy;
|
|
218
|
+
|
|
219
|
+
if (sparkCoord.y / sparkGridSize % 2.0 < 1.0) {
|
|
220
|
+
sparkCoord.x = sparkCoord.x + 0.5 * sparkGridSize;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
let sparkGridIndex = vec2<f32>(floor(sparkCoord / sparkGridSize));
|
|
224
|
+
let sparkRandom = prng(sparkGridIndex);
|
|
225
|
+
let sparkLife = min(10.0 * (1.0 - min((sparkGridIndex.y + (190.0 * realTime / sparkGridSize)) / (24.0 - 20.0 * sparkRandom), 1.0)), 1.0);
|
|
226
|
+
|
|
227
|
+
var sparks = vec3<f32>(0.0);
|
|
228
|
+
if (sparkLife > 0.0) {
|
|
229
|
+
let sparkSizeScaled = xfuel * xfuel * sparkRandom * 0.08 * sparkSize;
|
|
230
|
+
let sparkRadians = 999.0 * sparkRandom * 2.0 * PI + 2.0 * time;
|
|
231
|
+
let sparkCircular = vec2<f32>(sin(sparkRadians), cos(sparkRadians));
|
|
232
|
+
let sparkOffset = (0.5 - sparkSizeScaled) * sparkGridSize * sparkCircular;
|
|
233
|
+
let sparkModulus = (sparkCoord + sparkOffset) % sparkGridSize - 0.5 * vec2<f32>(sparkGridSize);
|
|
234
|
+
let sparkLength = length(sparkModulus);
|
|
235
|
+
let sparksGray = max(0.0, 1.0 - sparkLength / (sparkSizeScaled * sparkGridSize));
|
|
236
|
+
sparks = sparkLife * sparksGray * vec3<f32>(1.0, 0.3, 0.0);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
fire = fire * u.color0.rgb;
|
|
240
|
+
|
|
241
|
+
let finalColor = max(fire, sparks) + smoke;
|
|
242
|
+
return vec4<f32>(clamp(finalColor, vec3<f32>(0.0), vec3<f32>(1.0)), u.color0.a);
|
|
243
|
+
}
|
|
244
|
+
`;
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { ColorInput } from '../utils/colors';
|
|
4
|
+
import ShaderView from './ShaderView';
|
|
5
|
+
|
|
6
|
+
type Props = ViewProps & {
|
|
7
|
+
/** The color at the center of the gradient. */
|
|
8
|
+
centerColor: ColorInput;
|
|
9
|
+
/** The color at the edge of the gradient. Default: transparent */
|
|
10
|
+
edgeColor?: ColorInput;
|
|
11
|
+
/** Horizontal center position (0-1). Default: 0.5 */
|
|
12
|
+
centerX?: number;
|
|
13
|
+
/** Vertical center position (0-1). Default: 0.5 */
|
|
14
|
+
centerY?: number;
|
|
15
|
+
/** Horizontal radius. Default: 0.5 */
|
|
16
|
+
sizeX?: number;
|
|
17
|
+
/** Vertical radius. Default: 0.5 */
|
|
18
|
+
sizeY?: number;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export default function CircularGradient({
|
|
22
|
+
centerColor,
|
|
23
|
+
edgeColor = 'rgba(0,0,0,0)',
|
|
24
|
+
centerX = 0.5,
|
|
25
|
+
centerY = 0.5,
|
|
26
|
+
sizeX = 0.5,
|
|
27
|
+
sizeY = 0.5,
|
|
28
|
+
...viewProps
|
|
29
|
+
}: Props) {
|
|
30
|
+
const colors = useMemo(
|
|
31
|
+
() => [centerColor, edgeColor],
|
|
32
|
+
[centerColor, edgeColor]
|
|
33
|
+
);
|
|
34
|
+
const params = useMemo(
|
|
35
|
+
() => [centerX, centerY, sizeX, sizeY],
|
|
36
|
+
[centerX, centerY, sizeX, sizeY]
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<ShaderView
|
|
41
|
+
fragmentShader={CIRCULAR_GRADIENT_SHADER}
|
|
42
|
+
colors={colors}
|
|
43
|
+
params={params}
|
|
44
|
+
isStatic={true}
|
|
45
|
+
{...viewProps}
|
|
46
|
+
/>
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const CIRCULAR_GRADIENT_SHADER = /* wgsl */ `
|
|
51
|
+
struct Uniforms {
|
|
52
|
+
resolution: vec4<f32>,
|
|
53
|
+
time: vec4<f32>,
|
|
54
|
+
color0: vec4<f32>,
|
|
55
|
+
color1: vec4<f32>,
|
|
56
|
+
params0: vec4<f32>,
|
|
57
|
+
params1: vec4<f32>,
|
|
58
|
+
};
|
|
59
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
60
|
+
|
|
61
|
+
@fragment
|
|
62
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
63
|
+
let uv = (ndc * 0.5) + vec2<f32>(0.5, 0.5);
|
|
64
|
+
|
|
65
|
+
let center = u.params0.xy;
|
|
66
|
+
let size = u.params0.zw;
|
|
67
|
+
|
|
68
|
+
let diff = uv - center;
|
|
69
|
+
let normalizedDiff = diff / size;
|
|
70
|
+
let dist = length(normalizedDiff);
|
|
71
|
+
|
|
72
|
+
let t = smoothstep(0.0, 1.0, dist);
|
|
73
|
+
let color = mix(u.color0, u.color1, t);
|
|
74
|
+
return color;
|
|
75
|
+
}
|
|
76
|
+
`;
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { ColorInput } from '../utils/colors';
|
|
4
|
+
import ShaderView from './ShaderView';
|
|
5
|
+
|
|
6
|
+
type Props = ViewProps & {
|
|
7
|
+
/** The color tint for the iridescence effect. */
|
|
8
|
+
color?: ColorInput;
|
|
9
|
+
/** Animation speed multiplier. Default: 1.0 */
|
|
10
|
+
speed?: number;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default function Iridescence({
|
|
14
|
+
color = '#ffffff',
|
|
15
|
+
speed = 1.0,
|
|
16
|
+
...viewProps
|
|
17
|
+
}: Props) {
|
|
18
|
+
const colors = useMemo(() => [color], [color]);
|
|
19
|
+
|
|
20
|
+
return (
|
|
21
|
+
<ShaderView
|
|
22
|
+
fragmentShader={IRIDESCENCE_SHADER}
|
|
23
|
+
colors={colors}
|
|
24
|
+
params={[]}
|
|
25
|
+
speed={speed}
|
|
26
|
+
isStatic={false}
|
|
27
|
+
{...viewProps}
|
|
28
|
+
/>
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const IRIDESCENCE_SHADER = /* wgsl */ `
|
|
33
|
+
struct Uniforms {
|
|
34
|
+
resolution: vec4<f32>,
|
|
35
|
+
time: vec4<f32>,
|
|
36
|
+
color0: vec4<f32>,
|
|
37
|
+
color1: vec4<f32>,
|
|
38
|
+
params0: vec4<f32>,
|
|
39
|
+
params1: vec4<f32>,
|
|
40
|
+
};
|
|
41
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
42
|
+
|
|
43
|
+
@fragment
|
|
44
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
45
|
+
let time = u.time.x;
|
|
46
|
+
|
|
47
|
+
let vUv = ndc * 0.5 + vec2<f32>(0.5, 0.5);
|
|
48
|
+
let mr = min(u.resolution.x, u.resolution.y);
|
|
49
|
+
var uv = (vUv * 2.0 - vec2<f32>(1.0, 1.0)) * (u.resolution.xy / mr);
|
|
50
|
+
|
|
51
|
+
var d = -time * 0.5;
|
|
52
|
+
var a = 0.0;
|
|
53
|
+
for (var i: f32 = 0.0; i < 8.0; i = i + 1.0) {
|
|
54
|
+
a = a + cos(i - d - a * uv.x);
|
|
55
|
+
d = d + sin(uv.y * i + a);
|
|
56
|
+
}
|
|
57
|
+
d = d + time * 0.5;
|
|
58
|
+
|
|
59
|
+
let c1 = cos(uv * vec2<f32>(d, a)) * 0.6 + 0.4;
|
|
60
|
+
let c2 = cos(a + d) * 0.5 + 0.5;
|
|
61
|
+
let col = vec3<f32>(c1.x, c1.y, c2);
|
|
62
|
+
|
|
63
|
+
let finalCol = cos(col * cos(vec3<f32>(d, a, 2.5)) * 0.5 + 0.5);
|
|
64
|
+
let coloredCol = finalCol * u.color0.rgb;
|
|
65
|
+
return vec4<f32>(clamp(coloredCol, vec3<f32>(0.0), vec3<f32>(1.0)), u.color0.a);
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { ColorInput } from '../utils/colors';
|
|
4
|
+
import ShaderView from './ShaderView';
|
|
5
|
+
|
|
6
|
+
type Props = ViewProps & {
|
|
7
|
+
/** The color of the start of the gradient. */
|
|
8
|
+
startColor: ColorInput;
|
|
9
|
+
/** The color of the end of the gradient. */
|
|
10
|
+
endColor: ColorInput;
|
|
11
|
+
/** The angle of the gradient in degrees (0-360). */
|
|
12
|
+
angle: number;
|
|
13
|
+
/** Rotation speed in degrees/second. 0 = static. Default: 0 */
|
|
14
|
+
speed?: number;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export default function LinearGradient({
|
|
18
|
+
startColor,
|
|
19
|
+
endColor,
|
|
20
|
+
angle,
|
|
21
|
+
speed = 0,
|
|
22
|
+
...viewProps
|
|
23
|
+
}: Props) {
|
|
24
|
+
const colors = useMemo(() => [startColor, endColor], [startColor, endColor]);
|
|
25
|
+
const params = useMemo(() => [angle, speed], [angle, speed]);
|
|
26
|
+
|
|
27
|
+
return (
|
|
28
|
+
<ShaderView
|
|
29
|
+
fragmentShader={LINEAR_GRADIENT_SHADER}
|
|
30
|
+
colors={colors}
|
|
31
|
+
params={params}
|
|
32
|
+
speed={speed === 0 ? 0 : 1}
|
|
33
|
+
isStatic={speed === 0}
|
|
34
|
+
{...viewProps}
|
|
35
|
+
/>
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
const LINEAR_GRADIENT_SHADER = /* wgsl */ `
|
|
40
|
+
struct Uniforms {
|
|
41
|
+
resolution: vec4<f32>,
|
|
42
|
+
time: vec4<f32>,
|
|
43
|
+
color0: vec4<f32>,
|
|
44
|
+
color1: vec4<f32>,
|
|
45
|
+
params0: vec4<f32>,
|
|
46
|
+
params1: vec4<f32>,
|
|
47
|
+
};
|
|
48
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
49
|
+
|
|
50
|
+
@fragment
|
|
51
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
52
|
+
let uv = ndc * 0.5 + vec2<f32>(0.5, 0.5);
|
|
53
|
+
let baseAngle = u.params0.x;
|
|
54
|
+
let rotationSpeed = u.params0.y;
|
|
55
|
+
let angle = (baseAngle + u.time.x * rotationSpeed) * 3.14159265359 / 180.0;
|
|
56
|
+
let dir = vec2<f32>(cos(angle), sin(angle));
|
|
57
|
+
let fromCenter = uv - vec2<f32>(0.5, 0.5);
|
|
58
|
+
let corrected = vec2<f32>(fromCenter.x * u.resolution.z, fromCenter.y);
|
|
59
|
+
let t = clamp(dot(corrected, dir) + 0.5, 0.0, 1.0);
|
|
60
|
+
return mix(u.color0, u.color1, t);
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import type { ViewProps } from 'react-native';
|
|
3
|
+
import type { ColorInput } from '../utils/colors';
|
|
4
|
+
import ShaderView from './ShaderView';
|
|
5
|
+
|
|
6
|
+
type Props = ViewProps & {
|
|
7
|
+
/** The base color for the liquid chrome effect. */
|
|
8
|
+
color?: ColorInput;
|
|
9
|
+
/** Animation speed multiplier. Default: 0.2 */
|
|
10
|
+
speed?: number;
|
|
11
|
+
/** Amplitude of the distortion. Default: 0.3 */
|
|
12
|
+
amplitude?: number;
|
|
13
|
+
/** Horizontal frequency. Default: 3 */
|
|
14
|
+
frequencyX?: number;
|
|
15
|
+
/** Vertical frequency. Default: 3 */
|
|
16
|
+
frequencyY?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function LiquidChrome({
|
|
20
|
+
color = '#1a1a1a',
|
|
21
|
+
speed = 0.2,
|
|
22
|
+
amplitude = 0.3,
|
|
23
|
+
frequencyX = 3,
|
|
24
|
+
frequencyY = 3,
|
|
25
|
+
...viewProps
|
|
26
|
+
}: Props) {
|
|
27
|
+
const colors = useMemo(() => [color], [color]);
|
|
28
|
+
const params = useMemo(
|
|
29
|
+
() => [amplitude, frequencyX, frequencyY],
|
|
30
|
+
[amplitude, frequencyX, frequencyY]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ShaderView
|
|
35
|
+
fragmentShader={LIQUID_CHROME_SHADER}
|
|
36
|
+
colors={colors}
|
|
37
|
+
params={params}
|
|
38
|
+
speed={speed}
|
|
39
|
+
isStatic={false}
|
|
40
|
+
{...viewProps}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const LIQUID_CHROME_SHADER = /* wgsl */ `
|
|
46
|
+
struct Uniforms {
|
|
47
|
+
resolution: vec4<f32>,
|
|
48
|
+
time: vec4<f32>,
|
|
49
|
+
color0: vec4<f32>,
|
|
50
|
+
color1: vec4<f32>,
|
|
51
|
+
params0: vec4<f32>,
|
|
52
|
+
params1: vec4<f32>,
|
|
53
|
+
};
|
|
54
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
55
|
+
|
|
56
|
+
fn renderImage(uvCoord: vec2<f32>) -> vec4<f32> {
|
|
57
|
+
let resolution2D = u.resolution.xy;
|
|
58
|
+
let time = u.time.x;
|
|
59
|
+
let amplitude = u.params0.x;
|
|
60
|
+
let frequencyX = u.params0.y;
|
|
61
|
+
let frequencyY = u.params0.z;
|
|
62
|
+
|
|
63
|
+
let fragCoord = uvCoord * resolution2D;
|
|
64
|
+
var uv = (2.0 * fragCoord - resolution2D) / min(u.resolution.x, u.resolution.y);
|
|
65
|
+
|
|
66
|
+
for (var i: f32 = 1.0; i < 10.0; i = i + 1.0) {
|
|
67
|
+
uv.x = uv.x + amplitude / i * cos(i * frequencyX * uv.y + time);
|
|
68
|
+
uv.y = uv.y + amplitude / i * cos(i * frequencyY * uv.x + time);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
let baseColor = u.color0;
|
|
72
|
+
let color = baseColor.rgb / abs(sin(time - uv.y - uv.x));
|
|
73
|
+
return vec4<f32>(color, baseColor.a);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
@fragment
|
|
77
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
78
|
+
let vUv = ndc * 0.5 + vec2<f32>(0.5, 0.5);
|
|
79
|
+
let resolution2D = u.resolution.xy;
|
|
80
|
+
|
|
81
|
+
var col = vec4<f32>(0.0);
|
|
82
|
+
var samples = 0;
|
|
83
|
+
|
|
84
|
+
for (var i: i32 = -1; i <= 1; i = i + 1) {
|
|
85
|
+
for (var j: i32 = -1; j <= 1; j = j + 1) {
|
|
86
|
+
let offset = vec2<f32>(f32(i), f32(j)) * (1.0 / min(resolution2D.x, resolution2D.y));
|
|
87
|
+
col = col + renderImage(vUv + offset);
|
|
88
|
+
samples = samples + 1;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return col / f32(samples);
|
|
93
|
+
}
|
|
94
|
+
`;
|