react-native-effects 0.0.1 → 0.2.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 +313 -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 +252 -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/ShaderViewWithPanGesture/index.js +196 -0
- package/lib/module/components/ShaderViewWithPanGesture/index.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/useParamsSynchronizable.js +37 -0
- package/lib/module/hooks/useParamsSynchronizable.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 +15 -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 +21 -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 +35 -0
- package/lib/typescript/src/components/ShaderView/types.d.ts.map +1 -0
- package/lib/typescript/src/components/ShaderViewWithPanGesture/index.d.ts +35 -0
- package/lib/typescript/src/components/ShaderViewWithPanGesture/index.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/useParamsSynchronizable.d.ts +22 -0
- package/lib/typescript/src/hooks/useParamsSynchronizable.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 +16 -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 +175 -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 +262 -0
- package/src/components/ShaderView/types.ts +36 -0
- package/src/components/ShaderViewWithPanGesture/index.tsx +225 -0
- package/src/components/Silk.tsx +102 -0
- package/src/consts.ts +152 -0
- package/src/hooks/useClock.ts +20 -0
- package/src/hooks/useParamsSynchronizable.ts +52 -0
- package/src/hooks/useWGPUSetup.tsx +73 -0
- package/src/index.tsx +32 -0
- package/src/shaders/TRIANGLE_VERTEX_SHADER.ts +17 -0
- package/src/shaders/uniforms.ts +18 -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,203 @@
|
|
|
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
|
+
/** Base tint color for the aurora effect. */
|
|
8
|
+
color?: ColorInput;
|
|
9
|
+
/** Animation speed multiplier. Default: 1.0 */
|
|
10
|
+
speed?: number;
|
|
11
|
+
/** Brightness of the aurora bands. Default: 1.0 */
|
|
12
|
+
intensity?: number;
|
|
13
|
+
/** Number of aurora curtain layers (1-5). Default: 3 */
|
|
14
|
+
layers?: number;
|
|
15
|
+
/** How wavy/turbulent the curtains are. Default: 1.0 */
|
|
16
|
+
waviness?: number;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export default function Aurora({
|
|
20
|
+
color = '#4ade80',
|
|
21
|
+
speed = 1.0,
|
|
22
|
+
intensity = 1.0,
|
|
23
|
+
layers = 3.0,
|
|
24
|
+
waviness = 1.0,
|
|
25
|
+
...viewProps
|
|
26
|
+
}: Props) {
|
|
27
|
+
const colors = useMemo(() => [color], [color]);
|
|
28
|
+
const params = useMemo(
|
|
29
|
+
() => [intensity, layers, waviness],
|
|
30
|
+
[intensity, layers, waviness]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return (
|
|
34
|
+
<ShaderView
|
|
35
|
+
fragmentShader={AURORA_SHADER}
|
|
36
|
+
colors={colors}
|
|
37
|
+
params={params}
|
|
38
|
+
speed={speed}
|
|
39
|
+
isStatic={false}
|
|
40
|
+
{...viewProps}
|
|
41
|
+
/>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
const AURORA_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
|
+
// Hash function for pseudo-random values
|
|
57
|
+
fn hash(p: vec2<f32>) -> f32 {
|
|
58
|
+
var p3 = fract(vec3<f32>(p.x, p.y, p.x) * 0.13);
|
|
59
|
+
p3 += dot(p3, vec3<f32>(p3.y + 3.333, p3.z + 3.333, p3.x + 3.333));
|
|
60
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 2D noise
|
|
64
|
+
fn noise(p: vec2<f32>) -> f32 {
|
|
65
|
+
let i = floor(p);
|
|
66
|
+
let f = fract(p);
|
|
67
|
+
let u_s = f * f * (3.0 - 2.0 * f);
|
|
68
|
+
|
|
69
|
+
let a = hash(i);
|
|
70
|
+
let b = hash(i + vec2<f32>(1.0, 0.0));
|
|
71
|
+
let c = hash(i + vec2<f32>(0.0, 1.0));
|
|
72
|
+
let d = hash(i + vec2<f32>(1.0, 1.0));
|
|
73
|
+
|
|
74
|
+
return mix(mix(a, b, u_s.x), mix(c, d, u_s.x), u_s.y);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Fractional Brownian Motion
|
|
78
|
+
fn fbm(p_in: vec2<f32>, octaves: i32) -> f32 {
|
|
79
|
+
var p = p_in;
|
|
80
|
+
var value = 0.0;
|
|
81
|
+
var amplitude = 0.5;
|
|
82
|
+
var frequency = 1.0;
|
|
83
|
+
|
|
84
|
+
for (var i = 0; i < octaves; i++) {
|
|
85
|
+
value += amplitude * noise(p * frequency);
|
|
86
|
+
p = p * 2.01 + vec2<f32>(1.7, 9.2);
|
|
87
|
+
amplitude *= 0.5;
|
|
88
|
+
frequency *= 1.0;
|
|
89
|
+
}
|
|
90
|
+
return value;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// Single aurora curtain layer
|
|
94
|
+
fn auroraLayer(uv: vec2<f32>, time: f32, offset: f32, waviness: f32) -> f32 {
|
|
95
|
+
// Horizontal position with time-based drift
|
|
96
|
+
let drift = time * 0.15 + offset * 2.5;
|
|
97
|
+
|
|
98
|
+
// Create the curtain shape using sine waves
|
|
99
|
+
let wave1 = sin(uv.x * 2.0 * waviness + drift + offset * 6.0) * 0.3;
|
|
100
|
+
let wave2 = sin(uv.x * 3.5 * waviness + drift * 1.3 + offset * 4.0) * 0.15;
|
|
101
|
+
let wave3 = sin(uv.x * 7.0 * waviness + drift * 0.7 + offset * 8.0) * 0.08;
|
|
102
|
+
|
|
103
|
+
// FBM noise for organic turbulence
|
|
104
|
+
let noiseVal = fbm(vec2<f32>(uv.x * 1.5 * waviness + drift * 0.5, uv.y * 0.8 + offset * 3.0), 4);
|
|
105
|
+
|
|
106
|
+
// Curtain center position (wavy vertical line)
|
|
107
|
+
let curtainCenter = 0.5 + wave1 + wave2 + wave3 + (noiseVal - 0.5) * 0.25 * waviness;
|
|
108
|
+
|
|
109
|
+
// Distance from curtain center for glow
|
|
110
|
+
let dist = abs(uv.y - curtainCenter);
|
|
111
|
+
|
|
112
|
+
// Soft glow falloff
|
|
113
|
+
let glow = exp(-dist * dist * 15.0) * 0.8;
|
|
114
|
+
|
|
115
|
+
// Add shimmer using noise
|
|
116
|
+
let shimmer = fbm(vec2<f32>(uv.x * 4.0 + time * 0.3, uv.y * 8.0 + offset * 5.0), 3);
|
|
117
|
+
let shimmerEffect = glow * (0.7 + 0.3 * shimmer);
|
|
118
|
+
|
|
119
|
+
// Fade toward bottom of screen (aurora appears in upper portion)
|
|
120
|
+
let heightFade = smoothstep(0.0, 0.6, uv.y);
|
|
121
|
+
|
|
122
|
+
return shimmerEffect * heightFade;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Stars in the background
|
|
126
|
+
fn stars(uv: vec2<f32>, time: f32) -> f32 {
|
|
127
|
+
let grid = floor(uv * 50.0);
|
|
128
|
+
let h = hash(grid);
|
|
129
|
+
|
|
130
|
+
// Only show some cells as stars
|
|
131
|
+
let star = step(0.92, h);
|
|
132
|
+
|
|
133
|
+
// Twinkle effect
|
|
134
|
+
let twinkle = 0.5 + 0.5 * sin(time * (1.0 + h * 3.0) + h * 6.28);
|
|
135
|
+
|
|
136
|
+
let cellUv = fract(uv * 50.0) - 0.5;
|
|
137
|
+
let d = length(cellUv);
|
|
138
|
+
let point = exp(-d * d * 80.0);
|
|
139
|
+
|
|
140
|
+
return point * star * twinkle * 0.6;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
@fragment
|
|
144
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
145
|
+
let time = u.time.x;
|
|
146
|
+
let intensity = u.params0.x;
|
|
147
|
+
let layerCount = u.params0.y;
|
|
148
|
+
let waviness = u.params0.z;
|
|
149
|
+
|
|
150
|
+
// Map NDC (-1..1) to UV (0..1)
|
|
151
|
+
let uv = ndc * 0.5 + 0.5;
|
|
152
|
+
|
|
153
|
+
// Dark sky background
|
|
154
|
+
let skyTop = vec3<f32>(0.0, 0.0, 0.02);
|
|
155
|
+
let skyBottom = vec3<f32>(0.01, 0.01, 0.04);
|
|
156
|
+
var col = mix(skyBottom, skyTop, uv.y);
|
|
157
|
+
|
|
158
|
+
// Add stars
|
|
159
|
+
let starVal = stars(uv, time);
|
|
160
|
+
// Dim stars where aurora is bright (computed later)
|
|
161
|
+
var auroraTotal = 0.0;
|
|
162
|
+
|
|
163
|
+
// Aurora color palette
|
|
164
|
+
let green = vec3<f32>(0.2, 0.9, 0.4);
|
|
165
|
+
let cyan = vec3<f32>(0.1, 0.7, 0.8);
|
|
166
|
+
let purple = vec3<f32>(0.5, 0.2, 0.8);
|
|
167
|
+
let pink = vec3<f32>(0.7, 0.2, 0.5);
|
|
168
|
+
|
|
169
|
+
// Accumulate aurora layers
|
|
170
|
+
let numLayers = i32(clamp(layerCount, 1.0, 5.0));
|
|
171
|
+
|
|
172
|
+
for (var i = 0; i < 5; i++) {
|
|
173
|
+
if (i >= numLayers) { break; }
|
|
174
|
+
|
|
175
|
+
let fi = f32(i);
|
|
176
|
+
let layerOffset = fi * 0.7;
|
|
177
|
+
|
|
178
|
+
let layer = auroraLayer(uv, time, layerOffset, waviness);
|
|
179
|
+
|
|
180
|
+
// Color varies per layer and position
|
|
181
|
+
let colorPhase = fi / f32(numLayers) + uv.x * 0.3 + time * 0.02;
|
|
182
|
+
let c1 = mix(green, cyan, sin(colorPhase * 3.14) * 0.5 + 0.5);
|
|
183
|
+
let c2 = mix(purple, pink, cos(colorPhase * 2.5) * 0.5 + 0.5);
|
|
184
|
+
let layerColor = mix(c1, c2, sin(colorPhase * 2.0 + fi) * 0.5 + 0.5);
|
|
185
|
+
|
|
186
|
+
col += layerColor * layer * intensity * (1.0 / f32(numLayers)) * 2.5;
|
|
187
|
+
auroraTotal += layer;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Add stars (dimmed where aurora is bright)
|
|
191
|
+
let starDim = max(0.0, 1.0 - auroraTotal * 2.0);
|
|
192
|
+
col += vec3<f32>(starVal * starDim);
|
|
193
|
+
|
|
194
|
+
// Apply tint color
|
|
195
|
+
col *= u.color0.rgb;
|
|
196
|
+
|
|
197
|
+
// Tone mapping - prevent over-saturation
|
|
198
|
+
col = col / (col + vec3<f32>(1.0));
|
|
199
|
+
col = pow(col, vec3<f32>(0.9));
|
|
200
|
+
|
|
201
|
+
return vec4<f32>(col, u.color0.a);
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
@@ -0,0 +1,167 @@
|
|
|
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 calico swirl effect. */
|
|
8
|
+
color?: ColorInput;
|
|
9
|
+
/** Animation speed multiplier. Default: 1.0 */
|
|
10
|
+
speed?: number;
|
|
11
|
+
/** Intensity of the effect. Default: 1.0 */
|
|
12
|
+
intensity?: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export default function CalicoSwirl({
|
|
16
|
+
color = '#ffffff',
|
|
17
|
+
speed = 1.0,
|
|
18
|
+
intensity = 1.0,
|
|
19
|
+
...viewProps
|
|
20
|
+
}: Props) {
|
|
21
|
+
const colors = useMemo(() => [color], [color]);
|
|
22
|
+
const params = useMemo(() => [intensity], [intensity]);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ShaderView
|
|
26
|
+
fragmentShader={CALICO_SWIRL_SHADER}
|
|
27
|
+
colors={colors}
|
|
28
|
+
params={params}
|
|
29
|
+
speed={speed}
|
|
30
|
+
isStatic={false}
|
|
31
|
+
{...viewProps}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const CALICO_SWIRL_SHADER = /* wgsl */ `
|
|
37
|
+
struct Uniforms {
|
|
38
|
+
resolution: vec4<f32>,
|
|
39
|
+
time: vec4<f32>,
|
|
40
|
+
color0: vec4<f32>,
|
|
41
|
+
color1: vec4<f32>,
|
|
42
|
+
params0: vec4<f32>,
|
|
43
|
+
params1: vec4<f32>,
|
|
44
|
+
};
|
|
45
|
+
@group(0) @binding(0) var<uniform> u: Uniforms;
|
|
46
|
+
|
|
47
|
+
const m = mat2x2<f32>(0.80, 0.60, -0.60, 0.80);
|
|
48
|
+
|
|
49
|
+
fn noise(p: vec2<f32>) -> f32 {
|
|
50
|
+
return sin(p.x) * sin(p.y);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
fn fbm4(p_in: vec2<f32>) -> f32 {
|
|
54
|
+
var p = p_in;
|
|
55
|
+
var f = 0.0;
|
|
56
|
+
f += 0.5000 * noise(p);
|
|
57
|
+
p = m * p * 2.02;
|
|
58
|
+
f += 0.2500 * noise(p);
|
|
59
|
+
p = m * p * 2.03;
|
|
60
|
+
f += 0.1250 * noise(p);
|
|
61
|
+
p = m * p * 2.01;
|
|
62
|
+
f += 0.0625 * noise(p);
|
|
63
|
+
return f / 0.9375;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
fn fbm6(p_in: vec2<f32>) -> f32 {
|
|
67
|
+
var p = p_in;
|
|
68
|
+
var f = 0.0;
|
|
69
|
+
f += 0.500000 * (0.5 + 0.5 * noise(p));
|
|
70
|
+
p = m * p * 2.02;
|
|
71
|
+
f += 0.250000 * (0.5 + 0.5 * noise(p));
|
|
72
|
+
p = m * p * 2.03;
|
|
73
|
+
f += 0.125000 * (0.5 + 0.5 * noise(p));
|
|
74
|
+
p = m * p * 2.01;
|
|
75
|
+
f += 0.062500 * (0.5 + 0.5 * noise(p));
|
|
76
|
+
p = m * p * 2.04;
|
|
77
|
+
f += 0.031250 * (0.5 + 0.5 * noise(p));
|
|
78
|
+
p = m * p * 2.01;
|
|
79
|
+
f += 0.015625 * (0.5 + 0.5 * noise(p));
|
|
80
|
+
return f / 0.96875;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fn fbm4_2(p: vec2<f32>) -> vec2<f32> {
|
|
84
|
+
return vec2<f32>(fbm4(p), fbm4(p + vec2<f32>(7.8)));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
fn fbm6_2(p: vec2<f32>) -> vec2<f32> {
|
|
88
|
+
return vec2<f32>(fbm6(p + vec2<f32>(16.8)), fbm6(p + vec2<f32>(11.5)));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fn func(q: vec2<f32>, time: f32) -> vec4<f32> {
|
|
92
|
+
var q_mod = q;
|
|
93
|
+
q_mod += 0.03 * sin(vec2<f32>(0.27, 0.23) * time + length(q) * vec2<f32>(4.1, 4.3));
|
|
94
|
+
|
|
95
|
+
let o = fbm4_2(0.9 * q_mod);
|
|
96
|
+
|
|
97
|
+
var o_mod = o;
|
|
98
|
+
o_mod += 0.04 * sin(vec2<f32>(0.12, 0.14) * time + length(o));
|
|
99
|
+
|
|
100
|
+
let n = fbm6_2(3.0 * o_mod);
|
|
101
|
+
|
|
102
|
+
let f = 0.5 + 0.5 * fbm4(1.8 * q_mod + 6.0 * n);
|
|
103
|
+
|
|
104
|
+
let result = mix(f, f * f * f * 3.5, f * abs(n.x));
|
|
105
|
+
|
|
106
|
+
return vec4<f32>(o, n.x, n.y);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
@fragment
|
|
110
|
+
fn main(@location(0) ndc: vec2<f32>) -> @location(0) vec4<f32> {
|
|
111
|
+
let time = u.time.x;
|
|
112
|
+
let intensity = u.params0.x;
|
|
113
|
+
|
|
114
|
+
let resolution = u.resolution.xy;
|
|
115
|
+
let aspect = u.resolution.z;
|
|
116
|
+
|
|
117
|
+
var p = ndc;
|
|
118
|
+
p.y *= aspect;
|
|
119
|
+
|
|
120
|
+
let e = 2.0 / resolution.y;
|
|
121
|
+
|
|
122
|
+
let on = func(p, time);
|
|
123
|
+
|
|
124
|
+
let o = on.xy;
|
|
125
|
+
let n = on.zw;
|
|
126
|
+
|
|
127
|
+
var q = p;
|
|
128
|
+
q += 0.03 * sin(vec2<f32>(0.27, 0.23) * time + length(q) * vec2<f32>(4.1, 4.3));
|
|
129
|
+
let fbm_val = 0.5 + 0.5 * fbm4(1.8 * q + 6.0 * n);
|
|
130
|
+
let f = mix(fbm_val, fbm_val * fbm_val * fbm_val * 3.5, fbm_val * abs(n.x));
|
|
131
|
+
|
|
132
|
+
var col = vec3<f32>(0.0);
|
|
133
|
+
col = mix(vec3<f32>(0.2, 0.1, 0.4), vec3<f32>(0.3, 0.05, 0.05), f);
|
|
134
|
+
col = mix(col, vec3<f32>(0.9, 0.9, 0.9), dot(n, n));
|
|
135
|
+
col = mix(col, vec3<f32>(0.4, 0.3, 0.3), 0.2 + 0.5 * o.y * o.y);
|
|
136
|
+
col = mix(col, vec3<f32>(0.0, 0.2, 0.4), 0.5 * smoothstep(1.2, 1.3, abs(n.x) + abs(n.y)));
|
|
137
|
+
col = clamp(col * f * 2.0, vec3<f32>(0.0), vec3<f32>(1.0));
|
|
138
|
+
|
|
139
|
+
let kk1 = func(p + vec2<f32>(e, 0.0), time);
|
|
140
|
+
let kk2 = func(p + vec2<f32>(0.0, e), time);
|
|
141
|
+
|
|
142
|
+
var q1 = p + vec2<f32>(e, 0.0);
|
|
143
|
+
q1 += 0.03 * sin(vec2<f32>(0.27, 0.23) * time + length(q1) * vec2<f32>(4.1, 4.3));
|
|
144
|
+
let f1 = 0.5 + 0.5 * fbm4(1.8 * q1 + 6.0 * kk1.zw);
|
|
145
|
+
let fx = mix(f1, f1 * f1 * f1 * 3.5, f1 * abs(kk1.z));
|
|
146
|
+
|
|
147
|
+
var q2 = p + vec2<f32>(0.0, e);
|
|
148
|
+
q2 += 0.03 * sin(vec2<f32>(0.27, 0.23) * time + length(q2) * vec2<f32>(4.1, 4.3));
|
|
149
|
+
let f2 = 0.5 + 0.5 * fbm4(1.8 * q2 + 6.0 * kk2.zw);
|
|
150
|
+
let fy = mix(f2, f2 * f2 * f2 * 3.5, f2 * abs(kk2.z));
|
|
151
|
+
|
|
152
|
+
let nor = normalize(vec3<f32>(fx - f, 2.0 * e, fy - f));
|
|
153
|
+
|
|
154
|
+
let lig = normalize(vec3<f32>(0.9, 0.2, -0.4));
|
|
155
|
+
let dif = clamp(0.3 + 0.7 * dot(nor, lig), 0.0, 1.0);
|
|
156
|
+
let lin = vec3<f32>(0.70, 0.90, 0.95) * (nor.y * 0.5 + 0.5) + vec3<f32>(0.15, 0.10, 0.05) * dif;
|
|
157
|
+
col *= 1.2 * lin;
|
|
158
|
+
|
|
159
|
+
col = 1.0 - col;
|
|
160
|
+
col = 1.1 * col * col;
|
|
161
|
+
|
|
162
|
+
col = col * intensity;
|
|
163
|
+
col = col * u.color0.rgb;
|
|
164
|
+
|
|
165
|
+
return vec4<f32>(col, u.color0.a);
|
|
166
|
+
}
|
|
167
|
+
`;
|
|
@@ -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
|
+
`;
|