@tableslayer/ui 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -13
- package/src/lib/components/Avatar/Avatar.svelte +82 -0
- package/src/lib/components/Avatar/AvatarFileInput.svelte +85 -0
- package/src/lib/components/Avatar/AvatarPopover.svelte +34 -0
- package/src/lib/components/Avatar/index.ts +4 -0
- package/src/lib/components/Avatar/types.ts +24 -0
- package/src/lib/components/BrushSizeSlider/BrushSizeSlider.svelte +174 -0
- package/src/lib/components/BrushSizeSlider/index.ts +1 -0
- package/src/lib/components/Button/Button.svelte +182 -0
- package/src/lib/components/Button/ConfirmActionButton.svelte +98 -0
- package/src/lib/components/Button/IconButton.svelte +121 -0
- package/src/lib/components/Button/RadioButton.svelte +93 -0
- package/src/lib/components/Button/index.ts +5 -0
- package/src/lib/components/Button/types.ts +54 -0
- package/src/lib/components/CardFan/CardFan.svelte +165 -0
- package/src/lib/components/CardFan/index.ts +2 -0
- package/src/lib/components/CardFan/types.ts +6 -0
- package/src/lib/components/CodeBlock/Code.svelte +7 -0
- package/src/lib/components/CodeBlock/CodeBlock.svelte +102 -0
- package/src/lib/components/CodeBlock/index.ts +3 -0
- package/src/lib/components/CodeBlock/types.ts +10 -0
- package/src/lib/components/ColorMode/ColorMode.svelte +8 -0
- package/src/lib/components/ColorMode/index.ts +2 -0
- package/src/lib/components/ColorMode/types.ts +12 -0
- package/src/lib/components/ColorPicker/ColorPicker.svelte +838 -0
- package/src/lib/components/ColorPicker/ColorPickerSwatch.svelte +32 -0
- package/src/lib/components/ColorPicker/index.ts +3 -0
- package/src/lib/components/ColorPicker/types.ts +51 -0
- package/src/lib/components/ContextMenu/ContextMenu.svelte +86 -0
- package/src/lib/components/ContextMenu/index.ts +2 -0
- package/src/lib/components/ContextMenu/types.ts +15 -0
- package/src/lib/components/DrawingSliders/DrawingSliders.svelte +379 -0
- package/src/lib/components/DrawingSliders/index.ts +1 -0
- package/src/lib/components/Editor/Editor.svelte +825 -0
- package/src/lib/components/Editor/index.ts +1 -0
- package/src/lib/components/FogSliders/FogSliders.svelte +33 -0
- package/src/lib/components/FogSliders/index.ts +1 -0
- package/src/lib/components/Hr/Hr.svelte +15 -0
- package/src/lib/components/Hr/index.ts +1 -0
- package/src/lib/components/Icon/Icon.svelte +6 -0
- package/src/lib/components/Icon/index.ts +2 -0
- package/src/lib/components/Icon/types.ts +20 -0
- package/src/lib/components/Input/DualInputSlider.svelte +126 -0
- package/src/lib/components/Input/FileInput.svelte +176 -0
- package/src/lib/components/Input/FormControl.svelte +150 -0
- package/src/lib/components/Input/FormError.svelte +37 -0
- package/src/lib/components/Input/Input.svelte +56 -0
- package/src/lib/components/Input/InputCheckbox.svelte +99 -0
- package/src/lib/components/Input/InputSlider.svelte +86 -0
- package/src/lib/components/Input/Label.svelte +19 -0
- package/src/lib/components/Input/index.ts +9 -0
- package/src/lib/components/Input/types.ts +39 -0
- package/src/lib/components/Link/Link.svelte +41 -0
- package/src/lib/components/Link/LinkBox.svelte +20 -0
- package/src/lib/components/Link/LinkOverlay.svelte +23 -0
- package/src/lib/components/Link/index.ts +4 -0
- package/src/lib/components/Link/types.ts +17 -0
- package/src/lib/components/Loading/Loader.svelte +60 -0
- package/src/lib/components/Loading/Skeleton.svelte +9 -0
- package/src/lib/components/Loading/index.ts +2 -0
- package/src/lib/components/Logo/Logo.svelte +16 -0
- package/src/lib/components/Logo/index.ts +1 -0
- package/src/lib/components/MarkerTooltip/MarkerTooltip.svelte +435 -0
- package/src/lib/components/MarkerTooltip/index.ts +1 -0
- package/src/lib/components/Menu/SelectorMenu.svelte +280 -0
- package/src/lib/components/Menu/index.ts +2 -0
- package/src/lib/components/Menu/types.ts +17 -0
- package/src/lib/components/MyCounterButton.svelte +11 -0
- package/src/lib/components/Panel/index.ts +2 -0
- package/src/lib/components/Panel/panel.svelte +18 -0
- package/src/lib/components/Panel/types.ts +8 -0
- package/src/lib/components/PersistButton/PersistButton.svelte +100 -0
- package/src/lib/components/PersistButton/index.ts +1 -0
- package/src/lib/components/Popover/Popover.svelte +81 -0
- package/src/lib/components/Popover/index.ts +2 -0
- package/src/lib/components/Popover/types.ts +19 -0
- package/src/lib/components/PropsTable/PropsTable.svelte +107 -0
- package/src/lib/components/RadialMenu/EffectPreview.svelte +36 -0
- package/src/lib/components/RadialMenu/EffectPreviewScene.svelte +194 -0
- package/src/lib/components/RadialMenu/RadialMenu.svelte +503 -0
- package/src/lib/components/RadialMenu/RadialMenuItem.svelte +176 -0
- package/src/lib/components/RadialMenu/index.ts +2 -0
- package/src/lib/components/RadialMenu/types.ts +35 -0
- package/src/lib/components/Select/Select.svelte +342 -0
- package/src/lib/components/Select/index.ts +2 -0
- package/src/lib/components/Select/types.ts +22 -0
- package/src/lib/components/Spacer/Spacer.svelte +14 -0
- package/src/lib/components/Spacer/index.ts +2 -0
- package/src/lib/components/Spacer/types.ts +5 -0
- package/src/lib/components/Stage/components/AnnotationLayer/AnnotationLayer.svelte +445 -0
- package/src/lib/components/Stage/components/AnnotationLayer/AnnotationMaterial.svelte +167 -0
- package/src/lib/components/Stage/components/AnnotationLayer/types.ts +196 -0
- package/src/lib/components/Stage/components/CursorLayer/CursorLayer.svelte +148 -0
- package/src/lib/components/Stage/components/CursorLayer/cursor.svg +26 -0
- package/src/lib/components/Stage/components/CursorLayer/index.ts +2 -0
- package/src/lib/components/Stage/components/CursorLayer/types.ts +23 -0
- package/src/lib/components/Stage/components/DrawingLayer/DrawingMaterial.svelte +364 -0
- package/src/lib/components/Stage/components/DrawingLayer/types.ts +65 -0
- package/src/lib/components/Stage/components/EdgeOverlayLayer/EdgeOverlayLayer.svelte +72 -0
- package/src/lib/components/Stage/components/EdgeOverlayLayer/types.ts +34 -0
- package/src/lib/components/Stage/components/FogLayer/FogLayer.svelte +75 -0
- package/src/lib/components/Stage/components/FogLayer/types.ts +51 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarLayer.svelte +249 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/FogOfWarMaterial.svelte +200 -0
- package/src/lib/components/Stage/components/FogOfWarLayer/types.ts +116 -0
- package/src/lib/components/Stage/components/GridLayer/GridLayer.svelte +20 -0
- package/src/lib/components/Stage/components/GridLayer/GridMaterial.svelte +69 -0
- package/src/lib/components/Stage/components/GridLayer/types.ts +79 -0
- package/src/lib/components/Stage/components/LayerInput/LayerInput.svelte +300 -0
- package/src/lib/components/Stage/components/MapLayer/MapLayer.svelte +196 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/GifDataSource.ts +265 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/IMapDataSource.ts +55 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/ImageDataSource.ts +87 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/VideoDataSource.ts +150 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/dataSourceFactory.ts +48 -0
- package/src/lib/components/Stage/components/MapLayer/dataSources/index.ts +16 -0
- package/src/lib/components/Stage/components/MapLayer/types.ts +58 -0
- package/src/lib/components/Stage/components/MarkerLayer/MarkerLayer.svelte +398 -0
- package/src/lib/components/Stage/components/MarkerLayer/MarkerToken.svelte +262 -0
- package/src/lib/components/Stage/components/MarkerLayer/types.ts +126 -0
- package/src/lib/components/Stage/components/MeasurementLayer/MeasurementLayer.svelte +364 -0
- package/src/lib/components/Stage/components/MeasurementLayer/MeasurementManager.svelte +473 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/BaseMeasurement.ts +427 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/BeamMeasurement.ts +105 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/CircleMeasurement.ts +98 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/ConeMeasurement.ts +163 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/LineMeasurement.ts +102 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/RectangleMeasurement.ts +120 -0
- package/src/lib/components/Stage/components/MeasurementLayer/measurements/index.ts +7 -0
- package/src/lib/components/Stage/components/MeasurementLayer/types.ts +94 -0
- package/src/lib/components/Stage/components/MeasurementLayer/utils/canvasDrawing.ts +357 -0
- package/src/lib/components/Stage/components/MeasurementLayer/utils/distanceCalculations.ts +170 -0
- package/src/lib/components/Stage/components/ParticleSystem/ParticleSystem.svelte +220 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/ash.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/leaves.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/rain.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/particles/atlases/snow.png +0 -0
- package/src/lib/components/Stage/components/ParticleSystem/rng.js +20 -0
- package/src/lib/components/Stage/components/ParticleSystem/types.ts +95 -0
- package/src/lib/components/Stage/components/PerformanceDebugger/PerformanceDebugger.svelte +144 -0
- package/src/lib/components/Stage/components/PerformanceDebugger/index.ts +1 -0
- package/src/lib/components/Stage/components/PerformanceOverlay/PerformanceOverlay.svelte +208 -0
- package/src/lib/components/Stage/components/PerformanceOverlay/index.ts +1 -0
- package/src/lib/components/Stage/components/PointerInputManager/PointerInputManager.svelte +201 -0
- package/src/lib/components/Stage/components/Scene/Scene.svelte +651 -0
- package/src/lib/components/Stage/components/Scene/luts.ts +24 -0
- package/src/lib/components/Stage/components/Scene/types.ts +225 -0
- package/src/lib/components/Stage/components/Stage/Stage.svelte +332 -0
- package/src/lib/components/Stage/components/Stage/types.ts +136 -0
- package/src/lib/components/Stage/components/WeatherLayer/WeatherLayer.svelte +135 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/AshPreset.ts +71 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/LeavesPreset.ts +70 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/RainPreset.ts +68 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/SnowPreset.ts +70 -0
- package/src/lib/components/Stage/components/WeatherLayer/presets/index.ts +6 -0
- package/src/lib/components/Stage/components/WeatherLayer/types.ts +35 -0
- package/src/lib/components/Stage/helpers/clippingPlaneStore.svelte.ts +28 -0
- package/src/lib/components/Stage/helpers/debugState.svelte.ts +18 -0
- package/src/lib/components/Stage/helpers/grid.ts +548 -0
- package/src/lib/components/Stage/helpers/lazyBrush.ts +171 -0
- package/src/lib/components/Stage/helpers/performanceMetrics.svelte.ts +220 -0
- package/src/lib/components/Stage/helpers/utils.ts +21 -0
- package/src/lib/components/Stage/index.ts +49 -0
- package/src/lib/components/Stage/shaders/AnnotationEffects.frag +1070 -0
- package/src/lib/components/Stage/shaders/Annotations.frag +29 -0
- package/src/lib/components/Stage/shaders/Drawing.frag +83 -0
- package/src/lib/components/Stage/shaders/Drawing.vert +5 -0
- package/src/lib/components/Stage/shaders/Fog.frag +147 -0
- package/src/lib/components/Stage/shaders/FractalNoise.frag +96 -0
- package/src/lib/components/Stage/shaders/GridShader.frag +174 -0
- package/src/lib/components/Stage/shaders/Overlay.frag +23 -0
- package/src/lib/components/Stage/shaders/Overlay.vert +0 -0
- package/src/lib/components/Stage/shaders/Particles.frag +27 -0
- package/src/lib/components/Stage/shaders/Particles.vert +51 -0
- package/src/lib/components/Stage/shaders/ToolOutline.frag +59 -0
- package/src/lib/components/Stage/shaders/default.vert +8 -0
- package/src/lib/components/Stage/types.ts +4 -0
- package/src/lib/components/Table/Table.svelte +16 -0
- package/src/lib/components/Table/Td.svelte +17 -0
- package/src/lib/components/Table/Th.svelte +18 -0
- package/src/lib/components/Table/index.ts +4 -0
- package/src/lib/components/Table/types.ts +14 -0
- package/src/lib/components/Text/Text.svelte +23 -0
- package/src/lib/components/Text/index.ts +2 -0
- package/src/lib/components/Text/types.ts +12 -0
- package/src/lib/components/Title/Title.svelte +54 -0
- package/src/lib/components/Title/index.ts +2 -0
- package/src/lib/components/Title/types.ts +9 -0
- package/src/lib/components/Toast/Toast.svelte +155 -0
- package/src/lib/components/Toast/index.ts +5 -0
- package/src/lib/components/Toast/toastCookie.ts +24 -0
- package/src/lib/components/Toast/types.ts +6 -0
- package/src/lib/components/ToolTip/ToolTip.svelte +70 -0
- package/src/lib/components/ToolTip/index.ts +2 -0
- package/src/lib/components/ToolTip/types.ts +14 -0
- package/src/lib/components/index.ts +32 -0
- package/src/lib/components/types.ts +0 -0
- package/src/lib/index.ts +2 -0
- package/src/lib/styles/globals.css +108 -0
- package/src/lib/styles/normalize.css +9 -0
- package/src/lib/styles/reset.css +133 -0
- package/src/lib/styles/utilities.css +179 -0
- package/src/lib/styles/vars.css +1103 -0
- package/src/lib/types/awareness.ts +17 -0
- package/src/lib/utils/rle.ts +217 -0
|
@@ -0,0 +1,1070 @@
|
|
|
1
|
+
precision highp float;
|
|
2
|
+
|
|
3
|
+
uniform sampler2D uMaskTexture;
|
|
4
|
+
uniform float uTime;
|
|
5
|
+
uniform int uEffectType;
|
|
6
|
+
uniform vec3 uBaseColor;
|
|
7
|
+
uniform float uOpacity;
|
|
8
|
+
uniform float uSpeed;
|
|
9
|
+
uniform float uIntensity;
|
|
10
|
+
uniform float uSoftness;
|
|
11
|
+
uniform float uBorder;
|
|
12
|
+
uniform float uRoughness;
|
|
13
|
+
|
|
14
|
+
uniform int uEdgeMinMipMapLevel;
|
|
15
|
+
uniform int uEdgeMaxMipMapLevel;
|
|
16
|
+
|
|
17
|
+
uniform vec4 uClippingPlanes[NUM_CLIPPING_PLANES];
|
|
18
|
+
|
|
19
|
+
varying vec2 vUv;
|
|
20
|
+
varying vec3 vWorldPosition;
|
|
21
|
+
|
|
22
|
+
// Simplex noise from ashima/webgl-noise
|
|
23
|
+
vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
|
24
|
+
vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; }
|
|
25
|
+
vec3 permute(vec3 x) { return mod289(((x * 34.0) + 1.0) * x); }
|
|
26
|
+
|
|
27
|
+
float snoise(vec2 v) {
|
|
28
|
+
const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439);
|
|
29
|
+
vec2 i = floor(v + dot(v, C.yy));
|
|
30
|
+
vec2 x0 = v - i + dot(i, C.xx);
|
|
31
|
+
vec2 i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0);
|
|
32
|
+
vec4 x12 = x0.xyxy + C.xxzz;
|
|
33
|
+
x12.xy -= i1;
|
|
34
|
+
i = mod289(i);
|
|
35
|
+
vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0));
|
|
36
|
+
vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0);
|
|
37
|
+
m = m * m * m * m;
|
|
38
|
+
vec3 x = 2.0 * fract(p * C.www) - 1.0;
|
|
39
|
+
vec3 h = abs(x) - 0.5;
|
|
40
|
+
vec3 ox = floor(x + 0.5);
|
|
41
|
+
vec3 a0 = x - ox;
|
|
42
|
+
m *= 1.79284291400159 - 0.85373472095314 * (a0 * a0 + h * h);
|
|
43
|
+
vec3 g;
|
|
44
|
+
g.x = a0.x * x0.x + h.x * x0.y;
|
|
45
|
+
g.yz = a0.yz * x12.xz + h.yz * x12.yw;
|
|
46
|
+
return 130.0 * dot(m, g);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Fractal Brownian Motion
|
|
50
|
+
float fbm(vec2 p, int octaves, float persistence, float lacunarity) {
|
|
51
|
+
float sum = 0.0;
|
|
52
|
+
float amp = 1.0;
|
|
53
|
+
float freq = 1.0;
|
|
54
|
+
float maxSum = 0.0;
|
|
55
|
+
for(int i = 0; i < 8; i++) {
|
|
56
|
+
if(i >= octaves) break;
|
|
57
|
+
sum += amp * snoise(p * freq);
|
|
58
|
+
maxSum += amp;
|
|
59
|
+
amp *= persistence;
|
|
60
|
+
freq *= lacunarity;
|
|
61
|
+
}
|
|
62
|
+
return sum / maxSum;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Simplified fbm for performance
|
|
66
|
+
float fbm3(vec2 p) {
|
|
67
|
+
return fbm(p, 3, 0.5, 2.0);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
float fbm5(vec2 p) {
|
|
71
|
+
return fbm(p, 5, 0.5, 2.0);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// Domain warping - creates organic, natural patterns (Inigo Quilez technique)
|
|
75
|
+
float domainWarp(vec2 p, float time) {
|
|
76
|
+
vec2 q = vec2(fbm3(p + vec2(0.0, 0.0) + time * 0.1),
|
|
77
|
+
fbm3(p + vec2(5.2, 1.3) + time * 0.15));
|
|
78
|
+
vec2 r = vec2(fbm3(p + 4.0 * q + vec2(1.7, 9.2) + time * 0.2),
|
|
79
|
+
fbm3(p + 4.0 * q + vec2(8.3, 2.8) + time * 0.1));
|
|
80
|
+
return fbm3(p + 4.0 * r);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Get feathered mask with animated rolling edges (like Fog.frag)
|
|
84
|
+
float getVolumeMask(vec2 uv, vec2 texSize, float time, float edgeFreq, float edgeAmp, float edgeSpeed) {
|
|
85
|
+
// === ROUGHNESS: Add jagged edges via UV displacement ===
|
|
86
|
+
// Multiple noise frequencies for organic, random-looking edges
|
|
87
|
+
vec2 roughnessUV = uv * texSize * 0.008;
|
|
88
|
+
|
|
89
|
+
// Layer 1: Medium-scale jagged edges
|
|
90
|
+
float roughNoise1 = snoise(roughnessUV * 3.0 + time * 0.02);
|
|
91
|
+
float roughNoise2 = snoise(roughnessUV * 3.0 + vec2(50.0, 50.0) + time * 0.015);
|
|
92
|
+
|
|
93
|
+
// Layer 2: Fine detail roughness
|
|
94
|
+
float roughNoise3 = snoise(roughnessUV * 8.0 + time * 0.01);
|
|
95
|
+
float roughNoise4 = snoise(roughnessUV * 8.0 + vec2(100.0, 100.0) + time * 0.008);
|
|
96
|
+
|
|
97
|
+
// Layer 3: Large-scale variation
|
|
98
|
+
float roughNoise5 = snoise(roughnessUV * 1.0 + time * 0.005);
|
|
99
|
+
|
|
100
|
+
// Combine noise layers
|
|
101
|
+
vec2 roughnessOffset = vec2(
|
|
102
|
+
roughNoise1 * 0.5 + roughNoise3 * 0.3 + roughNoise5 * 0.2,
|
|
103
|
+
roughNoise2 * 0.5 + roughNoise4 * 0.3 + roughNoise5 * 0.2
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Scale offset by roughness - max displacement of ~3% of texture size
|
|
107
|
+
float roughnessStrength = uRoughness * 0.03;
|
|
108
|
+
vec2 displacedUV = uv + roughnessOffset * roughnessStrength;
|
|
109
|
+
|
|
110
|
+
// Remap softness to a much higher range
|
|
111
|
+
// 0 -> 0.8, 1 -> 2.0 (very strong effect across the board)
|
|
112
|
+
float softnessFactor = uSoftness * 1.2 + 0.8;
|
|
113
|
+
|
|
114
|
+
// Sample mask at multiple mipmap levels for soft edges
|
|
115
|
+
// Always sample at least 7 mip levels, up to 12 at max softness
|
|
116
|
+
float featheredMask = 0.0;
|
|
117
|
+
float totalWeight = 0.0;
|
|
118
|
+
int maxMip = int(7.0 + uSoftness * 5.0); // 7-12 mip levels
|
|
119
|
+
|
|
120
|
+
for(int i = 0; i <= 12; i++) {
|
|
121
|
+
if(i > maxMip) break;
|
|
122
|
+
// Higher softness = much more weight on higher mip levels
|
|
123
|
+
float weight = 1.0 + float(i) * softnessFactor;
|
|
124
|
+
// Use displaced UV for roughness effect
|
|
125
|
+
featheredMask += textureLod(uMaskTexture, displacedUV, float(i)).a * weight;
|
|
126
|
+
totalWeight += weight;
|
|
127
|
+
}
|
|
128
|
+
featheredMask /= totalWeight;
|
|
129
|
+
featheredMask = clamp(featheredMask, 0.0, 1.0);
|
|
130
|
+
|
|
131
|
+
// Edge width scales with softness - even wider range
|
|
132
|
+
float edgeWidth = 0.45 + uSoftness * 0.45; // 0.45-0.9 based on softness
|
|
133
|
+
|
|
134
|
+
// Create edge mask - only non-zero near the transition zone
|
|
135
|
+
float edgeMask = smoothstep(0.0, edgeWidth, featheredMask) *
|
|
136
|
+
(1.0 - smoothstep(1.0 - edgeWidth, 1.0, featheredMask));
|
|
137
|
+
|
|
138
|
+
// Add animated noise to the edges for rolling effect
|
|
139
|
+
// Scale noise UV based on softness (larger softness = larger scale noise)
|
|
140
|
+
float noiseScale = 0.005 + uSoftness * 0.008;
|
|
141
|
+
vec2 noiseUV = uv * texSize * noiseScale;
|
|
142
|
+
float edgeNoise = snoise(noiseUV * edgeFreq + time * edgeSpeed);
|
|
143
|
+
|
|
144
|
+
// Additional lower frequency noise for broader variance
|
|
145
|
+
float broadNoise = snoise(noiseUV * edgeFreq * 0.2 + time * edgeSpeed * 0.3);
|
|
146
|
+
|
|
147
|
+
// Blend noise at edges - combine frequencies for natural look
|
|
148
|
+
// More softness = more noise influence
|
|
149
|
+
float noiseInfluence = edgeAmp * (1.5 + uSoftness * 1.0);
|
|
150
|
+
float combinedNoise = edgeNoise * 0.5 + broadNoise * 0.5;
|
|
151
|
+
float finalMask = featheredMask + combinedNoise * noiseInfluence * edgeMask;
|
|
152
|
+
|
|
153
|
+
finalMask = clamp(finalMask, 0.0, 1.0);
|
|
154
|
+
|
|
155
|
+
// Outer falloff curve - softness controls how gradual the fade is
|
|
156
|
+
// Even at 0, we want a decent fade. At 1, very gradual fade.
|
|
157
|
+
float fadeStart = 0.2 - uSoftness * 0.18; // 0.2 to 0.02
|
|
158
|
+
float fadeEnd = 0.35 - uSoftness * 0.25; // 0.35 to 0.1
|
|
159
|
+
|
|
160
|
+
// Create smooth falloff - values below fadeEnd fade gradually to 0
|
|
161
|
+
float outerFalloff = smoothstep(0.0, fadeStart + 0.1, finalMask);
|
|
162
|
+
float innerRegion = smoothstep(fadeEnd, fadeEnd + 0.25, finalMask);
|
|
163
|
+
|
|
164
|
+
// Mix creates gradual fade at edges, solid in center
|
|
165
|
+
// Higher softness = more gradual outer fade (lower max for outerFalloff)
|
|
166
|
+
float outerMax = 0.65 - uSoftness * 0.35; // 0.65 to 0.3
|
|
167
|
+
return mix(outerFalloff * outerMax, 1.0, innerRegion);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Calculate edge intensity for distortion amplification
|
|
171
|
+
// Returns higher values near the mask boundaries (both inside and outside)
|
|
172
|
+
float getEdgeDistortion(vec2 uv, vec2 texSize) {
|
|
173
|
+
// Sample at multiple mip levels to get soft edge detection
|
|
174
|
+
float mask0 = textureLod(uMaskTexture, uv, 0.0).a;
|
|
175
|
+
float mask2 = textureLod(uMaskTexture, uv, 2.0).a;
|
|
176
|
+
float mask4 = textureLod(uMaskTexture, uv, 4.0).a;
|
|
177
|
+
float mask6 = textureLod(uMaskTexture, uv, 6.0).a;
|
|
178
|
+
|
|
179
|
+
// Edge is where there's difference between sharp and blurred versions
|
|
180
|
+
float edge = abs(mask0 - mask4) + abs(mask2 - mask6) * 0.5;
|
|
181
|
+
|
|
182
|
+
// Also detect transition zones in the blurred mask
|
|
183
|
+
float transitionZone = smoothstep(0.1, 0.4, mask4) * (1.0 - smoothstep(0.6, 0.9, mask4));
|
|
184
|
+
|
|
185
|
+
// Combine edge detection methods
|
|
186
|
+
float edgeIntensity = edge * 2.0 + transitionZone;
|
|
187
|
+
|
|
188
|
+
// Scale by softness - more softness = wider edge distortion zone
|
|
189
|
+
edgeIntensity *= (1.0 + uSoftness * 1.5);
|
|
190
|
+
|
|
191
|
+
return clamp(edgeIntensity, 0.0, 1.0);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
// Helper: get fire color from intensity
|
|
195
|
+
vec3 getFireColor(float t) {
|
|
196
|
+
vec3 black = vec3(0.1, 0.0, 0.0);
|
|
197
|
+
vec3 darkRed = vec3(0.5, 0.05, 0.0);
|
|
198
|
+
vec3 red = vec3(0.9, 0.15, 0.0);
|
|
199
|
+
vec3 orange = vec3(1.0, 0.4, 0.05);
|
|
200
|
+
vec3 yellow = vec3(1.1, 0.85, 0.2);
|
|
201
|
+
vec3 white = vec3(1.4, 1.2, 0.9);
|
|
202
|
+
|
|
203
|
+
if(t < 0.15) return mix(black, darkRed, t / 0.15);
|
|
204
|
+
if(t < 0.3) return mix(darkRed, red, (t - 0.15) / 0.15);
|
|
205
|
+
if(t < 0.5) return mix(red, orange, (t - 0.3) / 0.2);
|
|
206
|
+
if(t < 0.75) return mix(orange, yellow, (t - 0.5) / 0.25);
|
|
207
|
+
return mix(yellow, white, (t - 0.75) / 0.25);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Fire effect - multi-layered flames (top-down view)
|
|
211
|
+
vec4 fireEffect(vec2 uv, vec2 texSize, float time) {
|
|
212
|
+
float mask = getVolumeMask(uv, texSize, time, 3.0, 0.25, 1.5);
|
|
213
|
+
if(mask < 0.001) return vec4(0.0);
|
|
214
|
+
|
|
215
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
216
|
+
vec2 noiseUV = uv * texSize * 0.001;
|
|
217
|
+
float warpScale = 1.0 + edgeDist * 2.0 * uIntensity;
|
|
218
|
+
|
|
219
|
+
// === LAYER 1: Deep/base fire (large scale, slow) ===
|
|
220
|
+
float base1 = domainWarp(noiseUV * 0.8, time * 0.15);
|
|
221
|
+
float base2 = domainWarp(noiseUV * 1.0 + 50.0, time * 0.2 + 10.0);
|
|
222
|
+
float baseLayer = (base1 + base2) * 0.5;
|
|
223
|
+
baseLayer = baseLayer * 0.5 + 0.5;
|
|
224
|
+
float baseIntensity = baseLayer * mask * uIntensity * 0.7;
|
|
225
|
+
|
|
226
|
+
// === LAYER 2: Mid fire (medium scale, medium speed) ===
|
|
227
|
+
float mid1 = domainWarp(noiseUV * 1.5 + 100.0, time * 0.3) * warpScale;
|
|
228
|
+
float mid2 = domainWarp(noiseUV * 2.0 + 150.0, time * 0.35 + 5.0) * warpScale;
|
|
229
|
+
float midLayer = (mid1 + mid2) * 0.5;
|
|
230
|
+
midLayer = midLayer * 0.5 + 0.5;
|
|
231
|
+
// Offset the mid layer mask slightly for depth
|
|
232
|
+
float midMask = getVolumeMask(uv, texSize, time * 1.1, 2.5, 0.3, 1.2);
|
|
233
|
+
float midIntensity = midLayer * midMask * uIntensity * 0.85;
|
|
234
|
+
|
|
235
|
+
// === LAYER 3: Hot spots/flickers (small scale, fast) ===
|
|
236
|
+
float hot1 = domainWarp(noiseUV * 3.0 + 200.0, time * 0.5);
|
|
237
|
+
float hot2 = fbm3(noiseUV * 4.0 + time * 0.6 + 250.0);
|
|
238
|
+
float hotLayer = (hot1 + hot2) * 0.5;
|
|
239
|
+
hotLayer = hotLayer * 0.5 + 0.5;
|
|
240
|
+
hotLayer = pow(hotLayer, 0.7); // Boost hot spots
|
|
241
|
+
// Tighter mask for hot spots
|
|
242
|
+
float hotMask = getVolumeMask(uv, texSize, time * 1.3, 2.0, 0.2, 1.8);
|
|
243
|
+
float hotIntensity = hotLayer * hotMask * uIntensity;
|
|
244
|
+
|
|
245
|
+
// === LAYER 4: Edge turbulence ===
|
|
246
|
+
float edgeTurb = fbm5(noiseUV * 5.0 + time * 0.4) * edgeDist;
|
|
247
|
+
|
|
248
|
+
// Composite layers with screen-like blending
|
|
249
|
+
// Each layer contributes color independently
|
|
250
|
+
vec3 baseColor = getFireColor(baseIntensity) * baseIntensity;
|
|
251
|
+
vec3 midColor = getFireColor(midIntensity) * midIntensity;
|
|
252
|
+
vec3 hotColor = getFireColor(hotIntensity * 1.2) * hotIntensity; // Hotter = brighter colors
|
|
253
|
+
|
|
254
|
+
// Screen blend: result = 1 - (1-a)(1-b)(1-c)
|
|
255
|
+
vec3 color = baseColor + midColor + hotColor;
|
|
256
|
+
color += vec3(1.0, 0.5, 0.2) * edgeTurb * uBorder * uIntensity;
|
|
257
|
+
|
|
258
|
+
// Composite alpha from all layers
|
|
259
|
+
float alpha = max(max(baseIntensity, midIntensity), hotIntensity);
|
|
260
|
+
alpha = smoothstep(0.0, 0.2, alpha);
|
|
261
|
+
alpha *= mask * uOpacity;
|
|
262
|
+
|
|
263
|
+
return vec4(color, alpha);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Space tear - dark void with stars (top-down view)
|
|
267
|
+
// Hash function for consistent random values per grid cell
|
|
268
|
+
float hash(vec2 p) {
|
|
269
|
+
return fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
// Hash that returns vec2
|
|
273
|
+
vec2 hash2(vec2 p) {
|
|
274
|
+
return vec2(
|
|
275
|
+
fract(sin(dot(p, vec2(127.1, 311.7))) * 43758.5453),
|
|
276
|
+
fract(sin(dot(p, vec2(269.5, 183.3))) * 43758.5453)
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// Generate a single star layer with grid-based placement
|
|
281
|
+
// Returns: x = star intensity, yzw = star color
|
|
282
|
+
vec4 starLayer(vec2 uv, float time, float gridSize, float speed, float brightness, float twinkleSpeed) {
|
|
283
|
+
// Grid cell
|
|
284
|
+
vec2 gridUV = uv * gridSize;
|
|
285
|
+
vec2 cellId = floor(gridUV);
|
|
286
|
+
vec2 cellUV = fract(gridUV);
|
|
287
|
+
|
|
288
|
+
float totalStar = 0.0;
|
|
289
|
+
vec3 totalColor = vec3(0.0);
|
|
290
|
+
|
|
291
|
+
// Check this cell and neighbors for stars
|
|
292
|
+
for(int x = -1; x <= 1; x++) {
|
|
293
|
+
for(int y = -1; y <= 1; y++) {
|
|
294
|
+
vec2 neighborId = cellId + vec2(float(x), float(y));
|
|
295
|
+
|
|
296
|
+
// Random position within cell
|
|
297
|
+
vec2 starPos = hash2(neighborId);
|
|
298
|
+
|
|
299
|
+
// Add slow drift movement
|
|
300
|
+
starPos += vec2(
|
|
301
|
+
sin(time * speed * 0.3 + hash(neighborId) * 6.28) * 0.1,
|
|
302
|
+
cos(time * speed * 0.2 + hash(neighborId + 100.0) * 6.28) * 0.1
|
|
303
|
+
);
|
|
304
|
+
|
|
305
|
+
// Distance from current pixel to star center
|
|
306
|
+
vec2 toStar = (cellUV - vec2(float(x), float(y))) - starPos;
|
|
307
|
+
float dist = length(toStar);
|
|
308
|
+
|
|
309
|
+
// Star visibility (only some cells have stars)
|
|
310
|
+
float hasStar = step(0.7, hash(neighborId + 50.0));
|
|
311
|
+
|
|
312
|
+
// Star size varies
|
|
313
|
+
float starSize = 0.02 + hash(neighborId + 80.0) * 0.03;
|
|
314
|
+
|
|
315
|
+
// Core star (sharp point)
|
|
316
|
+
float star = smoothstep(starSize, 0.0, dist) * hasStar;
|
|
317
|
+
|
|
318
|
+
// Soft glow around star
|
|
319
|
+
float glow = smoothstep(starSize * 4.0, 0.0, dist) * 0.3 * hasStar;
|
|
320
|
+
|
|
321
|
+
// Independent twinkle per star
|
|
322
|
+
float twinklePhase = hash(neighborId + 200.0) * 6.28;
|
|
323
|
+
float twinkleFreq = 0.5 + hash(neighborId + 300.0) * 1.5;
|
|
324
|
+
float twinkle = sin(time * twinkleSpeed * twinkleFreq + twinklePhase);
|
|
325
|
+
twinkle = twinkle * 0.4 + 0.6;
|
|
326
|
+
|
|
327
|
+
// Some stars blink more dramatically
|
|
328
|
+
float blinkStrength = hash(neighborId + 400.0);
|
|
329
|
+
if(blinkStrength > 0.8) {
|
|
330
|
+
float blink = sin(time * twinkleSpeed * 0.3 + hash(neighborId + 500.0) * 6.28);
|
|
331
|
+
twinkle *= smoothstep(-0.8, 0.2, blink);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
// Star color based on temperature
|
|
335
|
+
float temp = hash(neighborId + 600.0);
|
|
336
|
+
vec3 starColor;
|
|
337
|
+
if(temp < 0.3) {
|
|
338
|
+
starColor = vec3(0.7, 0.85, 1.0); // Blue-white hot
|
|
339
|
+
} else if(temp < 0.7) {
|
|
340
|
+
starColor = vec3(1.0, 1.0, 1.0); // Pure white
|
|
341
|
+
} else if(temp < 0.9) {
|
|
342
|
+
starColor = vec3(1.0, 0.95, 0.8); // Yellow-white
|
|
343
|
+
} else {
|
|
344
|
+
starColor = vec3(1.0, 0.7, 0.5); // Orange-red cool
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
float finalStar = (star + glow) * twinkle * brightness;
|
|
348
|
+
totalStar += finalStar;
|
|
349
|
+
totalColor += starColor * finalStar;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
if(totalStar > 0.001) {
|
|
354
|
+
totalColor /= totalStar;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
return vec4(totalStar, totalColor);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
vec4 spaceTearEffect(vec2 uv, vec2 texSize, float time) {
|
|
361
|
+
float mask = getVolumeMask(uv, texSize, time, 1.5, 0.2, 0.5);
|
|
362
|
+
if(mask < 0.001) return vec4(0.0);
|
|
363
|
+
|
|
364
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
365
|
+
vec2 baseUV = uv * texSize * 0.001;
|
|
366
|
+
|
|
367
|
+
// === BASE: Deep black void with subtle variation ===
|
|
368
|
+
float voidNoise = fbm3(baseUV * 0.5 + time * 0.02);
|
|
369
|
+
vec3 voidColor = vec3(0.01, 0.01, 0.02) + vec3(0.01, 0.005, 0.02) * voidNoise;
|
|
370
|
+
|
|
371
|
+
// === STAR LAYERS with parallax movement ===
|
|
372
|
+
vec3 starColor = vec3(0.0);
|
|
373
|
+
|
|
374
|
+
// Layer 1: Distant tiny stars (many, dim, slow)
|
|
375
|
+
vec2 layer1UV = baseUV + vec2(time * 0.002, time * 0.001);
|
|
376
|
+
vec4 stars1 = starLayer(layer1UV, time, 25.0, 0.3, 0.5, 1.5);
|
|
377
|
+
starColor += stars1.yzw * stars1.x;
|
|
378
|
+
|
|
379
|
+
// Layer 2: Medium distance stars
|
|
380
|
+
vec2 layer2UV = baseUV + vec2(time * 0.004, -time * 0.002);
|
|
381
|
+
vec4 stars2 = starLayer(layer2UV, time, 15.0, 0.5, 0.8, 1.2);
|
|
382
|
+
starColor += stars2.yzw * stars2.x;
|
|
383
|
+
|
|
384
|
+
// Layer 3: Closer bright stars (fewer, brighter, faster drift)
|
|
385
|
+
vec2 layer3UV = baseUV + vec2(-time * 0.006, time * 0.003);
|
|
386
|
+
vec4 stars3 = starLayer(layer3UV, time, 8.0, 0.8, 1.2, 0.8);
|
|
387
|
+
starColor += stars3.yzw * stars3.x;
|
|
388
|
+
|
|
389
|
+
// Layer 4: Rare very bright stars with strong glow
|
|
390
|
+
vec2 layer4UV = baseUV + vec2(time * 0.003, time * 0.005);
|
|
391
|
+
vec4 stars4 = starLayer(layer4UV, time, 4.0, 0.4, 1.8, 0.5);
|
|
392
|
+
starColor += stars4.yzw * stars4.x;
|
|
393
|
+
|
|
394
|
+
// === NEBULA WISPS at edges ===
|
|
395
|
+
float nebula = domainWarp(baseUV * 1.5 + 300.0, time * 0.05);
|
|
396
|
+
nebula = nebula * 0.5 + 0.5;
|
|
397
|
+
nebula *= edgeDist * uBorder;
|
|
398
|
+
vec3 nebulaColor = vec3(0.12, 0.04, 0.2) * nebula;
|
|
399
|
+
|
|
400
|
+
// Occasional colored nebula patches
|
|
401
|
+
float nebulaHue = snoise(baseUV * 2.0 + 500.0);
|
|
402
|
+
if(nebulaHue > 0.3) {
|
|
403
|
+
nebulaColor = mix(nebulaColor, vec3(0.05, 0.1, 0.2), (nebulaHue - 0.3) * nebula);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// === COMBINE ===
|
|
407
|
+
vec3 color = voidColor + starColor * uIntensity + nebulaColor * uIntensity;
|
|
408
|
+
|
|
409
|
+
// Edge glow - subtle purple rim
|
|
410
|
+
color += vec3(0.08, 0.02, 0.12) * edgeDist * uBorder * uIntensity;
|
|
411
|
+
|
|
412
|
+
float alpha = mask * uOpacity;
|
|
413
|
+
|
|
414
|
+
return vec4(color, alpha);
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Water effect - proper ripples using sum of sine waves with lighting
|
|
418
|
+
vec4 waterEffect(vec2 uv, vec2 texSize, float time) {
|
|
419
|
+
float mask = getVolumeMask(uv, texSize, time, 2.0, 0.1, 1.0);
|
|
420
|
+
if(mask < 0.001) return vec4(0.0);
|
|
421
|
+
|
|
422
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
423
|
+
vec2 basePos = uv * texSize * 0.004; // Higher scale = smaller waves (viewing from ~100ft)
|
|
424
|
+
|
|
425
|
+
// === DOMAIN WARPING - bend waves organically to break up repetition ===
|
|
426
|
+
float warpStrength = 0.15;
|
|
427
|
+
vec2 warp = vec2(
|
|
428
|
+
snoise(basePos * 0.3 + time * 0.05),
|
|
429
|
+
snoise(basePos * 0.3 + vec2(50.0, 50.0) + time * 0.04)
|
|
430
|
+
);
|
|
431
|
+
vec2 pos = basePos + warp * warpStrength;
|
|
432
|
+
|
|
433
|
+
// === SUM OF DIRECTIONAL SINE WAVES ===
|
|
434
|
+
// Each wave has: direction, frequency, amplitude, speed
|
|
435
|
+
// Directions slowly rotate over time for organic movement
|
|
436
|
+
float height = 0.0;
|
|
437
|
+
vec2 gradient = vec2(0.0); // For normal calculation
|
|
438
|
+
|
|
439
|
+
// Local noise for phase variation - breaks up sync
|
|
440
|
+
float phaseNoise1 = snoise(basePos * 0.5) * 2.0;
|
|
441
|
+
float phaseNoise2 = snoise(basePos * 0.7 + 100.0) * 2.0;
|
|
442
|
+
|
|
443
|
+
// Wave 1: Primary wave - direction slowly rotates
|
|
444
|
+
float angle1 = time * 0.02;
|
|
445
|
+
vec2 dir1 = normalize(vec2(cos(angle1) + 0.3, sin(angle1) * 0.5 + 0.7));
|
|
446
|
+
float freq1 = 25.0;
|
|
447
|
+
float amp1 = 0.25 * (0.8 + snoise(basePos * 0.2) * 0.2); // Vary amplitude locally
|
|
448
|
+
float phase1 = dot(dir1, pos) * freq1 - time * 2.0 + phaseNoise1;
|
|
449
|
+
height += amp1 * sin(phase1);
|
|
450
|
+
gradient += dir1 * amp1 * freq1 * cos(phase1);
|
|
451
|
+
|
|
452
|
+
// Wave 2: Cross wave - counter-rotating
|
|
453
|
+
float angle2 = -time * 0.015 + 1.5;
|
|
454
|
+
vec2 dir2 = normalize(vec2(cos(angle2) - 0.5, sin(angle2) + 0.3));
|
|
455
|
+
float freq2 = 35.0;
|
|
456
|
+
float amp2 = 0.18 * (0.85 + snoise(basePos * 0.25 + 30.0) * 0.15);
|
|
457
|
+
float phase2 = dot(dir2, pos) * freq2 - time * 2.5 + phaseNoise2;
|
|
458
|
+
height += amp2 * sin(phase2);
|
|
459
|
+
gradient += dir2 * amp2 * freq2 * cos(phase2);
|
|
460
|
+
|
|
461
|
+
// Wave 3: Diagonal - slight wobble
|
|
462
|
+
float angle3 = sin(time * 0.03) * 0.2 + 2.35;
|
|
463
|
+
vec2 dir3 = normalize(vec2(cos(angle3), sin(angle3)));
|
|
464
|
+
float freq3 = 20.0;
|
|
465
|
+
float amp3 = 0.2;
|
|
466
|
+
float phase3 = dot(dir3, pos) * freq3 - time * 1.5 + phaseNoise1 * 0.5;
|
|
467
|
+
height += amp3 * sin(phase3);
|
|
468
|
+
gradient += dir3 * amp3 * freq3 * cos(phase3);
|
|
469
|
+
|
|
470
|
+
// Wave 4: Fine detail
|
|
471
|
+
float angle4 = time * 0.025 + 4.0;
|
|
472
|
+
vec2 dir4 = normalize(vec2(cos(angle4) - 0.3, sin(angle4) - 0.9));
|
|
473
|
+
float freq4 = 50.0;
|
|
474
|
+
float amp4 = 0.1;
|
|
475
|
+
float phase4 = dot(dir4, pos) * freq4 - time * 3.0 + phaseNoise2 * 0.7;
|
|
476
|
+
height += amp4 * sin(phase4);
|
|
477
|
+
gradient += dir4 * amp4 * freq4 * cos(phase4);
|
|
478
|
+
|
|
479
|
+
// Wave 5: Extra fine detail - faster rotation
|
|
480
|
+
float angle5 = -time * 0.03 + 1.0;
|
|
481
|
+
vec2 dir5 = normalize(vec2(cos(angle5) + 0.9, sin(angle5) + 0.5));
|
|
482
|
+
float freq5 = 65.0;
|
|
483
|
+
float amp5 = 0.08;
|
|
484
|
+
float phase5 = dot(dir5, pos) * freq5 - time * 3.5;
|
|
485
|
+
height += amp5 * sin(phase5);
|
|
486
|
+
gradient += dir5 * amp5 * freq5 * cos(phase5);
|
|
487
|
+
|
|
488
|
+
// === CONCENTRIC RIPPLES - centers drift slowly ===
|
|
489
|
+
for(int i = 0; i < 8; i++) {
|
|
490
|
+
// Ripple centers drift over time
|
|
491
|
+
float drift = time * 0.02;
|
|
492
|
+
vec2 center = vec2(
|
|
493
|
+
fract(sin(float(i) * 127.1) * 43758.5453 + drift * 0.1) * 0.8 + 0.1,
|
|
494
|
+
fract(sin(float(i) * 269.5) * 43758.5453 + drift * 0.07) * 0.8 + 0.1
|
|
495
|
+
);
|
|
496
|
+
// Add noise-based wobble to centers
|
|
497
|
+
center += vec2(
|
|
498
|
+
snoise(vec2(float(i) * 3.0, time * 0.1)) * 0.05,
|
|
499
|
+
snoise(vec2(time * 0.1, float(i) * 5.0)) * 0.05
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
vec2 toCenter = pos - center * texSize.x * 0.004;
|
|
503
|
+
float dist = length(toCenter);
|
|
504
|
+
float rippleFreq = 40.0 + float(i) * 5.0;
|
|
505
|
+
float rippleAmp = 0.12 / (1.0 + dist * 3.0);
|
|
506
|
+
// Vary ripple speed slightly per source
|
|
507
|
+
float rippleSpeed = 4.0 + snoise(vec2(float(i) * 10.0, 0.0)) * 0.5;
|
|
508
|
+
float ripplePhase = dist * rippleFreq - time * rippleSpeed - float(i) * 1.0;
|
|
509
|
+
|
|
510
|
+
height += rippleAmp * sin(ripplePhase);
|
|
511
|
+
if(dist > 0.001) {
|
|
512
|
+
vec2 rippleDir = toCenter / dist;
|
|
513
|
+
gradient += rippleDir * rippleAmp * rippleFreq * cos(ripplePhase);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
// === CALCULATE NORMAL FROM GRADIENT ===
|
|
518
|
+
vec3 normal = normalize(vec3(-gradient.x, -gradient.y, 1.0));
|
|
519
|
+
|
|
520
|
+
// === LIGHTING ===
|
|
521
|
+
vec3 lightDir = normalize(vec3(0.3, 0.3, 1.0)); // Light from above-front
|
|
522
|
+
float diffuse = max(dot(normal, lightDir), 0.0);
|
|
523
|
+
|
|
524
|
+
// Specular highlight (Blinn-Phong) - high exponent for small sharp highlights
|
|
525
|
+
vec3 viewDir = vec3(0.0, 0.0, 1.0); // Top-down view
|
|
526
|
+
vec3 halfDir = normalize(lightDir + viewDir);
|
|
527
|
+
float specular = pow(max(dot(normal, halfDir), 0.0), 128.0);
|
|
528
|
+
|
|
529
|
+
// === DEPTH/SHALLOWNESS - border controls how much shallow water ===
|
|
530
|
+
// Sample mask at multiple mipmap levels to find distance from edge
|
|
531
|
+
float maskHigh = textureLod(uMaskTexture, uv, 0.0).a;
|
|
532
|
+
float maskMid = textureLod(uMaskTexture, uv, 3.0).a;
|
|
533
|
+
float maskLow = textureLod(uMaskTexture, uv, 5.0).a;
|
|
534
|
+
float maskVeryLow = textureLod(uMaskTexture, uv, 7.0).a;
|
|
535
|
+
|
|
536
|
+
// Edge distance: higher at edges, lower in center
|
|
537
|
+
float edgeProximity = 1.0 - min(maskHigh, min(maskMid, maskLow));
|
|
538
|
+
|
|
539
|
+
// Border controls how far shallow water extends into the center
|
|
540
|
+
// At border=0, only very edge is shallow. At border=1, most of water is shallow
|
|
541
|
+
float shallowSpread = uBorder * 0.8 + 0.1; // 0.1 to 0.9
|
|
542
|
+
float shallowZone = smoothstep(0.0, shallowSpread, edgeProximity);
|
|
543
|
+
|
|
544
|
+
// Also use blurred mask difference for smoother depth transition
|
|
545
|
+
float depthGradient = abs(maskHigh - maskVeryLow);
|
|
546
|
+
shallowZone = max(shallowZone, depthGradient * uBorder * 2.0);
|
|
547
|
+
shallowZone = clamp(shallowZone, 0.0, 1.0);
|
|
548
|
+
|
|
549
|
+
// Add some noise to break up the depth bands
|
|
550
|
+
float depthNoise = snoise(pos * 2.0 + time * 0.05) * 0.15;
|
|
551
|
+
shallowZone = clamp(shallowZone + depthNoise * uBorder, 0.0, 1.0);
|
|
552
|
+
|
|
553
|
+
// === COLORS ===
|
|
554
|
+
vec3 deepColor = vec3(0.05, 0.15, 0.35); // Dark blue for deep water
|
|
555
|
+
vec3 midColor = vec3(0.1, 0.3, 0.5); // Medium blue
|
|
556
|
+
vec3 shallowColor = vec3(0.2, 0.5, 0.6); // Lighter cyan for shallow
|
|
557
|
+
vec3 veryShallowColor = vec3(0.35, 0.6, 0.55); // Turquoise/teal for very shallow
|
|
558
|
+
vec3 beachColor = vec3(0.55, 0.65, 0.5); // Sandy greenish for beach edge
|
|
559
|
+
vec3 highlightColor = vec3(0.9, 0.95, 1.0); // Slight blue tint to highlights
|
|
560
|
+
|
|
561
|
+
// Height affects color (deeper in troughs)
|
|
562
|
+
float heightNorm = height * 0.5 + 0.5;
|
|
563
|
+
|
|
564
|
+
// Multi-step depth gradient based on shallow zone
|
|
565
|
+
vec3 baseWaterColor;
|
|
566
|
+
if(shallowZone < 0.25) {
|
|
567
|
+
// Deep water
|
|
568
|
+
baseWaterColor = mix(deepColor, midColor, shallowZone * 4.0);
|
|
569
|
+
} else if(shallowZone < 0.5) {
|
|
570
|
+
// Mid depth
|
|
571
|
+
baseWaterColor = mix(midColor, shallowColor, (shallowZone - 0.25) * 4.0);
|
|
572
|
+
} else if(shallowZone < 0.75) {
|
|
573
|
+
// Shallow
|
|
574
|
+
baseWaterColor = mix(shallowColor, veryShallowColor, (shallowZone - 0.5) * 4.0);
|
|
575
|
+
} else {
|
|
576
|
+
// Very shallow / beach
|
|
577
|
+
baseWaterColor = mix(veryShallowColor, beachColor, (shallowZone - 0.75) * 4.0);
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
// Wave height creates visible color variation - more visible in shallow water
|
|
581
|
+
float heightInfluence = 0.3 + shallowZone * 0.3; // Shallow water shows more height variation
|
|
582
|
+
vec3 waterColor = mix(baseWaterColor * 0.85, baseWaterColor * 1.2, heightNorm * heightInfluence + diffuse * 0.3);
|
|
583
|
+
|
|
584
|
+
// Add specular highlights - stronger in shallow water where you can see the surface better
|
|
585
|
+
float specularStrength = 1.0 + shallowZone * 0.5;
|
|
586
|
+
waterColor += highlightColor * specular * specularStrength * uIntensity;
|
|
587
|
+
|
|
588
|
+
// Subtle foam on wave peaks in very shallow areas only
|
|
589
|
+
float foam = smoothstep(0.6, 0.9, heightNorm) * smoothstep(0.5, 0.8, shallowZone) * 0.3;
|
|
590
|
+
foam += edgeDist * smoothstep(0.7, 1.0, shallowZone) * 0.2; // Foam right at the edge
|
|
591
|
+
float foamNoise = snoise(pos * 8.0 + time * 0.5) * 0.5 + 0.5;
|
|
592
|
+
foam *= foamNoise;
|
|
593
|
+
waterColor += vec3(0.9, 0.85, 0.75) * foam;
|
|
594
|
+
|
|
595
|
+
// Final color with intensity
|
|
596
|
+
vec3 finalColor = waterColor * uIntensity;
|
|
597
|
+
|
|
598
|
+
float alpha = mask * uOpacity;
|
|
599
|
+
|
|
600
|
+
return vec4(finalColor, alpha);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
// Helper: get magic color from intensity (uses base color)
|
|
604
|
+
vec3 getMagicColor(float t) {
|
|
605
|
+
vec3 darkColor = uBaseColor * 0.2;
|
|
606
|
+
vec3 midColor = uBaseColor * 0.6;
|
|
607
|
+
vec3 brightColor = uBaseColor * 1.0;
|
|
608
|
+
vec3 glow = uBaseColor * 1.4 + vec3(0.2);
|
|
609
|
+
vec3 white = vec3(1.3, 1.3, 1.4);
|
|
610
|
+
|
|
611
|
+
if(t < 0.2) return mix(darkColor, midColor, t * 5.0);
|
|
612
|
+
if(t < 0.45) return mix(midColor, brightColor, (t - 0.2) * 4.0);
|
|
613
|
+
if(t < 0.7) return mix(brightColor, glow, (t - 0.45) * 4.0);
|
|
614
|
+
return mix(glow, white, (t - 0.7) / 0.3);
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// Magic effect - multi-layered arcane energy (top-down view)
|
|
618
|
+
vec4 magicEffect(vec2 uv, vec2 texSize, float time) {
|
|
619
|
+
float mask = getVolumeMask(uv, texSize, time, 2.5, 0.2, 1.2);
|
|
620
|
+
if(mask < 0.001) return vec4(0.0);
|
|
621
|
+
|
|
622
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
623
|
+
vec2 noiseUV = uv * texSize * 0.001;
|
|
624
|
+
float warpScale = 1.0 + edgeDist * 2.2 * uIntensity;
|
|
625
|
+
|
|
626
|
+
// Soft pulsating - affects all layers
|
|
627
|
+
float pulseNoise = fbm3(noiseUV * 0.2 + time * 0.25);
|
|
628
|
+
float pulse = pulseNoise * 0.12 + 0.88;
|
|
629
|
+
|
|
630
|
+
// === LAYER 1: Deep arcane base (large scale, slow) ===
|
|
631
|
+
float deep1 = domainWarp(noiseUV * 0.7, time * 0.12);
|
|
632
|
+
float deep2 = domainWarp(noiseUV * 0.9 + 25.0, time * 0.15 + 7.0);
|
|
633
|
+
float deepLayer = (deep1 + deep2) * 0.5;
|
|
634
|
+
deepLayer = deepLayer * 0.5 + 0.5;
|
|
635
|
+
float deepIntensity = deepLayer * mask * uIntensity * pulse * 0.6;
|
|
636
|
+
|
|
637
|
+
// === LAYER 2: Mid energy swirls (medium scale) ===
|
|
638
|
+
float mid1 = domainWarp(noiseUV * 1.4 + 50.0, time * 0.25) * warpScale;
|
|
639
|
+
float mid2 = domainWarp(noiseUV * 1.8 + 75.0, time * 0.3 + 4.0) * warpScale;
|
|
640
|
+
float midLayer = (mid1 + mid2) * 0.5;
|
|
641
|
+
midLayer = midLayer * 0.5 + 0.5;
|
|
642
|
+
float midMask = getVolumeMask(uv, texSize, time * 1.1, 2.2, 0.25, 1.0);
|
|
643
|
+
float midIntensity = midLayer * midMask * uIntensity * pulse * 0.8;
|
|
644
|
+
|
|
645
|
+
// === LAYER 3: Surface energy crackle (small scale, faster) ===
|
|
646
|
+
float surf1 = domainWarp(noiseUV * 2.5 + 100.0, time * 0.4);
|
|
647
|
+
float surf2 = fbm3(noiseUV * 3.0 + time * 0.35 + 130.0);
|
|
648
|
+
float surfLayer = (surf1 + surf2) * 0.5;
|
|
649
|
+
surfLayer = surfLayer * 0.5 + 0.5;
|
|
650
|
+
surfLayer = pow(surfLayer, 0.85); // Slight boost
|
|
651
|
+
float surfMask = getVolumeMask(uv, texSize, time * 1.25, 2.0, 0.2, 1.4);
|
|
652
|
+
float surfIntensity = surfLayer * surfMask * uIntensity * pulse;
|
|
653
|
+
|
|
654
|
+
// === LAYER 4: Edge turbulence and sparkles ===
|
|
655
|
+
float edgeTurb = fbm5(noiseUV * 4.5 + time * 0.5) * edgeDist;
|
|
656
|
+
|
|
657
|
+
// Soft sparkles - concentrated at edges
|
|
658
|
+
float sparkleBase = fbm5(noiseUV * 5.0 + time * 0.18);
|
|
659
|
+
float sparkle = smoothstep(0.45, 0.75, sparkleBase) * smoothstep(1.0, 0.65, sparkleBase);
|
|
660
|
+
sparkle *= (1.0 + edgeDist * 0.8);
|
|
661
|
+
|
|
662
|
+
// Composite layers with colors
|
|
663
|
+
vec3 deepColor = getMagicColor(deepIntensity * 0.9) * deepIntensity;
|
|
664
|
+
vec3 midColor = getMagicColor(midIntensity) * midIntensity;
|
|
665
|
+
vec3 surfColor = getMagicColor(surfIntensity * 1.2) * surfIntensity;
|
|
666
|
+
|
|
667
|
+
vec3 color = deepColor + midColor + surfColor;
|
|
668
|
+
|
|
669
|
+
// Add edge turbulence glow - controlled by border
|
|
670
|
+
color += uBaseColor * edgeTurb * uBorder * uIntensity;
|
|
671
|
+
|
|
672
|
+
// Soft white sparkles
|
|
673
|
+
color += vec3(1.2, 1.2, 1.3) * sparkle * 0.35 * uIntensity;
|
|
674
|
+
|
|
675
|
+
// Enhanced edge glow - controlled by border
|
|
676
|
+
float edgeGlow = edgeDist * uBorder * uIntensity;
|
|
677
|
+
color += uBaseColor * edgeGlow;
|
|
678
|
+
|
|
679
|
+
// Composite alpha from all layers
|
|
680
|
+
float alpha = max(max(deepIntensity, midIntensity), surfIntensity);
|
|
681
|
+
alpha = smoothstep(0.0, 0.12, alpha);
|
|
682
|
+
alpha *= mask * uOpacity;
|
|
683
|
+
|
|
684
|
+
return vec4(color, alpha);
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
// Grease effect - murky brown liquid with depth (same technique as water)
|
|
688
|
+
vec4 greaseEffect(vec2 uv, vec2 texSize, float time) {
|
|
689
|
+
float mask = getVolumeMask(uv, texSize, time, 2.0, 0.1, 0.8);
|
|
690
|
+
if(mask < 0.001) return vec4(0.0);
|
|
691
|
+
|
|
692
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
693
|
+
vec2 basePos = uv * texSize * 0.004;
|
|
694
|
+
|
|
695
|
+
// === DOMAIN WARPING - slower, more viscous movement ===
|
|
696
|
+
float warpStrength = 0.12;
|
|
697
|
+
vec2 warp = vec2(
|
|
698
|
+
snoise(basePos * 0.25 + time * 0.03),
|
|
699
|
+
snoise(basePos * 0.25 + vec2(50.0, 50.0) + time * 0.025)
|
|
700
|
+
);
|
|
701
|
+
vec2 pos = basePos + warp * warpStrength;
|
|
702
|
+
|
|
703
|
+
// === SLOWER SINE WAVES for viscous liquid ===
|
|
704
|
+
float height = 0.0;
|
|
705
|
+
vec2 gradient = vec2(0.0);
|
|
706
|
+
|
|
707
|
+
float phaseNoise1 = snoise(basePos * 0.5) * 2.0;
|
|
708
|
+
float phaseNoise2 = snoise(basePos * 0.7 + 100.0) * 2.0;
|
|
709
|
+
|
|
710
|
+
// Wave 1: Primary - slower
|
|
711
|
+
float angle1 = time * 0.015;
|
|
712
|
+
vec2 dir1 = normalize(vec2(cos(angle1) + 0.3, sin(angle1) * 0.5 + 0.7));
|
|
713
|
+
float freq1 = 20.0;
|
|
714
|
+
float amp1 = 0.2 * (0.8 + snoise(basePos * 0.2) * 0.2);
|
|
715
|
+
float phase1 = dot(dir1, pos) * freq1 - time * 1.2 + phaseNoise1;
|
|
716
|
+
height += amp1 * sin(phase1);
|
|
717
|
+
gradient += dir1 * amp1 * freq1 * cos(phase1);
|
|
718
|
+
|
|
719
|
+
// Wave 2: Cross wave
|
|
720
|
+
float angle2 = -time * 0.01 + 1.5;
|
|
721
|
+
vec2 dir2 = normalize(vec2(cos(angle2) - 0.5, sin(angle2) + 0.3));
|
|
722
|
+
float freq2 = 28.0;
|
|
723
|
+
float amp2 = 0.15 * (0.85 + snoise(basePos * 0.25 + 30.0) * 0.15);
|
|
724
|
+
float phase2 = dot(dir2, pos) * freq2 - time * 1.5 + phaseNoise2;
|
|
725
|
+
height += amp2 * sin(phase2);
|
|
726
|
+
gradient += dir2 * amp2 * freq2 * cos(phase2);
|
|
727
|
+
|
|
728
|
+
// Wave 3: Diagonal
|
|
729
|
+
float angle3 = sin(time * 0.02) * 0.2 + 2.35;
|
|
730
|
+
vec2 dir3 = normalize(vec2(cos(angle3), sin(angle3)));
|
|
731
|
+
float freq3 = 15.0;
|
|
732
|
+
float amp3 = 0.18;
|
|
733
|
+
float phase3 = dot(dir3, pos) * freq3 - time * 1.0 + phaseNoise1 * 0.5;
|
|
734
|
+
height += amp3 * sin(phase3);
|
|
735
|
+
gradient += dir3 * amp3 * freq3 * cos(phase3);
|
|
736
|
+
|
|
737
|
+
// Wave 4: Fine detail (less prominent for viscous look)
|
|
738
|
+
float angle4 = time * 0.018 + 4.0;
|
|
739
|
+
vec2 dir4 = normalize(vec2(cos(angle4) - 0.3, sin(angle4) - 0.9));
|
|
740
|
+
float freq4 = 40.0;
|
|
741
|
+
float amp4 = 0.08;
|
|
742
|
+
float phase4 = dot(dir4, pos) * freq4 - time * 2.0 + phaseNoise2 * 0.7;
|
|
743
|
+
height += amp4 * sin(phase4);
|
|
744
|
+
gradient += dir4 * amp4 * freq4 * cos(phase4);
|
|
745
|
+
|
|
746
|
+
// === CALCULATE NORMAL FROM GRADIENT ===
|
|
747
|
+
vec3 normal = normalize(vec3(-gradient.x, -gradient.y, 1.0));
|
|
748
|
+
|
|
749
|
+
// === LIGHTING ===
|
|
750
|
+
vec3 lightDir = normalize(vec3(0.3, 0.3, 1.0));
|
|
751
|
+
float diffuse = max(dot(normal, lightDir), 0.0);
|
|
752
|
+
|
|
753
|
+
vec3 viewDir = vec3(0.0, 0.0, 1.0);
|
|
754
|
+
vec3 halfDir = normalize(lightDir + viewDir);
|
|
755
|
+
float specular = pow(max(dot(normal, halfDir), 0.0), 64.0); // Lower exponent for broader highlights
|
|
756
|
+
|
|
757
|
+
// === DEPTH/THICKNESS - border controls how dark the edges are ===
|
|
758
|
+
float maskHigh = textureLod(uMaskTexture, uv, 0.0).a;
|
|
759
|
+
float maskMid = textureLod(uMaskTexture, uv, 3.0).a;
|
|
760
|
+
float maskLow = textureLod(uMaskTexture, uv, 5.0).a;
|
|
761
|
+
float maskVeryLow = textureLod(uMaskTexture, uv, 7.0).a;
|
|
762
|
+
|
|
763
|
+
// How far from center (1 = edge, 0 = center)
|
|
764
|
+
float edgeProximity = 1.0 - min(maskHigh, min(maskMid, maskLow));
|
|
765
|
+
|
|
766
|
+
// Border controls how much darkness spreads from edges
|
|
767
|
+
float darkSpread = uBorder * 0.8 + 0.1;
|
|
768
|
+
float darkZone = smoothstep(0.0, darkSpread, edgeProximity);
|
|
769
|
+
|
|
770
|
+
float depthGradient = abs(maskHigh - maskVeryLow);
|
|
771
|
+
darkZone = max(darkZone, depthGradient * uBorder * 2.0);
|
|
772
|
+
darkZone = clamp(darkZone, 0.0, 1.0);
|
|
773
|
+
|
|
774
|
+
float depthNoise = snoise(pos * 2.0 + time * 0.03) * 0.15;
|
|
775
|
+
darkZone = clamp(darkZone + depthNoise * uBorder, 0.0, 1.0);
|
|
776
|
+
|
|
777
|
+
// === BROWN COLORS - inverted: edges get darker with border (softened) ===
|
|
778
|
+
vec3 centerColor = vec3(0.4, 0.3, 0.18); // Lighter brown in center
|
|
779
|
+
vec3 midColor = vec3(0.32, 0.24, 0.14); // Medium brown
|
|
780
|
+
vec3 darkColor = vec3(0.24, 0.18, 0.1); // Dark brown
|
|
781
|
+
vec3 veryDarkColor = vec3(0.16, 0.12, 0.06); // Very dark brown
|
|
782
|
+
vec3 edgeColor = vec3(0.1, 0.07, 0.03); // Dark but not black at edges
|
|
783
|
+
vec3 highlightColor = vec3(0.8, 0.7, 0.5); // Warm highlights
|
|
784
|
+
|
|
785
|
+
float heightNorm = height * 0.5 + 0.5;
|
|
786
|
+
|
|
787
|
+
// Multi-step depth gradient - darker towards edges
|
|
788
|
+
vec3 baseGreaseColor;
|
|
789
|
+
if(darkZone < 0.25) {
|
|
790
|
+
baseGreaseColor = mix(centerColor, midColor, darkZone * 4.0);
|
|
791
|
+
} else if(darkZone < 0.5) {
|
|
792
|
+
baseGreaseColor = mix(midColor, darkColor, (darkZone - 0.25) * 4.0);
|
|
793
|
+
} else if(darkZone < 0.75) {
|
|
794
|
+
baseGreaseColor = mix(darkColor, veryDarkColor, (darkZone - 0.5) * 4.0);
|
|
795
|
+
} else {
|
|
796
|
+
baseGreaseColor = mix(veryDarkColor, edgeColor, (darkZone - 0.75) * 4.0);
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
float heightInfluence = 0.25 + (1.0 - darkZone) * 0.25; // More height variation in lighter areas
|
|
800
|
+
vec3 greaseColor = mix(baseGreaseColor * 0.85, baseGreaseColor * 1.15, heightNorm * heightInfluence + diffuse * 0.25);
|
|
801
|
+
|
|
802
|
+
// Specular highlights - oily sheen, stronger in lighter center areas
|
|
803
|
+
float specularStrength = 0.8 + (1.0 - darkZone) * 0.4;
|
|
804
|
+
greaseColor += highlightColor * specular * specularStrength * uIntensity * 0.6;
|
|
805
|
+
|
|
806
|
+
vec3 finalColor = greaseColor * uIntensity;
|
|
807
|
+
|
|
808
|
+
float alpha = mask * uOpacity;
|
|
809
|
+
|
|
810
|
+
return vec4(finalColor, alpha);
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
// Ice effect - frosted glass look that lets map show through
|
|
814
|
+
vec4 iceEffect(vec2 uv, vec2 texSize, float time) {
|
|
815
|
+
float mask = getVolumeMask(uv, texSize, time, 1.2, 0.05, 0.3);
|
|
816
|
+
if(mask < 0.001) return vec4(0.0);
|
|
817
|
+
|
|
818
|
+
float edgeDist = getEdgeDistortion(uv, texSize);
|
|
819
|
+
vec2 basePos = uv * texSize * 0.002;
|
|
820
|
+
|
|
821
|
+
// === FROST PATTERN - subtle, organic ice crystals with cold air movement ===
|
|
822
|
+
// Drifting direction for cold air effect
|
|
823
|
+
vec2 drift = vec2(time * 0.15, time * 0.08);
|
|
824
|
+
|
|
825
|
+
// Multiple layers of noise at different scales for natural frost look
|
|
826
|
+
float frost1 = fbm3(basePos * 4.0 + drift * 0.5) * 0.5 + 0.5;
|
|
827
|
+
float frost2 = fbm3(basePos * 8.0 + vec2(50.0, 50.0) + drift * 0.7) * 0.5 + 0.5;
|
|
828
|
+
float frost3 = snoise(basePos * 16.0 + drift) * 0.5 + 0.5;
|
|
829
|
+
|
|
830
|
+
// Combine for layered frost texture
|
|
831
|
+
float frostPattern = frost1 * 0.5 + frost2 * 0.3 + frost3 * 0.2;
|
|
832
|
+
|
|
833
|
+
// Cold air wisps - flowing patterns
|
|
834
|
+
float wisp1 = snoise(basePos * 3.0 + vec2(time * 0.2, time * 0.1)) * 0.5 + 0.5;
|
|
835
|
+
float wisp2 = snoise(basePos * 5.0 + vec2(-time * 0.15, time * 0.12) + 80.0) * 0.5 + 0.5;
|
|
836
|
+
float coldAir = wisp1 * 0.6 + wisp2 * 0.4;
|
|
837
|
+
coldAir = smoothstep(0.3, 0.7, coldAir); // Soften the wisps
|
|
838
|
+
|
|
839
|
+
// === GEOMETRIC CRACKS - voronoi cell edges for angular look ===
|
|
840
|
+
float crackScale = 20.0;
|
|
841
|
+
vec2 crackPos = basePos * crackScale;
|
|
842
|
+
|
|
843
|
+
// Voronoi for geometric angular cracks
|
|
844
|
+
vec2 cellId = floor(crackPos);
|
|
845
|
+
vec2 cellUV = fract(crackPos);
|
|
846
|
+
|
|
847
|
+
float minDist = 1.0;
|
|
848
|
+
float secondDist = 1.0;
|
|
849
|
+
|
|
850
|
+
// Find two closest cell centers
|
|
851
|
+
for(int x = -1; x <= 1; x++) {
|
|
852
|
+
for(int y = -1; y <= 1; y++) {
|
|
853
|
+
vec2 neighbor = vec2(float(x), float(y));
|
|
854
|
+
// Jittered cell centers for irregular but angular pattern
|
|
855
|
+
vec2 point = neighbor + hash2(cellId + neighbor) * 0.8 + 0.1;
|
|
856
|
+
float dist = length(cellUV - point);
|
|
857
|
+
|
|
858
|
+
if(dist < minDist) {
|
|
859
|
+
secondDist = minDist;
|
|
860
|
+
minDist = dist;
|
|
861
|
+
} else if(dist < secondDist) {
|
|
862
|
+
secondDist = dist;
|
|
863
|
+
}
|
|
864
|
+
}
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
// Crack lines are at cell boundaries (where distances are similar)
|
|
868
|
+
float cellEdgeDist = secondDist - minDist;
|
|
869
|
+
float cracks = 1.0 - smoothstep(0.0, 0.08, cellEdgeDist);
|
|
870
|
+
|
|
871
|
+
// Second layer at different scale for more detail
|
|
872
|
+
vec2 crackPos2 = basePos * crackScale * 2.5;
|
|
873
|
+
vec2 cellId2 = floor(crackPos2);
|
|
874
|
+
vec2 cellUV2 = fract(crackPos2);
|
|
875
|
+
|
|
876
|
+
float minDist2 = 1.0;
|
|
877
|
+
float secondDist2 = 1.0;
|
|
878
|
+
|
|
879
|
+
for(int x = -1; x <= 1; x++) {
|
|
880
|
+
for(int y = -1; y <= 1; y++) {
|
|
881
|
+
vec2 neighbor = vec2(float(x), float(y));
|
|
882
|
+
vec2 point = neighbor + hash2(cellId2 + neighbor + 200.0) * 0.7 + 0.15;
|
|
883
|
+
float dist = length(cellUV2 - point);
|
|
884
|
+
|
|
885
|
+
if(dist < minDist2) {
|
|
886
|
+
secondDist2 = minDist2;
|
|
887
|
+
minDist2 = dist;
|
|
888
|
+
} else if(dist < secondDist2) {
|
|
889
|
+
secondDist2 = dist;
|
|
890
|
+
}
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
float cellEdgeDist2 = secondDist2 - minDist2;
|
|
895
|
+
float cracks2 = 1.0 - smoothstep(0.0, 0.06, cellEdgeDist2);
|
|
896
|
+
|
|
897
|
+
// Combine both crack layers
|
|
898
|
+
cracks = max(cracks, cracks2 * 0.7);
|
|
899
|
+
|
|
900
|
+
// Always visible, roughness makes them stronger
|
|
901
|
+
cracks = cracks * (0.5 + uRoughness * 0.5);
|
|
902
|
+
|
|
903
|
+
// === DEPTH - border controls how much shallow/white ice at edges ===
|
|
904
|
+
float maskHigh = textureLod(uMaskTexture, uv, 0.0).a;
|
|
905
|
+
float maskMid = textureLod(uMaskTexture, uv, 3.0).a;
|
|
906
|
+
float maskLow = textureLod(uMaskTexture, uv, 5.0).a;
|
|
907
|
+
float maskVeryLow = textureLod(uMaskTexture, uv, 7.0).a;
|
|
908
|
+
|
|
909
|
+
// Edge proximity: higher at edges, lower in center
|
|
910
|
+
float edgeProximity = 1.0 - min(maskHigh, min(maskMid, maskLow));
|
|
911
|
+
|
|
912
|
+
// Border controls how far the light/white ice extends into center
|
|
913
|
+
float shallowSpread = uBorder * 0.8 + 0.1;
|
|
914
|
+
float shallowZone = smoothstep(0.0, shallowSpread, edgeProximity);
|
|
915
|
+
|
|
916
|
+
// Also use blurred mask difference for smoother depth transition
|
|
917
|
+
float depthGradient = abs(maskHigh - maskVeryLow);
|
|
918
|
+
shallowZone = max(shallowZone, depthGradient * uBorder * 2.0);
|
|
919
|
+
shallowZone = clamp(shallowZone, 0.0, 1.0);
|
|
920
|
+
|
|
921
|
+
// Add noise to break up depth bands
|
|
922
|
+
float depthNoise = snoise(basePos * 2.0 + drift * 0.3) * 0.1;
|
|
923
|
+
shallowZone = clamp(shallowZone + depthNoise * uBorder, 0.0, 1.0);
|
|
924
|
+
|
|
925
|
+
// === SUBTLE SHIMMER - slow sparkle ===
|
|
926
|
+
float shimmer = snoise(basePos * 6.0 + drift * 1.2) * 0.5 + 0.5;
|
|
927
|
+
shimmer = pow(shimmer, 3.0); // Make sparkles more sparse
|
|
928
|
+
|
|
929
|
+
// === COLORS - subtle blue center, white edges ===
|
|
930
|
+
vec3 deepBlue = vec3(0.45, 0.6, 0.8); // Lighter blue for center
|
|
931
|
+
vec3 midBlue = vec3(0.55, 0.7, 0.85); // Medium blue
|
|
932
|
+
vec3 lightBlue = vec3(0.7, 0.82, 0.92); // Light blue
|
|
933
|
+
vec3 paleBlue = vec3(0.82, 0.9, 0.97); // Pale blue
|
|
934
|
+
vec3 frostWhite = vec3(0.94, 0.97, 1.0); // White frost at edges
|
|
935
|
+
vec3 crackColor = vec3(0.08, 0.15, 0.3); // Darker crack lines for contrast
|
|
936
|
+
vec3 coldAirColor = vec3(0.85, 0.92, 1.0); // Pale blue for cold air
|
|
937
|
+
|
|
938
|
+
// Multi-step depth gradient - darker in center, lighter at edges
|
|
939
|
+
vec3 iceColor;
|
|
940
|
+
if(shallowZone < 0.25) {
|
|
941
|
+
iceColor = mix(deepBlue, midBlue, shallowZone * 4.0);
|
|
942
|
+
} else if(shallowZone < 0.5) {
|
|
943
|
+
iceColor = mix(midBlue, lightBlue, (shallowZone - 0.25) * 4.0);
|
|
944
|
+
} else if(shallowZone < 0.75) {
|
|
945
|
+
iceColor = mix(lightBlue, paleBlue, (shallowZone - 0.5) * 4.0);
|
|
946
|
+
} else {
|
|
947
|
+
iceColor = mix(paleBlue, frostWhite, (shallowZone - 0.75) * 4.0);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
// Add frost pattern variation
|
|
951
|
+
iceColor = mix(iceColor, iceColor * 1.1, frostPattern * 0.2);
|
|
952
|
+
|
|
953
|
+
// Add cold air wisps - subtle pale blue flowing over the ice
|
|
954
|
+
iceColor = mix(iceColor, coldAirColor, coldAir * 0.2);
|
|
955
|
+
|
|
956
|
+
// Add crack lines - dark blue cracks stand out
|
|
957
|
+
iceColor = mix(iceColor, crackColor, cracks * 0.8);
|
|
958
|
+
|
|
959
|
+
// Add sparse shimmer highlights - subtle
|
|
960
|
+
iceColor += frostWhite * shimmer * 0.2;
|
|
961
|
+
|
|
962
|
+
// Edge frost - lighter at edges
|
|
963
|
+
iceColor = mix(iceColor, lightBlue, edgeDist * 0.25);
|
|
964
|
+
|
|
965
|
+
// Apply intensity without washing out blue
|
|
966
|
+
vec3 finalColor = iceColor * (0.7 + uIntensity * 0.5);
|
|
967
|
+
|
|
968
|
+
// === ALPHA - semi-transparent to show map through ===
|
|
969
|
+
// Thicker/more opaque in center, thinner at edges
|
|
970
|
+
float iceThickness = 1.0 - shallowZone; // Inverse of shallow zone
|
|
971
|
+
float baseAlpha = 0.4 + iceThickness * 0.35; // 0.4 to 0.75 base
|
|
972
|
+
baseAlpha += frostPattern * 0.1; // Variation from frost pattern
|
|
973
|
+
baseAlpha += cracks * 0.15; // Cracks are more opaque
|
|
974
|
+
baseAlpha += coldAir * 0.08; // Cold air adds slight opacity variation
|
|
975
|
+
baseAlpha = clamp(baseAlpha, 0.0, 0.85); // Never fully opaque
|
|
976
|
+
|
|
977
|
+
float alpha = mask * uOpacity * baseAlpha;
|
|
978
|
+
|
|
979
|
+
return vec4(finalColor, alpha);
|
|
980
|
+
}
|
|
981
|
+
|
|
982
|
+
void main() {
|
|
983
|
+
// Clipping planes
|
|
984
|
+
vec4 plane;
|
|
985
|
+
#pragma unroll_loop
|
|
986
|
+
for(int i = 0; i < NUM_CLIPPING_PLANES; i++) {
|
|
987
|
+
plane = uClippingPlanes[i];
|
|
988
|
+
if(dot(-vWorldPosition, plane.xyz) > plane.w) {
|
|
989
|
+
discard;
|
|
990
|
+
}
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
float time = uTime * uSpeed;
|
|
994
|
+
vec2 texSize = vec2(textureSize(uMaskTexture, 0));
|
|
995
|
+
|
|
996
|
+
// === OUTER SHADOW - makes effects feel inset (color burn style) ===
|
|
997
|
+
// Sample mask at increasing mip levels to get expanded/blurred versions
|
|
998
|
+
// Higher mip = more blur = wider spread
|
|
999
|
+
float maskSharp = textureLod(uMaskTexture, vUv, 0.0).a;
|
|
1000
|
+
float maskBlur1 = textureLod(uMaskTexture, vUv, 4.0 + uBorder * 3.0).a;
|
|
1001
|
+
float maskBlur2 = textureLod(uMaskTexture, vUv, 6.0 + uBorder * 4.0).a;
|
|
1002
|
+
float maskBlur3 = textureLod(uMaskTexture, vUv, 8.0 + uBorder * 5.0).a;
|
|
1003
|
+
float maskBlur4 = textureLod(uMaskTexture, vUv, 10.0 + uBorder * 6.0).a;
|
|
1004
|
+
|
|
1005
|
+
// Noise for organic shadow edges
|
|
1006
|
+
vec2 shadowNoiseUV = vUv * texSize * 0.003;
|
|
1007
|
+
float shadowNoise1 = snoise(shadowNoiseUV * 2.0 + time * 0.03) * 0.5 + 0.5;
|
|
1008
|
+
float shadowNoise2 = snoise(shadowNoiseUV * 4.0 + time * 0.02 + 50.0) * 0.5 + 0.5;
|
|
1009
|
+
float combinedShadowNoise = shadowNoise1 * 0.6 + shadowNoise2 * 0.4;
|
|
1010
|
+
|
|
1011
|
+
// Inner shadow zone: close to the edge, darkest
|
|
1012
|
+
float innerZone = smoothstep(0.0, 0.7, maskBlur1) * (1.0 - smoothstep(0.0, 0.1, maskSharp));
|
|
1013
|
+
// Mid-inner shadow zone
|
|
1014
|
+
float midInnerZone = smoothstep(0.0, 0.6, maskBlur2) * (1.0 - smoothstep(0.0, 0.3, maskBlur1));
|
|
1015
|
+
// Mid-outer shadow zone
|
|
1016
|
+
float midOuterZone = smoothstep(0.0, 0.5, maskBlur3) * (1.0 - smoothstep(0.0, 0.25, maskBlur2));
|
|
1017
|
+
// Outer shadow zone: farthest, lightest
|
|
1018
|
+
float outerZone = smoothstep(0.0, 0.4, maskBlur4) * (1.0 - smoothstep(0.0, 0.2, maskBlur3));
|
|
1019
|
+
|
|
1020
|
+
// Apply noise to break up the shadow - more noise on outer zones
|
|
1021
|
+
innerZone *= (0.85 + combinedShadowNoise * 0.15);
|
|
1022
|
+
midInnerZone *= (0.7 + combinedShadowNoise * 0.3);
|
|
1023
|
+
midOuterZone *= (0.5 + combinedShadowNoise * 0.5);
|
|
1024
|
+
outerZone *= (0.3 + combinedShadowNoise * 0.7);
|
|
1025
|
+
|
|
1026
|
+
// Combine with heavier weight near the edge (color burn effect)
|
|
1027
|
+
float shadowIntensity = innerZone * 1.0 + midInnerZone * 0.7 + midOuterZone * 0.4 + outerZone * 0.2;
|
|
1028
|
+
shadowIntensity *= uBorder * uOpacity;
|
|
1029
|
+
|
|
1030
|
+
vec4 result;
|
|
1031
|
+
|
|
1032
|
+
if(uEffectType == 1) {
|
|
1033
|
+
result = fireEffect(vUv, texSize, time);
|
|
1034
|
+
} else if(uEffectType == 2) {
|
|
1035
|
+
result = spaceTearEffect(vUv, texSize, time);
|
|
1036
|
+
} else if(uEffectType == 3) {
|
|
1037
|
+
result = waterEffect(vUv, texSize, time);
|
|
1038
|
+
} else if(uEffectType == 4) {
|
|
1039
|
+
result = magicEffect(vUv, texSize, time);
|
|
1040
|
+
} else if(uEffectType == 5) {
|
|
1041
|
+
result = greaseEffect(vUv, texSize, time);
|
|
1042
|
+
} else if(uEffectType == 6) {
|
|
1043
|
+
result = iceEffect(vUv, texSize, time);
|
|
1044
|
+
} else {
|
|
1045
|
+
// No effect - solid color
|
|
1046
|
+
float mask = texture2D(uMaskTexture, vUv).a;
|
|
1047
|
+
if(mask < 0.001 && shadowIntensity < 0.001) discard;
|
|
1048
|
+
result = vec4(uBaseColor, mask * uOpacity);
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
// Blend outer shadow under the effect (skip for no effect, water, grease, ice - they handle their own depth or don't need it)
|
|
1052
|
+
// Shadow is dark, high opacity near edge for color burn effect
|
|
1053
|
+
vec3 shadowColor = vec3(0.0, 0.0, 0.0);
|
|
1054
|
+
float shadowAlpha = (uEffectType == 0 || uEffectType == 3 || uEffectType == 5 || uEffectType == 6) ? 0.0 : shadowIntensity * 0.85; // No shadow for plain color/water/grease/ice
|
|
1055
|
+
|
|
1056
|
+
// If we have shadow but no effect, show just the shadow
|
|
1057
|
+
if(result.a < 0.001 && shadowAlpha > 0.001) {
|
|
1058
|
+
gl_FragColor = vec4(shadowColor, shadowAlpha);
|
|
1059
|
+
return;
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
// Composite: shadow underneath, effect on top
|
|
1063
|
+
// Use standard alpha blending: result over shadow
|
|
1064
|
+
float finalAlpha = result.a + shadowAlpha * (1.0 - result.a);
|
|
1065
|
+
vec3 finalColor = (result.rgb * result.a + shadowColor * shadowAlpha * (1.0 - result.a)) / max(finalAlpha, 0.001);
|
|
1066
|
+
|
|
1067
|
+
if(finalAlpha < 0.001) discard;
|
|
1068
|
+
|
|
1069
|
+
gl_FragColor = vec4(finalColor, finalAlpha);
|
|
1070
|
+
}
|