@vib3code/sdk 2.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (258) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
  3. package/DOCS/CI_TESTING.md +38 -0
  4. package/DOCS/CLI_ONBOARDING.md +75 -0
  5. package/DOCS/CONTROL_REFERENCE.md +64 -0
  6. package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
  7. package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
  8. package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
  9. package/DOCS/ENV_SETUP.md +189 -0
  10. package/DOCS/EXPORT_FORMATS.md +417 -0
  11. package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
  12. package/DOCS/LICENSING_TIERS.md +275 -0
  13. package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
  14. package/DOCS/OBS_SETUP_GUIDE.md +98 -0
  15. package/DOCS/PROJECT_SETUP.md +66 -0
  16. package/DOCS/RENDERER_LIFECYCLE.md +40 -0
  17. package/DOCS/REPO_MANIFEST.md +121 -0
  18. package/DOCS/SESSION_014_PLAN.md +195 -0
  19. package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
  20. package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
  21. package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
  22. package/DOCS/SYSTEM_INVENTORY.md +520 -0
  23. package/DOCS/TELEMETRY_EXPORTS.md +34 -0
  24. package/DOCS/WEBGPU_STATUS.md +38 -0
  25. package/DOCS/XR_BENCHMARKS.md +608 -0
  26. package/LICENSE +21 -0
  27. package/README.md +426 -0
  28. package/docs/.nojekyll +0 -0
  29. package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
  30. package/docs/02-hyperspatial_ego_death.html +346 -0
  31. package/docs/03-post_cartesian_sublime.html +346 -0
  32. package/docs/04-crystalline_void_meditation.html +346 -0
  33. package/docs/05-quantum_decoherence_ballet.html +346 -0
  34. package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
  35. package/docs/07-hyperspatial_ego_death.html +346 -0
  36. package/docs/08-post_cartesian_sublime.html +346 -0
  37. package/docs/09-crystalline_void_meditation.html +346 -0
  38. package/docs/10-quantum_decoherence_ballet.html +346 -0
  39. package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
  40. package/docs/12-hyperspatial_ego_death.html +346 -0
  41. package/docs/13-post_cartesian_sublime.html +346 -0
  42. package/docs/index.html +794 -0
  43. package/docs/test-hub.html +441 -0
  44. package/docs/url-state.js +102 -0
  45. package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
  46. package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
  47. package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
  48. package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
  49. package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
  50. package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
  51. package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
  52. package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
  53. package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
  54. package/docs/vib3-exports/index.html +238 -0
  55. package/docs/webgpu-live.html +702 -0
  56. package/package.json +367 -0
  57. package/src/advanced/AIPresetGenerator.js +777 -0
  58. package/src/advanced/MIDIController.js +703 -0
  59. package/src/advanced/OffscreenWorker.js +1051 -0
  60. package/src/advanced/WebGPUCompute.js +1051 -0
  61. package/src/advanced/WebXRRenderer.js +680 -0
  62. package/src/agent/cli/AgentCLI.js +615 -0
  63. package/src/agent/cli/index.js +14 -0
  64. package/src/agent/index.js +73 -0
  65. package/src/agent/mcp/MCPServer.js +950 -0
  66. package/src/agent/mcp/index.js +9 -0
  67. package/src/agent/mcp/tools.js +548 -0
  68. package/src/agent/telemetry/EventStream.js +669 -0
  69. package/src/agent/telemetry/Instrumentation.js +618 -0
  70. package/src/agent/telemetry/TelemetryExporters.js +427 -0
  71. package/src/agent/telemetry/TelemetryService.js +464 -0
  72. package/src/agent/telemetry/index.js +52 -0
  73. package/src/benchmarks/BenchmarkRunner.js +381 -0
  74. package/src/benchmarks/MetricsCollector.js +299 -0
  75. package/src/benchmarks/index.js +9 -0
  76. package/src/benchmarks/scenes.js +259 -0
  77. package/src/cli/index.js +675 -0
  78. package/src/config/ApiConfig.js +88 -0
  79. package/src/core/CanvasManager.js +217 -0
  80. package/src/core/ErrorReporter.js +117 -0
  81. package/src/core/ParameterMapper.js +333 -0
  82. package/src/core/Parameters.js +396 -0
  83. package/src/core/RendererContracts.js +200 -0
  84. package/src/core/UnifiedResourceManager.js +370 -0
  85. package/src/core/VIB3Engine.js +636 -0
  86. package/src/core/renderers/FacetedRendererAdapter.js +32 -0
  87. package/src/core/renderers/HolographicRendererAdapter.js +29 -0
  88. package/src/core/renderers/QuantumRendererAdapter.js +29 -0
  89. package/src/core/renderers/RendererLifecycleManager.js +63 -0
  90. package/src/creative/ColorPresetsSystem.js +980 -0
  91. package/src/creative/ParameterTimeline.js +1061 -0
  92. package/src/creative/PostProcessingPipeline.js +1113 -0
  93. package/src/creative/TransitionAnimator.js +683 -0
  94. package/src/export/CSSExporter.js +226 -0
  95. package/src/export/CardGeneratorBase.js +279 -0
  96. package/src/export/ExportManager.js +580 -0
  97. package/src/export/FacetedCardGenerator.js +279 -0
  98. package/src/export/HolographicCardGenerator.js +543 -0
  99. package/src/export/LottieExporter.js +552 -0
  100. package/src/export/QuantumCardGenerator.js +315 -0
  101. package/src/export/SVGExporter.js +519 -0
  102. package/src/export/ShaderExporter.js +903 -0
  103. package/src/export/TradingCardGenerator.js +3055 -0
  104. package/src/export/TradingCardManager.js +181 -0
  105. package/src/export/VIB3PackageExporter.js +559 -0
  106. package/src/export/index.js +14 -0
  107. package/src/export/systems/TradingCardSystemFaceted.js +494 -0
  108. package/src/export/systems/TradingCardSystemHolographic.js +452 -0
  109. package/src/export/systems/TradingCardSystemQuantum.js +411 -0
  110. package/src/faceted/FacetedSystem.js +963 -0
  111. package/src/features/CollectionManager.js +433 -0
  112. package/src/gallery/CollectionManager.js +240 -0
  113. package/src/gallery/GallerySystem.js +485 -0
  114. package/src/geometry/GeometryFactory.js +314 -0
  115. package/src/geometry/GeometryLibrary.js +72 -0
  116. package/src/geometry/buffers/BufferBuilder.js +338 -0
  117. package/src/geometry/buffers/index.js +18 -0
  118. package/src/geometry/generators/Crystal.js +420 -0
  119. package/src/geometry/generators/Fractal.js +298 -0
  120. package/src/geometry/generators/KleinBottle.js +197 -0
  121. package/src/geometry/generators/Sphere.js +192 -0
  122. package/src/geometry/generators/Tesseract.js +160 -0
  123. package/src/geometry/generators/Tetrahedron.js +225 -0
  124. package/src/geometry/generators/Torus.js +304 -0
  125. package/src/geometry/generators/Wave.js +341 -0
  126. package/src/geometry/index.js +142 -0
  127. package/src/geometry/warp/HypersphereCore.js +211 -0
  128. package/src/geometry/warp/HypertetraCore.js +386 -0
  129. package/src/geometry/warp/index.js +57 -0
  130. package/src/holograms/HolographicVisualizer.js +1073 -0
  131. package/src/holograms/RealHolographicSystem.js +966 -0
  132. package/src/holograms/variantRegistry.js +69 -0
  133. package/src/integrations/FigmaPlugin.js +854 -0
  134. package/src/integrations/OBSMode.js +754 -0
  135. package/src/integrations/ThreeJsPackage.js +660 -0
  136. package/src/integrations/TouchDesignerExport.js +552 -0
  137. package/src/integrations/frameworks/Vib3React.js +591 -0
  138. package/src/integrations/frameworks/Vib3Svelte.js +654 -0
  139. package/src/integrations/frameworks/Vib3Vue.js +628 -0
  140. package/src/llm/LLMParameterInterface.js +240 -0
  141. package/src/llm/LLMParameterUI.js +577 -0
  142. package/src/math/Mat4x4.js +708 -0
  143. package/src/math/Projection.js +341 -0
  144. package/src/math/Rotor4D.js +637 -0
  145. package/src/math/Vec4.js +476 -0
  146. package/src/math/constants.js +164 -0
  147. package/src/math/index.js +68 -0
  148. package/src/math/projections.js +54 -0
  149. package/src/math/rotations.js +196 -0
  150. package/src/quantum/QuantumEngine.js +906 -0
  151. package/src/quantum/QuantumVisualizer.js +1103 -0
  152. package/src/reactivity/ReactivityConfig.js +499 -0
  153. package/src/reactivity/ReactivityManager.js +586 -0
  154. package/src/reactivity/SpatialInputSystem.js +1783 -0
  155. package/src/reactivity/index.js +93 -0
  156. package/src/render/CommandBuffer.js +465 -0
  157. package/src/render/MultiCanvasBridge.js +340 -0
  158. package/src/render/RenderCommand.js +514 -0
  159. package/src/render/RenderResourceRegistry.js +523 -0
  160. package/src/render/RenderState.js +552 -0
  161. package/src/render/RenderTarget.js +512 -0
  162. package/src/render/ShaderLoader.js +253 -0
  163. package/src/render/ShaderProgram.js +599 -0
  164. package/src/render/UnifiedRenderBridge.js +496 -0
  165. package/src/render/backends/WebGLBackend.js +1108 -0
  166. package/src/render/backends/WebGPUBackend.js +1409 -0
  167. package/src/render/commands/CommandBufferExecutor.js +607 -0
  168. package/src/render/commands/RenderCommandBuffer.js +661 -0
  169. package/src/render/commands/index.js +17 -0
  170. package/src/render/index.js +367 -0
  171. package/src/scene/Disposable.js +498 -0
  172. package/src/scene/MemoryPool.js +618 -0
  173. package/src/scene/Node4D.js +697 -0
  174. package/src/scene/ResourceManager.js +599 -0
  175. package/src/scene/Scene4D.js +540 -0
  176. package/src/scene/index.js +98 -0
  177. package/src/schemas/error.schema.json +84 -0
  178. package/src/schemas/extension.schema.json +88 -0
  179. package/src/schemas/index.js +214 -0
  180. package/src/schemas/parameters.schema.json +142 -0
  181. package/src/schemas/tool-pack.schema.json +44 -0
  182. package/src/schemas/tool-response.schema.json +127 -0
  183. package/src/shaders/common/fullscreen.vert.glsl +5 -0
  184. package/src/shaders/common/fullscreen.vert.wgsl +17 -0
  185. package/src/shaders/common/geometry24.glsl +65 -0
  186. package/src/shaders/common/geometry24.wgsl +54 -0
  187. package/src/shaders/common/rotation4d.glsl +85 -0
  188. package/src/shaders/common/rotation4d.wgsl +86 -0
  189. package/src/shaders/common/uniforms.glsl +44 -0
  190. package/src/shaders/common/uniforms.wgsl +48 -0
  191. package/src/shaders/faceted/faceted.frag.glsl +129 -0
  192. package/src/shaders/faceted/faceted.frag.wgsl +164 -0
  193. package/src/shaders/holographic/holographic.frag.glsl +406 -0
  194. package/src/shaders/holographic/holographic.frag.wgsl +185 -0
  195. package/src/shaders/quantum/quantum.frag.glsl +513 -0
  196. package/src/shaders/quantum/quantum.frag.wgsl +361 -0
  197. package/src/testing/ParallelTestFramework.js +519 -0
  198. package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
  199. package/src/testing/exportFormats.test.js +8 -0
  200. package/src/testing/projections.test.js +14 -0
  201. package/src/testing/rotations.test.js +37 -0
  202. package/src/ui/InteractivityMenu.js +516 -0
  203. package/src/ui/StatusManager.js +96 -0
  204. package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
  205. package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
  206. package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
  207. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
  208. package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
  209. package/src/variations/VariationManager.js +431 -0
  210. package/src/viewer/AudioReactivity.js +505 -0
  211. package/src/viewer/CardBending.js +481 -0
  212. package/src/viewer/GalleryUI.js +832 -0
  213. package/src/viewer/ReactivityManager.js +590 -0
  214. package/src/viewer/TradingCardExporter.js +600 -0
  215. package/src/viewer/ViewerPortal.js +374 -0
  216. package/src/viewer/index.js +12 -0
  217. package/src/wasm/WasmLoader.js +296 -0
  218. package/src/wasm/index.js +132 -0
  219. package/tools/agentic/mcpTools.js +88 -0
  220. package/tools/cli/agent-cli.js +92 -0
  221. package/tools/export/formats.js +24 -0
  222. package/tools/math/rotation-baseline.mjs +64 -0
  223. package/tools/shader-sync-verify.js +937 -0
  224. package/tools/telemetry/manifestPipeline.js +141 -0
  225. package/tools/telemetry/telemetryEvents.js +35 -0
  226. package/types/adaptive-sdk.d.ts +185 -0
  227. package/types/advanced/AIPresetGenerator.d.ts +81 -0
  228. package/types/advanced/MIDIController.d.ts +100 -0
  229. package/types/advanced/OffscreenWorker.d.ts +82 -0
  230. package/types/advanced/WebGPUCompute.d.ts +52 -0
  231. package/types/advanced/WebXRRenderer.d.ts +77 -0
  232. package/types/advanced/index.d.ts +46 -0
  233. package/types/core/ErrorReporter.d.ts +50 -0
  234. package/types/core/VIB3Engine.d.ts +204 -0
  235. package/types/creative/ColorPresetsSystem.d.ts +91 -0
  236. package/types/creative/ParameterTimeline.d.ts +74 -0
  237. package/types/creative/PostProcessingPipeline.d.ts +109 -0
  238. package/types/creative/TransitionAnimator.d.ts +71 -0
  239. package/types/creative/index.d.ts +35 -0
  240. package/types/integrations/FigmaPlugin.d.ts +46 -0
  241. package/types/integrations/OBSMode.d.ts +74 -0
  242. package/types/integrations/ThreeJsPackage.d.ts +62 -0
  243. package/types/integrations/TouchDesignerExport.d.ts +36 -0
  244. package/types/integrations/Vib3React.d.ts +74 -0
  245. package/types/integrations/Vib3Svelte.d.ts +63 -0
  246. package/types/integrations/Vib3Vue.d.ts +55 -0
  247. package/types/integrations/index.d.ts +52 -0
  248. package/types/reactivity/SpatialInputSystem.d.ts +173 -0
  249. package/types/reactivity/index.d.ts +394 -0
  250. package/types/render/CommandBuffer.d.ts +169 -0
  251. package/types/render/RenderCommand.d.ts +312 -0
  252. package/types/render/RenderState.d.ts +279 -0
  253. package/types/render/RenderTarget.d.ts +254 -0
  254. package/types/render/ShaderProgram.d.ts +277 -0
  255. package/types/render/UnifiedRenderBridge.d.ts +143 -0
  256. package/types/render/WebGLBackend.d.ts +168 -0
  257. package/types/render/WebGPUBackend.d.ts +186 -0
  258. package/types/render/index.d.ts +141 -0
@@ -0,0 +1,1073 @@
1
+ /**
2
+ * Core Holographic Visualizer - Clean WebGL rendering engine
3
+ * Extracted from working system, no debugging mess
4
+ */
5
+ export class HolographicVisualizer {
6
+ constructor(canvasIdOrElement, role = 'content', reactivity = 1.0, variant = 0) {
7
+ this.canvas = (canvasIdOrElement instanceof HTMLCanvasElement)
8
+ ? canvasIdOrElement
9
+ : document.getElementById(canvasIdOrElement);
10
+ this.role = role;
11
+ this.reactivity = reactivity;
12
+ this.variant = variant;
13
+
14
+ // CRITICAL FIX: Define contextOptions as instance property to match SmartCanvasPool
15
+ this.contextOptions = {
16
+ alpha: true,
17
+ depth: true,
18
+ stencil: false,
19
+ antialias: false, // Disable antialiasing on mobile for performance
20
+ premultipliedAlpha: true,
21
+ preserveDrawingBuffer: false,
22
+ powerPreference: 'high-performance',
23
+ failIfMajorPerformanceCaveat: false // Don't fail on mobile
24
+ };
25
+
26
+ // CRITICAL FIX: Check if context already exists from SmartCanvasPool
27
+ let existingContext = this.canvas.getContext('webgl2') ||
28
+ this.canvas.getContext('webgl') ||
29
+ this.canvas.getContext('experimental-webgl');
30
+
31
+ if (existingContext && !existingContext.isContextLost()) {
32
+ console.log(`🔄 Reusing existing WebGL context for ${canvasId}`);
33
+ this.gl = existingContext;
34
+ } else {
35
+ // Try WebGL2 first (better mobile support), then WebGL1
36
+ this.gl = this.canvas.getContext('webgl2', this.contextOptions) ||
37
+ this.canvas.getContext('webgl', this.contextOptions) ||
38
+ this.canvas.getContext('experimental-webgl', this.contextOptions);
39
+ }
40
+
41
+ if (!this.gl) {
42
+ console.error(`WebGL not supported for ${canvasId}`);
43
+ this.showWebGLError();
44
+ throw new Error(`WebGL not supported for ${canvasId}`);
45
+ }
46
+
47
+ this.variantParams = this.generateVariantParams(variant);
48
+ this.roleParams = this.generateRoleParams(role);
49
+
50
+ // Initialize state
51
+ this.mouseX = 0.5;
52
+ this.mouseY = 0.5;
53
+ this.mouseIntensity = 0.0;
54
+ this.clickIntensity = 0.0;
55
+ this.clickDecay = 0.95;
56
+
57
+ // Touch and scroll
58
+ this.touchX = 0.5;
59
+ this.touchY = 0.5;
60
+ this.touchActive = false;
61
+ this.touchMorph = 0.0;
62
+ this.touchChaos = 0.0;
63
+ this.scrollPosition = 0.0;
64
+ this.scrollVelocity = 0.0;
65
+ this.scrollDecay = 0.92;
66
+ this.parallaxDepth = 0.0;
67
+ this.gridDensityShift = 0.0;
68
+ this.colorScrollShift = 0.0;
69
+
70
+ // Density system
71
+ this.densityVariation = 0.0;
72
+ this.densityTarget = 0.0;
73
+
74
+ // Audio reactivity
75
+ this.audioData = { bass: 0, mid: 0, high: 0 };
76
+ this.audioDensityBoost = 0.0;
77
+ this.audioMorphBoost = 0.0;
78
+ this.audioSpeedBoost = 0.0;
79
+ this.audioChaosBoost = 0.0;
80
+ this.audioColorShift = 0.0;
81
+
82
+ this.startTime = Date.now();
83
+ this._contextLost = false;
84
+
85
+ // WebGL context loss/restore handlers
86
+ this._onContextLost = (e) => {
87
+ e.preventDefault();
88
+ this._contextLost = true;
89
+ console.warn(`WebGL context lost for ${canvasId}`);
90
+ };
91
+ this._onContextRestored = () => {
92
+ console.log(`WebGL context restored for ${canvasId}`);
93
+ this._contextLost = false;
94
+ try {
95
+ this.initShaders();
96
+ this.initBuffers();
97
+ this.resize();
98
+ } catch (err) {
99
+ console.error(`Failed to reinit after context restore for ${canvasId}:`, err);
100
+ }
101
+ };
102
+ this.canvas.addEventListener('webglcontextlost', this._onContextLost);
103
+ this.canvas.addEventListener('webglcontextrestored', this._onContextRestored);
104
+
105
+ this.initShaders();
106
+ this.initBuffers();
107
+ this.resize();
108
+ }
109
+
110
+ generateVariantParams(variant) {
111
+ const vib3Geometries = [
112
+ 'TETRAHEDRON', 'HYPERCUBE', 'SPHERE', 'TORUS',
113
+ 'KLEIN BOTTLE', 'FRACTAL', 'WAVE', 'CRYSTAL'
114
+ ];
115
+
116
+ const geometryMap = [
117
+ 0, 0, 0, 0, // 0-3: TETRAHEDRON variations
118
+ 1, 1, 1, 1, // 4-7: HYPERCUBE variations
119
+ 2, 2, 2, 2, // 8-11: SPHERE variations
120
+ 3, 3, 3, 3, // 12-15: TORUS variations
121
+ 4, 4, 4, 4, // 16-19: KLEIN BOTTLE variations
122
+ 5, 5, 5, // 20-22: FRACTAL variations
123
+ 6, 6, 6, // 23-25: WAVE variations
124
+ 7, 7, 7, 7 // 26-29: CRYSTAL variations
125
+ ];
126
+
127
+ const baseGeometry = geometryMap[variant] || 0;
128
+ const variationLevel = variant % 4;
129
+ const geometryName = vib3Geometries[baseGeometry];
130
+
131
+ const suffixes = [' LATTICE', ' FIELD', ' MATRIX', ' RESONANCE'];
132
+ const finalName = geometryName + suffixes[variationLevel];
133
+
134
+ const geometryConfigs = {
135
+ 0: { density: 0.8 + variationLevel * 0.2, speed: 0.3 + variationLevel * 0.1, chaos: variationLevel * 0.1, morph: 0.0 + variationLevel * 0.2 },
136
+ 1: { density: 1.0 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.1, chaos: variationLevel * 0.15, morph: variationLevel * 0.2 },
137
+ 2: { density: 1.2 + variationLevel * 0.4, speed: 0.4 + variationLevel * 0.2, chaos: 0.1 + variationLevel * 0.1, morph: 0.3 + variationLevel * 0.2 },
138
+ 3: { density: 0.9 + variationLevel * 0.3, speed: 0.6 + variationLevel * 0.2, chaos: 0.2 + variationLevel * 0.2, morph: 0.5 + variationLevel * 0.1 },
139
+ 4: { density: 1.4 + variationLevel * 0.5, speed: 0.7 + variationLevel * 0.1, chaos: 0.3 + variationLevel * 0.2, morph: 0.7 + variationLevel * 0.1 },
140
+ 5: { density: 1.8 + variationLevel * 0.3, speed: 0.5 + variationLevel * 0.3, chaos: 0.5 + variationLevel * 0.2, morph: 0.8 + variationLevel * 0.05 },
141
+ 6: { density: 0.6 + variationLevel * 0.4, speed: 0.8 + variationLevel * 0.4, chaos: 0.4 + variationLevel * 0.3, morph: 0.6 + variationLevel * 0.2 },
142
+ 7: { density: 1.6 + variationLevel * 0.2, speed: 0.2 + variationLevel * 0.1, chaos: 0.1 + variationLevel * 0.1, morph: 0.2 + variationLevel * 0.2 }
143
+ };
144
+
145
+ const config = geometryConfigs[baseGeometry];
146
+
147
+ return {
148
+ geometryType: baseGeometry,
149
+ name: finalName,
150
+ density: config.density,
151
+ speed: config.speed,
152
+ hue: (variant * 12.27) % 360,
153
+ saturation: 0.8 + (variationLevel * 0.05), // Add saturation parameter
154
+ intensity: 0.5 + (variationLevel * 0.1),
155
+ chaos: config.chaos,
156
+ morph: config.morph
157
+ };
158
+ }
159
+
160
+ generateRoleParams(role) {
161
+ const vp = this.variantParams;
162
+
163
+ const roleConfigs = {
164
+ 'background': {
165
+ densityMult: 0.4, speedMult: 0.2, colorShift: 0.0, intensity: 0.2,
166
+ mouseReactivity: 0.3, clickReactivity: 0.1
167
+ },
168
+ 'shadow': {
169
+ densityMult: 0.8, speedMult: 0.3, colorShift: 180.0, intensity: 0.4,
170
+ mouseReactivity: 0.5, clickReactivity: 0.3
171
+ },
172
+ 'content': {
173
+ densityMult: vp.density, speedMult: vp.speed,
174
+ colorShift: vp.hue, intensity: vp.intensity,
175
+ mouseReactivity: 1.0, clickReactivity: 0.8
176
+ },
177
+ 'highlight': {
178
+ densityMult: 1.5 + (vp.density * 0.3), speedMult: 0.8 + (vp.speed * 0.2),
179
+ colorShift: vp.hue + 60.0, intensity: 0.6 + (vp.intensity * 0.2),
180
+ mouseReactivity: 1.2, clickReactivity: 1.0
181
+ },
182
+ 'accent': {
183
+ densityMult: 2.5 + (vp.density * 0.5), speedMult: 0.4 + (vp.speed * 0.1),
184
+ colorShift: vp.hue + 300.0, intensity: 0.3 + (vp.intensity * 0.1),
185
+ mouseReactivity: 1.5, clickReactivity: 1.2
186
+ }
187
+ };
188
+
189
+ return roleConfigs[role] || {
190
+ densityMult: 1.0, speedMult: 0.5, colorShift: 0.0, intensity: 0.5,
191
+ mouseReactivity: 1.0, clickReactivity: 0.5
192
+ };
193
+ }
194
+
195
+ initShaders() {
196
+ const vertexShaderSource = `
197
+ attribute vec2 a_position;
198
+ void main() {
199
+ gl_Position = vec4(a_position, 0.0, 1.0);
200
+ }
201
+ `;
202
+
203
+ const fragmentShaderSource = `
204
+ precision highp float;
205
+
206
+ uniform vec2 u_resolution;
207
+ uniform float u_time;
208
+ uniform vec2 u_mouse;
209
+ uniform float u_geometry;
210
+ uniform float u_density;
211
+ uniform float u_speed;
212
+ uniform vec3 u_color;
213
+ uniform float u_intensity;
214
+ uniform float u_roleDensity;
215
+ uniform float u_roleSpeed;
216
+ uniform float u_colorShift;
217
+ uniform float u_chaosIntensity;
218
+ uniform float u_mouseIntensity;
219
+ uniform float u_clickIntensity;
220
+ uniform float u_densityVariation;
221
+ uniform float u_geometryType;
222
+ uniform float u_chaos;
223
+ uniform float u_morph;
224
+ uniform float u_touchMorph;
225
+ uniform float u_touchChaos;
226
+ uniform float u_scrollParallax;
227
+ uniform float u_gridDensityShift;
228
+ uniform float u_colorScrollShift;
229
+ uniform float u_audioDensityBoost;
230
+ uniform float u_audioMorphBoost;
231
+ uniform float u_audioSpeedBoost;
232
+ uniform float u_audioChaosBoost;
233
+ uniform float u_audioColorShift;
234
+ uniform float u_rot4dXY;
235
+ uniform float u_rot4dXZ;
236
+ uniform float u_rot4dYZ;
237
+ uniform float u_rot4dXW;
238
+ uniform float u_rot4dYW;
239
+ uniform float u_rot4dZW;
240
+
241
+ // 6D rotation matrices - 3D space rotations (XY, XZ, YZ)
242
+ mat4 rotateXY(float theta) {
243
+ float c = cos(theta);
244
+ float s = sin(theta);
245
+ return mat4(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
246
+ }
247
+
248
+ mat4 rotateXZ(float theta) {
249
+ float c = cos(theta);
250
+ float s = sin(theta);
251
+ return mat4(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
252
+ }
253
+
254
+ mat4 rotateYZ(float theta) {
255
+ float c = cos(theta);
256
+ float s = sin(theta);
257
+ return mat4(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
258
+ }
259
+
260
+ // 4D hyperspace rotations (XW, YW, ZW)
261
+ mat4 rotateXW(float theta) {
262
+ float c = cos(theta);
263
+ float s = sin(theta);
264
+ return mat4(c, 0, 0, -s, 0, 1, 0, 0, 0, 0, 1, 0, s, 0, 0, c);
265
+ }
266
+
267
+ mat4 rotateYW(float theta) {
268
+ float c = cos(theta);
269
+ float s = sin(theta);
270
+ return mat4(1, 0, 0, 0, 0, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c);
271
+ }
272
+
273
+ mat4 rotateZW(float theta) {
274
+ float c = cos(theta);
275
+ float s = sin(theta);
276
+ return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
277
+ }
278
+
279
+ // 4D to 3D projection
280
+ vec3 project4Dto3D(vec4 p) {
281
+ float w = 2.5 / (2.5 + p.w);
282
+ return vec3(p.x * w, p.y * w, p.z * w);
283
+ }
284
+
285
+ // ========================================
286
+ // POLYTOPE CORE WARP FUNCTIONS (24 Geometries)
287
+ // ========================================
288
+ vec3 warpHypersphereCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
289
+ float radius = length(p);
290
+ float morphBlend = clamp(u_morph * 0.6 + 0.3, 0.0, 2.0);
291
+ float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
292
+ w *= (0.4 + morphBlend * 0.45);
293
+
294
+ vec4 p4d = vec4(p * (1.0 + morphBlend * 0.2), w);
295
+ p4d = rotateXY(u_rot4dXY) * p4d;
296
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
297
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
298
+ p4d = rotateXW(u_rot4dXW) * p4d;
299
+ p4d = rotateYW(u_rot4dYW) * p4d;
300
+ p4d = rotateZW(u_rot4dZW) * p4d;
301
+
302
+ vec3 projected = project4Dto3D(p4d);
303
+ return mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
304
+ }
305
+
306
+ vec3 warpHypertetraCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
307
+ vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
308
+ vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
309
+ vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
310
+ vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
311
+
312
+ float morphBlend = clamp(u_morph * 0.8 + 0.2, 0.0, 2.0);
313
+ float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
314
+ float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed);
315
+ w *= cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
316
+ w *= (0.5 + morphBlend * 0.4);
317
+
318
+ vec3 offset = vec3(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
319
+ vec4 p4d = vec4(p + offset, w);
320
+ p4d = rotateXY(u_rot4dXY) * p4d;
321
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
322
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
323
+ p4d = rotateXW(u_rot4dXW) * p4d;
324
+ p4d = rotateYW(u_rot4dYW) * p4d;
325
+ p4d = rotateZW(u_rot4dZW) * p4d;
326
+
327
+ vec3 projected = project4Dto3D(p4d);
328
+
329
+ float planeInfluence = min(min(abs(dot(p, c1)), abs(dot(p, c2))), min(abs(dot(p, c3)), abs(dot(p, c4))));
330
+ vec3 blended = mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
331
+ return mix(blended, blended * (1.0 - planeInfluence * 0.55), 0.2 + morphBlend * 0.2);
332
+ }
333
+
334
+ vec3 applyCoreWarp(vec3 p, float geometryType, vec2 mouseDelta) {
335
+ float totalBase = 8.0;
336
+ float coreFloat = floor(geometryType / totalBase);
337
+ int coreIndex = int(clamp(coreFloat, 0.0, 2.0));
338
+ float baseGeomFloat = geometryType - floor(geometryType / totalBase) * totalBase;
339
+ int geometryIndex = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
340
+
341
+ if (coreIndex == 1) {
342
+ return warpHypersphereCore(p, geometryIndex, mouseDelta);
343
+ }
344
+ if (coreIndex == 2) {
345
+ return warpHypertetraCore(p, geometryIndex, mouseDelta);
346
+ }
347
+ return p;
348
+ }
349
+ // ========================================
350
+
351
+ // Enhanced VIB3 Geometry Library - Higher Fidelity
352
+ float tetrahedronLattice(vec3 p, float gridSize) {
353
+ vec3 q = fract(p * gridSize) - 0.5;
354
+
355
+ // Enhanced tetrahedron vertices with holographic shimmer
356
+ float d1 = length(q);
357
+ float d2 = length(q - vec3(0.35, 0.0, 0.0));
358
+ float d3 = length(q - vec3(0.0, 0.35, 0.0));
359
+ float d4 = length(q - vec3(0.0, 0.0, 0.35));
360
+ float d5 = length(q - vec3(0.2, 0.2, 0.0));
361
+ float d6 = length(q - vec3(0.2, 0.0, 0.2));
362
+ float d7 = length(q - vec3(0.0, 0.2, 0.2));
363
+
364
+ float vertices = 1.0 - smoothstep(0.0, 0.03, min(min(min(d1, d2), min(d3, d4)), min(min(d5, d6), d7)));
365
+
366
+ // Enhanced edge network with interference patterns
367
+ float edges = 0.0;
368
+ float shimmer = sin(u_time * 0.002) * 0.02;
369
+ edges = max(edges, 1.0 - smoothstep(0.0, 0.015, abs(length(q.xy) - (0.18 + shimmer))));
370
+ edges = max(edges, 1.0 - smoothstep(0.0, 0.015, abs(length(q.yz) - (0.18 + shimmer * 0.8))));
371
+ edges = max(edges, 1.0 - smoothstep(0.0, 0.015, abs(length(q.xz) - (0.18 + shimmer * 1.2))));
372
+
373
+ // Add interference patterns between vertices
374
+ float interference = sin(d1 * 25.0 + u_time * 0.003) * sin(d2 * 22.0 + u_time * 0.0025) * 0.1;
375
+
376
+ // Volumetric density based on distance field
377
+ float volume = exp(-length(q) * 3.0) * 0.15;
378
+
379
+ return max(vertices, edges * 0.7) + interference + volume;
380
+ }
381
+
382
+ float hypercubeLattice(vec3 p, float gridSize) {
383
+ vec3 grid = fract(p * gridSize);
384
+ vec3 q = grid - 0.5;
385
+
386
+ // Enhanced hypercube with 4D projection effects
387
+ vec3 edges = 1.0 - smoothstep(0.0, 0.025, abs(q));
388
+ float wireframe = max(max(edges.x, edges.y), edges.z);
389
+
390
+ // Add 4D hypercube vertices (8 corners + 8 hypervertices)
391
+ float vertices = 0.0;
392
+ for(int i = 0; i < 8; i++) {
393
+ // WebGL 1.0 compatible modulus replacement
394
+ float iFloat = float(i);
395
+ vec3 corner = vec3(
396
+ floor(iFloat - floor(iFloat / 2.0) * 2.0) - 0.5,
397
+ floor((iFloat / 2.0) - floor((iFloat / 2.0) / 2.0) * 2.0) - 0.5,
398
+ float(i / 4) - 0.5
399
+ );
400
+ float dist = length(q - corner * 0.4);
401
+ vertices = max(vertices, 1.0 - smoothstep(0.0, 0.04, dist));
402
+ }
403
+
404
+ // Holographic interference patterns
405
+ float interference = sin(length(q) * 20.0 + u_time * 0.002) * 0.08;
406
+
407
+ // Cross-dimensional glow
408
+ float glow = exp(-length(q) * 2.5) * 0.12;
409
+
410
+ return wireframe * 0.8 + vertices + interference + glow;
411
+ }
412
+
413
+ float sphereLattice(vec3 p, float gridSize) {
414
+ vec3 q = fract(p * gridSize) - 0.5;
415
+ float r = length(q);
416
+ return 1.0 - smoothstep(0.2, 0.5, r);
417
+ }
418
+
419
+ float torusLattice(vec3 p, float gridSize) {
420
+ vec3 q = fract(p * gridSize) - 0.5;
421
+ float r1 = sqrt(q.x*q.x + q.y*q.y);
422
+ float r2 = sqrt((r1 - 0.3)*(r1 - 0.3) + q.z*q.z);
423
+ return 1.0 - smoothstep(0.0, 0.1, r2);
424
+ }
425
+
426
+ float kleinLattice(vec3 p, float gridSize) {
427
+ vec3 q = fract(p * gridSize);
428
+ float u = q.x * 2.0 * 3.14159;
429
+ float v = q.y * 2.0 * 3.14159;
430
+ float x = cos(u) * (3.0 + cos(u/2.0) * sin(v) - sin(u/2.0) * sin(2.0*v));
431
+ float klein = length(vec2(x, q.z)) - 0.1;
432
+ return 1.0 - smoothstep(0.0, 0.05, abs(klein));
433
+ }
434
+
435
+ float fractalLattice(vec3 p, float gridSize) {
436
+ vec3 q = p * gridSize;
437
+ float scale = 1.0;
438
+ float fractal = 0.0;
439
+ for(int i = 0; i < 4; i++) {
440
+ q = fract(q) - 0.5;
441
+ fractal += abs(length(q)) / scale;
442
+ scale *= 2.0;
443
+ q *= 2.0;
444
+ }
445
+ return 1.0 - smoothstep(0.0, 1.0, fractal);
446
+ }
447
+
448
+ float waveLattice(vec3 p, float gridSize) {
449
+ vec3 q = p * gridSize;
450
+ float wave = sin(q.x * 2.0) * sin(q.y * 2.0) * sin(q.z * 2.0 + u_time);
451
+ return smoothstep(-0.5, 0.5, wave);
452
+ }
453
+
454
+ float crystalLattice(vec3 p, float gridSize) {
455
+ vec3 q = fract(p * gridSize) - 0.5;
456
+ float d = max(max(abs(q.x), abs(q.y)), abs(q.z));
457
+ return 1.0 - smoothstep(0.3, 0.5, d);
458
+ }
459
+
460
+ float getDynamicGeometry(vec3 p, float gridSize, float geometryType) {
461
+ // Apply polytope core warp transformation (24-geometry system)
462
+ vec3 warped = applyCoreWarp(p, geometryType, vec2(0.0, 0.0));
463
+
464
+ // WebGL 1.0 compatible modulus replacement - decode base geometry
465
+ float baseGeomFloat = geometryType - floor(geometryType / 8.0) * 8.0;
466
+ int baseGeom = int(baseGeomFloat);
467
+ float variation = floor(geometryType / 8.0) / 4.0;
468
+ float variedGridSize = gridSize * (0.5 + variation * 1.5);
469
+
470
+ // Call lattice functions with warped point (enables 24 geometry variants)
471
+ if (baseGeom == 0) return tetrahedronLattice(warped, variedGridSize);
472
+ else if (baseGeom == 1) return hypercubeLattice(warped, variedGridSize);
473
+ else if (baseGeom == 2) return sphereLattice(warped, variedGridSize);
474
+ else if (baseGeom == 3) return torusLattice(warped, variedGridSize);
475
+ else if (baseGeom == 4) return kleinLattice(warped, variedGridSize);
476
+ else if (baseGeom == 5) return fractalLattice(warped, variedGridSize);
477
+ else if (baseGeom == 6) return waveLattice(warped, variedGridSize);
478
+ else return crystalLattice(warped, variedGridSize);
479
+ }
480
+
481
+ vec3 hsv2rgb(vec3 c) {
482
+ vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
483
+ vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
484
+ return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
485
+ }
486
+
487
+ vec3 rgbGlitch(vec3 color, vec2 uv, float intensity) {
488
+ vec2 offset = vec2(intensity * 0.005, 0.0);
489
+ float r = color.r + sin(uv.y * 30.0 + u_time * 0.001) * intensity * 0.06;
490
+ float g = color.g + sin(uv.y * 28.0 + u_time * 0.0012) * intensity * 0.06;
491
+ float b = color.b + sin(uv.y * 32.0 + u_time * 0.0008) * intensity * 0.06;
492
+ return vec3(r, g, b);
493
+ }
494
+
495
+ float moirePattern(vec2 uv, float intensity) {
496
+ float freq1 = 12.0 + intensity * 6.0 + u_densityVariation * 3.0;
497
+ float freq2 = 14.0 + intensity * 8.0 + u_densityVariation * 4.0;
498
+ float pattern1 = sin(uv.x * freq1) * sin(uv.y * freq1);
499
+ float pattern2 = sin(uv.x * freq2) * sin(uv.y * freq2);
500
+ return (pattern1 * pattern2) * intensity * 0.15;
501
+ }
502
+
503
+ float gridOverlay(vec2 uv, float intensity) {
504
+ vec2 grid = fract(uv * (8.0 + u_densityVariation * 4.0));
505
+ float lines = 0.0;
506
+ lines = max(lines, 1.0 - smoothstep(0.0, 0.02, abs(grid.x - 0.5)));
507
+ lines = max(lines, 1.0 - smoothstep(0.0, 0.02, abs(grid.y - 0.5)));
508
+ return lines * intensity * 0.1;
509
+ }
510
+
511
+ void main() {
512
+ vec2 uv = gl_FragCoord.xy / u_resolution.xy;
513
+ float aspectRatio = u_resolution.x / u_resolution.y;
514
+ uv.x *= aspectRatio;
515
+ uv -= 0.5;
516
+
517
+ float time = u_time * 0.0004 * u_speed * u_roleSpeed;
518
+
519
+ float mouseInfluence = u_mouseIntensity * 0.25; // FIX: Reduce mouse jarring by 50%
520
+ vec2 mouseOffset = (u_mouse - 0.5) * mouseInfluence;
521
+
522
+ float parallaxOffset = u_scrollParallax * 0.2;
523
+ vec2 scrollOffset = vec2(parallaxOffset * 0.1, parallaxOffset * 0.05);
524
+
525
+ float morphOffset = u_touchMorph * 0.3;
526
+
527
+ vec4 p4d = vec4(uv + mouseOffset * 0.1 + scrollOffset,
528
+ sin(time * 0.1 + morphOffset) * 0.15,
529
+ cos(time * 0.08 + morphOffset * 0.5) * 0.15);
530
+
531
+ float scrollRotation = u_scrollParallax * 0.1;
532
+ float touchRotation = u_touchMorph * 0.2;
533
+
534
+ // Combine manual rotation with automatic/interactive rotation - 6D full rotation
535
+ p4d = rotateXY(u_rot4dXY + time * 0.1) * p4d;
536
+ p4d = rotateXZ(u_rot4dXZ + time * 0.12) * p4d;
537
+ p4d = rotateYZ(u_rot4dYZ + time * 0.08) * p4d;
538
+ p4d = rotateXW(u_rot4dXW + time * 0.2 + mouseOffset.y * 0.5 + scrollRotation) * p4d;
539
+ p4d = rotateYW(u_rot4dYW + time * 0.15 + mouseOffset.x * 0.5 + touchRotation) * p4d;
540
+ p4d = rotateZW(u_rot4dZW + time * 0.25 + u_clickIntensity * 0.3 + u_touchChaos * 0.4) * p4d;
541
+
542
+ vec3 p = project4Dto3D(p4d);
543
+
544
+ float scrollDensityMod = 1.0 + u_gridDensityShift * 0.3;
545
+ float audioDensityMod = 1.0 + u_audioDensityBoost * 0.5;
546
+ // FIX: Prevent density doubling by using base density with controlled variations
547
+ float baseDensity = u_density * u_roleDensity;
548
+ float densityVariations = (u_densityVariation * 0.3 + (scrollDensityMod - 1.0) * 0.4 + (audioDensityMod - 1.0) * 0.2);
549
+ float roleDensity = baseDensity + densityVariations;
550
+
551
+ float morphedGeometry = u_geometryType + u_morph * 3.0 + u_touchMorph * 2.0 + u_audioMorphBoost * 1.5;
552
+ float lattice = getDynamicGeometry(p, roleDensity, morphedGeometry);
553
+
554
+ // Enhanced holographic color processing
555
+ vec3 baseColor = u_color;
556
+ float latticeIntensity = lattice * u_intensity;
557
+
558
+ // Multi-layer color composition for higher fidelity
559
+ vec3 color = baseColor * (0.2 + latticeIntensity * 0.8);
560
+
561
+ // Holographic shimmer layers
562
+ vec3 shimmer1 = baseColor * lattice * 0.5;
563
+ vec3 shimmer2 = baseColor * sin(lattice * 8.0 + u_time * 0.001) * 0.2;
564
+ vec3 shimmer3 = baseColor * cos(lattice * 12.0 + u_time * 0.0008) * 0.15;
565
+
566
+ color += shimmer1 + shimmer2 + shimmer3;
567
+
568
+ // Enhanced brightness variations with interference
569
+ color += vec3(lattice * 0.6) * baseColor;
570
+ color += vec3(sin(lattice * 15.0) * 0.1) * baseColor;
571
+
572
+ // Depth-based coloring for 3D effect
573
+ float depth = 1.0 - length(p) * 0.3;
574
+ color *= (0.7 + depth * 0.3);
575
+
576
+ float enhancedChaos = u_chaos + u_chaosIntensity + u_touchChaos * 0.3 + u_audioChaosBoost * 0.4;
577
+ color += vec3(moirePattern(uv + scrollOffset, enhancedChaos));
578
+ color += vec3(gridOverlay(uv, u_mouseIntensity + u_scrollParallax * 0.1));
579
+ color = rgbGlitch(color, uv, enhancedChaos);
580
+
581
+ // Apply morph distortion to position
582
+ vec2 morphDistortion = vec2(sin(uv.y * 10.0 + u_time * 0.001) * u_morph * 0.1,
583
+ cos(uv.x * 10.0 + u_time * 0.001) * u_morph * 0.1);
584
+ color = mix(color, color * (1.0 + length(morphDistortion)), u_morph * 0.5);
585
+
586
+ // Enhanced holographic interaction effects
587
+ float mouseDist = length(uv - (u_mouse - 0.5) * vec2(aspectRatio, 1.0));
588
+
589
+ // Multi-layer mouse glow with holographic ripples
590
+ float mouseGlow = exp(-mouseDist * 1.2) * u_mouseIntensity * 0.25;
591
+ float mouseRipple = sin(mouseDist * 15.0 - u_time * 0.003) * exp(-mouseDist * 2.0) * u_mouseIntensity * 0.1;
592
+ color += vec3(mouseGlow + mouseRipple) * baseColor * 0.8;
593
+
594
+ // Enhanced click pulse with interference
595
+ float clickPulse = u_clickIntensity * exp(-mouseDist * 1.8) * 0.4;
596
+ float clickRing = sin(mouseDist * 20.0 - u_clickIntensity * 5.0) * u_clickIntensity * 0.15;
597
+ color += vec3(clickPulse + clickRing, (clickPulse + clickRing) * 0.6, (clickPulse + clickRing) * 1.2);
598
+
599
+ // Holographic interference from interactions
600
+ float interference = sin(mouseDist * 25.0 + u_time * 0.002) * u_mouseIntensity * 0.05;
601
+ color += vec3(interference) * baseColor;
602
+
603
+ gl_FragColor = vec4(color, 0.95);
604
+ }
605
+ `;
606
+
607
+ this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
608
+ this.uniforms = {
609
+ resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
610
+ time: this.gl.getUniformLocation(this.program, 'u_time'),
611
+ mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
612
+ geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
613
+ density: this.gl.getUniformLocation(this.program, 'u_density'),
614
+ speed: this.gl.getUniformLocation(this.program, 'u_speed'),
615
+ color: this.gl.getUniformLocation(this.program, 'u_color'),
616
+ intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
617
+ roleDensity: this.gl.getUniformLocation(this.program, 'u_roleDensity'),
618
+ roleSpeed: this.gl.getUniformLocation(this.program, 'u_roleSpeed'),
619
+ colorShift: this.gl.getUniformLocation(this.program, 'u_colorShift'),
620
+ chaosIntensity: this.gl.getUniformLocation(this.program, 'u_chaosIntensity'),
621
+ mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
622
+ clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
623
+ densityVariation: this.gl.getUniformLocation(this.program, 'u_densityVariation'),
624
+ geometryType: this.gl.getUniformLocation(this.program, 'u_geometryType'),
625
+ chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
626
+ morph: this.gl.getUniformLocation(this.program, 'u_morph'),
627
+ touchMorph: this.gl.getUniformLocation(this.program, 'u_touchMorph'),
628
+ touchChaos: this.gl.getUniformLocation(this.program, 'u_touchChaos'),
629
+ scrollParallax: this.gl.getUniformLocation(this.program, 'u_scrollParallax'),
630
+ gridDensityShift: this.gl.getUniformLocation(this.program, 'u_gridDensityShift'),
631
+ colorScrollShift: this.gl.getUniformLocation(this.program, 'u_colorScrollShift'),
632
+ audioDensityBoost: this.gl.getUniformLocation(this.program, 'u_audioDensityBoost'),
633
+ audioMorphBoost: this.gl.getUniformLocation(this.program, 'u_audioMorphBoost'),
634
+ audioSpeedBoost: this.gl.getUniformLocation(this.program, 'u_audioSpeedBoost'),
635
+ audioChaosBoost: this.gl.getUniformLocation(this.program, 'u_audioChaosBoost'),
636
+ audioColorShift: this.gl.getUniformLocation(this.program, 'u_audioColorShift'),
637
+ rot4dXY: this.gl.getUniformLocation(this.program, 'u_rot4dXY'),
638
+ rot4dXZ: this.gl.getUniformLocation(this.program, 'u_rot4dXZ'),
639
+ rot4dYZ: this.gl.getUniformLocation(this.program, 'u_rot4dYZ'),
640
+ rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
641
+ rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
642
+ rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW')
643
+ };
644
+ }
645
+
646
+ createProgram(vertexSource, fragmentSource) {
647
+ const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
648
+ const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
649
+
650
+ const program = this.gl.createProgram();
651
+ this.gl.attachShader(program, vertexShader);
652
+ this.gl.attachShader(program, fragmentShader);
653
+ this.gl.linkProgram(program);
654
+
655
+ if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
656
+ throw new Error('Program linking failed: ' + this.gl.getProgramInfoLog(program));
657
+ }
658
+
659
+ return program;
660
+ }
661
+
662
+ createShader(type, source) {
663
+ // CRITICAL FIX: Check WebGL context state before shader operations
664
+ if (!this.gl) {
665
+ console.error('❌ Cannot create shader: WebGL context is null');
666
+ throw new Error('WebGL context is null');
667
+ }
668
+
669
+ if (this.gl.isContextLost()) {
670
+ console.error('❌ Cannot create shader: WebGL context is lost');
671
+ throw new Error('WebGL context is lost');
672
+ }
673
+
674
+ try {
675
+ const shader = this.gl.createShader(type);
676
+
677
+ if (!shader) {
678
+ console.error('❌ Failed to create shader object - WebGL context may be invalid');
679
+ throw new Error('Failed to create shader object - WebGL context may be invalid');
680
+ }
681
+
682
+ this.gl.shaderSource(shader, source);
683
+ this.gl.compileShader(shader);
684
+
685
+ if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
686
+ const error = this.gl.getShaderInfoLog(shader);
687
+ const shaderType = type === this.gl.VERTEX_SHADER ? 'vertex' : 'fragment';
688
+
689
+ // CRITICAL FIX: Show actual error instead of null
690
+ if (error) {
691
+ console.error(`❌ ${shaderType} shader compilation failed:`, error);
692
+ throw new Error(`${shaderType} shader compilation failed: ${error}`);
693
+ } else {
694
+ console.error(`❌ ${shaderType} shader compilation failed: WebGL returned no error info (context may be invalid)`);
695
+ throw new Error(`${shaderType} shader compilation failed: WebGL returned no error info (context may be invalid)`);
696
+ }
697
+ }
698
+
699
+ return shader;
700
+ } catch (error) {
701
+ console.error('❌ Exception during shader creation:', error);
702
+ throw error;
703
+ }
704
+ }
705
+
706
+ initBuffers() {
707
+ const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
708
+
709
+ this.buffer = this.gl.createBuffer();
710
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
711
+ this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
712
+
713
+ const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
714
+ this.gl.enableVertexAttribArray(positionLocation);
715
+ this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
716
+ }
717
+
718
+ resize() {
719
+ // Mobile-optimized canvas sizing
720
+ const dpr = Math.min(window.devicePixelRatio || 1, 2); // Cap at 2x for mobile performance
721
+ const width = this.canvas.clientWidth;
722
+ const height = this.canvas.clientHeight;
723
+
724
+ // Only resize if dimensions actually changed (mobile optimization)
725
+ if (this.canvas.width !== width * dpr || this.canvas.height !== height * dpr) {
726
+ this.canvas.width = width * dpr;
727
+ this.canvas.height = height * dpr;
728
+ this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
729
+ }
730
+ }
731
+
732
+ /**
733
+ * Show user-friendly WebGL error message
734
+ */
735
+ showWebGLError() {
736
+ if (!this.canvas) return;
737
+ const ctx = this.canvas.getContext('2d');
738
+ if (ctx) {
739
+ ctx.fillStyle = '#000';
740
+ ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
741
+ ctx.fillStyle = '#ff64ff';
742
+ ctx.font = '16px Orbitron, monospace';
743
+ ctx.textAlign = 'center';
744
+ ctx.fillText('WebGL Required', this.canvas.width / 2, this.canvas.height / 2);
745
+ ctx.fillStyle = '#888';
746
+ ctx.font = '12px Orbitron, monospace';
747
+ ctx.fillText('Please enable WebGL in your browser', this.canvas.width / 2, this.canvas.height / 2 + 25);
748
+ }
749
+ }
750
+
751
+ updateInteraction(mouseX, mouseY, intensity) {
752
+ this.mouseX = mouseX;
753
+ this.mouseY = mouseY;
754
+ this.mouseIntensity = intensity * this.roleParams.mouseReactivity * this.reactivity;
755
+ }
756
+
757
+ triggerClick(x, y) {
758
+ this.clickIntensity = Math.min(1.0, this.clickIntensity + this.roleParams.clickReactivity * this.reactivity);
759
+ }
760
+
761
+ updateDensity(variation) {
762
+ this.densityTarget = variation;
763
+ }
764
+
765
+ updateTouch(touchX, touchY, active) {
766
+ this.touchX = touchX;
767
+ this.touchY = touchY;
768
+ this.touchActive = active;
769
+ this.touchMorph = (touchX - 0.5) * 2.0;
770
+ this.touchChaos = Math.abs(touchY - 0.5) * 2.0;
771
+ }
772
+
773
+ updateScroll(deltaY) {
774
+ this.scrollVelocity += deltaY * 0.001;
775
+ this.scrollVelocity = Math.max(-2.0, Math.min(2.0, this.scrollVelocity));
776
+ }
777
+
778
+ // Audio reactivity now handled directly in render() loop
779
+ updateAudio_DISABLED() {
780
+ return; // No longer used - audio handled in render()
781
+
782
+ // Musical visualization approach - responsive but controlled
783
+ const smoothing = 0.6; // Less smoothing for more reactivity
784
+
785
+ // Initialize if needed
786
+ if (!this.audioSmooth) {
787
+ this.audioSmooth = {
788
+ density: 0, morph: 0, speed: 0, chaos: 0, color: 0, beat: 0
789
+ };
790
+ }
791
+
792
+ // Speed: More responsive to rhythm and bass
793
+ const targetSpeed = audioData.rhythm > 0 ? audioData.rhythm * 0.8 :
794
+ audioData.bass > 0.3 ? audioData.bass * 0.6 : 0;
795
+ this.audioSmooth.speed = this.audioSmooth.speed * smoothing + targetSpeed * (1 - smoothing);
796
+ this.audioSpeedBoost = this.audioSmooth.speed;
797
+
798
+ // Density: More reactive to energy
799
+ const targetDensity = audioData.energy * 1.2 + audioData.bass * 0.8;
800
+ this.audioSmooth.density = this.audioSmooth.density * smoothing + targetDensity * (1 - smoothing);
801
+ this.audioDensityBoost = this.audioSmooth.density;
802
+
803
+ // Morph: More flowing with melody and mid frequencies
804
+ const targetMorph = audioData.melody * 1.2 + audioData.mid * 0.8;
805
+ this.audioSmooth.morph = this.audioSmooth.morph * smoothing + targetMorph * (1 - smoothing);
806
+ this.audioMorphBoost = this.audioSmooth.morph;
807
+
808
+ // Chaos: More responsive to bass and high frequencies
809
+ const targetChaos = audioData.bass > 0.4 ? audioData.bass * 0.8 :
810
+ audioData.high > 0.6 ? audioData.high * 0.6 : 0;
811
+ this.audioSmooth.chaos = this.audioSmooth.chaos * smoothing + targetChaos * (1 - smoothing);
812
+ this.audioChaosBoost = this.audioSmooth.chaos;
813
+
814
+ // Color: More dynamic color shifting
815
+ const targetColor = (audioData.melody + audioData.high + audioData.mid) * 0.6;
816
+ this.audioSmooth.color = this.audioSmooth.color * smoothing + targetColor * (1 - smoothing);
817
+ this.audioColorShift = this.audioSmooth.color * Math.PI;
818
+
819
+ // Beat detection creates sharp visual pulses
820
+ if (audioData.rhythm > 0.5) { // Lower threshold for beat detection
821
+ this.clickIntensity = Math.max(this.clickIntensity, 1.0);
822
+ this.audioSmooth.beat = 1.0;
823
+ }
824
+ this.audioSmooth.beat *= 0.8; // Faster beat decay for more responsive pulses
825
+ }
826
+
827
+ updateScrollPhysics() {
828
+ this.scrollPosition += this.scrollVelocity;
829
+ this.scrollVelocity *= this.scrollDecay;
830
+ this.parallaxDepth = Math.sin(this.scrollPosition * 0.1) * 0.5;
831
+ this.gridDensityShift = Math.sin(this.scrollPosition * 0.05) * 0.3;
832
+ this.colorScrollShift = (this.scrollPosition * 0.02) % (Math.PI * 2);
833
+ }
834
+
835
+ render() {
836
+ if (!this.program || this._contextLost) return;
837
+ if (this.gl.isContextLost()) {
838
+ this._contextLost = true;
839
+ return;
840
+ }
841
+
842
+ this.resize();
843
+ this.gl.useProgram(this.program);
844
+
845
+ this.densityVariation += (this.densityTarget - this.densityVariation) * 0.05;
846
+ this.clickIntensity *= this.clickDecay;
847
+ this.updateScrollPhysics();
848
+
849
+ const time = Date.now() - this.startTime;
850
+
851
+ // Convert HSL to RGB for color uniform
852
+ const hue = (this.variantParams.hue || 0) / 360; // Convert to 0-1 range
853
+ const saturation = this.variantParams.saturation || 0.8;
854
+ const lightness = Math.max(0.2, Math.min(0.8, this.variantParams.intensity || 0.5)); // Use intensity for lightness
855
+
856
+ // HSL to RGB conversion
857
+ const hslToRgb = (h, s, l) => {
858
+ let r, g, b;
859
+ if (s === 0) {
860
+ r = g = b = l; // achromatic
861
+ } else {
862
+ const hue2rgb = (p, q, t) => {
863
+ if (t < 0) t += 1;
864
+ if (t > 1) t -= 1;
865
+ if (t < 1/6) return p + (q - p) * 6 * t;
866
+ if (t < 1/2) return q;
867
+ if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
868
+ return p;
869
+ };
870
+ const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
871
+ const p = 2 * l - q;
872
+ r = hue2rgb(p, q, h + 1/3);
873
+ g = hue2rgb(p, q, h);
874
+ b = hue2rgb(p, q, h - 1/3);
875
+ }
876
+ return [r, g, b];
877
+ };
878
+
879
+ const rgbColor = hslToRgb(hue, saturation, lightness);
880
+
881
+ // Set uniforms with proper variant parameters
882
+ this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
883
+ this.gl.uniform1f(this.uniforms.time, time);
884
+ this.gl.uniform2f(this.uniforms.mouse, this.mouseX, this.mouseY);
885
+ this.gl.uniform1f(this.uniforms.geometryType, this.variantParams.geometryType || 0);
886
+ this.gl.uniform1f(this.uniforms.density, this.variantParams.density || 1.0);
887
+ // FIX: Controlled speed calculation - base speed controls main movement, audio provides subtle boost
888
+ const baseSpeed = (this.variantParams.speed || 0.5) * 0.2; // Much slower base speed
889
+ const audioBoost = (this.audioSpeedBoost || 0.0) * 0.1; // Subtle audio boost only
890
+ this.gl.uniform1f(this.uniforms.speed, baseSpeed + audioBoost);
891
+ this.gl.uniform3fv(this.uniforms.color, new Float32Array(rgbColor));
892
+ this.gl.uniform1f(this.uniforms.intensity, (this.variantParams.intensity || 0.5) * this.roleParams.intensity);
893
+ this.gl.uniform1f(this.uniforms.roleDensity, this.roleParams.densityMult);
894
+ this.gl.uniform1f(this.uniforms.roleSpeed, this.roleParams.speedMult);
895
+ this.gl.uniform1f(this.uniforms.colorShift, this.roleParams.colorShift + (this.variantParams.hue || 0) / 360);
896
+ this.gl.uniform1f(this.uniforms.chaosIntensity, this.variantParams.chaos || 0.0);
897
+ this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity);
898
+ this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity);
899
+ this.gl.uniform1f(this.uniforms.densityVariation, this.densityVariation);
900
+ this.gl.uniform1f(this.uniforms.geometryType, this.variantParams.geometryType !== undefined ? this.variantParams.geometryType : this.variant || 0);
901
+ this.gl.uniform1f(this.uniforms.chaos, this.variantParams.chaos || 0.0);
902
+ this.gl.uniform1f(this.uniforms.morph, this.variantParams.morph || 0.0);
903
+
904
+ // Touch and scroll uniforms
905
+ this.gl.uniform1f(this.uniforms.touchMorph, this.touchMorph);
906
+ this.gl.uniform1f(this.uniforms.touchChaos, this.touchChaos);
907
+ this.gl.uniform1f(this.uniforms.scrollParallax, this.parallaxDepth);
908
+ this.gl.uniform1f(this.uniforms.gridDensityShift, this.gridDensityShift);
909
+ this.gl.uniform1f(this.uniforms.colorScrollShift, this.colorScrollShift);
910
+
911
+ // 🎵 HOLOGRAPHIC AUDIO REACTIVITY - Direct and beautiful
912
+ let audioDensity = 0, audioMorph = 0, audioSpeed = 0, audioChaos = 0, audioColor = 0;
913
+
914
+ if (window.audioEnabled && window.audioReactive) {
915
+ // Holographic audio mapping: Rich volumetric effects
916
+ audioDensity = window.audioReactive.bass * 1.5; // Bass creates density in holographic layers
917
+ audioMorph = window.audioReactive.mid * 1.2; // Mid frequencies morph the hologram
918
+ audioSpeed = window.audioReactive.high * 0.8; // High frequencies speed up animation
919
+ audioChaos = window.audioReactive.energy * 0.6; // Energy creates chaotic holographic distortion
920
+ audioColor = window.audioReactive.bass * 45; // Bass affects holographic color shifts
921
+
922
+ // Debug logging every 10 seconds to verify holographic audio reactivity
923
+ if (Date.now() % 10000 < 16) {
924
+ console.log(`✨ Holographic audio reactivity: Density+${audioDensity.toFixed(2)} Morph+${audioMorph.toFixed(2)} Speed+${audioSpeed.toFixed(2)} Chaos+${audioChaos.toFixed(2)} Color+${audioColor.toFixed(1)}`);
925
+ }
926
+ }
927
+
928
+ this.gl.uniform1f(this.uniforms.audioDensityBoost, audioDensity);
929
+ this.gl.uniform1f(this.uniforms.audioMorphBoost, audioMorph);
930
+ this.gl.uniform1f(this.uniforms.audioSpeedBoost, audioSpeed);
931
+ this.gl.uniform1f(this.uniforms.audioChaosBoost, audioChaos);
932
+ this.gl.uniform1f(this.uniforms.audioColorShift, audioColor);
933
+
934
+ // 6D rotation uniforms - 3D space + 4D hyperspace
935
+ this.gl.uniform1f(this.uniforms.rot4dXY, this.variantParams.rot4dXY || 0.0);
936
+ this.gl.uniform1f(this.uniforms.rot4dXZ, this.variantParams.rot4dXZ || 0.0);
937
+ this.gl.uniform1f(this.uniforms.rot4dYZ, this.variantParams.rot4dYZ || 0.0);
938
+ this.gl.uniform1f(this.uniforms.rot4dXW, this.variantParams.rot4dXW || 0.0);
939
+ this.gl.uniform1f(this.uniforms.rot4dYW, this.variantParams.rot4dYW || 0.0);
940
+ this.gl.uniform1f(this.uniforms.rot4dZW, this.variantParams.rot4dZW || 0.0);
941
+
942
+ this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
943
+ }
944
+
945
+ /**
946
+ * CRITICAL FIX: Reinitialize WebGL context and resources after SmartCanvasPool context recreation
947
+ */
948
+ reinitializeContext() {
949
+ console.log(`🔄 Reinitializing WebGL context for ${this.canvas?.id}`);
950
+
951
+ // Clear ALL old WebGL references
952
+ this.program = null;
953
+ this.buffer = null;
954
+ this.uniforms = null;
955
+ this.gl = null;
956
+
957
+ // CRITICAL FIX: Don't create new context - SmartCanvasPool already did this
958
+ // Just get the existing context that SmartCanvasPool created
959
+ this.gl = this.canvas.getContext('webgl2') ||
960
+ this.canvas.getContext('webgl') ||
961
+ this.canvas.getContext('experimental-webgl');
962
+
963
+ if (!this.gl) {
964
+ console.error(`❌ No WebGL context available for ${this.canvas?.id} - SmartCanvasPool should have created one`);
965
+ return false;
966
+ }
967
+
968
+ if (this.gl.isContextLost()) {
969
+ console.error(`❌ WebGL context is lost for ${this.canvas?.id}`);
970
+ return false;
971
+ }
972
+
973
+ // Reinitialize shaders and buffers if context is valid
974
+ try {
975
+ this.initShaders();
976
+ this.initBuffers();
977
+ this.resize();
978
+
979
+ console.log(`✅ ${this.canvas?.id}: Holographic context reinitialized successfully`);
980
+ return true;
981
+ } catch (error) {
982
+ console.error(`❌ Failed to reinitialize holographic WebGL resources for ${this.canvas?.id}:`, error);
983
+ return false;
984
+ }
985
+ }
986
+
987
+ /**
988
+ * CRITICAL FIX: Update visualization parameters with immediate re-render
989
+ * This method was missing and causing parameter sliders to not work in holographic system
990
+ */
991
+ updateParameters(params) {
992
+ if (!params || typeof params !== 'object') return;
993
+ // Update variant parameters with proper mapping and scaling
994
+ if (this.variantParams) {
995
+ Object.keys(params).forEach(param => {
996
+ const mappedParam = this.mapParameterName(param);
997
+ if (mappedParam !== null) {
998
+ let scaledValue = params[param];
999
+ // Guard against NaN/Infinity reaching GPU uniforms
1000
+ if (typeof scaledValue !== 'number' || !Number.isFinite(scaledValue)) return;
1001
+
1002
+ // FIX: Scale gridDensity to reasonable holographic density range (back to normal levels)
1003
+ if (param === 'gridDensity') {
1004
+ // Convert gridDensity (5-100) to holographic density (0.3-2.5) - reasonable range
1005
+ // Formula: density = 0.3 + (gridDensity - 5) / (100 - 5) * (2.5 - 0.3)
1006
+ scaledValue = 0.3 + (parseFloat(params[param]) - 5) / 95 * 2.2;
1007
+ console.log(`🔧 Density scaling: gridDensity=${params[param]} → density=${scaledValue.toFixed(3)} (normal range)`);
1008
+ }
1009
+
1010
+ this.variantParams[mappedParam] = scaledValue;
1011
+
1012
+ // Handle special parameter types
1013
+ if (mappedParam === 'geometryType') {
1014
+ // Regenerate role params with new geometry
1015
+ this.roleParams = this.generateRoleParams(this.role);
1016
+ }
1017
+ }
1018
+ });
1019
+ }
1020
+
1021
+ // Don't call render() here - engine will call it to prevent infinite loop
1022
+ }
1023
+
1024
+ /**
1025
+ * Map global parameter names to holographic system parameter names
1026
+ */
1027
+ mapParameterName(globalParam) {
1028
+ const paramMap = {
1029
+ 'gridDensity': 'density',
1030
+ 'morphFactor': 'morph',
1031
+ 'rot4dXW': 'rot4dXW',
1032
+ 'rot4dYW': 'rot4dYW',
1033
+ 'rot4dZW': 'rot4dZW',
1034
+ 'hue': 'hue',
1035
+ 'intensity': 'intensity',
1036
+ 'saturation': 'saturation',
1037
+ 'chaos': 'chaos',
1038
+ 'speed': 'speed',
1039
+ 'geometry': 'geometryType'
1040
+ };
1041
+ return paramMap[globalParam] || globalParam;
1042
+ }
1043
+
1044
+ /**
1045
+ * Clean up all WebGL resources and event listeners
1046
+ */
1047
+ destroy() {
1048
+ // Remove context loss listeners
1049
+ if (this.canvas) {
1050
+ if (this._onContextLost) {
1051
+ this.canvas.removeEventListener('webglcontextlost', this._onContextLost);
1052
+ }
1053
+ if (this._onContextRestored) {
1054
+ this.canvas.removeEventListener('webglcontextrestored', this._onContextRestored);
1055
+ }
1056
+ }
1057
+
1058
+ // Clean up WebGL resources (guard against lost context)
1059
+ if (this.gl && !this.gl.isContextLost()) {
1060
+ if (this.program) {
1061
+ this.gl.deleteProgram(this.program);
1062
+ }
1063
+ if (this.buffer) {
1064
+ this.gl.deleteBuffer(this.buffer);
1065
+ }
1066
+ }
1067
+
1068
+ this.program = null;
1069
+ this.buffer = null;
1070
+ this.gl = null;
1071
+ this._contextLost = true;
1072
+ }
1073
+ }