@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,908 @@
|
|
|
1
|
+
import _slicedToArray from '@babel/runtime/helpers/slicedToArray';
|
|
2
|
+
import _asyncToGenerator from '@babel/runtime/helpers/asyncToGenerator';
|
|
3
|
+
import _classCallCheck from '@babel/runtime/helpers/classCallCheck';
|
|
4
|
+
import _createClass from '@babel/runtime/helpers/createClass';
|
|
5
|
+
import _defineProperty from '@babel/runtime/helpers/defineProperty';
|
|
6
|
+
import _regeneratorRuntime from '@babel/runtime/regenerator';
|
|
7
|
+
import { rzpGlassVertexShader, rzpGlassFragmentShader } from './rzpGlassShader.js';
|
|
8
|
+
import { DEFAULT_CONFIG } from './presets.js';
|
|
9
|
+
import { isSafari, bestGuessBrowserZoom, loadImage, loadVideo } from './utils.js';
|
|
10
|
+
import { createProgram, setupFullscreenQuad, Texture } from './webgl-utils.js';
|
|
11
|
+
import { LEVEL_RENDER_SETTINGS, WebGLPerformanceController } from './PerformanceManager.js';
|
|
12
|
+
|
|
13
|
+
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
|
|
14
|
+
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
|
|
15
|
+
// Reference resolution for zoom-independent displacement
|
|
16
|
+
var REF_RESOLUTION = {
|
|
17
|
+
width: 3000,
|
|
18
|
+
height: 2000
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
// Default max pixel count (1920 * 1080 * 4 = 8,294,400 pixels)
|
|
22
|
+
var DEFAULT_MAX_PIXEL_COUNT = 1920 * 1080 * 4;
|
|
23
|
+
|
|
24
|
+
// Default styles for the shader container
|
|
25
|
+
var defaultStyle = "@layer rzp-glass {\n :where([data-rzp-glass]) {\n isolation: isolate;\n position: relative;\n overflow: hidden;\n\n & canvas {\n contain: strict;\n display: block;\n position: absolute;\n z-index: -1;\n border-radius: inherit;\n }\n }\n}";
|
|
26
|
+
|
|
27
|
+
/** Map of config keys to uniform names */
|
|
28
|
+
var CONFIG_TO_UNIFORM = {
|
|
29
|
+
enableDisplacement: 'uEnableDisplacement',
|
|
30
|
+
enableColorama: 'uEnableColorama',
|
|
31
|
+
enableBloom: 'uEnableBloom',
|
|
32
|
+
enableLightSweep: 'uEnableLightSweep',
|
|
33
|
+
inputMin: 'uInputMin',
|
|
34
|
+
inputMax: 'uInputMax',
|
|
35
|
+
modifyGamma: 'uModifyGamma',
|
|
36
|
+
posterizeLevels: 'uPosterizeLevels',
|
|
37
|
+
cycleRepetitions: 'uCycleRepetitions',
|
|
38
|
+
phaseShift: 'uPhaseShift',
|
|
39
|
+
cycleSpeed: 'uCycleSpeed',
|
|
40
|
+
wrapMode: 'uWrapMode',
|
|
41
|
+
reverse: 'uReverse',
|
|
42
|
+
blendWithOriginal: 'uBlendWithOriginal',
|
|
43
|
+
lightIntensity: 'uLightIntensity',
|
|
44
|
+
lightStartFrame: 'uLightStartFrame',
|
|
45
|
+
numSegments: 'uNumSegments',
|
|
46
|
+
slitAngle: 'uSlitAngle',
|
|
47
|
+
displacementX: 'uDisplacementX',
|
|
48
|
+
displacementY: 'uDisplacementY',
|
|
49
|
+
enableCenterElement: 'uEnableCenterElement',
|
|
50
|
+
centerAnimDuration: 'uCenterAnimDuration',
|
|
51
|
+
ccBlackPoint: 'uCCBlackPoint',
|
|
52
|
+
ccWhitePoint: 'uCCWhitePoint',
|
|
53
|
+
ccMidtoneGamma: 'uCCMidtoneGamma',
|
|
54
|
+
ccGamma: 'uCCGamma',
|
|
55
|
+
ccContrast: 'uCCContrast',
|
|
56
|
+
zoom: 'uZoom',
|
|
57
|
+
// panX and panY are combined into uPan (vec2) in setUniformValues
|
|
58
|
+
// backgroundColor is handled separately (needs clear color update)
|
|
59
|
+
edgeFeather: 'uEdgeFeather'
|
|
60
|
+
};
|
|
61
|
+
var RzpGlassMount = /*#__PURE__*/function () {
|
|
62
|
+
function RzpGlassMount(parentElement, assets) {
|
|
63
|
+
var _this = this,
|
|
64
|
+
_visualViewport2;
|
|
65
|
+
var config = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
66
|
+
var frame = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 0;
|
|
67
|
+
var _minPixelRatio = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
|
|
68
|
+
var _maxPixelCount = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : DEFAULT_MAX_PIXEL_COUNT;
|
|
69
|
+
_classCallCheck(this, RzpGlassMount);
|
|
70
|
+
_defineProperty(this, "program", null);
|
|
71
|
+
_defineProperty(this, "uniformLocations", {});
|
|
72
|
+
_defineProperty(this, "uniformCache", {});
|
|
73
|
+
// Textures
|
|
74
|
+
_defineProperty(this, "videoTexture", null);
|
|
75
|
+
_defineProperty(this, "gradientMapTexture", null);
|
|
76
|
+
_defineProperty(this, "gradientMap2Texture", null);
|
|
77
|
+
_defineProperty(this, "centerGradientMapTexture", null);
|
|
78
|
+
// Gradient map blend animation state
|
|
79
|
+
_defineProperty(this, "currentGradientMapBlend", 0);
|
|
80
|
+
// Video element
|
|
81
|
+
_defineProperty(this, "video", null);
|
|
82
|
+
_defineProperty(this, "videoFrameCallbackId", null);
|
|
83
|
+
// Animation state (paper-shader style)
|
|
84
|
+
_defineProperty(this, "rafId", null);
|
|
85
|
+
/** Last render time in seconds */
|
|
86
|
+
_defineProperty(this, "lastRenderTime", 0);
|
|
87
|
+
/** Frame count (increments every frame) */
|
|
88
|
+
_defineProperty(this, "currentFrame", 0);
|
|
89
|
+
// Video-specific animation state
|
|
90
|
+
/** Time for independent light animation (accumulates deltaTime) */
|
|
91
|
+
_defineProperty(this, "independentLightTime", 0);
|
|
92
|
+
/** Last video animation time (for detecting jumps) */
|
|
93
|
+
_defineProperty(this, "lastVideoTime", 0);
|
|
94
|
+
// State flags
|
|
95
|
+
_defineProperty(this, "hasBeenDisposed", false);
|
|
96
|
+
_defineProperty(this, "isInitialized", false);
|
|
97
|
+
_defineProperty(this, "resolutionChanged", true);
|
|
98
|
+
// Visible UV bounds (where container clips the canvas)
|
|
99
|
+
// vec4(minX, minY, maxX, maxY) - portion of canvas UV that's visible
|
|
100
|
+
_defineProperty(this, "visibleUvBounds", [0, 0, 1, 1]);
|
|
101
|
+
// Resize handling
|
|
102
|
+
_defineProperty(this, "resizeObserver", null);
|
|
103
|
+
_defineProperty(this, "renderScale", 1);
|
|
104
|
+
_defineProperty(this, "parentWidth", 0);
|
|
105
|
+
_defineProperty(this, "parentHeight", 0);
|
|
106
|
+
_defineProperty(this, "parentDevicePixelWidth", 0);
|
|
107
|
+
_defineProperty(this, "parentDevicePixelHeight", 0);
|
|
108
|
+
_defineProperty(this, "devicePixelsSupported", false);
|
|
109
|
+
_defineProperty(this, "isSafariBrowser", isSafari());
|
|
110
|
+
// Performance monitoring
|
|
111
|
+
_defineProperty(this, "performanceController", null);
|
|
112
|
+
_defineProperty(this, "handleVisualViewportChange", function () {
|
|
113
|
+
var _this$resizeObserver;
|
|
114
|
+
// Restart resize observer to get fresh callback on zoom change
|
|
115
|
+
(_this$resizeObserver = _this.resizeObserver) === null || _this$resizeObserver === void 0 || _this$resizeObserver.disconnect();
|
|
116
|
+
_this.setupResizeObserver();
|
|
117
|
+
});
|
|
118
|
+
_defineProperty(this, "handleResize", function () {
|
|
119
|
+
var _visualViewport$scale, _visualViewport;
|
|
120
|
+
// Container dimensions (use stored values or fallback to clientWidth/Height)
|
|
121
|
+
var containerWidth = _this.parentWidth || _this.parentElement.clientWidth;
|
|
122
|
+
var containerHeight = _this.parentHeight || _this.parentElement.clientHeight;
|
|
123
|
+
var containerAspect = containerWidth / containerHeight;
|
|
124
|
+
|
|
125
|
+
// "Cover" behavior: fill container while maintaining aspect ratio (crop overflow)
|
|
126
|
+
var canvasWidth;
|
|
127
|
+
var canvasHeight;
|
|
128
|
+
var targetAspectRatio = _this.config.aspectRatio;
|
|
129
|
+
if (containerAspect > targetAspectRatio) {
|
|
130
|
+
// Container is wider than target - fit to width, crop top/bottom
|
|
131
|
+
canvasWidth = containerWidth;
|
|
132
|
+
canvasHeight = containerWidth / targetAspectRatio;
|
|
133
|
+
} else {
|
|
134
|
+
// Container is taller than target - fit to height, crop left/right
|
|
135
|
+
canvasHeight = containerHeight;
|
|
136
|
+
canvasWidth = containerHeight * targetAspectRatio;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Center the canvas (overflow will be hidden by parent)
|
|
140
|
+
var offsetX = (containerWidth - canvasWidth) / 2;
|
|
141
|
+
var offsetY = (containerHeight - canvasHeight) / 2;
|
|
142
|
+
|
|
143
|
+
// Calculate visible UV bounds (where container clips the canvas)
|
|
144
|
+
// When canvas overflows container, we need to know which portion is visible
|
|
145
|
+
var visibleMinX = -offsetX / canvasWidth;
|
|
146
|
+
var visibleMaxX = (containerWidth - offsetX) / canvasWidth;
|
|
147
|
+
var visibleMinY = -offsetY / canvasHeight;
|
|
148
|
+
var visibleMaxY = (containerHeight - offsetY) / canvasHeight;
|
|
149
|
+
_this.visibleUvBounds = [visibleMinX, visibleMinY, visibleMaxX, visibleMaxY];
|
|
150
|
+
|
|
151
|
+
// Set display size (CSS pixels)
|
|
152
|
+
_this.canvasElement.style.width = "".concat(canvasWidth, "px");
|
|
153
|
+
_this.canvasElement.style.height = "".concat(canvasHeight, "px");
|
|
154
|
+
_this.canvasElement.style.left = "".concat(offsetX, "px");
|
|
155
|
+
_this.canvasElement.style.top = "".concat(offsetY, "px");
|
|
156
|
+
|
|
157
|
+
// Calculate target pixel dimensions for rendering
|
|
158
|
+
var targetPixelWidth = 0;
|
|
159
|
+
var targetPixelHeight = 0;
|
|
160
|
+
var dpr = Math.max(1, window.devicePixelRatio);
|
|
161
|
+
var pinchZoom = (_visualViewport$scale = (_visualViewport = visualViewport) === null || _visualViewport === void 0 ? void 0 : _visualViewport.scale) !== null && _visualViewport$scale !== void 0 ? _visualViewport$scale : 1;
|
|
162
|
+
if (_this.devicePixelsSupported) {
|
|
163
|
+
// Use real pixel size if we know it, but maintain aspect ratio
|
|
164
|
+
// Calculate the scale ratio from parent to canvas (for aspect ratio correction)
|
|
165
|
+
var canvasToParentRatioX = canvasWidth / containerWidth;
|
|
166
|
+
var canvasToParentRatioY = canvasHeight / containerHeight;
|
|
167
|
+
var scaleToMeetMinPixelRatio = Math.max(1, _this.minPixelRatio / dpr);
|
|
168
|
+
// Apply aspect ratio correction to device pixel dimensions
|
|
169
|
+
targetPixelWidth = _this.parentDevicePixelWidth * canvasToParentRatioX * scaleToMeetMinPixelRatio * pinchZoom;
|
|
170
|
+
targetPixelHeight = _this.parentDevicePixelHeight * canvasToParentRatioY * scaleToMeetMinPixelRatio * pinchZoom;
|
|
171
|
+
} else {
|
|
172
|
+
// Approximate using devicePixelRatio
|
|
173
|
+
var targetRenderScale = Math.max(dpr, _this.minPixelRatio) * pinchZoom;
|
|
174
|
+
if (_this.isSafariBrowser) {
|
|
175
|
+
// Safari reports physical devicePixelRatio, need to factor in zoom manually
|
|
176
|
+
var zoomLevel = bestGuessBrowserZoom();
|
|
177
|
+
targetRenderScale *= Math.max(1, zoomLevel);
|
|
178
|
+
}
|
|
179
|
+
targetPixelWidth = Math.round(canvasWidth) * targetRenderScale;
|
|
180
|
+
targetPixelHeight = Math.round(canvasHeight) * targetRenderScale;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Prevent total rendered pixels from exceeding maxPixelCount
|
|
184
|
+
var maxPixelCountHeadroom = Math.sqrt(_this.maxPixelCount) / Math.sqrt(targetPixelWidth * targetPixelHeight);
|
|
185
|
+
var scaleToMeetMaxPixelCount = Math.min(1, maxPixelCountHeadroom);
|
|
186
|
+
var newWidth = Math.round(targetPixelWidth * scaleToMeetMaxPixelCount);
|
|
187
|
+
var newHeight = Math.round(targetPixelHeight * scaleToMeetMaxPixelCount);
|
|
188
|
+
var newRenderScale = newWidth / Math.round(canvasWidth);
|
|
189
|
+
if (_this.canvasElement.width !== newWidth || _this.canvasElement.height !== newHeight || _this.renderScale !== newRenderScale) {
|
|
190
|
+
_this.renderScale = newRenderScale;
|
|
191
|
+
_this.canvasElement.width = newWidth;
|
|
192
|
+
_this.canvasElement.height = newHeight;
|
|
193
|
+
_this.resolutionChanged = true;
|
|
194
|
+
_this.gl.viewport(0, 0, newWidth, newHeight);
|
|
195
|
+
|
|
196
|
+
// Only render immediately when the loop isn't running — if it is,
|
|
197
|
+
// resolutionChanged=true is enough and the next RAF picks it up.
|
|
198
|
+
// Calling render() while the loop is active spawns a duplicate RAF chain.
|
|
199
|
+
if (_this.rafId === null) {
|
|
200
|
+
_this.render(performance.now());
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
_defineProperty(this, "handleDocumentVisibilityChange", function () {
|
|
205
|
+
if (document.hidden) {
|
|
206
|
+
var _this$video;
|
|
207
|
+
// Pause render loop when tab is hidden
|
|
208
|
+
_this.stopRenderLoop();
|
|
209
|
+
(_this$video = _this.video) === null || _this$video === void 0 || _this$video.pause();
|
|
210
|
+
} else {
|
|
211
|
+
// Resume render loop when tab is visible
|
|
212
|
+
_this.startRenderLoop();
|
|
213
|
+
// Only resume video if not paused
|
|
214
|
+
if (!_this.config.paused) {
|
|
215
|
+
var _this$video2;
|
|
216
|
+
(_this$video2 = _this.video) === null || _this$video2 === void 0 || _this$video2.play()["catch"](function () {});
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
_defineProperty(this, "render", function (currentTime) {
|
|
221
|
+
if (_this.hasBeenDisposed) return;
|
|
222
|
+
|
|
223
|
+
// ALWAYS schedule next frame first (like the original loop)
|
|
224
|
+
_this.rafId = requestAnimationFrame(_this.render);
|
|
225
|
+
if (_this.program === null) {
|
|
226
|
+
console.warn('Tried to render before program was initialized');
|
|
227
|
+
return;
|
|
228
|
+
}
|
|
229
|
+
var gl = _this.gl;
|
|
230
|
+
var video = _this.video;
|
|
231
|
+
|
|
232
|
+
// Always clear canvas to transparent (even before video is ready)
|
|
233
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
234
|
+
|
|
235
|
+
// Calculate delta time in seconds (framerate independent)
|
|
236
|
+
var currentTimeSeconds = currentTime * 0.001; // Convert ms to seconds
|
|
237
|
+
var deltaTime = currentTimeSeconds - _this.lastRenderTime;
|
|
238
|
+
_this.lastRenderTime = currentTimeSeconds;
|
|
239
|
+
_this.currentFrame++; // Increment frame count every frame
|
|
240
|
+
|
|
241
|
+
var usingStaticImage = !video && _this.videoTexture !== null;
|
|
242
|
+
|
|
243
|
+
// Skip rendering if video isn't ready (canvas stays transparent).
|
|
244
|
+
// Static-image mode bypasses this guard since there's no video element.
|
|
245
|
+
if (!usingStaticImage) {
|
|
246
|
+
if (!video || video.readyState < video.HAVE_CURRENT_DATA) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
// Update video texture (fallback for browsers without requestVideoFrameCallback)
|
|
251
|
+
if (!('requestVideoFrameCallback' in video) && _this.videoTexture) {
|
|
252
|
+
_this.videoTexture.update(video);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Handle video looping within start/end time range (only when not paused)
|
|
256
|
+
if (!_this.config.paused) {
|
|
257
|
+
if (video.currentTime < _this.config.startTime || video.currentTime >= _this.config.endTime) {
|
|
258
|
+
video.currentTime = _this.config.startTime;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Animation time: driven by video position for video mode, real elapsed time for static image
|
|
264
|
+
var videoAnimTime = usingStaticImage ? currentTimeSeconds : video.currentTime - _this.config.startTime;
|
|
265
|
+
|
|
266
|
+
// Update center animation time (always accumulate real time for smooth animation)
|
|
267
|
+
if (_this.config.animateLightIndependently || usingStaticImage) {
|
|
268
|
+
_this.independentLightTime += deltaTime;
|
|
269
|
+
} else {
|
|
270
|
+
var videoTimeDelta = videoAnimTime - _this.lastVideoTime;
|
|
271
|
+
var isVideoJump = Math.abs(videoTimeDelta) > 0.1 || videoTimeDelta < -0.01;
|
|
272
|
+
if (isVideoJump) {
|
|
273
|
+
_this.independentLightTime = videoAnimTime;
|
|
274
|
+
} else {
|
|
275
|
+
_this.independentLightTime += deltaTime;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
_this.lastVideoTime = videoAnimTime;
|
|
279
|
+
|
|
280
|
+
// Use program and set per-frame uniforms
|
|
281
|
+
gl.useProgram(_this.program);
|
|
282
|
+
|
|
283
|
+
// Time uniforms
|
|
284
|
+
gl.uniform1f(_this.uniformLocations.uTime, currentTimeSeconds);
|
|
285
|
+
// When animateLightIndependently is true, use real elapsed time for frame count
|
|
286
|
+
// so light effects aren't tied to video playback
|
|
287
|
+
var frameCount = _this.config.animateLightIndependently ? _this.independentLightTime * 30 // Use independent time (in seconds * 30fps)
|
|
288
|
+
: videoAnimTime * 30; // Use video time (in seconds * 30fps)
|
|
289
|
+
gl.uniform1f(_this.uniformLocations.uFrameCount, frameCount);
|
|
290
|
+
gl.uniform1f(_this.uniformLocations.uCenterAnimTime, _this.independentLightTime);
|
|
291
|
+
|
|
292
|
+
// Resolution uniforms (only when changed)
|
|
293
|
+
if (_this.resolutionChanged) {
|
|
294
|
+
gl.uniform2f(_this.uniformLocations.iResolution, _this.canvasElement.width, _this.canvasElement.height);
|
|
295
|
+
gl.uniform1f(_this.uniformLocations.uDpr, _this.renderScale);
|
|
296
|
+
// Update visible UV bounds (where container clips the canvas)
|
|
297
|
+
gl.uniform4f(_this.uniformLocations.uVisibleUvBounds, _this.visibleUvBounds[0], _this.visibleUvBounds[1], _this.visibleUvBounds[2], _this.visibleUvBounds[3]);
|
|
298
|
+
_this.resolutionChanged = false;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Animate cycleRepetitions if enabled
|
|
302
|
+
if (_this.config.animateCycleReps && _this.currentFrame > _this.config.cycleRepetitionsStartFrame) {
|
|
303
|
+
var elapsed = _this.currentFrame - _this.config.cycleRepetitionsStartFrame;
|
|
304
|
+
var cycleProgress = elapsed % (_this.config.cycleRepetitionsDuration * 2) / _this.config.cycleRepetitionsDuration;
|
|
305
|
+
var pingPong = cycleProgress <= 1 ? cycleProgress : 2 - cycleProgress;
|
|
306
|
+
var eased = pingPong * pingPong * (3 - 2 * pingPong); // smoothstep
|
|
307
|
+
var delta = _this.config.cycleRepetitionsEnd - _this.config.cycleRepetitionsStart;
|
|
308
|
+
gl.uniform1f(_this.uniformLocations.uCycleRepetitions, _this.config.cycleRepetitionsStart + eased * delta);
|
|
309
|
+
} else {
|
|
310
|
+
gl.uniform1f(_this.uniformLocations.uCycleRepetitions, _this.config.cycleRepetitions);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// Animate gradientMapBlend smoothly towards target
|
|
314
|
+
var targetBlend = _this.config.gradientMapBlend;
|
|
315
|
+
if (_this.currentGradientMapBlend !== targetBlend) {
|
|
316
|
+
var speed = 1.0 / _this.config.gradientMapBlendDuration;
|
|
317
|
+
var diff = targetBlend - _this.currentGradientMapBlend;
|
|
318
|
+
var step = Math.sign(diff) * Math.min(Math.abs(diff), speed * deltaTime);
|
|
319
|
+
_this.currentGradientMapBlend += step;
|
|
320
|
+
gl.uniform1f(_this.uniformLocations.uGradientMapBlend, _this.currentGradientMapBlend);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Draw
|
|
324
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
325
|
+
});
|
|
326
|
+
_defineProperty(this, "handlePerformanceLevelChange", function (level) {
|
|
327
|
+
if (level === 0) {
|
|
328
|
+
_this.stopRenderLoop();
|
|
329
|
+
_this.canvasElement.style.display = 'none';
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
332
|
+
var _LEVEL_RENDER_SETTING = LEVEL_RENDER_SETTINGS[level],
|
|
333
|
+
maxPixelCount = _LEVEL_RENDER_SETTING.maxPixelCount,
|
|
334
|
+
minPixelRatio = _LEVEL_RENDER_SETTING.minPixelRatio;
|
|
335
|
+
_this.maxPixelCount = maxPixelCount;
|
|
336
|
+
_this.minPixelRatio = minPixelRatio;
|
|
337
|
+
|
|
338
|
+
// Restore canvas + render loop if they were previously hidden/stopped
|
|
339
|
+
if (_this.canvasElement.style.display === 'none') {
|
|
340
|
+
_this.canvasElement.style.display = '';
|
|
341
|
+
}
|
|
342
|
+
if (_this.isInitialized) {
|
|
343
|
+
_this.startRenderLoop();
|
|
344
|
+
}
|
|
345
|
+
_this.handleResize();
|
|
346
|
+
});
|
|
347
|
+
this.parentElement = parentElement;
|
|
348
|
+
this.assets = assets;
|
|
349
|
+
this.config = _objectSpread(_objectSpread({}, DEFAULT_CONFIG), config);
|
|
350
|
+
this.currentFrame = frame;
|
|
351
|
+
this.minPixelRatio = _minPixelRatio;
|
|
352
|
+
this.maxPixelCount = _maxPixelCount;
|
|
353
|
+
|
|
354
|
+
// Inject default styles if not already present
|
|
355
|
+
if (!document.querySelector('style[data-rzp-glass-style]')) {
|
|
356
|
+
var styleElement = document.createElement('style');
|
|
357
|
+
styleElement.innerHTML = defaultStyle;
|
|
358
|
+
styleElement.setAttribute('data-rzp-glass-style', '');
|
|
359
|
+
document.head.prepend(styleElement);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
// Create canvas element
|
|
363
|
+
this.canvasElement = document.createElement('canvas');
|
|
364
|
+
this.parentElement.prepend(this.canvasElement);
|
|
365
|
+
this.parentElement.setAttribute('data-rzp-glass', '');
|
|
366
|
+
|
|
367
|
+
// Get WebGL context with alpha for transparency during loading
|
|
368
|
+
var _gl = this.canvasElement.getContext('webgl', {
|
|
369
|
+
antialias: false,
|
|
370
|
+
premultipliedAlpha: false,
|
|
371
|
+
depth: false,
|
|
372
|
+
alpha: true,
|
|
373
|
+
powerPreference: 'high-performance'
|
|
374
|
+
});
|
|
375
|
+
this.gl = _gl;
|
|
376
|
+
this.performanceController = new WebGLPerformanceController({
|
|
377
|
+
gl: this.gl,
|
|
378
|
+
onLevelChange: this.handlePerformanceLevelChange
|
|
379
|
+
});
|
|
380
|
+
this.stopIfPotato();
|
|
381
|
+
|
|
382
|
+
// Flip Y axis when uploading textures (video/images have Y=0 at top, WebGL has Y=0 at bottom)
|
|
383
|
+
_gl.pixelStorei(_gl.UNPACK_FLIP_Y_WEBGL, true);
|
|
384
|
+
|
|
385
|
+
// WebGL state setup (matching OGL defaults for 2D rendering)
|
|
386
|
+
_gl.disable(_gl.DEPTH_TEST);
|
|
387
|
+
_gl.disable(_gl.CULL_FACE);
|
|
388
|
+
|
|
389
|
+
// Set clear color to transparent (for alpha blending during loading)
|
|
390
|
+
_gl.clearColor(0, 0, 0, 0);
|
|
391
|
+
|
|
392
|
+
// Initialize program
|
|
393
|
+
this.initProgram();
|
|
394
|
+
this.setupPositionAttribute();
|
|
395
|
+
this.setupUniformLocations();
|
|
396
|
+
this.setupResizeObserver();
|
|
397
|
+
|
|
398
|
+
// Visual viewport listener for zoom changes
|
|
399
|
+
(_visualViewport2 = visualViewport) === null || _visualViewport2 === void 0 || _visualViewport2.addEventListener('resize', this.handleVisualViewportChange);
|
|
400
|
+
|
|
401
|
+
// Listen for visibility changes to pause when tab is hidden
|
|
402
|
+
document.addEventListener('visibilitychange', this.handleDocumentVisibilityChange);
|
|
403
|
+
}
|
|
404
|
+
return _createClass(RzpGlassMount, [{
|
|
405
|
+
key: "stopIfPotato",
|
|
406
|
+
value: function stopIfPotato() {
|
|
407
|
+
var _this$performanceCont;
|
|
408
|
+
if (!((_this$performanceCont = this.performanceController) !== null && _this$performanceCont !== void 0 && _this$performanceCont.isPotato())) {
|
|
409
|
+
return;
|
|
410
|
+
}
|
|
411
|
+
this.stopRenderLoop();
|
|
412
|
+
throw new Error('RzpGlass: WebGL is not supported in this browser');
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
/**
|
|
416
|
+
* Load all assets (video or static image + gradient maps) and start rendering.
|
|
417
|
+
* When `assets.imageSrc` is provided it is used as a static base texture and
|
|
418
|
+
* no video element is created.
|
|
419
|
+
*/
|
|
420
|
+
}, {
|
|
421
|
+
key: "loadAssets",
|
|
422
|
+
value: (function () {
|
|
423
|
+
var _loadAssets = _asyncToGenerator(/*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
|
|
424
|
+
var _this$assets$gradient, useStaticImage, gradientMap2Src, _yield$Promise$all, _yield$Promise$all2, baseAsset, gradientMap, gradientMap2, centerGradientMap, _t;
|
|
425
|
+
return _regeneratorRuntime.wrap(function (_context) {
|
|
426
|
+
while (1) switch (_context.prev = _context.next) {
|
|
427
|
+
case 0:
|
|
428
|
+
this.stopIfPotato();
|
|
429
|
+
_context.prev = 1;
|
|
430
|
+
useStaticImage = Boolean(this.assets.imageSrc);
|
|
431
|
+
gradientMap2Src = (_this$assets$gradient = this.assets.gradientMap2Src) !== null && _this$assets$gradient !== void 0 ? _this$assets$gradient : this.assets.gradientMapSrc;
|
|
432
|
+
_context.next = 2;
|
|
433
|
+
return Promise.all([useStaticImage ? loadImage(this.assets.imageSrc) : loadVideo(this.assets.videoSrc), loadImage(this.assets.gradientMapSrc), loadImage(gradientMap2Src), loadImage(this.assets.centerGradientMapSrc)]);
|
|
434
|
+
case 2:
|
|
435
|
+
_yield$Promise$all = _context.sent;
|
|
436
|
+
_yield$Promise$all2 = _slicedToArray(_yield$Promise$all, 4);
|
|
437
|
+
baseAsset = _yield$Promise$all2[0];
|
|
438
|
+
gradientMap = _yield$Promise$all2[1];
|
|
439
|
+
gradientMap2 = _yield$Promise$all2[2];
|
|
440
|
+
centerGradientMap = _yield$Promise$all2[3];
|
|
441
|
+
if (!useStaticImage) {
|
|
442
|
+
_context.next = 3;
|
|
443
|
+
break;
|
|
444
|
+
}
|
|
445
|
+
// Static image path — upload once to texture unit 0, no video loop needed
|
|
446
|
+
this.setupImageTexture('uVideoTexture', baseAsset, 0);
|
|
447
|
+
_context.next = 4;
|
|
448
|
+
break;
|
|
449
|
+
case 3:
|
|
450
|
+
this.video = baseAsset;
|
|
451
|
+
this.setupVideoTexture();
|
|
452
|
+
// Set video to start time and apply playback rate before playback
|
|
453
|
+
this.video.currentTime = this.config.startTime;
|
|
454
|
+
this.video.playbackRate = this.config.playbackRate;
|
|
455
|
+
if (this.config.paused) {
|
|
456
|
+
_context.next = 4;
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
_context.next = 4;
|
|
460
|
+
return this.video.play()["catch"](function (e) {
|
|
461
|
+
console.warn('Video autoplay failed:', e);
|
|
462
|
+
});
|
|
463
|
+
case 4:
|
|
464
|
+
this.setupImageTexture('uGradientMap', gradientMap, 1);
|
|
465
|
+
this.setupImageTexture('uCenterGradientMap', centerGradientMap, 2);
|
|
466
|
+
this.setupImageTexture('uGradientMap2', gradientMap2, 3);
|
|
467
|
+
|
|
468
|
+
// Set initial uniform values
|
|
469
|
+
this.setAllUniforms();
|
|
470
|
+
this.isInitialized = true;
|
|
471
|
+
|
|
472
|
+
// Initial resize
|
|
473
|
+
this.handleResize();
|
|
474
|
+
|
|
475
|
+
// Start the render loop (runs continuously)
|
|
476
|
+
this.startRenderLoop();
|
|
477
|
+
_context.next = 6;
|
|
478
|
+
break;
|
|
479
|
+
case 5:
|
|
480
|
+
_context.prev = 5;
|
|
481
|
+
_t = _context["catch"](1);
|
|
482
|
+
console.error('RzpGlass: Failed to load assets', _t);
|
|
483
|
+
throw _t;
|
|
484
|
+
case 6:
|
|
485
|
+
case "end":
|
|
486
|
+
return _context.stop();
|
|
487
|
+
}
|
|
488
|
+
}, _callee, this, [[1, 5]]);
|
|
489
|
+
}));
|
|
490
|
+
function loadAssets() {
|
|
491
|
+
return _loadAssets.apply(this, arguments);
|
|
492
|
+
}
|
|
493
|
+
return loadAssets;
|
|
494
|
+
}())
|
|
495
|
+
}, {
|
|
496
|
+
key: "initProgram",
|
|
497
|
+
value: function initProgram() {
|
|
498
|
+
var program = createProgram(this.gl, rzpGlassVertexShader, rzpGlassFragmentShader);
|
|
499
|
+
if (!program) {
|
|
500
|
+
throw new Error('RzpGlass: Failed to create WebGL program');
|
|
501
|
+
}
|
|
502
|
+
this.program = program;
|
|
503
|
+
}
|
|
504
|
+
}, {
|
|
505
|
+
key: "setupPositionAttribute",
|
|
506
|
+
value: function setupPositionAttribute() {
|
|
507
|
+
var buffers = setupFullscreenQuad(this.gl, this.program);
|
|
508
|
+
if (!buffers) {
|
|
509
|
+
throw new Error('RzpGlass: Failed to setup fullscreen quad');
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}, {
|
|
513
|
+
key: "setupUniformLocations",
|
|
514
|
+
value: function setupUniformLocations() {
|
|
515
|
+
var gl = this.gl;
|
|
516
|
+
var program = this.program;
|
|
517
|
+
|
|
518
|
+
// All uniform names from the shader
|
|
519
|
+
var uniformNames = ['uTime', 'iResolution', 'uDpr', 'uVideoTexture', 'uGradientMap', 'uGradientMap2', 'uGradientMapBlend', 'uCenterGradientMap', 'uEnableDisplacement', 'uEnableColorama', 'uEnableBloom', 'uEnableLightSweep', 'uInputMin', 'uInputMax', 'uModifyGamma', 'uPosterizeLevels', 'uCycleRepetitions', 'uPhaseShift', 'uCycleSpeed', 'uWrapMode', 'uReverse', 'uBlendWithOriginal', 'uLightIntensity', 'uFrameCount', 'uLightStartFrame', 'uNumSegments', 'uSlitAngle', 'uDisplacementX', 'uDisplacementY', 'uEnableCenterElement', 'uCenterAnimDuration', 'uCenterAnimTime', 'uCCBlackPoint', 'uCCWhitePoint', 'uCCMidtoneGamma', 'uCCGamma', 'uCCContrast', 'uZoom', 'uPan',
|
|
520
|
+
// vec2(panX, panY) - set in vertex shader
|
|
521
|
+
'uEdgeFeather', 'uRefResolution', 'uVisibleUvBounds',
|
|
522
|
+
// vec4(minX, minY, maxX, maxY) - visible portion of canvas in UV space
|
|
523
|
+
'uBackgroundColor',
|
|
524
|
+
// vec3(r, g, b) - background color to blend with
|
|
525
|
+
// Ripple wave
|
|
526
|
+
'uEnableRippleWave', 'uRippleSpeed', 'uRippleBlend', 'uRippleAngularPower', 'uRippleRadialFalloff', 'uRippleWaitTime'];
|
|
527
|
+
for (var _i = 0, _uniformNames = uniformNames; _i < _uniformNames.length; _i++) {
|
|
528
|
+
var name = _uniformNames[_i];
|
|
529
|
+
this.uniformLocations[name] = gl.getUniformLocation(program, name);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}, {
|
|
533
|
+
key: "setupVideoTexture",
|
|
534
|
+
value: function setupVideoTexture() {
|
|
535
|
+
var _this2 = this;
|
|
536
|
+
this.videoTexture = new Texture(this.gl, {
|
|
537
|
+
textureUnit: 0
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
// Use requestVideoFrameCallback for efficient video texture updates
|
|
541
|
+
if (this.video && 'requestVideoFrameCallback' in this.video) {
|
|
542
|
+
var _updateVideoFrame = function updateVideoFrame() {
|
|
543
|
+
if (_this2.hasBeenDisposed || !_this2.video || !_this2.videoTexture) return;
|
|
544
|
+
_this2.videoTexture.update(_this2.video);
|
|
545
|
+
_this2.videoFrameCallbackId = _this2.video.requestVideoFrameCallback(_updateVideoFrame);
|
|
546
|
+
};
|
|
547
|
+
this.videoFrameCallbackId = this.video.requestVideoFrameCallback(_updateVideoFrame);
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
}, {
|
|
551
|
+
key: "setupImageTexture",
|
|
552
|
+
value: function setupImageTexture(uniformName, image, textureUnit) {
|
|
553
|
+
var texture = new Texture(this.gl, {
|
|
554
|
+
textureUnit: textureUnit
|
|
555
|
+
});
|
|
556
|
+
texture.image(image);
|
|
557
|
+
if (uniformName === 'uVideoTexture') {
|
|
558
|
+
this.videoTexture = texture;
|
|
559
|
+
} else if (uniformName === 'uGradientMap') {
|
|
560
|
+
this.gradientMapTexture = texture;
|
|
561
|
+
} else if (uniformName === 'uGradientMap2') {
|
|
562
|
+
this.gradientMap2Texture = texture;
|
|
563
|
+
} else if (uniformName === 'uCenterGradientMap') {
|
|
564
|
+
this.centerGradientMapTexture = texture;
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/**
|
|
569
|
+
* Hot-swap the gradient map texture at runtime.
|
|
570
|
+
* Accepts an HTMLCanvasElement (generated by generateGradientCanvas) or an HTMLImageElement.
|
|
571
|
+
* No reinitialization required — the next frame will pick up the new texture.
|
|
572
|
+
*/
|
|
573
|
+
}, {
|
|
574
|
+
key: "updateGradientMapTexture",
|
|
575
|
+
value: function updateGradientMapTexture(source) {
|
|
576
|
+
if (!this.isInitialized || !this.gradientMapTexture) return;
|
|
577
|
+
this.gradientMapTexture.image(source);
|
|
578
|
+
}
|
|
579
|
+
}, {
|
|
580
|
+
key: "setupResizeObserver",
|
|
581
|
+
value: function setupResizeObserver() {
|
|
582
|
+
var _this3 = this;
|
|
583
|
+
this.resizeObserver = new ResizeObserver(function (_ref) {
|
|
584
|
+
var _ref2 = _slicedToArray(_ref, 1),
|
|
585
|
+
entry = _ref2[0];
|
|
586
|
+
if (entry !== null && entry !== void 0 && entry.borderBoxSize[0]) {
|
|
587
|
+
var _entry$devicePixelCon;
|
|
588
|
+
var physicalPixelSize = (_entry$devicePixelCon = entry.devicePixelContentBoxSize) === null || _entry$devicePixelCon === void 0 ? void 0 : _entry$devicePixelCon[0];
|
|
589
|
+
if (physicalPixelSize !== undefined) {
|
|
590
|
+
_this3.devicePixelsSupported = true;
|
|
591
|
+
_this3.parentDevicePixelWidth = physicalPixelSize.inlineSize;
|
|
592
|
+
_this3.parentDevicePixelHeight = physicalPixelSize.blockSize;
|
|
593
|
+
}
|
|
594
|
+
_this3.parentWidth = entry.borderBoxSize[0].inlineSize;
|
|
595
|
+
_this3.parentHeight = entry.borderBoxSize[0].blockSize;
|
|
596
|
+
}
|
|
597
|
+
_this3.handleResize();
|
|
598
|
+
});
|
|
599
|
+
this.resizeObserver.observe(this.parentElement);
|
|
600
|
+
}
|
|
601
|
+
}, {
|
|
602
|
+
key: "setAllUniforms",
|
|
603
|
+
value: function setAllUniforms() {
|
|
604
|
+
var gl = this.gl;
|
|
605
|
+
gl.useProgram(this.program);
|
|
606
|
+
|
|
607
|
+
// Texture units
|
|
608
|
+
gl.uniform1i(this.uniformLocations.uVideoTexture, 0);
|
|
609
|
+
gl.uniform1i(this.uniformLocations.uGradientMap, 1);
|
|
610
|
+
gl.uniform1i(this.uniformLocations.uCenterGradientMap, 2);
|
|
611
|
+
gl.uniform1i(this.uniformLocations.uGradientMap2, 3);
|
|
612
|
+
gl.uniform1f(this.uniformLocations.uGradientMapBlend, this.currentGradientMapBlend);
|
|
613
|
+
|
|
614
|
+
// Set all config-based uniforms
|
|
615
|
+
this.setUniformValues(this.config);
|
|
616
|
+
|
|
617
|
+
// Explicitly set pan uniform (vertex shader uniform)
|
|
618
|
+
gl.uniform2f(this.uniformLocations.uPan, this.config.panX, this.config.panY);
|
|
619
|
+
|
|
620
|
+
// Reference resolution (constant)
|
|
621
|
+
gl.uniform2f(this.uniformLocations.uRefResolution, REF_RESOLUTION.width, REF_RESOLUTION.height);
|
|
622
|
+
|
|
623
|
+
// Background color (or set to -1 if not provided)
|
|
624
|
+
if (this.config.backgroundColor) {
|
|
625
|
+
var _this$config$backgrou = _slicedToArray(this.config.backgroundColor, 3),
|
|
626
|
+
r = _this$config$backgrou[0],
|
|
627
|
+
g = _this$config$backgrou[1],
|
|
628
|
+
b = _this$config$backgrou[2];
|
|
629
|
+
gl.uniform3f(this.uniformLocations.uBackgroundColor, r, g, b);
|
|
630
|
+
// Also set clear color to match
|
|
631
|
+
gl.clearColor(r, g, b, 1.0);
|
|
632
|
+
} else {
|
|
633
|
+
// Set to -1 to indicate no background color blending
|
|
634
|
+
gl.uniform3f(this.uniformLocations.uBackgroundColor, -1.0, -1.0, -1.0);
|
|
635
|
+
// Use transparent clear color
|
|
636
|
+
gl.clearColor(0, 0, 0, 0);
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
// Visible UV bounds (where container clips the canvas)
|
|
640
|
+
gl.uniform4f(this.uniformLocations.uVisibleUvBounds, this.visibleUvBounds[0], this.visibleUvBounds[1], this.visibleUvBounds[2], this.visibleUvBounds[3]);
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
/** Check if uniform values are equal (handles arrays) */
|
|
644
|
+
}, {
|
|
645
|
+
key: "areUniformValuesEqual",
|
|
646
|
+
value: function areUniformValuesEqual(a, b) {
|
|
647
|
+
var _this4 = this;
|
|
648
|
+
if (a === b) return true;
|
|
649
|
+
if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
|
|
650
|
+
return a.every(function (val, i) {
|
|
651
|
+
return _this4.areUniformValuesEqual(val, b[i]);
|
|
652
|
+
});
|
|
653
|
+
}
|
|
654
|
+
return false;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/** Set uniform values with caching to avoid redundant updates */
|
|
658
|
+
}, {
|
|
659
|
+
key: "setUniformValues",
|
|
660
|
+
value: function setUniformValues(config) {
|
|
661
|
+
var _this5 = this;
|
|
662
|
+
var gl = this.gl;
|
|
663
|
+
gl.useProgram(this.program);
|
|
664
|
+
Object.entries(config).forEach(function (_ref3) {
|
|
665
|
+
var _ref4 = _slicedToArray(_ref3, 2),
|
|
666
|
+
key = _ref4[0],
|
|
667
|
+
value = _ref4[1];
|
|
668
|
+
if (value === undefined) return;
|
|
669
|
+
|
|
670
|
+
// Check if value has changed
|
|
671
|
+
if (_this5.areUniformValuesEqual(_this5.uniformCache[key], value)) return;
|
|
672
|
+
_this5.uniformCache[key] = value;
|
|
673
|
+
|
|
674
|
+
// Get uniform name from config key
|
|
675
|
+
var uniformName = CONFIG_TO_UNIFORM[key];
|
|
676
|
+
if (!uniformName) return; // Skip non-uniform config values
|
|
677
|
+
|
|
678
|
+
var location = _this5.uniformLocations[uniformName];
|
|
679
|
+
if (!location) return;
|
|
680
|
+
if (typeof value === 'boolean') {
|
|
681
|
+
gl.uniform1f(location, value ? 1 : 0);
|
|
682
|
+
} else if (typeof value === 'number') {
|
|
683
|
+
gl.uniform1f(location, value);
|
|
684
|
+
} else if (Array.isArray(value)) {
|
|
685
|
+
// Handle array uniforms (cast to number[] since config values are all numbers/booleans)
|
|
686
|
+
var flatArray = value.flat();
|
|
687
|
+
switch (flatArray.length) {
|
|
688
|
+
case 2:
|
|
689
|
+
gl.uniform2fv(location, flatArray);
|
|
690
|
+
break;
|
|
691
|
+
case 3:
|
|
692
|
+
gl.uniform3fv(location, flatArray);
|
|
693
|
+
break;
|
|
694
|
+
case 4:
|
|
695
|
+
gl.uniform4fv(location, flatArray);
|
|
696
|
+
break;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
// Handle special pan uniform (vec2 in vertex shader)
|
|
702
|
+
if (config.panX !== undefined || config.panY !== undefined) {
|
|
703
|
+
var panCacheKey = 'pan';
|
|
704
|
+
var panValue = [this.config.panX, this.config.panY];
|
|
705
|
+
if (!this.areUniformValuesEqual(this.uniformCache[panCacheKey], panValue)) {
|
|
706
|
+
this.uniformCache[panCacheKey] = panValue;
|
|
707
|
+
gl.uniform2f(this.uniformLocations.uPan, panValue[0], panValue[1]);
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
// Handle special backgroundColor uniform (vec3 in fragment shader)
|
|
712
|
+
if (config.backgroundColor !== undefined) {
|
|
713
|
+
var bgCacheKey = 'backgroundColor';
|
|
714
|
+
if (!this.areUniformValuesEqual(this.uniformCache[bgCacheKey], config.backgroundColor)) {
|
|
715
|
+
this.uniformCache[bgCacheKey] = config.backgroundColor;
|
|
716
|
+
if (config.backgroundColor) {
|
|
717
|
+
var _config$backgroundCol = _slicedToArray(config.backgroundColor, 3),
|
|
718
|
+
r = _config$backgroundCol[0],
|
|
719
|
+
g = _config$backgroundCol[1],
|
|
720
|
+
b = _config$backgroundCol[2];
|
|
721
|
+
gl.uniform3f(this.uniformLocations.uBackgroundColor, r, g, b);
|
|
722
|
+
// Also update clear color to match
|
|
723
|
+
gl.clearColor(r, g, b, 1.0);
|
|
724
|
+
} else {
|
|
725
|
+
// Set to -1 to indicate no background color blending
|
|
726
|
+
gl.uniform3f(this.uniformLocations.uBackgroundColor, -1.0, -1.0, -1.0);
|
|
727
|
+
// Use transparent clear color
|
|
728
|
+
gl.clearColor(0, 0, 0, 0);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* Update uniforms from config (partial update supported)
|
|
736
|
+
*/
|
|
737
|
+
}, {
|
|
738
|
+
key: "setUniforms",
|
|
739
|
+
value: function setUniforms(newConfig) {
|
|
740
|
+
this.config = _objectSpread(_objectSpread({}, this.config), newConfig);
|
|
741
|
+
if (!this.isInitialized) return;
|
|
742
|
+
|
|
743
|
+
// Use the new caching-based uniform setter
|
|
744
|
+
this.setUniformValues(newConfig);
|
|
745
|
+
|
|
746
|
+
// Handle paused state changes - control video play/pause
|
|
747
|
+
if (newConfig.paused !== undefined) {
|
|
748
|
+
if (newConfig.paused) {
|
|
749
|
+
var _this$video3;
|
|
750
|
+
(_this$video3 = this.video) === null || _this$video3 === void 0 || _this$video3.pause();
|
|
751
|
+
} else {
|
|
752
|
+
var _this$video4;
|
|
753
|
+
(_this$video4 = this.video) === null || _this$video4 === void 0 || _this$video4.play()["catch"](function () {});
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
if (newConfig.playbackRate !== undefined && this.video) {
|
|
757
|
+
this.video.playbackRate = newConfig.playbackRate;
|
|
758
|
+
}
|
|
759
|
+
if (newConfig.aspectRatio !== undefined) {
|
|
760
|
+
this.handleResize();
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}, {
|
|
764
|
+
key: "startRenderLoop",
|
|
765
|
+
value: function startRenderLoop() {
|
|
766
|
+
if (this.rafId !== null) return; // Already running
|
|
767
|
+
this.lastRenderTime = performance.now() * 0.001; // Initialize in seconds
|
|
768
|
+
this.rafId = requestAnimationFrame(this.render);
|
|
769
|
+
}
|
|
770
|
+
}, {
|
|
771
|
+
key: "stopRenderLoop",
|
|
772
|
+
value: function stopRenderLoop() {
|
|
773
|
+
if (this.rafId !== null) {
|
|
774
|
+
cancelAnimationFrame(this.rafId);
|
|
775
|
+
this.rafId = null;
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
}, {
|
|
779
|
+
key: "getCurrentFrame",
|
|
780
|
+
value:
|
|
781
|
+
// ===== Public API (paper-shader style) =====
|
|
782
|
+
|
|
783
|
+
/** Get the current animation frame (in ms) */
|
|
784
|
+
function getCurrentFrame() {
|
|
785
|
+
return this.currentFrame;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
/** Set a specific frame for deterministic results */
|
|
789
|
+
}, {
|
|
790
|
+
key: "setFrame",
|
|
791
|
+
value: function setFrame(newFrame) {
|
|
792
|
+
this.currentFrame = newFrame;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
/** Set the maximum pixel count for performance tuning */
|
|
796
|
+
}, {
|
|
797
|
+
key: "setMaxPixelCount",
|
|
798
|
+
value: function setMaxPixelCount() {
|
|
799
|
+
var newMaxPixelCount = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : DEFAULT_MAX_PIXEL_COUNT;
|
|
800
|
+
this.maxPixelCount = newMaxPixelCount;
|
|
801
|
+
this.handleResize();
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
/** Set the minimum pixel ratio for quality tuning */
|
|
805
|
+
}, {
|
|
806
|
+
key: "setMinPixelRatio",
|
|
807
|
+
value: function setMinPixelRatio() {
|
|
808
|
+
var newMinPixelRatio = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 2;
|
|
809
|
+
this.minPixelRatio = newMinPixelRatio;
|
|
810
|
+
this.handleResize();
|
|
811
|
+
}
|
|
812
|
+
|
|
813
|
+
/** Play video */
|
|
814
|
+
}, {
|
|
815
|
+
key: "play",
|
|
816
|
+
value: function play() {
|
|
817
|
+
var _this$video5;
|
|
818
|
+
this.config.paused = false;
|
|
819
|
+
(_this$video5 = this.video) === null || _this$video5 === void 0 || _this$video5.play()["catch"](function () {});
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
/** Pause video */
|
|
823
|
+
}, {
|
|
824
|
+
key: "pause",
|
|
825
|
+
value: function pause() {
|
|
826
|
+
var _this$video6;
|
|
827
|
+
this.config.paused = true;
|
|
828
|
+
(_this$video6 = this.video) === null || _this$video6 === void 0 || _this$video6.pause();
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/** Seek to specific time in video */
|
|
832
|
+
}, {
|
|
833
|
+
key: "setTime",
|
|
834
|
+
value: function setTime(time) {
|
|
835
|
+
if (this.video) {
|
|
836
|
+
this.video.currentTime = time;
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
}, {
|
|
840
|
+
key: "dispose",
|
|
841
|
+
value: /** Clean up all WebGL resources */
|
|
842
|
+
function dispose() {
|
|
843
|
+
var _this$performanceCont2, _visualViewport3;
|
|
844
|
+
// Immediately mark as disposed to prevent future renders
|
|
845
|
+
this.hasBeenDisposed = true;
|
|
846
|
+
|
|
847
|
+
// Cancel any pending RAF
|
|
848
|
+
if (this.rafId !== null) {
|
|
849
|
+
cancelAnimationFrame(this.rafId);
|
|
850
|
+
this.rafId = null;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Cancel video frame callback
|
|
854
|
+
if (this.videoFrameCallbackId !== null && this.video && 'cancelVideoFrameCallback' in this.video) {
|
|
855
|
+
this.video.cancelVideoFrameCallback(this.videoFrameCallbackId);
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
// Pause and remove video
|
|
859
|
+
if (this.video) {
|
|
860
|
+
this.video.pause();
|
|
861
|
+
this.video.src = '';
|
|
862
|
+
this.video.load();
|
|
863
|
+
this.video = null;
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
// Clean up WebGL resources
|
|
867
|
+
if (this.gl && this.program) {
|
|
868
|
+
var _this$videoTexture, _this$gradientMapText, _this$gradientMap2Tex, _this$centerGradientM;
|
|
869
|
+
(_this$videoTexture = this.videoTexture) === null || _this$videoTexture === void 0 || _this$videoTexture.destroy();
|
|
870
|
+
(_this$gradientMapText = this.gradientMapTexture) === null || _this$gradientMapText === void 0 || _this$gradientMapText.destroy();
|
|
871
|
+
(_this$gradientMap2Tex = this.gradientMap2Texture) === null || _this$gradientMap2Tex === void 0 || _this$gradientMap2Tex.destroy();
|
|
872
|
+
(_this$centerGradientM = this.centerGradientMapTexture) === null || _this$centerGradientM === void 0 || _this$centerGradientM.destroy();
|
|
873
|
+
this.gl.deleteProgram(this.program);
|
|
874
|
+
this.program = null;
|
|
875
|
+
|
|
876
|
+
// Reset WebGL state
|
|
877
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, null);
|
|
878
|
+
this.gl.bindBuffer(this.gl.ELEMENT_ARRAY_BUFFER, null);
|
|
879
|
+
this.gl.bindRenderbuffer(this.gl.RENDERBUFFER, null);
|
|
880
|
+
this.gl.bindFramebuffer(this.gl.FRAMEBUFFER, null);
|
|
881
|
+
|
|
882
|
+
// Clear any errors
|
|
883
|
+
this.gl.getError();
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
// Clean up performance controller
|
|
887
|
+
(_this$performanceCont2 = this.performanceController) === null || _this$performanceCont2 === void 0 || _this$performanceCont2.dispose();
|
|
888
|
+
this.performanceController = null;
|
|
889
|
+
|
|
890
|
+
// Clean up observers and listeners
|
|
891
|
+
if (this.resizeObserver) {
|
|
892
|
+
this.resizeObserver.disconnect();
|
|
893
|
+
this.resizeObserver = null;
|
|
894
|
+
}
|
|
895
|
+
(_visualViewport3 = visualViewport) === null || _visualViewport3 === void 0 || _visualViewport3.removeEventListener('resize', this.handleVisualViewportChange);
|
|
896
|
+
document.removeEventListener('visibilitychange', this.handleDocumentVisibilityChange);
|
|
897
|
+
this.uniformLocations = {};
|
|
898
|
+
this.uniformCache = {};
|
|
899
|
+
|
|
900
|
+
// Remove canvas
|
|
901
|
+
this.canvasElement.remove();
|
|
902
|
+
this.parentElement.removeAttribute('data-rzp-glass');
|
|
903
|
+
}
|
|
904
|
+
}]);
|
|
905
|
+
}();
|
|
906
|
+
|
|
907
|
+
export { RzpGlassMount };
|
|
908
|
+
//# sourceMappingURL=RzpGlassMount.js.map
|