@razorpay/blade 12.92.0 → 12.93.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/spark/bottom-frame.jpg +0 -0
- package/assets/spark/colorama-center-gradient-map.jpg +0 -0
- package/assets/spark/colorama-gradient-map-blue.jpg +0 -0
- package/assets/spark/colorama-gradient-map-green.jpg +0 -0
- package/assets/spark/ray-pulse.mp4 +0 -0
- package/assets/spark/spark-base-video.mp4 +0 -0
- package/assets/spark/success-animation-circle.mp4 +0 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/FluidGradient.js +9 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/FluidGradient.js.map +1 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/FluidGradientMount.js +18 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/FluidGradientMount.js.map +1 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/shader.js +69 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/shader.js.map +1 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/useFluidGradient.js +7 -0
- package/build/lib/native/components/Spark/RazorSenseGradient/useFluidGradient.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/PerformanceManager.js +7 -0
- package/build/lib/native/components/Spark/RzpGlass/PerformanceManager.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/RzpGlass.js +13 -0
- package/build/lib/native/components/Spark/RzpGlass/RzpGlass.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/RzpGlassMount.js +28 -0
- package/build/lib/native/components/Spark/RzpGlass/RzpGlassMount.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/presets.js +4 -0
- package/build/lib/native/components/Spark/RzpGlass/presets.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/rzpGlassShader.js +920 -0
- package/build/lib/native/components/Spark/RzpGlass/rzpGlassShader.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/utils.js +4 -0
- package/build/lib/native/components/Spark/RzpGlass/utils.js.map +1 -0
- package/build/lib/native/components/Spark/RzpGlass/webgl-utils.js +7 -0
- package/build/lib/native/components/Spark/RzpGlass/webgl-utils.js.map +1 -0
- package/build/lib/native/components/index.js +2 -0
- package/build/lib/native/components/index.js.map +1 -1
- package/build/lib/web/development/_virtual/flatten.js +1 -1
- package/build/lib/web/development/_virtual/flatten3.js +1 -1
- package/build/lib/web/development/components/Dropdown/FilterChipSelectInput.web.js +23 -15
- package/build/lib/web/development/components/Dropdown/FilterChipSelectInput.web.js.map +1 -1
- package/build/lib/web/development/components/SideNav/SideNav.web.js +21 -21
- package/build/lib/web/development/components/SideNav/SideNav.web.js.map +1 -1
- package/build/lib/web/development/components/SideNav/SideNavItems/SideNavLink.web.js +4 -4
- package/build/lib/web/development/components/SideNav/SideNavItems/SideNavLink.web.js.map +1 -1
- package/build/lib/web/development/components/Spark/RazorSenseGradient/FluidGradient.js +92 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/FluidGradient.js.map +1 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/FluidGradientMount.js +110 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/FluidGradientMount.js.map +1 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/index.js +2 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/index.js.map +1 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/shader.js +18 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/shader.js.map +1 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/useFluidGradient.js +34 -0
- package/build/lib/web/development/components/Spark/RazorSenseGradient/useFluidGradient.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/PerformanceManager.js +455 -0
- package/build/lib/web/development/components/Spark/RzpGlass/PerformanceManager.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/RzpGlass.js +263 -0
- package/build/lib/web/development/components/Spark/RzpGlass/RzpGlass.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/RzpGlassMount.js +908 -0
- package/build/lib/web/development/components/Spark/RzpGlass/RzpGlassMount.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/index.js +24 -0
- package/build/lib/web/development/components/Spark/RzpGlass/index.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/presets.js +151 -0
- package/build/lib/web/development/components/Spark/RzpGlass/presets.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/rzpGlassShader.js +5 -0
- package/build/lib/web/development/components/Spark/RzpGlass/rzpGlassShader.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/utils.js +77 -0
- package/build/lib/web/development/components/Spark/RzpGlass/utils.js.map +1 -0
- package/build/lib/web/development/components/Spark/RzpGlass/webgl-utils.js +200 -0
- package/build/lib/web/development/components/Spark/RzpGlass/webgl-utils.js.map +1 -0
- package/build/lib/web/development/components/Spark/index.js +3 -0
- package/build/lib/web/development/components/Spark/index.js.map +1 -0
- package/build/lib/web/development/components/index.js +3 -0
- package/build/lib/web/development/components/index.js.map +1 -1
- package/build/lib/web/development/node_modules/es-toolkit/dist/array/flatten.js +1 -1
- package/build/lib/web/development/node_modules/es-toolkit/dist/compat/array/flatten.js +1 -1
- package/build/lib/web/development/node_modules/es-toolkit/dist/compat/array/sortBy.js +2 -2
- package/build/lib/web/development/node_modules/es-toolkit/dist/compat/object/omit.js +2 -2
- package/build/lib/web/production/components/Dropdown/FilterChipSelectInput.web.js +23 -15
- package/build/lib/web/production/components/Dropdown/FilterChipSelectInput.web.js.map +1 -1
- package/build/lib/web/production/components/SideNav/SideNav.web.js +21 -21
- package/build/lib/web/production/components/SideNav/SideNav.web.js.map +1 -1
- package/build/lib/web/production/components/SideNav/SideNavItems/SideNavLink.web.js +4 -4
- package/build/lib/web/production/components/SideNav/SideNavItems/SideNavLink.web.js.map +1 -1
- package/build/lib/web/production/components/Spark/RazorSenseGradient/FluidGradient.js +92 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/FluidGradient.js.map +1 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/FluidGradientMount.js +110 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/FluidGradientMount.js.map +1 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/index.js +2 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/index.js.map +1 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/shader.js +18 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/shader.js.map +1 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/useFluidGradient.js +34 -0
- package/build/lib/web/production/components/Spark/RazorSenseGradient/useFluidGradient.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/PerformanceManager.js +455 -0
- package/build/lib/web/production/components/Spark/RzpGlass/PerformanceManager.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/RzpGlass.js +263 -0
- package/build/lib/web/production/components/Spark/RzpGlass/RzpGlass.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/RzpGlassMount.js +908 -0
- package/build/lib/web/production/components/Spark/RzpGlass/RzpGlassMount.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/index.js +24 -0
- package/build/lib/web/production/components/Spark/RzpGlass/index.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/presets.js +151 -0
- package/build/lib/web/production/components/Spark/RzpGlass/presets.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/rzpGlassShader.js +5 -0
- package/build/lib/web/production/components/Spark/RzpGlass/rzpGlassShader.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/utils.js +77 -0
- package/build/lib/web/production/components/Spark/RzpGlass/utils.js.map +1 -0
- package/build/lib/web/production/components/Spark/RzpGlass/webgl-utils.js +200 -0
- package/build/lib/web/production/components/Spark/RzpGlass/webgl-utils.js.map +1 -0
- package/build/lib/web/production/components/Spark/index.js +3 -0
- package/build/lib/web/production/components/Spark/index.js.map +1 -0
- package/build/lib/web/production/components/index.js +3 -0
- package/build/lib/web/production/components/index.js.map +1 -1
- package/build/types/components/index.d.ts +297 -1
- package/build/types/components/index.native.d.ts +297 -1
- package/package.json +2 -1
|
@@ -0,0 +1,920 @@
|
|
|
1
|
+
var rzpGlassVertexShader=`
|
|
2
|
+
precision mediump float;
|
|
3
|
+
|
|
4
|
+
attribute vec2 position;
|
|
5
|
+
attribute vec2 uv;
|
|
6
|
+
|
|
7
|
+
// Zoom & Pan uniforms (computed in vertex shader for efficiency)
|
|
8
|
+
uniform float uZoom;
|
|
9
|
+
uniform vec2 uPan; // vec2(uPanX, uPanY)
|
|
10
|
+
|
|
11
|
+
// Output varyings
|
|
12
|
+
varying vec2 vUv; // Raw screen UV (for screen-space effects like feathering)
|
|
13
|
+
varying vec2 vContentUv; // Transformed UV for video/content sampling (zoom + pan applied)
|
|
14
|
+
|
|
15
|
+
void main() {
|
|
16
|
+
// Raw screen UV for screen-space effects
|
|
17
|
+
vUv = uv;
|
|
18
|
+
|
|
19
|
+
// Compute zoomed/panned UV for content sampling
|
|
20
|
+
// Zoom: scale around center (0.5, 0.5)
|
|
21
|
+
// Pan: offset the view
|
|
22
|
+
vContentUv = (uv - 0.5) / uZoom + 0.5;
|
|
23
|
+
vContentUv += uPan;
|
|
24
|
+
|
|
25
|
+
gl_Position = vec4(position, 0, 1);
|
|
26
|
+
}
|
|
27
|
+
`;var rzpGlassFragmentShader=`
|
|
28
|
+
precision mediump float;
|
|
29
|
+
|
|
30
|
+
uniform float uTime;
|
|
31
|
+
uniform vec2 iResolution;
|
|
32
|
+
uniform float uDpr;
|
|
33
|
+
uniform sampler2D uVideoTexture;
|
|
34
|
+
uniform sampler2D uGradientMap;
|
|
35
|
+
uniform sampler2D uGradientMap2; // Second gradient map for cross-fade blending
|
|
36
|
+
uniform sampler2D uCenterGradientMap; // Separate gradient map for center ellipse
|
|
37
|
+
|
|
38
|
+
// Layer toggles (enable/disable actual effects)
|
|
39
|
+
uniform float uEnableDisplacement;
|
|
40
|
+
uniform float uEnableColorama;
|
|
41
|
+
uniform float uEnableBloom;
|
|
42
|
+
uniform float uEnableLightSweep;
|
|
43
|
+
|
|
44
|
+
// ============================================
|
|
45
|
+
// COLORAMA UNIFORMS (Adobe AE v5 Pipeline)
|
|
46
|
+
// Pipeline: Scalar → Remap → Warp → Wrap → Lookup → Blend
|
|
47
|
+
// ============================================
|
|
48
|
+
|
|
49
|
+
// --- 1. INPUT PHASE (Scalar Index Generation) ---
|
|
50
|
+
uniform float uInputMin; // Input range min (default 0.0)
|
|
51
|
+
uniform float uInputMax; // Input range max (default 1.0)
|
|
52
|
+
|
|
53
|
+
// --- 2. MODIFY PHASE (Index Space Warping) ---
|
|
54
|
+
uniform float uModifyGamma; // Gamma curve: <1 = brights, >1 = darks (default 1.0)
|
|
55
|
+
uniform float uPosterizeLevels; // 0 = off, >0 = number of discrete steps
|
|
56
|
+
uniform float uCycleRepetitions; // Stretch/compress the index (default 1.0)
|
|
57
|
+
uniform float uPhaseShift; // Static offset (default 0.0)
|
|
58
|
+
uniform float uCycleSpeed; // Cycling animation speed (default 0.0)
|
|
59
|
+
|
|
60
|
+
// --- 3. OUTPUT CYCLE (Wrap & Lookup) ---
|
|
61
|
+
uniform float uWrapMode; // 0 = clamp, 1 = wrap/fract (default 1.0)
|
|
62
|
+
uniform float uReverse; // 0 = normal, 1 = reverse gradient (default 0.0)
|
|
63
|
+
|
|
64
|
+
// --- 4. COMPOSITE ---
|
|
65
|
+
uniform float uBlendWithOriginal; // 0 = full effect, 1 = original (default 0.0)
|
|
66
|
+
uniform float uGradientMapBlend; // 0 = uGradientMap, 1 = uGradientMap2 (default 0.0)
|
|
67
|
+
|
|
68
|
+
// --- 5. LIGHT EFFECT ---
|
|
69
|
+
uniform float uLightIntensity; // Strength of light sweep effect
|
|
70
|
+
uniform float uFrameCount; // Current frame number
|
|
71
|
+
uniform float uLightStartFrame; // Frame when light effect starts
|
|
72
|
+
|
|
73
|
+
// --- 6. DISPLACEMENT ---
|
|
74
|
+
uniform float uNumSegments; // Number of glass slits (default 45.0)
|
|
75
|
+
uniform float uSlitAngle; // Angle of slits in radians (default 0.13)
|
|
76
|
+
uniform float uDisplacementX; // X displacement amount (default -12.0)
|
|
77
|
+
uniform float uDisplacementY; // Y displacement amount (default -20.0)
|
|
78
|
+
|
|
79
|
+
// --- 7. CENTER ELEMENT ---
|
|
80
|
+
uniform float uEnableCenterElement; // Toggle center element (0 = off, 1 = on)
|
|
81
|
+
uniform float uCenterAnimDuration; // Duration of one animation cycle in seconds
|
|
82
|
+
uniform float uCenterAnimTime; // Current animation time in seconds (resets with video loop)
|
|
83
|
+
|
|
84
|
+
// --- 8. COLOR CORRECTION ---
|
|
85
|
+
uniform float uCCBlackPoint; // Levels black point (default 0.0)
|
|
86
|
+
uniform float uCCWhitePoint; // Levels white point (default 1.0)
|
|
87
|
+
uniform float uCCMidtoneGamma; // Midtone gamma (default 1.2)
|
|
88
|
+
uniform float uCCGamma; // Output gamma (default 1.2)
|
|
89
|
+
uniform float uCCContrast; // Contrast boost (default 0.0)
|
|
90
|
+
|
|
91
|
+
// --- 9. ZOOM & PAN ---
|
|
92
|
+
uniform float uZoom; // Zoom level (1.0 = normal, 2.0 = 2x zoom) - still needed for edge feather check
|
|
93
|
+
uniform vec4 uEdgeFeather; // Per-side feathering: vec4(top, right, bottom, left) clockwise, 0 = none, 1 = max
|
|
94
|
+
uniform vec2 uRefResolution; // Reference resolution for zoom-independent displacement
|
|
95
|
+
uniform vec4 uVisibleUvBounds; // vec4(minX, minY, maxX, maxY) - visible portion of canvas in container
|
|
96
|
+
|
|
97
|
+
// --- 10. BACKGROUND COLOR ---
|
|
98
|
+
uniform vec3 uBackgroundColor; // Background color to blend with (RGB 0-1)
|
|
99
|
+
|
|
100
|
+
// UV coordinates from the vertex shader
|
|
101
|
+
varying vec2 vUv; // Raw screen UV (for screen-space effects)
|
|
102
|
+
varying vec2 vContentUv; // Transformed UV with zoom/pan applied (for content sampling)
|
|
103
|
+
|
|
104
|
+
// ============================================
|
|
105
|
+
// UTILITY FUNCTIONS
|
|
106
|
+
// ============================================
|
|
107
|
+
// Rec. 709 luminance calculation
|
|
108
|
+
float luminance(vec3 color) {
|
|
109
|
+
return dot(color, vec3(0.2126, 0.7152, 0.0722));
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// ============================================
|
|
113
|
+
// COLORAMA EFFECT (Adobe After Effects v5 Pipeline)
|
|
114
|
+
// ============================================
|
|
115
|
+
//
|
|
116
|
+
// Pipeline:
|
|
117
|
+
// Image → Scalar Field (0-1) → Warp/Animate → Gradient Lookup → Composite
|
|
118
|
+
//
|
|
119
|
+
// This matches AE's indexed gradient remapping with time-domain cycling.
|
|
120
|
+
vec3 applyColoramaWithGradient(
|
|
121
|
+
sampler2D gradientMap, // Gradient map texture to sample from
|
|
122
|
+
float rawIntensity, // Raw luminance from pixel
|
|
123
|
+
float inputMin, // Input range min
|
|
124
|
+
float inputMax, // Input range max
|
|
125
|
+
float gamma, // Gamma curve (pow)
|
|
126
|
+
float posterizeLevels, // 0 = off, else discrete steps
|
|
127
|
+
float cycleReps, // Cycle repetitions (stretch)
|
|
128
|
+
float phaseShift, // Static offset
|
|
129
|
+
float cycleSpeed, // Time-based cycling
|
|
130
|
+
float wrapMode, // 0 = clamp, 1 = wrap
|
|
131
|
+
float reverse // 0 = normal, 1 = flip
|
|
132
|
+
) {
|
|
133
|
+
// ─────────────────────────────────────────────
|
|
134
|
+
// STEP 1: INPUT PHASE - Scalar Index Generation
|
|
135
|
+
// ─────────────────────────────────────────────
|
|
136
|
+
// Normalize intensity to input range
|
|
137
|
+
float t = clamp((rawIntensity - inputMin) / (inputMax - inputMin), 0.0, 1.0);
|
|
138
|
+
|
|
139
|
+
// ─────────────────────────────────────────────
|
|
140
|
+
// STEP 2: MODIFY PHASE - Index Space Warping
|
|
141
|
+
// ─────────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
// a) Gamma / Curves - reshape the intensity distribution
|
|
144
|
+
t = pow(t, gamma);
|
|
145
|
+
|
|
146
|
+
// b) Posterize - quantize to discrete levels (branchless)
|
|
147
|
+
// When posterizeLevels <= 0, keeps t unchanged
|
|
148
|
+
float posterized = floor(t * posterizeLevels + 0.0001) / max(posterizeLevels, 0.0001);
|
|
149
|
+
t = mix(t, posterized, step(0.001, posterizeLevels));
|
|
150
|
+
|
|
151
|
+
// c) Cycle Repetitions - stretch/compress across gradient
|
|
152
|
+
t = t * cycleReps;
|
|
153
|
+
|
|
154
|
+
// d) Phase Shift - static offset
|
|
155
|
+
t = t + phaseShift;
|
|
156
|
+
|
|
157
|
+
// e) Cycling Animation - time-based offset
|
|
158
|
+
t = t + cycleSpeed * uTime;
|
|
159
|
+
|
|
160
|
+
// ─────────────────────────────────────────────
|
|
161
|
+
// STEP 3: OUTPUT CYCLE - Wrap & Lookup (branchless)
|
|
162
|
+
// ─────────────────────────────────────────────
|
|
163
|
+
|
|
164
|
+
// Wrap (fract) vs Clamp - branchless selection
|
|
165
|
+
t = mix(clamp(t, 0.0, 1.0), fract(t), step(0.5, wrapMode));
|
|
166
|
+
|
|
167
|
+
// Reverse direction - branchless
|
|
168
|
+
t = mix(t, 1.0 - t, step(0.5, reverse));
|
|
169
|
+
|
|
170
|
+
// Gradient lookup (1D texture sample)
|
|
171
|
+
return texture2D(gradientMap, vec2(t, 0.5)).rgb;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// ============================================
|
|
175
|
+
// DISPLACEMENT FUNCTIONS
|
|
176
|
+
// ============================================
|
|
177
|
+
// Create striped displacement map for glass refraction effect
|
|
178
|
+
// Returns: x = signed displacement (-1 to 1), y = local UV x position within segment
|
|
179
|
+
// gradientStart: gradient value at left edge (typically 1.0 for white)
|
|
180
|
+
// gradientEnd: gradient value at right edge (typically 0.0 for black)
|
|
181
|
+
// gradientPower: power curve for falloff (1.0 = linear, <1.0 = steeper, >1.0 = gentler)
|
|
182
|
+
// centerPoint: center value for signed conversion (typically 0.5)
|
|
183
|
+
// aspect: screen aspect ratio (width/height) for consistent slit angle
|
|
184
|
+
vec2 createStripedDisplacement(
|
|
185
|
+
vec2 uv,
|
|
186
|
+
float numSegments,
|
|
187
|
+
float angle,
|
|
188
|
+
float gradientStart,
|
|
189
|
+
float gradientEnd,
|
|
190
|
+
float gradientPower,
|
|
191
|
+
float centerPoint,
|
|
192
|
+
float aspect
|
|
193
|
+
) {
|
|
194
|
+
// Work in aspect-corrected UV space where x and y have equal visual scale
|
|
195
|
+
// This ensures consistent slit angle regardless of viewport dimensions
|
|
196
|
+
vec2 aspectUV = uv * vec2(aspect, 1.0);
|
|
197
|
+
|
|
198
|
+
// Apply slant in aspect-corrected space
|
|
199
|
+
float slantedX = aspectUV.x - aspectUV.y * tan(angle);
|
|
200
|
+
|
|
201
|
+
// Calculate segment properties (account for aspect-scaled x range)
|
|
202
|
+
float segmentWidth = aspect / numSegments;
|
|
203
|
+
float localUVx = fract(slantedX / segmentWidth); // 0-1 within each segment
|
|
204
|
+
|
|
205
|
+
// Create the displacement map gradient
|
|
206
|
+
// Use smoothstep for smoother interpolation
|
|
207
|
+
float smoothUVx = smoothstep(0.0, 1.0, localUVx);
|
|
208
|
+
// Interpolate from gradientEnd (left) to gradientStart (right)
|
|
209
|
+
float rawGradient = mix(gradientEnd, gradientStart, smoothUVx);
|
|
210
|
+
|
|
211
|
+
// Apply power curve for falloff control
|
|
212
|
+
rawGradient = pow(rawGradient, gradientPower);
|
|
213
|
+
|
|
214
|
+
// Convert to signed displacement (-1 to 1) using centerPoint
|
|
215
|
+
// centerPoint is the neutral value (typically 0.5)
|
|
216
|
+
float signedDisplacement = (rawGradient - centerPoint) / centerPoint;
|
|
217
|
+
|
|
218
|
+
return vec2(signedDisplacement, localUVx);
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// Apply displacement offset to UV coordinates
|
|
222
|
+
vec2 applyDisplacement(vec2 uv, float signedDisplacement, vec2 maxDisplacement, vec2 resolution) {
|
|
223
|
+
vec2 displaceOffset = vec2(
|
|
224
|
+
signedDisplacement * maxDisplacement.x / resolution.x,
|
|
225
|
+
signedDisplacement * maxDisplacement.y / resolution.y
|
|
226
|
+
);
|
|
227
|
+
return uv + displaceOffset;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// Create thin slanted stripes with multi-stop gradient color
|
|
231
|
+
// Returns RGB color: gradient stripes with 3 color stops
|
|
232
|
+
// Stop 1 (0%): colorStart, Stop 2 (stopPosition): colorMid, Stop 3 (100%): transparent
|
|
233
|
+
vec4 createStripes(
|
|
234
|
+
vec2 uv,
|
|
235
|
+
float numSegments,
|
|
236
|
+
float angle,
|
|
237
|
+
float stopPosition, // Position of middle stop (0.0 to 1.0)
|
|
238
|
+
vec4 colorStart, // Color at 0% (left edge)
|
|
239
|
+
vec4 colorMid, // Color at stopPosition
|
|
240
|
+
float aspect // Screen aspect ratio for consistent angle
|
|
241
|
+
) {
|
|
242
|
+
// Work in aspect-corrected UV space where x and y have equal visual scale
|
|
243
|
+
vec2 aspectUV = uv * vec2(aspect, 1.0);
|
|
244
|
+
|
|
245
|
+
// Apply slant in aspect-corrected space
|
|
246
|
+
float slantedX = aspectUV.x - aspectUV.y * tan(angle);
|
|
247
|
+
|
|
248
|
+
// Calculate segment properties (account for aspect-scaled x range)
|
|
249
|
+
float segmentWidth = aspect / numSegments;
|
|
250
|
+
float localUVx = 1.0 - fract(slantedX / segmentWidth); // 0-1 within each segment, reversed
|
|
251
|
+
|
|
252
|
+
// Multi-stop gradient:
|
|
253
|
+
// 0% -> colorStart (green)
|
|
254
|
+
// stopPosition -> colorMid (white)
|
|
255
|
+
// 100% -> transparent (black with 0 opacity)
|
|
256
|
+
|
|
257
|
+
vec4 gradientColor;
|
|
258
|
+
float opacity;
|
|
259
|
+
|
|
260
|
+
if (localUVx < stopPosition) {
|
|
261
|
+
float t = localUVx / stopPosition;
|
|
262
|
+
gradientColor = mix(colorMid, colorStart, t);
|
|
263
|
+
opacity = 0.5;
|
|
264
|
+
} else {
|
|
265
|
+
float t = (localUVx - stopPosition) / (1.0 - stopPosition);
|
|
266
|
+
gradientColor = mix(vec4(0.0), colorMid, t);
|
|
267
|
+
opacity = 0.5 - t * 0.5;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return gradientColor * opacity;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Sample texture with displacement applied
|
|
274
|
+
vec4 sampleWithDisplacement(
|
|
275
|
+
sampler2D tex,
|
|
276
|
+
vec2 uv,
|
|
277
|
+
float signedDisplacement,
|
|
278
|
+
vec2 maxDisplacement,
|
|
279
|
+
vec2 resolution
|
|
280
|
+
) {
|
|
281
|
+
vec2 displacedUV = applyDisplacement(uv, signedDisplacement, maxDisplacement, resolution);
|
|
282
|
+
return texture2D(tex, displacedUV);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ============================================
|
|
286
|
+
// POST-PROCESSING EFFECTS
|
|
287
|
+
// ============================================
|
|
288
|
+
vec3 applyBloom(vec3 color, float intensity, float innerMask) {
|
|
289
|
+
const float whiteCoreThresholdMin = 0.5; // Start of white core mask
|
|
290
|
+
const float whiteCoreThresholdMax = 0.85; // End of white core mask
|
|
291
|
+
const float whiteCoreBlendStrength = 0.85; // How much to blend towards pure white
|
|
292
|
+
|
|
293
|
+
const float bloomThresholdMin = 0.3; // Start of bloom glow
|
|
294
|
+
const float bloomThresholdMax = 0.7; // End of bloom glow
|
|
295
|
+
const vec3 bloomColor = vec3(1.0, 0.99, 0.97); // Warm white bloom tint
|
|
296
|
+
const float bloomStrength = 0.10; // Intensity of bloom glow
|
|
297
|
+
// -------------------------------
|
|
298
|
+
|
|
299
|
+
// Calculate how much we're in the "center" bright area
|
|
300
|
+
// Use a tighter threshold for the white core
|
|
301
|
+
float whiteCoreMask = smoothstep(whiteCoreThresholdMin, whiteCoreThresholdMax, intensity) * innerMask;
|
|
302
|
+
|
|
303
|
+
// Pure white target
|
|
304
|
+
vec3 pureWhite = vec3(1.0);
|
|
305
|
+
|
|
306
|
+
// Blend the center towards pure white (not additive, but replacement blend)
|
|
307
|
+
// This ensures the very center goes to white, not gray
|
|
308
|
+
color = mix(color, pureWhite, whiteCoreMask * whiteCoreBlendStrength);
|
|
309
|
+
|
|
310
|
+
// Additional soft bloom glow around the white core
|
|
311
|
+
float bloomBase = smoothstep(bloomThresholdMin, bloomThresholdMax, intensity);
|
|
312
|
+
float bloomAmount = bloomBase * innerMask;
|
|
313
|
+
color += bloomColor * bloomAmount * bloomStrength;
|
|
314
|
+
|
|
315
|
+
return color;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// ============================================
|
|
319
|
+
// ANIMATED POLYGON SHAPE
|
|
320
|
+
// ============================================
|
|
321
|
+
// Struct to return shape data
|
|
322
|
+
struct ShapeData {
|
|
323
|
+
float shape; // The shape value (0 = outside, 1 = center)
|
|
324
|
+
float gradient; // Gradient from gray (edge) to white (center)
|
|
325
|
+
};
|
|
326
|
+
|
|
327
|
+
// Signed distance function for a regular polygon
|
|
328
|
+
// p: point to test, r: radius, n: number of sides
|
|
329
|
+
float sdPolygon(vec2 p, float r, float n) {
|
|
330
|
+
// Angle and radius
|
|
331
|
+
float an = 3.141593 / n;
|
|
332
|
+
vec2 acs = vec2(cos(an), sin(an));
|
|
333
|
+
|
|
334
|
+
// Reduce to first sector
|
|
335
|
+
float bn = mod(atan(p.x, p.y), 2.0 * an) - an;
|
|
336
|
+
p = length(p) * vec2(cos(bn), abs(sin(bn)));
|
|
337
|
+
|
|
338
|
+
// Line sdf
|
|
339
|
+
p -= r * acs;
|
|
340
|
+
p.y += clamp(-p.y, 0.0, r * acs.y);
|
|
341
|
+
|
|
342
|
+
return length(p) * sign(p.x);
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Fast signed distance function for an ellipse
|
|
346
|
+
// Approximation that avoids expensive acos(), cube roots, and branching
|
|
347
|
+
// Accurate enough for visual effects, ~5x faster than exact version
|
|
348
|
+
float sdEllipse(vec2 p, vec2 ab) {
|
|
349
|
+
// Normalize point by ellipse radii
|
|
350
|
+
vec2 q = p / ab;
|
|
351
|
+
float k1 = length(q);
|
|
352
|
+
|
|
353
|
+
// Early out for points very close to center (avoid division issues)
|
|
354
|
+
if (k1 < 0.0001) return -min(ab.x, ab.y);
|
|
355
|
+
|
|
356
|
+
// Gradient-based distance approximation
|
|
357
|
+
vec2 q2 = q / ab; // Second normalization for gradient
|
|
358
|
+
float k2 = length(q2);
|
|
359
|
+
|
|
360
|
+
return k1 * (k1 - 1.0) / k2;
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// Helper: Calculate a single shape instance at a given animation phase
|
|
364
|
+
ShapeData calculateSingleShape(
|
|
365
|
+
vec2 uv,
|
|
366
|
+
float linearT, // Animation phase 0-1
|
|
367
|
+
float solidCoreMask,
|
|
368
|
+
vec2 resolution,
|
|
369
|
+
// Shape parameters
|
|
370
|
+
float shapeType,
|
|
371
|
+
float shapeWidth,
|
|
372
|
+
float shapeHeight,
|
|
373
|
+
float centerY,
|
|
374
|
+
float animRange,
|
|
375
|
+
float edgeSoftness,
|
|
376
|
+
float grayLevel,
|
|
377
|
+
float shapeAngleStart,
|
|
378
|
+
float shapeAngleEnd,
|
|
379
|
+
float shapeSize
|
|
380
|
+
) {
|
|
381
|
+
// Map 0-1 to position range (left to right)
|
|
382
|
+
float posOffset = (linearT * 2.0 - 1.0) * animRange;
|
|
383
|
+
float centerX = 0.5 + posOffset;
|
|
384
|
+
|
|
385
|
+
// Animate rotation
|
|
386
|
+
float animatedAngle = mix(shapeAngleStart, shapeAngleEnd, linearT);
|
|
387
|
+
|
|
388
|
+
// Correct for aspect ratio
|
|
389
|
+
float aspect = resolution.x / resolution.y;
|
|
390
|
+
|
|
391
|
+
// Calculate position relative to center
|
|
392
|
+
vec2 shapeCenter = vec2(centerX, centerY);
|
|
393
|
+
vec2 delta = uv - shapeCenter;
|
|
394
|
+
|
|
395
|
+
// Rotate delta by animated angle FIRST
|
|
396
|
+
float cosA = cos(animatedAngle);
|
|
397
|
+
float sinA = sin(animatedAngle);
|
|
398
|
+
vec2 rotatedDelta = vec2(
|
|
399
|
+
delta.x * cosA - delta.y * sinA,
|
|
400
|
+
delta.x * sinA + delta.y * cosA
|
|
401
|
+
);
|
|
402
|
+
|
|
403
|
+
// Apply aspect correction AFTER rotation
|
|
404
|
+
rotatedDelta.x *= aspect;
|
|
405
|
+
|
|
406
|
+
// Calculate distance based on shape type
|
|
407
|
+
float dist;
|
|
408
|
+
if (shapeType < 0.5) {
|
|
409
|
+
dist = sdEllipse(rotatedDelta, vec2(shapeWidth, shapeHeight));
|
|
410
|
+
} else {
|
|
411
|
+
vec2 scaledDelta = rotatedDelta / vec2(shapeWidth, shapeHeight);
|
|
412
|
+
dist = sdPolygon(scaledDelta, shapeSize / min(shapeWidth, shapeHeight), shapeType);
|
|
413
|
+
dist *= min(shapeWidth, shapeHeight);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Normalize distance for gradient
|
|
417
|
+
float normalizedDist;
|
|
418
|
+
if (shapeType < 0.5) {
|
|
419
|
+
normalizedDist = dist / max(shapeWidth, shapeHeight) + 1.0;
|
|
420
|
+
} else {
|
|
421
|
+
normalizedDist = (dist / shapeSize) + 1.0;
|
|
422
|
+
}
|
|
423
|
+
normalizedDist = clamp(normalizedDist, 0.0, 1.0);
|
|
424
|
+
|
|
425
|
+
// Create soft shape mask
|
|
426
|
+
float shapeMask = 1.0 - smoothstep(-edgeSoftness * 0.1, edgeSoftness * 0.05, dist);
|
|
427
|
+
|
|
428
|
+
// Create gradient
|
|
429
|
+
float gradient = mix(1.0, grayLevel, smoothstep(0.0, 1.0, normalizedDist));
|
|
430
|
+
|
|
431
|
+
// Apply solid core mask
|
|
432
|
+
shapeMask *= solidCoreMask;
|
|
433
|
+
|
|
434
|
+
ShapeData result;
|
|
435
|
+
result.shape = shapeMask;
|
|
436
|
+
result.gradient = gradient;
|
|
437
|
+
return result;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
// Creates two staggered animated shapes that move left-to-right
|
|
441
|
+
// When one reaches the far edge, another appears from the left
|
|
442
|
+
ShapeData calculateAnimatedShape(
|
|
443
|
+
vec2 uv,
|
|
444
|
+
float time, // Current animation time in seconds
|
|
445
|
+
float solidCoreMask,
|
|
446
|
+
vec2 resolution
|
|
447
|
+
) {
|
|
448
|
+
// --- Configurable parameters ---
|
|
449
|
+
const float shapeType = 3.0; // 0 = ellipse, 3 = triangle, 4 = square, 5 = pentagon, etc.
|
|
450
|
+
const float shapeWidth = 0.1; // Width/horizontal scale (wide)
|
|
451
|
+
const float shapeHeight = 0.8; // Height/vertical scale (short)
|
|
452
|
+
const float centerY = 0.4; // Vertical center position
|
|
453
|
+
float cycleDuration = uCenterAnimDuration; // Seconds per animation cycle (from uniform)
|
|
454
|
+
const float animRange = 0.7; // How far left/right it travels
|
|
455
|
+
const float edgeSoftness = 0.5; // Softness of shape edge
|
|
456
|
+
const float grayLevel = 0.5; // Gray color at shape edge
|
|
457
|
+
const float shapeAngleStart = 0.6; // Rotation angle at start (slight tilt)
|
|
458
|
+
const float shapeAngleEnd = 0.1; // Rotation angle at end (opposite tilt)
|
|
459
|
+
const float shapeSize = 0.4; // Overall size for polygon mode
|
|
460
|
+
const float staggerOffset = 0.4; // Offset between the two shapes (0.5 = half cycle apart)
|
|
461
|
+
const float shape2Scale = 1.3; // Scale multiplier for 2nd shape (1.0 = same size)
|
|
462
|
+
// -------------------------------
|
|
463
|
+
|
|
464
|
+
// Time-based animation: time / cycleDuration gives progress through cycle
|
|
465
|
+
float linearT1 = fract(time / cycleDuration); // Shape 1: 0->1 repeating
|
|
466
|
+
float linearT2 = fract(time / cycleDuration + staggerOffset); // Shape 2: offset by staggerOffset
|
|
467
|
+
|
|
468
|
+
// Calculate both shapes (shape 2 is slightly larger)
|
|
469
|
+
ShapeData shape1 = calculateSingleShape(
|
|
470
|
+
uv, linearT1, solidCoreMask, resolution,
|
|
471
|
+
shapeType, shapeWidth, shapeHeight, centerY, animRange,
|
|
472
|
+
edgeSoftness, grayLevel, shapeAngleStart, shapeAngleEnd, shapeSize
|
|
473
|
+
);
|
|
474
|
+
|
|
475
|
+
ShapeData shape2 = calculateSingleShape(
|
|
476
|
+
uv, linearT2, solidCoreMask, resolution,
|
|
477
|
+
shapeType, shapeWidth * shape2Scale, shapeHeight * shape2Scale, centerY, animRange,
|
|
478
|
+
edgeSoftness, grayLevel, shapeAngleStart, shapeAngleEnd, shapeSize * shape2Scale
|
|
479
|
+
);
|
|
480
|
+
|
|
481
|
+
// Combine both shapes (take max of masks, blend gradients)
|
|
482
|
+
ShapeData result;
|
|
483
|
+
result.shape = max(shape1.shape, shape2.shape);
|
|
484
|
+
// Weighted average of gradients based on shape masks
|
|
485
|
+
float totalMask = shape1.shape + shape2.shape;
|
|
486
|
+
if (totalMask > 0.001) {
|
|
487
|
+
result.gradient = (shape1.gradient * shape1.shape + shape2.gradient * shape2.shape) / totalMask;
|
|
488
|
+
} else {
|
|
489
|
+
result.gradient = 0.5;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
return result;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
// Apply shape effect to intensity (for colorama/displacement pipeline)
|
|
496
|
+
float applyShapeToIntensity(
|
|
497
|
+
float baseIntensity,
|
|
498
|
+
ShapeData shapeData,
|
|
499
|
+
float effectStrength
|
|
500
|
+
) {
|
|
501
|
+
// Blend the shape gradient into the base intensity
|
|
502
|
+
// This makes the shape area brighter/differently colored through colorama
|
|
503
|
+
float shapeContribution = shapeData.gradient * shapeData.shape;
|
|
504
|
+
return mix(baseIntensity, shapeContribution, shapeData.shape * effectStrength);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
|
|
508
|
+
// AE-style color processing (levels, gamma, contrast). Used in both ripple and normal mode.
|
|
509
|
+
vec3 applyColorCorrection(vec3 color) {
|
|
510
|
+
color = (color - uCCBlackPoint) / (uCCWhitePoint - uCCBlackPoint);
|
|
511
|
+
color = pow(max(color, vec3(0.0)), vec3(1.0 / (uCCMidtoneGamma * uCCGamma)));
|
|
512
|
+
color = color * (1.0 + uCCContrast) - uCCContrast * 0.5;
|
|
513
|
+
return clamp(color, 0.0, 1.0);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// Feather at container edges (visible bounds). Used in both ripple and normal mode.
|
|
517
|
+
vec3 applyEdgeFeathering(vec3 color) {
|
|
518
|
+
// Apply edge feathering when zoomed in
|
|
519
|
+
// Feathering is applied at the container edges (visible bounds), not canvas edges
|
|
520
|
+
// uEdgeFeather = vec4(top, right, bottom, left) — clockwise like CSS
|
|
521
|
+
if (any(greaterThan(uEdgeFeather, vec4(0.0)))) {
|
|
522
|
+
vec2 screenUV = vUv;
|
|
523
|
+
|
|
524
|
+
// Get visible UV bounds (where container clips the canvas)
|
|
525
|
+
float visMinX = uVisibleUvBounds.x;
|
|
526
|
+
float visMinY = uVisibleUvBounds.y;
|
|
527
|
+
float visMaxX = uVisibleUvBounds.z;
|
|
528
|
+
float visMaxY = uVisibleUvBounds.w;
|
|
529
|
+
|
|
530
|
+
// Calculate visible dimensions in UV space for aspect-correct feathering on X axis
|
|
531
|
+
float visibleWidth = visMaxX - visMinX;
|
|
532
|
+
float visibleHeight = visMaxY - visMinY;
|
|
533
|
+
float visibleAspect = visibleWidth / visibleHeight;
|
|
534
|
+
|
|
535
|
+
// Per-side feather amounts (X sides get aspect correction for pixel-equal width)
|
|
536
|
+
float featherTop = uEdgeFeather.x * 0.15 / visibleAspect;
|
|
537
|
+
float featherRight = uEdgeFeather.y * 0.15 / visibleAspect;
|
|
538
|
+
float featherBottom = uEdgeFeather.z * 0.15 / visibleAspect;
|
|
539
|
+
float featherLeft = uEdgeFeather.w * 0.15 / visibleAspect;
|
|
540
|
+
|
|
541
|
+
// Apply feathering at container edges (visible bounds)
|
|
542
|
+
float left = smoothstep(visMinX, visMinX + featherLeft, screenUV.x);
|
|
543
|
+
float right = smoothstep(visMaxX, visMaxX - featherRight, screenUV.x);
|
|
544
|
+
float bottom = smoothstep(visMinY, visMinY + featherBottom, screenUV.y);
|
|
545
|
+
float top = smoothstep(visMaxY, visMaxY - featherTop, screenUV.y);
|
|
546
|
+
|
|
547
|
+
float edgeMask = left * right * bottom * top;
|
|
548
|
+
color = mix(vec3(1.0), color, edgeMask);
|
|
549
|
+
}
|
|
550
|
+
return color;
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
void main() {
|
|
554
|
+
// ============================================
|
|
555
|
+
// LAYER 1: Base glass effect (fine slits, whole image)
|
|
556
|
+
// ============================================
|
|
557
|
+
float numSegments = uNumSegments;
|
|
558
|
+
float angle = uSlitAngle;
|
|
559
|
+
const float blurRadius = 9.0;
|
|
560
|
+
const float sigma = 4.0;
|
|
561
|
+
|
|
562
|
+
// Calculate aspect ratio for consistent slit angles
|
|
563
|
+
float aspect = iResolution.x / iResolution.y;
|
|
564
|
+
|
|
565
|
+
// Displacement parameters (in pixels, scaled by DPR)
|
|
566
|
+
// Scale displacement by reference resolution ratio to maintain consistency across browser zoom levels
|
|
567
|
+
float resolutionScale = iResolution.x / uRefResolution.x;
|
|
568
|
+
vec2 maxDisplacement = vec2(uDisplacementX, uDisplacementY) * uDpr * resolutionScale;
|
|
569
|
+
|
|
570
|
+
// Use pre-computed UV from vertex shader (zoom + pan already applied)
|
|
571
|
+
vec2 uv = vContentUv;
|
|
572
|
+
|
|
573
|
+
// Base displacement (fine slits)
|
|
574
|
+
// Use raw screen UV (vUv) so slit positions stay fixed on screen regardless of pan/zoom
|
|
575
|
+
float gradientStart = 1.0;
|
|
576
|
+
float gradientEnd = 0.0;
|
|
577
|
+
float gradientPower = 1.0;
|
|
578
|
+
float centerPoint = 0.5;
|
|
579
|
+
vec2 displacementData = createStripedDisplacement(
|
|
580
|
+
vUv,
|
|
581
|
+
numSegments,
|
|
582
|
+
angle,
|
|
583
|
+
gradientStart,
|
|
584
|
+
gradientEnd,
|
|
585
|
+
gradientPower,
|
|
586
|
+
centerPoint,
|
|
587
|
+
aspect
|
|
588
|
+
);
|
|
589
|
+
float signedDisplacement = displacementData.x;
|
|
590
|
+
float localUVx = displacementData.y;
|
|
591
|
+
|
|
592
|
+
// ============================================
|
|
593
|
+
// LAYER 2: Inner glass effect (larger slits, center only, STATIC)
|
|
594
|
+
// ============================================
|
|
595
|
+
// Inner segments are a divisor of outer segments for perfect alignment
|
|
596
|
+
// 45 / 5 = 9 segments (5x larger slits that align with outer grid)
|
|
597
|
+
float innerNumSegments = numSegments;
|
|
598
|
+
float innerAngle = angle; // Same angle as outer
|
|
599
|
+
|
|
600
|
+
// Inner slits are STATIC - use raw screen UV so slits stay fixed on screen
|
|
601
|
+
vec2 innerDisplacementData = createStripedDisplacement(
|
|
602
|
+
vUv,
|
|
603
|
+
innerNumSegments,
|
|
604
|
+
innerAngle,
|
|
605
|
+
gradientStart,
|
|
606
|
+
gradientEnd,
|
|
607
|
+
gradientPower,
|
|
608
|
+
centerPoint,
|
|
609
|
+
aspect
|
|
610
|
+
);
|
|
611
|
+
float innerSignedDisplacement = innerDisplacementData.x;
|
|
612
|
+
float innerLocalUVx = innerDisplacementData.y;
|
|
613
|
+
|
|
614
|
+
// ============================================
|
|
615
|
+
// COMPUTE SOLID CORE MASK EARLY (needed for light & displacement masking)
|
|
616
|
+
// ============================================
|
|
617
|
+
vec4 videoFrameSample = texture2D(uVideoTexture, uv);
|
|
618
|
+
float maskIntensity = luminance(videoFrameSample.rgb);
|
|
619
|
+
float solidCoreMask = smoothstep(0.4, 0.7, maskIntensity);
|
|
620
|
+
|
|
621
|
+
// Store original displacement for shape refraction (before masking)
|
|
622
|
+
float originalInnerDisplacement = innerSignedDisplacement;
|
|
623
|
+
|
|
624
|
+
// Mask inner displacement by solidCoreMask - no inner displacement in center
|
|
625
|
+
innerSignedDisplacement *= (1.0 - solidCoreMask);
|
|
626
|
+
|
|
627
|
+
// Inner layer displacement uses same values (scaled by resolutionScale for zoom independence)
|
|
628
|
+
vec2 innerMaxDisplacement = vec2(30.0, 0.0) * uDpr * resolutionScale;
|
|
629
|
+
|
|
630
|
+
// ============================================
|
|
631
|
+
// CENTER ELEMENT (Static Ellipse + Animated Shapes)
|
|
632
|
+
// ============================================
|
|
633
|
+
float staticEllipseMask = 0.0;
|
|
634
|
+
float staticEllipseGradient = 0.0;
|
|
635
|
+
ShapeData shapeData;
|
|
636
|
+
shapeData.shape = 0.0;
|
|
637
|
+
shapeData.gradient = 0.0;
|
|
638
|
+
|
|
639
|
+
float centerFadeInDuration = 10.0;
|
|
640
|
+
float centerFramesSinceStart = uFrameCount - uLightStartFrame;
|
|
641
|
+
float centerEffectActivation = clamp(centerFramesSinceStart / centerFadeInDuration, 0.0, 1.0);
|
|
642
|
+
|
|
643
|
+
if (uEnableCenterElement > 0.5) {
|
|
644
|
+
// Calculate static ellipse mask
|
|
645
|
+
{
|
|
646
|
+
const float ellipseCenterX = 0.3;
|
|
647
|
+
const float ellipseCenterY = -0.15;
|
|
648
|
+
const float ellipseWidth = 0.5;
|
|
649
|
+
const float ellipseHeight = 0.8;
|
|
650
|
+
const float ellipseAngle = 0.3;
|
|
651
|
+
const float ellipseSoftness = 1.0;
|
|
652
|
+
const float ellipseGrayLevel = 0.5;
|
|
653
|
+
|
|
654
|
+
float aspect = iResolution.x / iResolution.y;
|
|
655
|
+
|
|
656
|
+
// Use RAW UV (no displacement) for the mask calculation
|
|
657
|
+
vec2 delta = uv - vec2(ellipseCenterX, ellipseCenterY);
|
|
658
|
+
|
|
659
|
+
// Rotate
|
|
660
|
+
float cosA = cos(ellipseAngle);
|
|
661
|
+
float sinA = sin(ellipseAngle);
|
|
662
|
+
vec2 rotatedDelta = vec2(
|
|
663
|
+
delta.x * cosA - delta.y * sinA,
|
|
664
|
+
delta.x * sinA + delta.y * cosA
|
|
665
|
+
);
|
|
666
|
+
rotatedDelta.x *= aspect;
|
|
667
|
+
|
|
668
|
+
// Calculate ellipse distance
|
|
669
|
+
float ellipseDist = sdEllipse(rotatedDelta, vec2(ellipseWidth, ellipseHeight));
|
|
670
|
+
|
|
671
|
+
// Soft shape mask
|
|
672
|
+
staticEllipseMask = 1.0 - smoothstep(-ellipseSoftness * 0.1, ellipseSoftness * 0.05, ellipseDist);
|
|
673
|
+
|
|
674
|
+
// Gradient
|
|
675
|
+
float normalizedDist = ellipseDist / max(ellipseWidth, ellipseHeight) + 1.0;
|
|
676
|
+
normalizedDist = clamp(normalizedDist, 0.0, 1.0);
|
|
677
|
+
staticEllipseGradient = mix(1.0, ellipseGrayLevel, smoothstep(0.0, 1.0, normalizedDist));
|
|
678
|
+
|
|
679
|
+
// Apply solid core mask
|
|
680
|
+
staticEllipseMask *= solidCoreMask;
|
|
681
|
+
}
|
|
682
|
+
|
|
683
|
+
// Block displacement inside the static ellipse
|
|
684
|
+
originalInnerDisplacement *= (1.0 - staticEllipseMask);
|
|
685
|
+
innerSignedDisplacement *= (1.0 - staticEllipseMask);
|
|
686
|
+
signedDisplacement *= (1.0 - staticEllipseMask);
|
|
687
|
+
|
|
688
|
+
|
|
689
|
+
|
|
690
|
+
// Calculate displaced UV for shape - use inner displacement for the shape refraction
|
|
691
|
+
vec2 shapeDisplacedUV = applyDisplacement(uv, originalInnerDisplacement, innerMaxDisplacement, iResolution);
|
|
692
|
+
|
|
693
|
+
// Calculate animated shape using DISPLACED UVs so glass slits refract through it
|
|
694
|
+
shapeData = calculateAnimatedShape(
|
|
695
|
+
shapeDisplacedUV, // Use displaced UVs!
|
|
696
|
+
uCenterAnimTime, // Time-based animation in seconds (resets with video loop)
|
|
697
|
+
solidCoreMask,
|
|
698
|
+
iResolution
|
|
699
|
+
);
|
|
700
|
+
|
|
701
|
+
// Combine static ellipse with animated shapes
|
|
702
|
+
{
|
|
703
|
+
float combinedShape = max(shapeData.shape, staticEllipseMask) * centerEffectActivation;
|
|
704
|
+
float totalMask = shapeData.shape + staticEllipseMask;
|
|
705
|
+
float combinedGradient = shapeData.gradient;
|
|
706
|
+
if (totalMask > 0.001) {
|
|
707
|
+
combinedGradient = (shapeData.gradient * shapeData.shape + staticEllipseGradient * staticEllipseMask) / totalMask;
|
|
708
|
+
}
|
|
709
|
+
shapeData.shape = combinedShape;
|
|
710
|
+
shapeData.gradient = combinedGradient;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// ============================================
|
|
715
|
+
// INNER EFFECT ACTIVATION - starts after uLightStartFrame
|
|
716
|
+
// ============================================
|
|
717
|
+
float innerFadeInDuration = 10.0; // Slower fade-in for inner effect
|
|
718
|
+
float innerFramesSinceStart = uFrameCount - uLightStartFrame;
|
|
719
|
+
float innerEffectActivation = clamp(innerFramesSinceStart / innerFadeInDuration, 0.0, 1.0);
|
|
720
|
+
|
|
721
|
+
// Create edge mask (solidCoreMask already computed earlier for light masking)
|
|
722
|
+
float edgeMask = smoothstep(0.3, 0.6, maskIntensity); // Where shape starts
|
|
723
|
+
|
|
724
|
+
// Blend outer and inner slits on the edges
|
|
725
|
+
// Inner contribution is multiplied by activation (fades in after frame 200)
|
|
726
|
+
float outerContribution = 1.0 - edgeMask * 0.5 * innerEffectActivation;
|
|
727
|
+
float innerContribution = edgeMask * innerEffectActivation;
|
|
728
|
+
|
|
729
|
+
// Combined displacement: inner effect fades in over time
|
|
730
|
+
float combinedDisplacement = signedDisplacement * outerContribution +
|
|
731
|
+
innerSignedDisplacement * innerContribution;
|
|
732
|
+
|
|
733
|
+
// Blend max displacement smoothly
|
|
734
|
+
vec2 combinedMaxDisplacement = maxDisplacement * outerContribution +
|
|
735
|
+
innerMaxDisplacement * innerContribution;
|
|
736
|
+
|
|
737
|
+
// For the CENTER area (solidCoreMask): use 100% inner (larger) slits displacement
|
|
738
|
+
// For the EDGES: use the combined displacement (blended outer + inner)
|
|
739
|
+
// This ensures the logo center always has the larger slits
|
|
740
|
+
combinedDisplacement = mix(combinedDisplacement, originalInnerDisplacement, solidCoreMask);
|
|
741
|
+
combinedMaxDisplacement = mix(combinedMaxDisplacement, innerMaxDisplacement, solidCoreMask);
|
|
742
|
+
|
|
743
|
+
// ============================================
|
|
744
|
+
// LAYER 1: DISPLACEMENT (toggleable)
|
|
745
|
+
// ============================================
|
|
746
|
+
vec4 textureSample;
|
|
747
|
+
if (uEnableDisplacement > 0.5) {
|
|
748
|
+
textureSample = sampleWithDisplacement(
|
|
749
|
+
uVideoTexture, uv,
|
|
750
|
+
combinedDisplacement, combinedMaxDisplacement,
|
|
751
|
+
iResolution
|
|
752
|
+
);
|
|
753
|
+
} else {
|
|
754
|
+
// No displacement - sample directly
|
|
755
|
+
textureSample = texture2D(uVideoTexture, uv);
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
// Blend localUVx for highlights - also fades in with activation
|
|
759
|
+
float combinedLocalUVx = localUVx * outerContribution + innerLocalUVx * innerContribution;
|
|
760
|
+
localUVx = combinedLocalUVx;
|
|
761
|
+
|
|
762
|
+
// Store innerMask for later use (bloom, etc.) - also tied to activation
|
|
763
|
+
float innerMask = edgeMask * innerEffectActivation;
|
|
764
|
+
|
|
765
|
+
// Get Phase From: Intensity (Rec. 709 luminance)
|
|
766
|
+
float baseIntensity = luminance(textureSample.rgb);
|
|
767
|
+
|
|
768
|
+
// Boost intensity in center areas to push them more towards white
|
|
769
|
+
float centerWhiteBoost = 0.1;
|
|
770
|
+
baseIntensity = baseIntensity + innerMask * centerWhiteBoost;
|
|
771
|
+
baseIntensity = clamp(baseIntensity, 0.0, 1.0);
|
|
772
|
+
|
|
773
|
+
// Keep base intensity for outer colorama (using uGradientMap)
|
|
774
|
+
float outerIntensity = baseIntensity;
|
|
775
|
+
|
|
776
|
+
// ============================================
|
|
777
|
+
// CENTER GREEN STRIPES OVERLAY (before colorama)
|
|
778
|
+
// ============================================
|
|
779
|
+
float stripeFadeOutDuration = 10.0;
|
|
780
|
+
float stripeFramesSinceStart = uFrameCount - uLightStartFrame;
|
|
781
|
+
// Effect is active UNTIL uLightStartFrame, then fades out
|
|
782
|
+
float stripeEffectActivation = 1.0 - clamp(stripeFramesSinceStart / stripeFadeOutDuration, 0.0, 1.0);
|
|
783
|
+
|
|
784
|
+
// Animated vertical height mask - grows from 0 to full height
|
|
785
|
+
// Height animation: starts at center (0.5) and expands outward
|
|
786
|
+
float stripeHeightDelay = 15.0; // frames to wait before starting
|
|
787
|
+
float stripeHeightGrowDuration = 80.0; // frames to reach full height
|
|
788
|
+
float stripeHeightProgress = clamp((uFrameCount - stripeHeightDelay) / stripeHeightGrowDuration, 0.0, 1.0);
|
|
789
|
+
// Ease the progress for smoother animation
|
|
790
|
+
float easedHeightProgress = 1.0 - pow(1.0 - stripeHeightProgress, 2.0);
|
|
791
|
+
|
|
792
|
+
// Calculate animated bounds - expand from center (0.5) outward
|
|
793
|
+
float heightHalfSpan = 0.2 * easedHeightProgress; // 0.06 = half of the 0.12 total height (0.44 to 0.56)
|
|
794
|
+
float softEdge = 0.1 * easedHeightProgress; // Soft edge also scales with progress
|
|
795
|
+
float bottomEdge = 0.5 - heightHalfSpan - softEdge;
|
|
796
|
+
float bottomFull = 0.5 - heightHalfSpan;
|
|
797
|
+
float topFull = 0.5 + heightHalfSpan;
|
|
798
|
+
float topEdge = 0.5 + heightHalfSpan + softEdge;
|
|
799
|
+
|
|
800
|
+
// When progress is 0, force mask to 0 to avoid glitchy edge at y=0.5
|
|
801
|
+
float stripeHeightMask = easedHeightProgress > 0.001
|
|
802
|
+
? smoothstep(bottomEdge, bottomFull, uv.y) * smoothstep(topEdge, topFull, uv.y)
|
|
803
|
+
: 0.0;
|
|
804
|
+
|
|
805
|
+
vec4 centerGreenSlantedLines = createStripes(
|
|
806
|
+
vUv + vec2(-0.0035, 0.0), // slight offset to avoid moiré
|
|
807
|
+
numSegments,
|
|
808
|
+
uSlitAngle,
|
|
809
|
+
0.15, // stopPosition (20%)
|
|
810
|
+
vec4(20.0/255.0, 200.0/255.0, 20.0/255.0, 0.2), // colorStart (green at 0%)
|
|
811
|
+
vec4(0.0, 0.0, 0.0, 0.0), // colorMid (white at 20%)
|
|
812
|
+
aspect // aspect ratio for consistent angle
|
|
813
|
+
) * solidCoreMask * stripeHeightMask;
|
|
814
|
+
|
|
815
|
+
// Overlay green stripes on center element area
|
|
816
|
+
float stripeOverlayMask = solidCoreMask * stripeEffectActivation;
|
|
817
|
+
// Modify baseIntensity/outerIntensity with stripes before colorama
|
|
818
|
+
vec4 stripedTexture = vec4(textureSample.rgb, 1.0) - centerGreenSlantedLines*0.7 * stripeOverlayMask;
|
|
819
|
+
stripedTexture = clamp(stripedTexture, 0.0, 1.0);
|
|
820
|
+
|
|
821
|
+
// Update intensity for colorama input
|
|
822
|
+
float stripedIntensity = luminance(stripedTexture.rgb);
|
|
823
|
+
outerIntensity = mix(baseIntensity, stripedIntensity, stripeOverlayMask);
|
|
824
|
+
|
|
825
|
+
// ============================================
|
|
826
|
+
// LAYER 2: COLORAMA (toggleable)
|
|
827
|
+
// ============================================
|
|
828
|
+
vec3 color;
|
|
829
|
+
if (uEnableColorama > 0.5) {
|
|
830
|
+
// OUTER colorama: uses base intensity, cross-fades between uGradientMap and uGradientMap2
|
|
831
|
+
vec3 outerColoramaResult1 = applyColoramaWithGradient(
|
|
832
|
+
uGradientMap, outerIntensity,
|
|
833
|
+
uInputMin, uInputMax, uModifyGamma, uPosterizeLevels,
|
|
834
|
+
uCycleRepetitions, uPhaseShift, uCycleSpeed,
|
|
835
|
+
uWrapMode, uReverse
|
|
836
|
+
);
|
|
837
|
+
vec3 outerColoramaResult2 = applyColoramaWithGradient(
|
|
838
|
+
uGradientMap2, outerIntensity,
|
|
839
|
+
uInputMin, uInputMax, uModifyGamma, uPosterizeLevels,
|
|
840
|
+
uCycleRepetitions, uPhaseShift, uCycleSpeed,
|
|
841
|
+
uWrapMode, uReverse
|
|
842
|
+
);
|
|
843
|
+
vec3 outerColoramaResult = mix(outerColoramaResult1, outerColoramaResult2, uGradientMapBlend);
|
|
844
|
+
|
|
845
|
+
// Start with outer colorama as base
|
|
846
|
+
vec3 blendedColorama = outerColoramaResult;
|
|
847
|
+
|
|
848
|
+
// CENTER colorama: only compute when inside shape (skip texture sample otherwise)
|
|
849
|
+
// This saves a texture lookup + specular pow() for ~90% of pixels
|
|
850
|
+
if (shapeData.shape > 0.001) {
|
|
851
|
+
vec3 centerColoramaResult = applyColoramaWithGradient(
|
|
852
|
+
uCenterGradientMap, shapeData.gradient,
|
|
853
|
+
uInputMin, uInputMax, uModifyGamma, uPosterizeLevels,
|
|
854
|
+
uCycleRepetitions, uPhaseShift, uCycleSpeed,
|
|
855
|
+
uWrapMode, uReverse
|
|
856
|
+
);
|
|
857
|
+
|
|
858
|
+
// Add specular highlight to center (shiny reflection effect)
|
|
859
|
+
float specularPower = 8.0; // Higher = tighter/smaller highlight
|
|
860
|
+
float specularIntensity = 1.9; // Brightness of the specular
|
|
861
|
+
float specular = pow(shapeData.gradient, specularPower) * specularIntensity;
|
|
862
|
+
centerColoramaResult += vec3(specular); // Add bright highlight
|
|
863
|
+
|
|
864
|
+
// Blend between outer and center colorama based on shape
|
|
865
|
+
blendedColorama = mix(outerColoramaResult, centerColoramaResult, shapeData.shape);
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
color = mix(blendedColorama, textureSample.rgb, uBlendWithOriginal);
|
|
869
|
+
} else {
|
|
870
|
+
color = textureSample.rgb;
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
// Store intensity for bloom (use the blended value)
|
|
874
|
+
float intensity = mix(outerIntensity, shapeData.gradient, shapeData.shape);
|
|
875
|
+
|
|
876
|
+
// ============================================
|
|
877
|
+
// LAYER 3: BLOOM (toggleable)
|
|
878
|
+
// ============================================
|
|
879
|
+
if (uEnableBloom > 0.5) {
|
|
880
|
+
color = applyBloom(color, intensity, innerMask);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
// ============================================
|
|
884
|
+
// LAYER 4: SHAPE HIGHLIGHT (toggleable via light sweep toggle)
|
|
885
|
+
// ============================================
|
|
886
|
+
if (uEnableLightSweep > 0.5) {
|
|
887
|
+
float lightFadeInDuration = 30.0;
|
|
888
|
+
float framesSinceStart = uFrameCount - uLightStartFrame;
|
|
889
|
+
float lightActivation = clamp(framesSinceStart / lightFadeInDuration, 0.0, 1.0);
|
|
890
|
+
|
|
891
|
+
// Add subtle brightness boost at shape center
|
|
892
|
+
float shapeHighlight = pow(shapeData.gradient, 2.0) * shapeData.shape;
|
|
893
|
+
color += vec3(1.0) * shapeHighlight * 0.15 * uLightIntensity * lightActivation;
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// Color correction and edge feathering (shared with ripple mode)
|
|
897
|
+
color = applyColorCorrection(color);
|
|
898
|
+
color = applyEdgeFeathering(color);
|
|
899
|
+
|
|
900
|
+
// Blend with background color if provided (uBackgroundColor.r < 0 means not set)
|
|
901
|
+
if (uBackgroundColor.r >= 0.0) {
|
|
902
|
+
// Calculate luminance to determine how bright the pixel is
|
|
903
|
+
float brightness = luminance(color);
|
|
904
|
+
|
|
905
|
+
// Blend white/bright areas with background color
|
|
906
|
+
// Bright areas (close to white) become the background color
|
|
907
|
+
float blendStart = 0.98; // Start blending at this brightness
|
|
908
|
+
float blendEnd = 1.0; // Fully background color at this brightness
|
|
909
|
+
float blendAmount = smoothstep(blendStart, blendEnd, brightness);
|
|
910
|
+
|
|
911
|
+
// Mix the shader color with background color
|
|
912
|
+
color = mix(color, uBackgroundColor, blendAmount);
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
gl_FragColor = vec4(color, 1.0);
|
|
916
|
+
}
|
|
917
|
+
`;
|
|
918
|
+
|
|
919
|
+
export { rzpGlassFragmentShader, rzpGlassVertexShader };
|
|
920
|
+
//# sourceMappingURL=rzpGlassShader.js.map
|