@elyri/motion 0.0.0-stage → 0.0.1
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 +21 -0
- package/README.md +70 -2
- package/dist/chunk-A7JCTGZO.js +230 -0
- package/dist/chunk-A7JCTGZO.js.map +1 -0
- package/dist/core.cjs +238 -0
- package/dist/core.cjs.map +1 -0
- package/dist/core.d.cts +77 -0
- package/dist/core.d.ts +77 -0
- package/dist/core.js +3 -0
- package/dist/core.js.map +1 -0
- package/dist/index.cjs +4288 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.css +1118 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.cts +532 -0
- package/dist/index.d.ts +532 -0
- package/dist/index.js +4029 -0
- package/dist/index.js.map +1 -0
- package/package.json +60 -3
- package/src/components/animations/CountUp/CountUp.css +4 -0
- package/src/components/animations/CountUp/CountUp.tsx +100 -0
- package/src/components/animations/CountUp/index.ts +2 -0
- package/src/components/animations/FadeIn/FadeIn.css +43 -0
- package/src/components/animations/FadeIn/FadeIn.tsx +72 -0
- package/src/components/animations/FadeIn/index.ts +2 -0
- package/src/components/animations/Magnetic/Magnetic.css +11 -0
- package/src/components/animations/Magnetic/Magnetic.tsx +107 -0
- package/src/components/animations/Magnetic/index.ts +2 -0
- package/src/components/animations/ScaleIn/ScaleIn.css +24 -0
- package/src/components/animations/ScaleIn/ScaleIn.tsx +65 -0
- package/src/components/animations/ScaleIn/index.ts +2 -0
- package/src/components/animations/Spotlight/Spotlight.css +93 -0
- package/src/components/animations/Spotlight/Spotlight.tsx +100 -0
- package/src/components/animations/Spotlight/index.ts +2 -0
- package/src/components/animations/Tilt/Tilt.css +35 -0
- package/src/components/animations/Tilt/Tilt.tsx +123 -0
- package/src/components/animations/Tilt/index.ts +2 -0
- package/src/components/animations/index.ts +12 -0
- package/src/components/backgrounds/Aurora/Aurora.css +33 -0
- package/src/components/backgrounds/Aurora/Aurora.tsx +147 -0
- package/src/components/backgrounds/Aurora/index.ts +2 -0
- package/src/components/backgrounds/Caustics/Caustics.css +34 -0
- package/src/components/backgrounds/Caustics/Caustics.tsx +142 -0
- package/src/components/backgrounds/Caustics/index.ts +2 -0
- package/src/components/backgrounds/Contours/Contours.css +42 -0
- package/src/components/backgrounds/Contours/Contours.tsx +147 -0
- package/src/components/backgrounds/Contours/index.ts +2 -0
- package/src/components/backgrounds/DotField/DotField.css +44 -0
- package/src/components/backgrounds/DotField/DotField.tsx +135 -0
- package/src/components/backgrounds/DotField/index.ts +2 -0
- package/src/components/backgrounds/DragonScales/DragonScales.css +44 -0
- package/src/components/backgrounds/DragonScales/DragonScales.tsx +250 -0
- package/src/components/backgrounds/DragonScales/index.ts +2 -0
- package/src/components/backgrounds/Filaments/Filaments.css +38 -0
- package/src/components/backgrounds/Filaments/Filaments.tsx +138 -0
- package/src/components/backgrounds/Filaments/index.ts +2 -0
- package/src/components/backgrounds/FlipTiles/FlipTiles.css +44 -0
- package/src/components/backgrounds/FlipTiles/FlipTiles.tsx +368 -0
- package/src/components/backgrounds/FlipTiles/index.ts +2 -0
- package/src/components/backgrounds/Halo/Halo.css +43 -0
- package/src/components/backgrounds/Halo/Halo.tsx +122 -0
- package/src/components/backgrounds/Halo/index.ts +2 -0
- package/src/components/backgrounds/MeshGradient/MeshGradient.css +43 -0
- package/src/components/backgrounds/MeshGradient/MeshGradient.tsx +195 -0
- package/src/components/backgrounds/MeshGradient/index.ts +2 -0
- package/src/components/backgrounds/PixelVortex/PixelVortex.css +44 -0
- package/src/components/backgrounds/PixelVortex/PixelVortex.tsx +278 -0
- package/src/components/backgrounds/PixelVortex/index.ts +2 -0
- package/src/components/backgrounds/Planet/Planet.css +39 -0
- package/src/components/backgrounds/Planet/Planet.tsx +736 -0
- package/src/components/backgrounds/Planet/index.ts +2 -0
- package/src/components/backgrounds/SilkWaves/SilkWaves.css +44 -0
- package/src/components/backgrounds/SilkWaves/SilkWaves.tsx +144 -0
- package/src/components/backgrounds/SilkWaves/index.ts +2 -0
- package/src/components/backgrounds/Velvet/Velvet.css +35 -0
- package/src/components/backgrounds/Velvet/Velvet.tsx +246 -0
- package/src/components/backgrounds/Velvet/index.ts +2 -0
- package/src/components/backgrounds/index.ts +26 -0
- package/src/components/index.ts +4 -0
- package/src/components/media/AsciiImage/AsciiImage.css +16 -0
- package/src/components/media/AsciiImage/AsciiImage.tsx +366 -0
- package/src/components/media/AsciiImage/index.ts +2 -0
- package/src/components/media/index.ts +2 -0
- package/src/components/text/GradientText/GradientText.css +32 -0
- package/src/components/text/GradientText/GradientText.tsx +27 -0
- package/src/components/text/GradientText/index.ts +2 -0
- package/src/components/text/Marquee/Marquee.css +91 -0
- package/src/components/text/Marquee/Marquee.tsx +130 -0
- package/src/components/text/Marquee/index.ts +2 -0
- package/src/components/text/ParticleText/ParticleText.css +16 -0
- package/src/components/text/ParticleText/ParticleText.tsx +279 -0
- package/src/components/text/ParticleText/index.ts +2 -0
- package/src/components/text/RotatingText/RotatingText.css +133 -0
- package/src/components/text/RotatingText/RotatingText.tsx +112 -0
- package/src/components/text/RotatingText/index.ts +2 -0
- package/src/components/text/ScrambleText/ScrambleText.css +48 -0
- package/src/components/text/ScrambleText/ScrambleText.tsx +141 -0
- package/src/components/text/ScrambleText/index.ts +2 -0
- package/src/components/text/ScrollMarquee/ScrollMarquee.css +33 -0
- package/src/components/text/ScrollMarquee/ScrollMarquee.tsx +110 -0
- package/src/components/text/ScrollMarquee/index.ts +2 -0
- package/src/components/text/ScrollReveal/ScrollReveal.css +51 -0
- package/src/components/text/ScrollReveal/ScrollReveal.tsx +186 -0
- package/src/components/text/ScrollReveal/index.ts +2 -0
- package/src/components/text/SplitReveal/SplitReveal.css +52 -0
- package/src/components/text/SplitReveal/SplitReveal.tsx +127 -0
- package/src/components/text/SplitReveal/index.ts +2 -0
- package/src/components/text/Typewriter/Typewriter.css +37 -0
- package/src/components/text/Typewriter/Typewriter.tsx +80 -0
- package/src/components/text/Typewriter/index.ts +2 -0
- package/src/components/text/WaveText/WaveText.css +28 -0
- package/src/components/text/WaveText/WaveText.tsx +52 -0
- package/src/components/text/WaveText/index.ts +2 -0
- package/src/components/text/index.ts +20 -0
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
import { cn, hexToLinearRgb, useShaderCanvas } from '../../../core';
|
|
4
|
+
|
|
5
|
+
import './Planet.css';
|
|
6
|
+
|
|
7
|
+
export type PlanetKind = 'mars' | 'jupiter' | 'earth';
|
|
8
|
+
|
|
9
|
+
export interface PlanetProps {
|
|
10
|
+
children?: ReactNode;
|
|
11
|
+
className?: string;
|
|
12
|
+
planet?: PlanetKind;
|
|
13
|
+
color?: string;
|
|
14
|
+
terrainColor?: string;
|
|
15
|
+
atmosphereColor?: string;
|
|
16
|
+
atmosphere?: number;
|
|
17
|
+
craters?: number;
|
|
18
|
+
cityLights?: boolean;
|
|
19
|
+
stars?: number;
|
|
20
|
+
horizon?: number;
|
|
21
|
+
speed?: number;
|
|
22
|
+
sun?: boolean;
|
|
23
|
+
sunPosition?: { x: number; y: number };
|
|
24
|
+
interactive?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const PLANET_PRESETS: Record<
|
|
28
|
+
PlanetKind,
|
|
29
|
+
{ color: string; terrainColor: string; atmosphereColor: string; atmosphere: number }
|
|
30
|
+
> = {
|
|
31
|
+
mars: { color: '#c1532b', terrainColor: '#4e1e12', atmosphereColor: '#f2a57c', atmosphere: 0.6 },
|
|
32
|
+
jupiter: { color: '#ecdcc0', terrainColor: '#a86a3a', atmosphereColor: '#d9cdb8', atmosphere: 0.3 },
|
|
33
|
+
earth: { color: '#3f5a2a', terrainColor: '#0a2744', atmosphereColor: '#6fa8ff', atmosphere: 0.55 },
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
const COMMON = `
|
|
37
|
+
precision highp float;
|
|
38
|
+
|
|
39
|
+
#define PI 3.14159265
|
|
40
|
+
#define HALF 8
|
|
41
|
+
|
|
42
|
+
uniform vec2 uResolution;
|
|
43
|
+
uniform float uTime;
|
|
44
|
+
uniform vec2 uPointer;
|
|
45
|
+
uniform vec3 uSurface;
|
|
46
|
+
uniform vec3 uTerrain;
|
|
47
|
+
uniform vec3 uAtmosphere;
|
|
48
|
+
uniform float uDensity;
|
|
49
|
+
uniform float uStars;
|
|
50
|
+
uniform float uHorizon;
|
|
51
|
+
uniform float uSun;
|
|
52
|
+
uniform vec2 uSunPos;
|
|
53
|
+
uniform float uSunFixed;
|
|
54
|
+
|
|
55
|
+
const float ALT = 0.15;
|
|
56
|
+
const float FL = 1.25;
|
|
57
|
+
const float H = 0.0045;
|
|
58
|
+
const float RT = 1.0 + 10.0 * H;
|
|
59
|
+
const float SUN_I = 5.0;
|
|
60
|
+
const float SUN_R = 0.012;
|
|
61
|
+
|
|
62
|
+
float hash12(vec2 p) {
|
|
63
|
+
vec3 p3 = fract(vec3(p.xyx) * 0.1031);
|
|
64
|
+
p3 += dot(p3, p3.yzx + 33.33);
|
|
65
|
+
return fract((p3.x + p3.y) * p3.z);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
float hash13(vec3 p) {
|
|
69
|
+
p = fract(p * 0.1031);
|
|
70
|
+
p += dot(p, p.zyx + 31.32);
|
|
71
|
+
return fract((p.x + p.y) * p.z);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
vec3 hash33(vec3 p) {
|
|
75
|
+
p = fract(p * vec3(0.1031, 0.1030, 0.0973));
|
|
76
|
+
p += dot(p, p.yxz + 33.33);
|
|
77
|
+
return fract((p.xxy + p.yxx) * p.zyx);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
float noise2(vec2 p) {
|
|
81
|
+
vec2 i = floor(p);
|
|
82
|
+
vec2 f = fract(p);
|
|
83
|
+
vec2 u = f * f * (3.0 - 2.0 * f);
|
|
84
|
+
return mix(
|
|
85
|
+
mix(hash12(i), hash12(i + vec2(1.0, 0.0)), u.x),
|
|
86
|
+
mix(hash12(i + vec2(0.0, 1.0)), hash12(i + vec2(1.0, 1.0)), u.x),
|
|
87
|
+
u.y
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
float noise3(vec3 x) {
|
|
92
|
+
vec3 i = floor(x);
|
|
93
|
+
vec3 f = fract(x);
|
|
94
|
+
vec3 u = f * f * (3.0 - 2.0 * f);
|
|
95
|
+
return mix(
|
|
96
|
+
mix(mix(hash13(i), hash13(i + vec3(1, 0, 0)), u.x), mix(hash13(i + vec3(0, 1, 0)), hash13(i + vec3(1, 1, 0)), u.x), u.y),
|
|
97
|
+
mix(mix(hash13(i + vec3(0, 0, 1)), hash13(i + vec3(1, 0, 1)), u.x), mix(hash13(i + vec3(0, 1, 1)), hash13(i + vec3(1, 1, 1)), u.x), u.y),
|
|
98
|
+
u.z
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
float lod(float freqTimesFootprint) {
|
|
103
|
+
return 1.0 - smoothstep(0.25, 0.6, freqTimesFootprint);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
float fbm3(vec3 p, float fp, int octaves) {
|
|
107
|
+
float s = 0.0;
|
|
108
|
+
float a = 0.5;
|
|
109
|
+
float f = 1.0;
|
|
110
|
+
for (int i = 0; i < 8; i++) {
|
|
111
|
+
float w = lod(f * fp);
|
|
112
|
+
if (i >= octaves || w <= 0.0) break;
|
|
113
|
+
s += a * w * (noise3(p * f + float(i) * 7.13) - 0.5);
|
|
114
|
+
a *= 0.55;
|
|
115
|
+
f *= 2.02;
|
|
116
|
+
}
|
|
117
|
+
return s;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
float chapman(float X, float h, float coschi) {
|
|
121
|
+
float c = sqrt(X + h);
|
|
122
|
+
if (coschi >= 0.0) return c / (c * coschi + 1.0) * exp(-h);
|
|
123
|
+
float x0 = sqrt(1.0 - coschi * coschi) * (X + h);
|
|
124
|
+
return 2.0 * sqrt(x0) * exp(min(X - x0, 40.0)) - c / (1.0 - c * coschi) * exp(-h);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
vec3 stars(vec3 rd, float pixAngle) {
|
|
128
|
+
vec2 a = vec2(atan(rd.x, -rd.z), asin(clamp(rd.y, -1.0, 1.0)));
|
|
129
|
+
vec3 col = vec3(0.0);
|
|
130
|
+
for (int layer = 0; layer < 2; layer++) {
|
|
131
|
+
float scale = layer == 0 ? 70.0 : 190.0;
|
|
132
|
+
float seed = float(layer) * 17.0;
|
|
133
|
+
vec2 g = a * scale;
|
|
134
|
+
vec2 cell = floor(g);
|
|
135
|
+
if (hash12(cell + seed) > uStars * (layer == 0 ? 0.22 : 0.2)) continue;
|
|
136
|
+
vec2 pos = 0.2 + 0.6 * vec2(hash12(cell + seed + 3.1), hash12(cell + seed + 7.7));
|
|
137
|
+
float px = length(fract(g) - pos) / scale / pixAngle;
|
|
138
|
+
float h = hash12(cell + seed + 5.3);
|
|
139
|
+
float mag = layer == 0 ? 0.05 + 2.0 * pow(h, 8.0) : 0.015 + 0.05 * h;
|
|
140
|
+
float tw = 0.7 + 0.3 * sin(uTime * (0.8 + 2.5 * h) + h * 40.0);
|
|
141
|
+
vec3 tint = mix(vec3(0.62, 0.74, 1.0), vec3(1.0, 0.82, 0.64), hash12(cell + seed + 9.9));
|
|
142
|
+
col += tint * mag * tw * exp(-px * px * 1.4);
|
|
143
|
+
}
|
|
144
|
+
vec2 q = a * vec2(2.2, 3.4);
|
|
145
|
+
float neb = noise2(q) * 0.55 + noise2(q * 2.1 + 4.0) * 0.3 + noise2(q * 4.3 + 9.0) * 0.15;
|
|
146
|
+
float band = exp(-pow((a.y + 0.35 * a.x + 0.05) * 2.6, 2.0));
|
|
147
|
+
col += mix(vec3(0.05, 0.04, 0.12), vec3(0.1, 0.05, 0.07), neb) * smoothstep(0.35, 0.85, neb) * band * 0.12 * uStars;
|
|
148
|
+
return col;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
vec3 aces(vec3 x) {
|
|
152
|
+
return clamp((x * (2.51 * x + 0.03)) / (x * (2.43 * x + 0.59) + 0.14), 0.0, 1.0);
|
|
153
|
+
}
|
|
154
|
+
`;
|
|
155
|
+
|
|
156
|
+
const RELIEF = `
|
|
157
|
+
vec4 noised(vec3 x) {
|
|
158
|
+
vec3 i = floor(x);
|
|
159
|
+
vec3 w = fract(x);
|
|
160
|
+
vec3 u = w * w * w * (w * (w * 6.0 - 15.0) + 10.0);
|
|
161
|
+
vec3 du = 30.0 * w * w * (w * (w - 2.0) + 1.0);
|
|
162
|
+
float a = hash13(i);
|
|
163
|
+
float b = hash13(i + vec3(1, 0, 0));
|
|
164
|
+
float c = hash13(i + vec3(0, 1, 0));
|
|
165
|
+
float d = hash13(i + vec3(1, 1, 0));
|
|
166
|
+
float e = hash13(i + vec3(0, 0, 1));
|
|
167
|
+
float f = hash13(i + vec3(1, 0, 1));
|
|
168
|
+
float g = hash13(i + vec3(0, 1, 1));
|
|
169
|
+
float h = hash13(i + vec3(1, 1, 1));
|
|
170
|
+
float k1 = b - a;
|
|
171
|
+
float k2 = c - a;
|
|
172
|
+
float k3 = e - a;
|
|
173
|
+
float k4 = a - b - c + d;
|
|
174
|
+
float k5 = a - c - e + g;
|
|
175
|
+
float k6 = a - b - e + f;
|
|
176
|
+
float k7 = -a + b + c - d + e - f - g + h;
|
|
177
|
+
return vec4(
|
|
178
|
+
a + k1 * u.x + k2 * u.y + k3 * u.z + k4 * u.x * u.y + k5 * u.y * u.z + k6 * u.z * u.x + k7 * u.x * u.y * u.z,
|
|
179
|
+
du * vec3(
|
|
180
|
+
k1 + k4 * u.y + k6 * u.z + k7 * u.y * u.z,
|
|
181
|
+
k2 + k5 * u.z + k4 * u.x + k7 * u.z * u.x,
|
|
182
|
+
k3 + k6 * u.x + k5 * u.y + k7 * u.x * u.y
|
|
183
|
+
)
|
|
184
|
+
);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
vec4 terrain(vec3 p, float fp) {
|
|
188
|
+
vec4 s = vec4(0.0);
|
|
189
|
+
vec3 dsum = vec3(0.0);
|
|
190
|
+
float a = 0.5;
|
|
191
|
+
float f = 1.0;
|
|
192
|
+
for (int i = 0; i < 10; i++) {
|
|
193
|
+
float w = lod(f * fp);
|
|
194
|
+
if (w <= 0.0) break;
|
|
195
|
+
vec4 n = noised(p * f + float(i) * vec3(3.1, 7.7, 1.3));
|
|
196
|
+
vec3 g = n.yzw * f;
|
|
197
|
+
dsum += g * a;
|
|
198
|
+
float k = a * w / (1.0 + 0.35 * dot(dsum, dsum));
|
|
199
|
+
s.x += k * (n.x - 0.5);
|
|
200
|
+
s.yzw += k * g;
|
|
201
|
+
a *= 0.5;
|
|
202
|
+
f *= 2.03;
|
|
203
|
+
}
|
|
204
|
+
return s;
|
|
205
|
+
}
|
|
206
|
+
`;
|
|
207
|
+
|
|
208
|
+
const MARS_SURFACE = `
|
|
209
|
+
uniform float uCraters;
|
|
210
|
+
|
|
211
|
+
const float BUMP = 0.06;
|
|
212
|
+
|
|
213
|
+
float craterProfile(float x) {
|
|
214
|
+
return 0.8 * (smoothstep(0.0, 1.0, x) - 1.0) + 0.3 * exp(-10.0 * (x - 1.0) * (x - 1.0));
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
float craterLayer(vec3 p, float scale, float fp, float seed, inout vec3 grad) {
|
|
218
|
+
vec3 g = p * scale + seed;
|
|
219
|
+
vec3 cell = floor(g);
|
|
220
|
+
vec3 r = hash33(cell + seed);
|
|
221
|
+
if (r.x > 0.75 * uCraters) return 0.0;
|
|
222
|
+
vec3 c = cell + 0.3 + 0.4 * hash33(cell * 1.7 + seed + 11.0);
|
|
223
|
+
float R = mix(0.07, 0.18, r.y * r.y);
|
|
224
|
+
vec3 d = g - c;
|
|
225
|
+
float dist = length(d);
|
|
226
|
+
float x = dist / R;
|
|
227
|
+
if (x > 1.6) return 0.0;
|
|
228
|
+
float w = 1.0 - smoothstep(0.1, 0.4, fp * scale / R);
|
|
229
|
+
float depth = uCraters * mix(0.5, 1.0, r.z) * w;
|
|
230
|
+
float dh = (craterProfile(x + 0.01) - craterProfile(x - 0.01)) / 0.02;
|
|
231
|
+
grad += dh * d / max(dist, 1e-4) * depth * 0.8;
|
|
232
|
+
return craterProfile(x) * w;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
vec3 shadeSurface(vec3 n, float ndv, float pix, vec3 sun, vec3 beta, float X) {
|
|
236
|
+
float fp = pix / max(sqrt(ndv), 0.12);
|
|
237
|
+
|
|
238
|
+
float ang = -uTime * 0.01;
|
|
239
|
+
float cs = cos(ang);
|
|
240
|
+
float sn = sin(ang);
|
|
241
|
+
mat3 spin = mat3(1.0, 0.0, 0.0, 0.0, cs, sn, 0.0, -sn, cs);
|
|
242
|
+
vec3 q = spin * n;
|
|
243
|
+
|
|
244
|
+
vec4 ter = terrain(q * 4.0 + 2.0, fp * 4.0);
|
|
245
|
+
vec3 grad = ter.yzw * 4.0 * BUMP;
|
|
246
|
+
float crater = 0.0;
|
|
247
|
+
crater += craterLayer(q, 5.0, fp, 1.3, grad);
|
|
248
|
+
crater += craterLayer(q, 11.0, fp, 7.9, grad);
|
|
249
|
+
crater += craterLayer(q, 23.0, fp, 4.1, grad);
|
|
250
|
+
crater += craterLayer(q, 47.0, fp, 9.6, grad);
|
|
251
|
+
crater += craterLayer(q, 97.0, fp, 5.7, grad);
|
|
252
|
+
crater += craterLayer(q, 199.0, fp, 2.2, grad);
|
|
253
|
+
grad = grad * spin;
|
|
254
|
+
grad -= dot(grad, n) * n;
|
|
255
|
+
vec3 nb = normalize(n - grad);
|
|
256
|
+
|
|
257
|
+
float big = fbm3(q * 1.7 + 4.0, fp * 1.7, 8);
|
|
258
|
+
float mid = fbm3(q * 9.0 + 1.0, fp * 9.0, 8);
|
|
259
|
+
float fine = fbm3(q * 70.0 + 3.0, fp * 70.0, 8);
|
|
260
|
+
vec3 albedo = mix(uSurface, uTerrain, smoothstep(-0.12, 0.22, big + 0.35 * mid + 0.15 * fine));
|
|
261
|
+
albedo *= 0.8 + 0.7 * (mid + 0.5) * 0.6 + 2.0 * ter.x + 0.5 * fine;
|
|
262
|
+
albedo *= 1.0 + 0.3 * crater;
|
|
263
|
+
albedo = max(albedo, 0.0);
|
|
264
|
+
|
|
265
|
+
float ngl = dot(n, sun);
|
|
266
|
+
float mu0 = max(dot(nb, sun), 0.0);
|
|
267
|
+
float lsl = mu0 / (mu0 + ndv + 1e-3);
|
|
268
|
+
float brdf = mix(mu0, lsl, 0.35) * smoothstep(-0.03, 0.08, ngl);
|
|
269
|
+
vec3 sunT = exp(-beta * H * chapman(X, 0.0, ngl));
|
|
270
|
+
vec3 sky = uAtmosphere * uDensity * 0.05 * smoothstep(-0.3, 0.4, ngl);
|
|
271
|
+
return albedo * (SUN_I * 0.9 * sunT * brdf + sky + 0.004);
|
|
272
|
+
}
|
|
273
|
+
`;
|
|
274
|
+
|
|
275
|
+
const JUPITER_SURFACE = `
|
|
276
|
+
const vec3 AXIS = vec3(0.0, 0.2955, -0.9553);
|
|
277
|
+
const vec3 EAST0 = vec3(1.0, 0.0, 0.0);
|
|
278
|
+
const vec3 MERIDIAN0 = vec3(0.0, 0.9553, 0.2955);
|
|
279
|
+
const float FLOW_T = 24.0;
|
|
280
|
+
|
|
281
|
+
vec3 spinAxis(vec3 p, float a) {
|
|
282
|
+
float c = cos(a);
|
|
283
|
+
float s = sin(a);
|
|
284
|
+
return p * c + cross(AXIS, p) * s + AXIS * dot(AXIS, p) * (1.0 - c);
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
vec3 fromLatLon(float lat, float lon) {
|
|
288
|
+
return cos(lat) * (cos(lon) * MERIDIAN0 + sin(lon) * EAST0) + sin(lat) * AXIS;
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
vec2 harmonic(float lat, float k, float a, float ph, float fpLat) {
|
|
292
|
+
float w = a * lod(k * fpLat / (2.0 * PI));
|
|
293
|
+
return w * vec2(sin(k * lat + ph), k * cos(k * lat + ph));
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
vec2 bandField(float lat, float fpLat) {
|
|
297
|
+
return harmonic(lat, 61.0, 1.0, 0.9, fpLat)
|
|
298
|
+
+ harmonic(lat, 107.0, 0.55, 2.4, fpLat)
|
|
299
|
+
+ harmonic(lat, 211.0, 0.3, 4.1, fpLat)
|
|
300
|
+
+ harmonic(lat, 409.0, 0.16, 1.7, fpLat);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
float jet(float lat) {
|
|
304
|
+
return 0.00011 * (61.0 * cos(61.0 * lat + 0.9) + 0.55 * 107.0 * cos(107.0 * lat + 2.4));
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
vec2 cloudPhase(vec3 p, float lat, float t, float seed, float fp) {
|
|
308
|
+
vec3 q = spinAxis(p, -jet(lat) * t);
|
|
309
|
+
q += AXIS * dot(q, AXIS) * 2.0;
|
|
310
|
+
q += seed * vec3(1.7, 9.2, 4.3);
|
|
311
|
+
float wx = fbm3(q * 7.0, fp * 14.0, 5);
|
|
312
|
+
float wy = fbm3(q * 7.0 + 5.2, fp * 14.0, 5);
|
|
313
|
+
float detail = fbm3(q * 30.0 + vec3(wx, wy, wx - wy) * 9.0, fp * 60.0, 7);
|
|
314
|
+
return vec2(wx, detail);
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
vec2 vortexFrame(vec3 p, float lat0, float lon0, vec2 radii) {
|
|
318
|
+
vec3 c = fromLatLon(lat0, lon0);
|
|
319
|
+
vec3 east = normalize(cross(AXIS, c));
|
|
320
|
+
vec3 north = cross(c, east);
|
|
321
|
+
vec3 d = p - c;
|
|
322
|
+
return vec2(dot(d, east), dot(d, north)) / radii;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
vec2 vortex(vec2 v, float spin, float seed, float fp) {
|
|
326
|
+
float r = length(v);
|
|
327
|
+
float ang = spin * uTime + 2.4 * (1.0 - smoothstep(0.0, 1.1, r));
|
|
328
|
+
float c = cos(ang);
|
|
329
|
+
float s = sin(ang);
|
|
330
|
+
vec2 w = mat2(c, -s, s, c) * v;
|
|
331
|
+
float tex = fbm3(vec3(w * 2.4, r * 6.0 + seed), fp * 6.0, 6);
|
|
332
|
+
float mask = 1.0 - smoothstep(0.6, 1.0, r + tex * 0.5);
|
|
333
|
+
return vec2(mask, tex);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
float vortexPush(vec2 v, float radiusY) {
|
|
337
|
+
float r = length(v);
|
|
338
|
+
return v.y / max(r, 1e-3) * radiusY * 0.7 * (1.0 - smoothstep(0.9, 2.6, r)) * smoothstep(0.0, 0.9, r);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
vec3 shadeSurface(vec3 n, float ndv, float pix, vec3 sun, vec3 beta, float X) {
|
|
342
|
+
float fp = pix / max(sqrt(ndv), 0.12);
|
|
343
|
+
float fpLat = pix / max(ndv, 0.03);
|
|
344
|
+
|
|
345
|
+
float lat = asin(clamp(dot(n, AXIS), -1.0, 1.0));
|
|
346
|
+
|
|
347
|
+
float cyc = uTime / FLOW_T;
|
|
348
|
+
float phA = fract(cyc);
|
|
349
|
+
float phB = fract(cyc + 0.5);
|
|
350
|
+
float wA = 1.0 - abs(2.0 * phA - 1.0);
|
|
351
|
+
vec2 A = cloudPhase(n, lat, phA * FLOW_T, mod(floor(cyc), 61.0), fp);
|
|
352
|
+
vec2 B = cloudPhase(n, lat, phB * FLOW_T, mod(floor(cyc + 0.5), 61.0) + 0.5, fp);
|
|
353
|
+
vec2 cl = (A * wA + B * (1.0 - wA)) / sqrt(wA * wA + (1.0 - wA) * (1.0 - wA));
|
|
354
|
+
|
|
355
|
+
const vec2 GRS_R = vec2(0.05, 0.028);
|
|
356
|
+
vec2 grs = vortexFrame(n, 0.6, -0.1 + 0.03 * sin(uTime * 0.021), GRS_R);
|
|
357
|
+
float push = vortexPush(grs, GRS_R.y);
|
|
358
|
+
const vec2 OVAL_R = vec2(0.013, 0.0085);
|
|
359
|
+
vec2 ovals[5];
|
|
360
|
+
for (int i = 0; i < 5; i++) {
|
|
361
|
+
float fi = float(i);
|
|
362
|
+
float lon = fi * 0.085 - 0.3 + 0.02 * sin(uTime * 0.017 + fi * 1.9);
|
|
363
|
+
ovals[i] = vortexFrame(n, 0.545 + 0.003 * sin(fi * 2.3), lon, OVAL_R);
|
|
364
|
+
push += vortexPush(ovals[i], OVAL_R.y);
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
float latB = lat + cl.x * 0.02 + push;
|
|
368
|
+
vec2 band = bandField(latB, fpLat);
|
|
369
|
+
float soft = 0.25 + abs(band.y) * fpLat;
|
|
370
|
+
float belt = smoothstep(-soft, soft, band.x - 0.1);
|
|
371
|
+
float edge = 1.0 - abs(2.0 * belt - 1.0);
|
|
372
|
+
|
|
373
|
+
float hue = 0.5 + 0.5 * sin(latB * 17.0 + 1.7);
|
|
374
|
+
vec3 beltCol = mix(uTerrain, uTerrain * vec3(1.25, 0.9, 0.62), hue);
|
|
375
|
+
vec3 zoneCol = mix(uSurface, uSurface * vec3(1.0, 0.9, 0.72), 1.0 - hue);
|
|
376
|
+
vec3 albedo = mix(zoneCol, beltCol, belt);
|
|
377
|
+
albedo *= 1.0 + cl.y * (1.6 + 2.4 * edge) + 0.1 * band.x;
|
|
378
|
+
float festoon = smoothstep(0.05, 0.2, cl.y) * edge;
|
|
379
|
+
albedo = mix(albedo, albedo * vec3(0.5, 0.62, 0.78), festoon * 0.55);
|
|
380
|
+
|
|
381
|
+
float rg = length(grs);
|
|
382
|
+
vec2 gv = vortex(grs, 0.18, 3.0, fp / GRS_R.y);
|
|
383
|
+
float collar = exp(-pow((rg - 1.1) / 0.22, 2.0));
|
|
384
|
+
albedo = mix(albedo, zoneCol * (1.1 + cl.y), collar * 0.75);
|
|
385
|
+
vec3 red = uTerrain * vec3(1.7, 0.66, 0.4);
|
|
386
|
+
red *= (0.7 + 0.4 * smoothstep(0.0, 0.85, rg)) * (1.0 + 1.8 * gv.y);
|
|
387
|
+
albedo = mix(albedo, red, gv.x);
|
|
388
|
+
|
|
389
|
+
for (int i = 0; i < 5; i++) {
|
|
390
|
+
float r = length(ovals[i]);
|
|
391
|
+
if (r < 1.6) {
|
|
392
|
+
vec2 o = vortex(ovals[i], -0.4, float(i) * 3.1, fp / OVAL_R.y);
|
|
393
|
+
albedo *= 1.0 - 0.35 * exp(-pow((r - 1.0) / 0.18, 2.0));
|
|
394
|
+
albedo = mix(albedo, uSurface * (1.08 + 1.4 * o.y) * (0.9 + 0.15 * smoothstep(0.0, 0.7, r)), o.x * 0.92);
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
albedo = max(albedo, 0.0);
|
|
398
|
+
|
|
399
|
+
float ngl = dot(n, sun);
|
|
400
|
+
float mu0 = max(ngl, 0.0);
|
|
401
|
+
float brdf = mu0 * smoothstep(-0.02, 0.1, ngl) + 0.015 * smoothstep(-0.12, 0.04, ngl);
|
|
402
|
+
vec3 sunT = exp(-beta * H * chapman(X, 0.0, ngl));
|
|
403
|
+
vec3 sky = uAtmosphere * uDensity * 0.05 * smoothstep(-0.3, 0.4, ngl);
|
|
404
|
+
return albedo * (SUN_I * 0.9 * sunT * brdf + sky + 0.004);
|
|
405
|
+
}
|
|
406
|
+
`;
|
|
407
|
+
|
|
408
|
+
const EARTH_SURFACE = `
|
|
409
|
+
uniform float uCityLights;
|
|
410
|
+
|
|
411
|
+
const float CLOUD_H = 0.0016;
|
|
412
|
+
const vec3 CITY_WARM = vec3(1.0, 0.5, 0.16);
|
|
413
|
+
const vec3 CITY_COOL = vec3(1.0, 0.86, 0.66);
|
|
414
|
+
|
|
415
|
+
mat3 spinX(float a) {
|
|
416
|
+
float c = cos(a);
|
|
417
|
+
float s = sin(a);
|
|
418
|
+
return mat3(1.0, 0.0, 0.0, 0.0, c, s, 0.0, -s, c);
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
vec3 cloudWarp(vec3 p, float fp) {
|
|
422
|
+
vec3 s = p * 1.8 + vec3(0.0, 0.0, uTime * 0.0035);
|
|
423
|
+
return vec3(fbm3(s + 1.3, fp * 1.8, 4), fbm3(s + 7.1, fp * 1.8, 4), fbm3(s + 4.4, fp * 1.8, 4));
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
float cloudCover(vec3 p, vec3 w, float fp) {
|
|
427
|
+
float t = uTime * 0.006;
|
|
428
|
+
float big = fbm3(p * 3.2 + w * 2.4 + vec3(t, 0.0, -t), fp * 3.2, 6);
|
|
429
|
+
float puff = fbm3(p * 21.0 + w * 5.0 - vec3(0.0, t, t) * 3.0, fp * 21.0, 6);
|
|
430
|
+
float c = big + 0.4 * puff * smoothstep(-0.15, 0.1, big);
|
|
431
|
+
return smoothstep(0.03, 0.26, c + 0.02);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// 每个格子至多一座聚落,位置在格内完全随机;查 2x2x2 邻格避免被格子边界截断
|
|
435
|
+
float settlements(vec3 q, float scale, float fp, float P, float seed) {
|
|
436
|
+
vec3 g = q * scale + seed * 17.0;
|
|
437
|
+
vec3 base = floor(g - 0.5);
|
|
438
|
+
float f2 = fp * scale * fp * scale * 0.25;
|
|
439
|
+
float sum = 0.0;
|
|
440
|
+
for (int i = 0; i < 8; i++) {
|
|
441
|
+
float fi = float(i);
|
|
442
|
+
vec3 cell = base + vec3(mod(fi, 2.0), mod(floor(fi * 0.5), 2.0), floor(fi * 0.25));
|
|
443
|
+
vec3 r = hash33(cell + seed);
|
|
444
|
+
float w = smoothstep(r.x, r.x + 0.15, P);
|
|
445
|
+
if (w <= 0.0) continue;
|
|
446
|
+
vec3 d = g - cell - hash33(cell * 1.7 + seed + 5.0);
|
|
447
|
+
d -= dot(d, q) * q;
|
|
448
|
+
float s2 = mix(0.03, 0.14, r.y * r.y);
|
|
449
|
+
s2 *= s2;
|
|
450
|
+
float t2 = s2 + f2;
|
|
451
|
+
sum += w * exp(-dot(d, d) / t2) * s2 / t2 * (0.5 + 0.5 * r.z);
|
|
452
|
+
}
|
|
453
|
+
return sum;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
vec3 cityLights(vec3 q, float fp, float P) {
|
|
457
|
+
float metro = settlements(q, 40.0, fp, P * 0.75, 1.0);
|
|
458
|
+
float town = settlements(q, 170.0, fp, P * 0.45 + min(metro, 1.0) * 0.4, 2.0);
|
|
459
|
+
float t = min(metro, 1.0);
|
|
460
|
+
// 街区颗粒:市中心连成一片,越往郊区越破碎
|
|
461
|
+
float grain = 0.6 * noise3(q * 1800.0) + 0.4 * noise3(q * 700.0 + 3.1);
|
|
462
|
+
float lo = 0.72 - 0.55 * t;
|
|
463
|
+
float mask = mix(0.2 + 0.6 * t, smoothstep(lo, lo + 0.2, grain), lod(fp * 1800.0));
|
|
464
|
+
vec3 tint = mix(CITY_WARM, CITY_COOL, t * t * 0.8);
|
|
465
|
+
return tint * metro * mask * 1.1 + CITY_WARM * min(town, 1.5) * 0.35;
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
vec3 shadeSurface(vec3 n, float ndv, float pix, vec3 sun, vec3 beta, float X) {
|
|
469
|
+
float fp = pix / max(sqrt(ndv), 0.12);
|
|
470
|
+
|
|
471
|
+
mat3 spin = spinX(-uTime * 0.008);
|
|
472
|
+
vec3 q = spin * n;
|
|
473
|
+
|
|
474
|
+
vec3 cw = vec3(fbm3(q * 1.2 + 3.7, fp * 1.2, 4), fbm3(q * 1.2 + 9.1, fp * 1.2, 4), fbm3(q * 1.2 + 5.3, fp * 1.2, 4));
|
|
475
|
+
float cont = fbm3(q * 1.9 + cw * 1.4 + 0.7, fp * 1.9, 6);
|
|
476
|
+
vec4 ter = terrain(q * 7.0 + 2.0, fp * 7.0);
|
|
477
|
+
float e = cont + 0.3 * ter.x - 0.035;
|
|
478
|
+
float aa = fp * 4.0 + 5e-4;
|
|
479
|
+
float land = smoothstep(-aa, aa, e);
|
|
480
|
+
float alt = max(e, 0.0);
|
|
481
|
+
float mtn = smoothstep(0.02, 0.14, alt + 0.15 * ter.x);
|
|
482
|
+
|
|
483
|
+
vec3 grad = ter.yzw * 7.0 * 0.022 * (0.35 + 2.0 * mtn) * land;
|
|
484
|
+
grad = grad * spin;
|
|
485
|
+
grad -= dot(grad, n) * n;
|
|
486
|
+
vec3 nb = normalize(n - grad);
|
|
487
|
+
|
|
488
|
+
float mid = fbm3(q * 14.0 + 1.0, fp * 14.0, 6);
|
|
489
|
+
float dry = 0.0;
|
|
490
|
+
float snow = 0.0;
|
|
491
|
+
vec3 ground = uTerrain;
|
|
492
|
+
if (land > 0.0) {
|
|
493
|
+
float fine = fbm3(q * 60.0 + 3.0, fp * 60.0, 5);
|
|
494
|
+
float moist = fbm3(q * 2.6 + 8.0, fp * 2.6, 6) + 0.15 * exp(-alt * 25.0);
|
|
495
|
+
dry = 1.0 - smoothstep(-0.12, 0.02, moist + 0.25 * mid);
|
|
496
|
+
float wet = smoothstep(-0.02, 0.12, moist + 0.2 * mid);
|
|
497
|
+
vec3 grass = uSurface * vec3(1.9, 1.55, 1.0) + vec3(0.02, 0.012, 0.0);
|
|
498
|
+
vec3 la = mix(grass, uSurface, wet);
|
|
499
|
+
la = mix(la, vec3(0.36, 0.25, 0.13) * (0.85 + 0.4 * mid), dry);
|
|
500
|
+
la = mix(la, vec3(0.1, 0.085, 0.07), mtn * 0.8);
|
|
501
|
+
snow = smoothstep(0.17, 0.22, alt + 0.06 * fine + 0.04 * mid + 0.1 * abs(q.x));
|
|
502
|
+
la = mix(la, vec3(0.8), snow);
|
|
503
|
+
la *= max(0.85 + 0.5 * fine + 0.25 * mid, 0.2);
|
|
504
|
+
ground = la;
|
|
505
|
+
}
|
|
506
|
+
float depth = max(-e, 0.0);
|
|
507
|
+
vec3 ocean = mix(uTerrain, uTerrain * vec3(0.6, 2.4, 2.0) + vec3(0.0, 0.02, 0.02), exp(-depth * 60.0));
|
|
508
|
+
ocean *= 0.9 + 0.4 * mid;
|
|
509
|
+
vec3 albedo = mix(ocean, ground, land);
|
|
510
|
+
|
|
511
|
+
float ngl = dot(n, sun);
|
|
512
|
+
float mu0 = max(dot(nb, sun), 0.0);
|
|
513
|
+
float lsl = mu0 / (mu0 + ndv + 1e-3);
|
|
514
|
+
float day = smoothstep(-0.03, 0.08, ngl);
|
|
515
|
+
float brdf = mix(mu0, lsl, 0.25) * day;
|
|
516
|
+
vec3 sunT = exp(-beta * H * chapman(X, 0.0, ngl));
|
|
517
|
+
vec3 sky = uAtmosphere * uDensity * 0.05 * smoothstep(-0.3, 0.4, ngl);
|
|
518
|
+
|
|
519
|
+
mat3 cspin = spinX(-uTime * 0.0095);
|
|
520
|
+
vec3 c = cspin * n;
|
|
521
|
+
vec3 w = cloudWarp(c, fp);
|
|
522
|
+
float cov = cloudCover(c, w, fp);
|
|
523
|
+
vec3 sunTan = sun - ngl * n;
|
|
524
|
+
sunTan = cspin * (sunTan * inversesqrt(max(dot(sunTan, sunTan), 1e-6)));
|
|
525
|
+
float shade = 1.0;
|
|
526
|
+
float relief = 1.0;
|
|
527
|
+
if (ngl > -0.06) {
|
|
528
|
+
float reach = CLOUD_H * sqrt(max(1.0 - ngl * ngl, 0.0)) / max(ngl, 0.05);
|
|
529
|
+
shade = 1.0 - 0.75 * cloudCover(c + sunTan * reach, w, fp);
|
|
530
|
+
relief = clamp(1.0 - 2.2 * (cloudCover(c + sunTan * 0.006, w, fp) - cov), 0.3, 1.25);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
vec3 color = albedo * (SUN_I * 0.9 * sunT * brdf * shade + sky + 0.004);
|
|
534
|
+
|
|
535
|
+
if (land < 1.0) {
|
|
536
|
+
vec3 v = normalize(vec3(0.0, 1.0 + ALT, 0.0) - n);
|
|
537
|
+
float wind = fbm3(q * vec3(10.0, 10.0, 34.0) + 4.2, fp * 34.0, 5);
|
|
538
|
+
float alpha = mix(0.1, 0.3, smoothstep(-0.18, 0.18, wind));
|
|
539
|
+
float a2 = alpha * alpha;
|
|
540
|
+
vec3 hv = normalize(sun + v);
|
|
541
|
+
float nh = max(dot(n, hv), 0.0);
|
|
542
|
+
float nl = max(ngl, 0.0);
|
|
543
|
+
float nv = max(dot(n, v), 1e-3);
|
|
544
|
+
float dd = nh * nh * (a2 - 1.0) + 1.0;
|
|
545
|
+
float k = alpha * 0.5;
|
|
546
|
+
float G = nl / (nl * (1.0 - k) + k) * nv / (nv * (1.0 - k) + k);
|
|
547
|
+
float F = 0.02 + 0.98 * pow(1.0 - max(dot(v, hv), 0.0), 5.0);
|
|
548
|
+
float spec = a2 / (PI * dd * dd) * G * F / (4.0 * nv) * day;
|
|
549
|
+
float Fv = 0.02 + 0.98 * pow(1.0 - nv, 5.0);
|
|
550
|
+
vec3 skyRefl = uAtmosphere * uDensity * 0.35 * smoothstep(-0.2, 0.35, ngl) * Fv;
|
|
551
|
+
color += (SUN_I * 0.9 * sunT * spec * shade + skyRefl) * (1.0 - land);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
float night = (1.0 - smoothstep(-0.08, -0.01, ngl)) * uCityLights;
|
|
555
|
+
vec3 lights = vec3(0.0);
|
|
556
|
+
if (night > 0.0 && land > 0.0) {
|
|
557
|
+
float pop = fbm3(q * 4.3 + 13.0, fp * 4.3, 5) + 0.35 * fbm3(q * 17.0 + 2.0, fp * 17.0, 4);
|
|
558
|
+
float P = smoothstep(-0.02, 0.2, pop + 0.12 * exp(-alt * 22.0) - 0.25 * dry - 0.3 * mtn - 0.5 * snow);
|
|
559
|
+
lights = cityLights(q, fp, P) * land * night;
|
|
560
|
+
color += lights;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
float ngc = ngl + 0.055;
|
|
564
|
+
vec3 sunTc = exp(-beta * H * chapman(X, CLOUD_H / H, ngl));
|
|
565
|
+
float cBrdf = mix(max(ngc, 0.0), ngc / (abs(ngc) + ndv + 1e-3), 0.3) * smoothstep(0.0, 0.1, ngc) * relief;
|
|
566
|
+
vec3 cloud = vec3(0.78) * (SUN_I * 0.9 * sunTc * max(cBrdf, 0.0) + sky * 2.0 + 0.004);
|
|
567
|
+
cloud += lights * 0.12;
|
|
568
|
+
return mix(color, cloud, cov);
|
|
569
|
+
}
|
|
570
|
+
`;
|
|
571
|
+
|
|
572
|
+
const MAIN = `
|
|
573
|
+
void main() {
|
|
574
|
+
vec2 frag = gl_FragCoord.xy;
|
|
575
|
+
vec2 uv = (frag - 0.5 * uResolution) / uResolution.y;
|
|
576
|
+
vec2 ptr = uPointer / uResolution;
|
|
577
|
+
float pixAngle = 1.0 / (uResolution.y * FL);
|
|
578
|
+
|
|
579
|
+
float D = 1.0 + ALT;
|
|
580
|
+
float dip = acos(1.0 / D);
|
|
581
|
+
float yaw = (ptr.x - 0.5) * 0.04;
|
|
582
|
+
float pitch = dip + atan((0.5 - uHorizon) / FL) + (ptr.y - 0.5) * 0.015;
|
|
583
|
+
vec3 ro = vec3(0.0, D, 0.0);
|
|
584
|
+
vec3 fw = vec3(sin(yaw) * cos(pitch), -sin(pitch), -cos(yaw) * cos(pitch));
|
|
585
|
+
vec3 right = normalize(cross(fw, vec3(0.0, 1.0, 0.0)));
|
|
586
|
+
vec3 up = cross(right, fw);
|
|
587
|
+
vec3 rd = normalize(uv.x * right + uv.y * up + FL * fw);
|
|
588
|
+
|
|
589
|
+
vec2 sunRef = mix(ptr, uSunPos, uSunFixed);
|
|
590
|
+
float az = -0.85 + (sunRef.x - 0.5) * 1.2;
|
|
591
|
+
float el = -0.24 - (sunRef.y - 0.5) * 0.3;
|
|
592
|
+
vec3 sun = normalize(vec3(sin(az) * cos(el), sin(el), -cos(az) * cos(el)));
|
|
593
|
+
|
|
594
|
+
vec3 beta = uAtmosphere * 7.0 * uDensity + 1e-4;
|
|
595
|
+
float X = 1.0 / H;
|
|
596
|
+
|
|
597
|
+
float b = dot(ro, rd);
|
|
598
|
+
float tc = -b;
|
|
599
|
+
float impact = sqrt(max(dot(ro, ro) - b * b, 0.0));
|
|
600
|
+
float coverage = clamp(0.5 - (impact - 1.0) / (tc * pixAngle), 0.0, 1.0);
|
|
601
|
+
float disc = b * b - dot(ro, ro) + 1.0;
|
|
602
|
+
float tPlanet = disc > 0.0 ? -b - sqrt(disc) : tc;
|
|
603
|
+
|
|
604
|
+
float mu = dot(rd, sun);
|
|
605
|
+
float sunAng = sqrt(max(2.0 * (1.0 - mu), 0.0));
|
|
606
|
+
vec3 space = stars(rd, pixAngle);
|
|
607
|
+
space += vec3(1.0, 0.96, 0.9) * 60.0 * smoothstep(SUN_R, SUN_R * 0.75, sunAng) * uSun;
|
|
608
|
+
|
|
609
|
+
vec3 background = space;
|
|
610
|
+
if (coverage > 0.0) {
|
|
611
|
+
vec3 n = normalize(ro + rd * tPlanet);
|
|
612
|
+
float ndv = max(dot(n, -rd), 0.0);
|
|
613
|
+
vec3 surface = shadeSurface(n, ndv, tPlanet * pixAngle, sun, beta, X);
|
|
614
|
+
background = mix(space, surface, coverage);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
vec3 inscatter = vec3(0.0);
|
|
618
|
+
vec3 trans = vec3(1.0);
|
|
619
|
+
float bA = b * b - dot(ro, ro) + RT * RT;
|
|
620
|
+
if (bA > 0.0) {
|
|
621
|
+
float t0 = max(-b - sqrt(bA), 0.0);
|
|
622
|
+
float t1 = mix(-b + sqrt(bA), tPlanet, coverage);
|
|
623
|
+
float tm = clamp(tc, t0, t1);
|
|
624
|
+
float jitter = fract(52.9829189 * fract(dot(frag, vec2(0.06711056, 0.00583715))));
|
|
625
|
+
float du = 1.0 / float(HALF);
|
|
626
|
+
float od = 0.0;
|
|
627
|
+
vec3 scat = vec3(0.0);
|
|
628
|
+
for (int i = 0; i < 2 * HALF; i++) {
|
|
629
|
+
bool near = i < HALF;
|
|
630
|
+
float u = ((near ? float(HALF - 1 - i) : float(i - HALF)) + jitter) * du;
|
|
631
|
+
float len = near ? tm - t0 : t1 - tm;
|
|
632
|
+
float t = near ? tm - len * u * u : tm + len * u * u;
|
|
633
|
+
vec3 p = ro + rd * t;
|
|
634
|
+
float r = length(p);
|
|
635
|
+
float h = max(r - 1.0, 0.0) / H;
|
|
636
|
+
float dens = exp(-h) * 2.0 * u * len * du;
|
|
637
|
+
float odSun = H * chapman(X, h, dot(p, sun) / r);
|
|
638
|
+
scat += dens * exp(-beta * (od + 0.5 * dens + odSun));
|
|
639
|
+
od += dens;
|
|
640
|
+
}
|
|
641
|
+
trans = exp(-beta * od);
|
|
642
|
+
float g = 0.76;
|
|
643
|
+
float phaseR = 3.0 / (16.0 * PI) * (1.0 + mu * mu);
|
|
644
|
+
float phaseM = (1.0 - g * g) / (4.0 * PI * pow(1.0 + g * g - 2.0 * g * mu, 1.5));
|
|
645
|
+
inscatter = SUN_I * 7.0 * beta * scat * mix(phaseR, phaseM, 0.4 - 0.25 * coverage);
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
vec3 color = inscatter + trans * background;
|
|
649
|
+
|
|
650
|
+
vec3 toCenter = -normalize(ro);
|
|
651
|
+
float sunCos = dot(sun, toCenter);
|
|
652
|
+
float clearance = acos(clamp(sunCos, -1.0, 1.0)) - asin(1.0 / D);
|
|
653
|
+
float sunImpact = D * sqrt(max(1.0 - sunCos * sunCos, 0.0));
|
|
654
|
+
float hs = max(sunImpact - 1.0, 0.0) / H;
|
|
655
|
+
vec3 sunTrans = sunCos > 0.0 ? exp(-beta * H * 2.0 * sqrt(X + hs) * exp(-hs)) : vec3(1.0);
|
|
656
|
+
float sunVis = smoothstep(-SUN_R, SUN_R * 2.0, clearance);
|
|
657
|
+
vec2 sunUv = vec2(dot(sun, right), dot(sun, up)) / max(dot(sun, fw), 1e-3) * FL;
|
|
658
|
+
vec2 sd = uv - sunUv;
|
|
659
|
+
float glow = 0.9 * exp(-sunAng * 30.0) + 0.1 * exp(-sunAng * 7.0) + 0.015 * exp(-sunAng * 2.0);
|
|
660
|
+
float streak = exp(-abs(sd.y) * 110.0) * exp(-abs(sd.x) * 3.0) * 0.08 * step(0.0, dot(sun, fw));
|
|
661
|
+
color += vec3(1.0, 0.93, 0.85) * sunTrans * sunVis * (glow + streak) * uSun;
|
|
662
|
+
|
|
663
|
+
color *= 1.0 - 0.35 * dot(uv * vec2(0.6, 1.0), uv * vec2(0.6, 1.0));
|
|
664
|
+
color = pow(aces(color * 0.9), vec3(1.0 / 2.2));
|
|
665
|
+
color += (hash12(frag + fract(uTime)) - 0.5) / 255.0;
|
|
666
|
+
|
|
667
|
+
gl_FragColor = vec4(color, 1.0);
|
|
668
|
+
}
|
|
669
|
+
`;
|
|
670
|
+
|
|
671
|
+
const SHADERS: Record<PlanetKind, string> = {
|
|
672
|
+
mars: COMMON + RELIEF + MARS_SURFACE + MAIN,
|
|
673
|
+
jupiter: COMMON + JUPITER_SURFACE + MAIN,
|
|
674
|
+
earth: COMMON + RELIEF + EARTH_SURFACE + MAIN,
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
export function Planet({
|
|
678
|
+
children,
|
|
679
|
+
className,
|
|
680
|
+
planet = 'mars',
|
|
681
|
+
color,
|
|
682
|
+
terrainColor,
|
|
683
|
+
atmosphereColor,
|
|
684
|
+
atmosphere,
|
|
685
|
+
craters = 0.6,
|
|
686
|
+
cityLights = true,
|
|
687
|
+
stars = 0.6,
|
|
688
|
+
horizon = 0.62,
|
|
689
|
+
speed = 1,
|
|
690
|
+
sun = false,
|
|
691
|
+
sunPosition,
|
|
692
|
+
interactive = true,
|
|
693
|
+
}: PlanetProps) {
|
|
694
|
+
const preset = PLANET_PRESETS[planet] ?? PLANET_PRESETS.mars;
|
|
695
|
+
const surfaceColor = color ?? preset.color;
|
|
696
|
+
const darkColor = terrainColor ?? preset.terrainColor;
|
|
697
|
+
const airColor = atmosphereColor ?? preset.atmosphereColor;
|
|
698
|
+
const density = atmosphere ?? preset.atmosphere;
|
|
699
|
+
|
|
700
|
+
const canvasRef = useShaderCanvas({
|
|
701
|
+
fragmentShader: SHADERS[planet] ?? SHADERS.mars,
|
|
702
|
+
speed,
|
|
703
|
+
interactive,
|
|
704
|
+
onDraw: ({ gl, uniform }) => {
|
|
705
|
+
const clamp01 = (value: number) => Math.min(1, Math.max(0, value));
|
|
706
|
+
gl.uniform3fv(uniform('uSurface'), hexToLinearRgb(surfaceColor));
|
|
707
|
+
gl.uniform3fv(uniform('uTerrain'), hexToLinearRgb(darkColor));
|
|
708
|
+
gl.uniform3fv(uniform('uAtmosphere'), hexToLinearRgb(airColor));
|
|
709
|
+
gl.uniform1f(uniform('uDensity'), clamp01(density));
|
|
710
|
+
gl.uniform1f(uniform('uCraters'), clamp01(craters));
|
|
711
|
+
gl.uniform1f(uniform('uCityLights'), cityLights ? 1 : 0);
|
|
712
|
+
gl.uniform1f(uniform('uStars'), clamp01(stars));
|
|
713
|
+
gl.uniform1f(uniform('uHorizon'), Math.min(0.95, Math.max(0.05, horizon)));
|
|
714
|
+
gl.uniform1f(uniform('uSun'), sun ? 1 : 0);
|
|
715
|
+
gl.uniform2f(uniform('uSunPos'), clamp01(sunPosition?.x ?? 0.5), clamp01(sunPosition?.y ?? 0.5));
|
|
716
|
+
gl.uniform1f(uniform('uSunFixed'), sunPosition ? 1 : 0);
|
|
717
|
+
},
|
|
718
|
+
});
|
|
719
|
+
|
|
720
|
+
return (
|
|
721
|
+
<div
|
|
722
|
+
className={cn('elyri-planet', className)}
|
|
723
|
+
data-planet={planet}
|
|
724
|
+
style={
|
|
725
|
+
{
|
|
726
|
+
'--elyri-planet-color': surfaceColor,
|
|
727
|
+
'--elyri-planet-atmosphere': airColor,
|
|
728
|
+
'--elyri-planet-horizon': `${horizon * 100}%`,
|
|
729
|
+
} as CSSProperties
|
|
730
|
+
}
|
|
731
|
+
>
|
|
732
|
+
<canvas ref={canvasRef} className="elyri-planet__canvas" aria-hidden="true" />
|
|
733
|
+
{children != null && <div className="elyri-planet__content">{children}</div>}
|
|
734
|
+
</div>
|
|
735
|
+
);
|
|
736
|
+
}
|