@vib3code/sdk 2.0.1 → 2.0.3-canary.75a3290

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 (136) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +243 -0
  3. package/DOCS/CLI_ONBOARDING.md +1 -1
  4. package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +117 -0
  5. package/DOCS/EPIC_SCROLL_EVENTS.md +773 -0
  6. package/DOCS/HANDOFF_LANDING_PAGE.md +154 -0
  7. package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +493 -0
  8. package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +937 -0
  9. package/DOCS/PRODUCT_STRATEGY.md +63 -0
  10. package/DOCS/README.md +103 -0
  11. package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +97 -0
  12. package/DOCS/ROADMAP.md +111 -0
  13. package/DOCS/SCROLL_TIMELINE_v3.md +269 -0
  14. package/DOCS/SITE_REFACTOR_PLAN.md +100 -0
  15. package/DOCS/STATUS.md +24 -0
  16. package/DOCS/SYSTEM_INVENTORY.md +33 -30
  17. package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +85 -0
  18. package/DOCS/VISUAL_ANALYSIS_FACETAD.md +133 -0
  19. package/DOCS/VISUAL_ANALYSIS_SIMONE.md +95 -0
  20. package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +86 -0
  21. package/DOCS/{BLUEPRINT_EXECUTION_PLAN_2026-01-07.md → archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md} +1 -1
  22. package/DOCS/{DEV_TRACK_ANALYSIS.md → archive/DEV_TRACK_ANALYSIS.md} +3 -0
  23. package/DOCS/{SYSTEM_AUDIT_2026-01-30.md → archive/SYSTEM_AUDIT_2026-01-30.md} +3 -0
  24. package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +1 -1
  25. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +231 -0
  26. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +127 -0
  27. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +142 -0
  28. package/DOCS/dev-tracks/README.md +10 -0
  29. package/README.md +26 -13
  30. package/cpp/CMakeLists.txt +236 -0
  31. package/cpp/bindings/embind.cpp +269 -0
  32. package/cpp/build.sh +129 -0
  33. package/cpp/geometry/Crystal.cpp +103 -0
  34. package/cpp/geometry/Fractal.cpp +136 -0
  35. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  36. package/cpp/geometry/KleinBottle.cpp +71 -0
  37. package/cpp/geometry/Sphere.cpp +134 -0
  38. package/cpp/geometry/Tesseract.cpp +94 -0
  39. package/cpp/geometry/Tetrahedron.cpp +83 -0
  40. package/cpp/geometry/Torus.cpp +65 -0
  41. package/cpp/geometry/WarpFunctions.cpp +238 -0
  42. package/cpp/geometry/Wave.cpp +85 -0
  43. package/cpp/include/vib3_ffi.h +238 -0
  44. package/cpp/math/Mat4x4.cpp +409 -0
  45. package/cpp/math/Mat4x4.hpp +209 -0
  46. package/cpp/math/Projection.cpp +142 -0
  47. package/cpp/math/Projection.hpp +148 -0
  48. package/cpp/math/Rotor4D.cpp +322 -0
  49. package/cpp/math/Rotor4D.hpp +204 -0
  50. package/cpp/math/Vec4.cpp +303 -0
  51. package/cpp/math/Vec4.hpp +225 -0
  52. package/cpp/src/vib3_ffi.cpp +607 -0
  53. package/cpp/tests/Geometry_test.cpp +213 -0
  54. package/cpp/tests/Mat4x4_test.cpp +494 -0
  55. package/cpp/tests/Projection_test.cpp +298 -0
  56. package/cpp/tests/Rotor4D_test.cpp +423 -0
  57. package/cpp/tests/Vec4_test.cpp +489 -0
  58. package/package.json +40 -27
  59. package/src/agent/index.js +1 -3
  60. package/src/agent/mcp/MCPServer.js +918 -0
  61. package/src/agent/mcp/index.js +1 -1
  62. package/src/agent/mcp/stdio-server.js +264 -0
  63. package/src/agent/mcp/tools.js +454 -0
  64. package/src/cli/index.js +374 -44
  65. package/src/core/CanvasManager.js +97 -204
  66. package/src/core/ErrorReporter.js +1 -1
  67. package/src/core/Parameters.js +1 -1
  68. package/src/core/VIB3Engine.js +93 -4
  69. package/src/core/VitalitySystem.js +53 -0
  70. package/src/core/index.js +18 -0
  71. package/src/core/renderers/FacetedRendererAdapter.js +10 -9
  72. package/src/core/renderers/HolographicRendererAdapter.js +13 -9
  73. package/src/core/renderers/QuantumRendererAdapter.js +11 -7
  74. package/src/creative/AestheticMapper.js +628 -0
  75. package/src/creative/ChoreographyPlayer.js +481 -0
  76. package/src/creative/index.js +11 -0
  77. package/src/export/TradingCardManager.js +3 -4
  78. package/src/export/index.js +11 -1
  79. package/src/faceted/FacetedSystem.js +241 -388
  80. package/src/holograms/HolographicVisualizer.js +29 -12
  81. package/src/holograms/RealHolographicSystem.js +194 -43
  82. package/src/math/index.js +7 -7
  83. package/src/polychora/PolychoraSystem.js +77 -0
  84. package/src/quantum/QuantumEngine.js +103 -66
  85. package/src/quantum/QuantumVisualizer.js +7 -2
  86. package/src/reactivity/index.js +3 -5
  87. package/src/render/LayerPresetManager.js +372 -0
  88. package/src/render/LayerReactivityBridge.js +344 -0
  89. package/src/render/LayerRelationshipGraph.js +610 -0
  90. package/src/render/MultiCanvasBridge.js +148 -25
  91. package/src/render/UnifiedRenderBridge.js +3 -0
  92. package/src/render/index.js +27 -2
  93. package/src/scene/index.js +4 -4
  94. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  95. package/src/shaders/faceted/faceted.frag.wgsl +138 -97
  96. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  97. package/src/shaders/holographic/holographic.frag.wgsl +107 -38
  98. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  99. package/src/shaders/quantum/quantum.frag.wgsl +1 -1
  100. package/src/testing/ParallelTestFramework.js +2 -2
  101. package/src/viewer/GalleryUI.js +17 -0
  102. package/src/viewer/ViewerPortal.js +2 -2
  103. package/src/viewer/index.js +1 -1
  104. package/tools/headless-renderer.js +258 -0
  105. package/tools/shader-sync-verify.js +8 -4
  106. package/tools/site-analysis/all-reports.json +32 -0
  107. package/tools/site-analysis/combined-analysis.md +50 -0
  108. package/tools/site-analyzer.mjs +779 -0
  109. package/tools/visual-catalog/capture.js +276 -0
  110. package/tools/visual-catalog/composite.js +138 -0
  111. package/types/adaptive-sdk.d.ts +204 -5
  112. package/types/agent/cli.d.ts +78 -0
  113. package/types/agent/index.d.ts +18 -0
  114. package/types/agent/mcp.d.ts +87 -0
  115. package/types/agent/telemetry.d.ts +190 -0
  116. package/types/core/VIB3Engine.d.ts +26 -0
  117. package/types/core/index.d.ts +261 -0
  118. package/types/creative/AestheticMapper.d.ts +72 -0
  119. package/types/creative/ChoreographyPlayer.d.ts +96 -0
  120. package/types/creative/index.d.ts +17 -0
  121. package/types/export/index.d.ts +243 -0
  122. package/types/geometry/index.d.ts +164 -0
  123. package/types/math/index.d.ts +214 -0
  124. package/types/render/LayerPresetManager.d.ts +78 -0
  125. package/types/render/LayerReactivityBridge.d.ts +85 -0
  126. package/types/render/LayerRelationshipGraph.d.ts +174 -0
  127. package/types/render/index.d.ts +3 -0
  128. package/types/scene/index.d.ts +204 -0
  129. package/types/systems/index.d.ts +244 -0
  130. package/types/variations/index.d.ts +62 -0
  131. package/types/viewer/index.d.ts +225 -0
  132. /package/DOCS/{DEV_TRACK_PLAN_2026-01-07.md → archive/DEV_TRACK_PLAN_2026-01-07.md} +0 -0
  133. /package/DOCS/{SESSION_014_PLAN.md → archive/SESSION_014_PLAN.md} +0 -0
  134. /package/DOCS/{SESSION_LOG_2026-01-07.md → archive/SESSION_LOG_2026-01-07.md} +0 -0
  135. /package/DOCS/{STRATEGIC_BLUEPRINT_2026-01-07.md → archive/STRATEGIC_BLUEPRINT_2026-01-07.md} +0 -0
  136. /package/src/viewer/{ReactivityManager.js → ViewerInputHandler.js} +0 -0
@@ -50,6 +50,7 @@ const FRAGMENT_SHADER_GLSL = `
50
50
  uniform float u_bass;
51
51
  uniform float u_mid;
52
52
  uniform float u_high;
53
+ uniform float u_breath; // Vitality System Breath (0.0 - 1.0)
53
54
 
54
55
  // ── 6D Rotation Matrices ──
55
56
 
@@ -267,7 +268,11 @@ const FRAGMENT_SHADER_GLSL = `
267
268
  // Intensity from lattice
268
269
  float geometryIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
269
270
  geometryIntensity += u_clickIntensity * 0.3;
270
- float finalIntensity = geometryIntensity * u_intensity;
271
+
272
+ // Exhale: Vitality Breath Modulation
273
+ float breathMod = 1.0 + (u_breath * 0.3); // +30% intensity at full breath
274
+
275
+ float finalIntensity = geometryIntensity * u_intensity * breathMod;
271
276
 
272
277
  // Audio-reactive hue shift
273
278
  float hue = u_hue / 360.0 + value * 0.1 + u_high * 0.08;
@@ -283,7 +288,7 @@ const FRAGMENT_SHADER_GLSL = `
283
288
  float gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
284
289
  vec3 color = mix(vec3(gray), baseColor, u_saturation) * finalIntensity;
285
290
 
286
- gl_FragColor = vec4(color, finalIntensity * u_roleIntensity);
291
+ gl_FragColor = vec4(color, finalIntensity);
287
292
  }
288
293
  `;
289
294
 
@@ -291,7 +296,7 @@ const FRAGMENT_SHADER_GLSL = `
291
296
  const FRAGMENT_SHADER_WGSL = `
292
297
  struct VIB3Uniforms {
293
298
  time: f32,
294
- speed: f32,
299
+ _pad0: f32,
295
300
  resolution: vec2<f32>,
296
301
  geometry: f32,
297
302
  rot4dXY: f32,
@@ -304,18 +309,24 @@ struct VIB3Uniforms {
304
309
  gridDensity: f32,
305
310
  morphFactor: f32,
306
311
  chaos: f32,
312
+ speed: f32,
307
313
  hue: f32,
308
314
  intensity: f32,
309
315
  saturation: f32,
310
316
  mouseIntensity: f32,
311
317
  clickIntensity: f32,
312
- roleIntensity: f32,
313
318
  bass: f32,
314
319
  mid: f32,
315
320
  high: f32,
316
- _pad0: f32,
317
- mouse: vec2<f32>,
318
- _pad1: vec2<f32>,
321
+ layerScale: f32,
322
+ layerOpacity: f32,
323
+ _pad1: f32,
324
+ layerColorR: f32,
325
+ layerColorG: f32,
326
+ layerColorB: f32,
327
+ densityMult: f32,
328
+ speedMult: f32,
329
+ breath: f32, // Index 32
319
330
  };
320
331
 
321
332
  @group(0) @binding(0) var<uniform> u: VIB3Uniforms;
@@ -406,7 +417,7 @@ fn warpHypertetraCore_w(p: vec3<f32>, geomIdx: i32) -> vec3<f32> {
406
417
  fn applyCoreWarp_w(p: vec3<f32>, geomType: f32, mouseDelta: vec2<f32>) -> vec3<f32> {
407
418
  let coreFloat = floor(geomType / 8.0);
408
419
  let coreIndex = i32(clamp(coreFloat, 0.0, 2.0));
409
- let baseFloat = geomType - coreFloat * 8.0;
420
+ let baseFloat = geomType - floor(geomType / 8.0) * 8.0;
410
421
  let geomIdx = i32(clamp(floor(baseFloat + 0.5), 0.0, 7.0));
411
422
  if (coreIndex == 1) { return warpHypersphereCore_w(p, geomIdx); }
412
423
  if (coreIndex == 2) { return warpHypertetraCore_w(p, geomIdx); }
@@ -459,7 +470,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
459
470
  let timeSpeed = u.time * 0.0001 * u.speed;
460
471
 
461
472
  var pos = vec4<f32>(uv2 * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
462
- pos = vec4<f32>(pos.xy + (u.mouse - 0.5) * u.mouseIntensity * 2.0, pos.z, pos.w);
473
+ pos = vec4<f32>(pos.xy + (vec2<f32>(0.5, 0.5) - 0.5) * u.mouseIntensity * 2.0, pos.z, pos.w);
463
474
 
464
475
  pos = rotateXY_w(u.rot4dXY) * pos;
465
476
  pos = rotateXZ_w(u.rot4dXZ) * pos;
@@ -469,7 +480,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
469
480
  pos = rotateZW_w(u.rot4dZW) * pos;
470
481
 
471
482
  let basePoint = project4Dto3D_w(pos);
472
- let warpedPoint = applyCoreWarp_w(basePoint, u.geometry, u.mouse - 0.5);
483
+ let warpedPoint = applyCoreWarp_w(basePoint, u.geometry, vec2<f32>(0.0, 0.0));
473
484
  let warpedPos = vec4<f32>(warpedPoint, pos.w);
474
485
  var value = geometryFunction_w(warpedPos);
475
486
 
@@ -478,7 +489,10 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
478
489
 
479
490
  var geomIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
480
491
  geomIntensity += u.clickIntensity * 0.3;
481
- let finalIntensity = geomIntensity * u.intensity;
492
+
493
+ // Vitality (Breath) modulation
494
+ let breathMod = 1.0 + (u.breath * 0.3);
495
+ let finalIntensity = geomIntensity * u.intensity * breathMod;
482
496
 
483
497
  let hueVal = u.hue / 360.0 + value * 0.1 + u.high * 0.08;
484
498
  let baseColor = vec3<f32>(
@@ -488,7 +502,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
488
502
  let gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
489
503
  let color = mix(vec3<f32>(gray), baseColor, u.saturation) * finalIntensity;
490
504
 
491
- return vec4<f32>(color, finalIntensity * u.roleIntensity);
505
+ return vec4<f32>(color, finalIntensity);
492
506
  }
493
507
  `;
494
508
 
@@ -498,466 +512,305 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
498
512
 
499
513
  export class FacetedSystem {
500
514
  constructor() {
515
+ this.bridge = null;
501
516
  this.canvas = null;
502
517
  this.gl = null;
503
518
  this.program = null;
504
- this.isActive = false;
505
- this.time = 0;
506
- this.parameters = {
507
- geometry: 0,
508
- rot4dXY: 0, rot4dXZ: 0, rot4dYZ: 0,
509
- rot4dXW: 0, rot4dYW: 0, rot4dZW: 0,
510
- gridDensity: 15,
511
- morphFactor: 1.0,
512
- chaos: 0.2,
513
- speed: 1.0,
514
- hue: 200,
515
- intensity: 0.7,
516
- saturation: 0.8,
517
- dimension: 3.5,
518
- mouseX: 0.5,
519
- mouseY: 0.5,
520
- mouseIntensity: 0.0,
521
- clickIntensity: 0.0,
522
- roleIntensity: 1.0,
523
- bass: 0.0,
524
- mid: 0.0,
525
- high: 0.0
526
- };
527
-
528
- /** @type {UnifiedRenderBridge|null} */
529
- this._bridge = null;
530
-
531
- /** @type {'direct'|'bridge'} Rendering mode */
532
- this._renderMode = 'direct';
519
+ this.params = {};
520
+ this.initialized = false;
521
+ this.contextLost = false;
522
+ this._animFrame = null;
523
+ this._time = 0;
524
+ this._running = false;
525
+ this._quadBuffer = null;
526
+ this._uniformLocations = {};
527
+ this._useDirectGL = false;
533
528
  }
534
529
 
530
+ // ─── Synchronous Direct WebGL Init (matches Quantum/Holographic pattern) ───
531
+
535
532
  /**
536
- * Initialize with UnifiedRenderBridge for WebGL/WebGPU abstraction.
537
- * @param {HTMLCanvasElement} canvas
538
- * @param {object} [options]
539
- * @param {boolean} [options.preferWebGPU=true]
540
- * @param {boolean} [options.debug=false]
541
- * @returns {Promise<boolean>}
533
+ * Initialize directly with WebGL on a given canvas.
534
+ * Synchronous no async bridge, no WebGPU.
535
+ * This is the preferred path for the landing page and adapters.
542
536
  */
543
- async initWithBridge(canvas, options = {}) {
537
+ initDirect(canvas) {
544
538
  this.canvas = canvas;
545
539
  try {
546
- this._bridge = await UnifiedRenderBridge.create(canvas, options);
547
-
548
- // Try loading external shader files first, fall back to inline
549
- let sources = {
550
- glslVertex: VERTEX_SHADER_GLSL,
551
- glslFragment: FRAGMENT_SHADER_GLSL,
552
- wgslFragment: FRAGMENT_SHADER_WGSL
553
- };
554
-
555
- try {
556
- const external = await shaderLoader.loadShaderPair('faceted', 'faceted/faceted.frag');
557
- if (external.glslFragment) {
558
- sources.glslFragment = external.glslFragment;
559
- }
560
- if (external.wgslFragment) {
561
- sources.wgslFragment = external.wgslFragment;
562
- }
563
- if (external.glslVertex) {
564
- sources.glslVertex = external.glslVertex;
565
- }
566
- } catch (loadErr) {
567
- // External load failed — use inline shaders (already set above)
568
- }
569
-
570
- const compiled = this._bridge.compileShader('faceted', sources);
571
-
572
- if (!compiled) {
573
- console.error('Failed to compile faceted shaders via bridge');
574
- return false;
575
- }
576
-
577
- this._renderMode = 'bridge';
578
- console.log(`Faceted System initialized via ${this._bridge.getBackendType()} bridge`);
579
- return true;
540
+ this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
580
541
  } catch (e) {
581
- console.error('Faceted bridge init failed, falling back to direct:', e);
582
- return this.initialize(canvas);
583
- }
584
- }
585
-
586
- /**
587
- * Initialize faceted system (direct WebGL mode)
588
- * Finds canvas by ID in DOM (matches reference architecture)
589
- */
590
- initialize(canvasOverride = null) {
591
- this.canvas = canvasOverride ?? document.getElementById('content-canvas');
592
- if (!this.canvas) {
593
- console.error('Faceted canvas (content-canvas) not found in DOM');
594
- console.log('Looking for canvas IDs:', ['background-canvas', 'shadow-canvas', 'content-canvas', 'highlight-canvas', 'accent-canvas']);
542
+ console.warn('FacetedSystem: WebGL context creation failed', e);
595
543
  return false;
596
544
  }
597
-
598
- this.gl = this.canvas.getContext('webgl');
599
545
  if (!this.gl) {
600
- console.error('WebGL not available for Faceted System');
546
+ console.warn('FacetedSystem: WebGL not available');
601
547
  return false;
602
548
  }
603
549
 
604
- this._contextLost = false;
605
-
606
- // WebGL context loss/restore handlers
607
- this._onContextLost = (e) => {
608
- e.preventDefault();
609
- this._contextLost = true;
610
- console.warn('Faceted: WebGL context lost');
611
- };
612
- this._onContextRestored = () => {
613
- console.log('Faceted: WebGL context restored');
614
- this._contextLost = false;
615
- this.createShaderProgram();
616
- };
617
- this.canvas.addEventListener('webglcontextlost', this._onContextLost);
618
- this.canvas.addEventListener('webglcontextrestored', this._onContextRestored);
619
-
620
- if (!this.createShaderProgram()) {
621
- console.error('Failed to create faceted shader program');
550
+ // Compile shader program
551
+ this.program = this._compileProgram(this.gl, VERTEX_SHADER_GLSL, FRAGMENT_SHADER_GLSL);
552
+ if (!this.program) {
553
+ console.error('FacetedSystem: Shader compilation failed');
622
554
  return false;
623
555
  }
624
556
 
625
- this.setupCanvasSize();
626
- this._renderMode = 'direct';
627
- console.log('Faceted System initialized on content-canvas');
628
- return true;
629
- }
630
-
631
- /**
632
- * Create shader program with 6D rotation and 24 geometry support
633
- */
634
- createShaderProgram() {
635
- this.program = this.compileProgram(VERTEX_SHADER_GLSL, FRAGMENT_SHADER_GLSL);
636
- if (!this.program) return false;
637
-
638
- // Create fullscreen quad
639
- const vertices = new Float32Array([-1, -1, 1, -1, -1, 1, -1, 1, 1, -1, 1, 1]);
640
- const buffer = this.gl.createBuffer();
641
- this.gl.bindBuffer(this.gl.ARRAY_BUFFER, buffer);
557
+ // Create fullscreen quad buffer
558
+ const vertices = new Float32Array([-1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1]);
559
+ this._quadBuffer = this.gl.createBuffer();
560
+ this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._quadBuffer);
642
561
  this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
643
562
 
563
+ // Cache uniform locations
564
+ const gl = this.gl;
565
+ const numUniforms = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
566
+ for (let i = 0; i < numUniforms; i++) {
567
+ const info = gl.getActiveUniform(this.program, i);
568
+ if (info) {
569
+ this._uniformLocations[info.name] = gl.getUniformLocation(this.program, info.name);
570
+ }
571
+ }
572
+
573
+ this._useDirectGL = true;
574
+ this.initialized = true;
575
+ this.start();
644
576
  return true;
645
577
  }
646
578
 
647
- /**
648
- * Compile shader program
649
- */
650
- compileProgram(vertexSource, fragmentSource) {
651
- const vertexShader = this.compileShader(this.gl.VERTEX_SHADER, vertexSource);
652
- const fragmentShader = this.compileShader(this.gl.FRAGMENT_SHADER, fragmentSource);
579
+ _compileProgram(gl, vertexSrc, fragmentSrc) {
580
+ const vs = this._compileShader(gl, gl.VERTEX_SHADER, vertexSrc);
581
+ const fs = this._compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
582
+ if (!vs || !fs) return null;
653
583
 
654
- if (!vertexShader || !fragmentShader) return null;
584
+ const program = gl.createProgram();
585
+ gl.attachShader(program, vs);
586
+ gl.attachShader(program, fs);
587
+ gl.linkProgram(program);
655
588
 
656
- const program = this.gl.createProgram();
657
- this.gl.attachShader(program, vertexShader);
658
- this.gl.attachShader(program, fragmentShader);
659
- this.gl.linkProgram(program);
660
-
661
- if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
662
- console.error('Shader program link error:', this.gl.getProgramInfoLog(program));
589
+ if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
590
+ console.error('FacetedSystem link error:', gl.getProgramInfoLog(program));
663
591
  return null;
664
592
  }
665
593
 
594
+ gl.deleteShader(vs);
595
+ gl.deleteShader(fs);
666
596
  return program;
667
597
  }
668
598
 
669
- /**
670
- * Compile individual shader
671
- */
672
- compileShader(type, source) {
673
- const shader = this.gl.createShader(type);
674
- this.gl.shaderSource(shader, source);
675
- this.gl.compileShader(shader);
676
-
677
- if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
678
- console.error('Shader compile error:', this.gl.getShaderInfoLog(shader));
599
+ _compileShader(gl, type, source) {
600
+ const shader = gl.createShader(type);
601
+ gl.shaderSource(shader, source);
602
+ gl.compileShader(shader);
603
+ if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
604
+ console.error('FacetedSystem shader error:', gl.getShaderInfoLog(shader));
605
+ gl.deleteShader(shader);
679
606
  return null;
680
607
  }
681
-
682
608
  return shader;
683
609
  }
684
610
 
685
- /**
686
- * Setup canvas size
687
- */
688
- setupCanvasSize() {
689
- const rect = this.canvas.parentElement.getBoundingClientRect();
690
- this.canvas.width = rect.width || 800;
691
- this.canvas.height = rect.height || 600;
692
- if (this.gl) {
693
- this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
694
- }
695
- }
611
+ // ─── Async Bridge Init (for SDK/WebGPU usage) ───
696
612
 
697
- /**
698
- * Start rendering
699
- */
700
- start() {
701
- this.isActive = true;
702
- this.render();
703
- console.log('Faceted System started');
704
- }
705
-
706
- /**
707
- * Stop rendering
708
- */
709
- stop() {
710
- this.isActive = false;
711
- console.log('Faceted System stopped');
613
+ async initWithBridge(canvas, options) {
614
+ this.canvas = canvas;
615
+ try {
616
+ this.bridge = await UnifiedRenderBridge.create(canvas, options);
617
+ if (this.bridge) {
618
+ const success = this.bridge.compileShader('faceted', {
619
+ glslVertex: VERTEX_SHADER_GLSL,
620
+ glslFragment: FRAGMENT_SHADER_GLSL,
621
+ wgslFragment: FRAGMENT_SHADER_WGSL
622
+ });
623
+ if (!success) {
624
+ console.error("Faceted shader compilation failed");
625
+ return false;
626
+ }
627
+ this.initialized = true;
628
+ this.start();
629
+ return true;
630
+ }
631
+ } catch (e) {
632
+ console.error("Faceted initWithBridge failed:", e);
633
+ }
634
+ return false;
712
635
  }
713
636
 
714
- /**
715
- * Set active state
716
- */
717
- setActive(active) {
718
- if (active) {
719
- this.start();
720
- } else {
721
- this.stop();
637
+ async initialize(options = {}) {
638
+ if (this.initialized) return true;
639
+ const canvas = options.canvas ||
640
+ document.getElementById('faceted-content-canvas') ||
641
+ document.getElementById('content-canvas');
642
+ if (!canvas) {
643
+ console.warn("FacetedSystem: No canvas found for initialize()");
644
+ return false;
722
645
  }
646
+ return this.initWithBridge(canvas, {
647
+ preferWebGPU: options.preferWebGPU !== undefined ? options.preferWebGPU : true,
648
+ debug: options.debug || false
649
+ });
723
650
  }
724
651
 
725
- /**
726
- * Get the current rendering backend type
727
- * @returns {'webgl'|'webgpu'|'direct-webgl'}
728
- */
729
- getBackendType() {
730
- if (this._renderMode === 'bridge' && this._bridge) {
731
- return this._bridge.getBackendType();
732
- }
733
- return 'direct-webgl';
652
+ // ─── Parameters ───
653
+
654
+ updateParameters(params) {
655
+ if (!params) return;
656
+ this.params = { ...this.params, ...params };
734
657
  }
735
658
 
736
659
  /**
737
- * Build uniform object for current parameters
738
- * @private
660
+ * Build the uniform object with proper u_ prefixed names for the shader.
739
661
  */
740
662
  _buildUniforms() {
663
+ const p = this.params;
741
664
  return {
742
- u_time: this.time,
743
- u_resolution: [this.canvas.width, this.canvas.height],
744
- u_mouse: [this.parameters.mouseX || 0.5, this.parameters.mouseY || 0.5],
745
- u_geometry: this.parameters.geometry,
746
- u_rot4dXY: this.parameters.rot4dXY,
747
- u_rot4dXZ: this.parameters.rot4dXZ,
748
- u_rot4dYZ: this.parameters.rot4dYZ,
749
- u_rot4dXW: this.parameters.rot4dXW,
750
- u_rot4dYW: this.parameters.rot4dYW,
751
- u_rot4dZW: this.parameters.rot4dZW,
752
- u_dimension: this.parameters.dimension,
753
- u_gridDensity: this.parameters.gridDensity,
754
- u_morphFactor: this.parameters.morphFactor,
755
- u_chaos: this.parameters.chaos,
756
- u_speed: this.parameters.speed,
757
- u_hue: this.parameters.hue,
758
- u_intensity: this.parameters.intensity,
759
- u_saturation: this.parameters.saturation,
760
- u_mouseIntensity: this.parameters.mouseIntensity || 0,
761
- u_clickIntensity: this.parameters.clickIntensity || 0,
762
- u_roleIntensity: this.parameters.roleIntensity || 1.0,
763
- u_bass: this.parameters.bass || 0,
764
- u_mid: this.parameters.mid || 0,
765
- u_high: this.parameters.high || 0
665
+ u_time: this._time,
666
+ u_resolution: [this.canvas?.width || 800, this.canvas?.height || 600],
667
+ u_geometry: p.geometry ?? 0,
668
+ u_rot4dXY: p.rot4dXY ?? 0,
669
+ u_rot4dXZ: p.rot4dXZ ?? 0,
670
+ u_rot4dYZ: p.rot4dYZ ?? 0,
671
+ u_rot4dXW: p.rot4dXW ?? 0,
672
+ u_rot4dYW: p.rot4dYW ?? 0,
673
+ u_rot4dZW: p.rot4dZW ?? 0,
674
+ u_dimension: p.dimension ?? 3.5,
675
+ u_gridDensity: p.gridDensity ?? 15,
676
+ u_morphFactor: p.morphFactor ?? 1.0,
677
+ u_chaos: p.chaos ?? 0.2,
678
+ u_speed: p.speed ?? 1.0,
679
+ u_hue: p.hue ?? 200,
680
+ u_intensity: p.intensity ?? 0.7,
681
+ u_saturation: p.saturation ?? 0.8,
682
+ u_mouseIntensity: p.mouseIntensity ?? 0,
683
+ u_clickIntensity: p.clickIntensity ?? 0,
684
+ u_bass: p.bass ?? 0,
685
+ u_mid: p.mid ?? 0,
686
+ u_high: p.high ?? 0,
687
+ u_breath: p.breath ?? 0,
688
+ u_mouse: p.mouse ?? [0.5, 0.5],
766
689
  };
767
690
  }
768
691
 
769
- /**
770
- * Render a single frame (bridge mode)
771
- * @private
772
- */
773
- _renderBridgeFrame() {
774
- if (!this._bridge) return;
775
- this._bridge.setUniforms(this._buildUniforms());
776
- this._bridge.render('faceted');
692
+ // ─── Render Loop ───
693
+
694
+ start() {
695
+ if (this._running) return;
696
+ this._running = true;
697
+ this._renderLoop();
777
698
  }
778
699
 
779
- /**
780
- * Render a single frame (direct WebGL mode)
781
- * @private
782
- */
783
- _renderDirectFrame() {
784
- if (!this.gl || !this.program || this._contextLost) return;
785
- if (this.gl.isContextLost()) {
786
- this._contextLost = true;
787
- return;
700
+ stop() {
701
+ this._running = false;
702
+ if (this._animFrame) {
703
+ cancelAnimationFrame(this._animFrame);
704
+ this._animFrame = null;
788
705
  }
789
-
790
- this.gl.useProgram(this.program);
791
- this.gl.enable(this.gl.BLEND);
792
- this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
793
-
794
- this.gl.clearColor(0, 0, 0, 1);
795
- this.gl.clear(this.gl.COLOR_BUFFER_BIT);
796
-
797
- const uniforms = this._buildUniforms();
798
-
799
- Object.entries(uniforms).forEach(([name, value]) => {
800
- const location = this.gl.getUniformLocation(this.program, name);
801
- if (location !== null) {
802
- if (Array.isArray(value)) {
803
- this.gl.uniform2fv(location, value);
804
- } else {
805
- this.gl.uniform1f(location, value);
806
- }
807
- }
808
- });
809
-
810
- // Draw fullscreen quad
811
- const posLocation = this.gl.getAttribLocation(this.program, 'a_position');
812
- this.gl.enableVertexAttribArray(posLocation);
813
- this.gl.vertexAttribPointer(posLocation, 2, this.gl.FLOAT, false, 0, 0);
814
- this.gl.drawArrays(this.gl.TRIANGLES, 0, 6);
815
706
  }
816
707
 
817
- /**
818
- * Render a single frame
819
- */
820
- renderFrame() {
821
- if (!this.isActive) return;
822
-
823
- // Apply audio reactivity
824
- if (window.audioEnabled && window.audioReactive) {
825
- this.parameters.bass = window.audioReactive.bass || 0;
826
- this.parameters.mid = window.audioReactive.mid || 0;
827
- this.parameters.high = window.audioReactive.high || 0;
828
- }
708
+ _renderLoop() {
709
+ if (!this._running) return;
829
710
 
830
- this.time += 0.016 * this.parameters.speed;
711
+ this._time += 16.0 * (this.params.speed ?? 1.0);
831
712
 
832
- if (this._renderMode === 'bridge') {
833
- this._renderBridgeFrame();
834
- } else {
835
- this._renderDirectFrame();
713
+ if (this._useDirectGL) {
714
+ this._renderDirectGL();
715
+ } else if (this.bridge) {
716
+ this.bridge.setUniforms(this._buildUniforms());
717
+ this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
836
718
  }
719
+
720
+ this._animFrame = requestAnimationFrame(() => this._renderLoop());
837
721
  }
838
722
 
839
723
  /**
840
- * Render loop
724
+ * Direct WebGL rendering — no bridge, just raw GL calls.
725
+ * Matches the original working FacetedSystem pattern.
841
726
  */
842
- render(frameState = {}) {
843
- // Apply frameState parameters if provided
844
- if (frameState.params) {
845
- Object.assign(this.parameters, frameState.params);
846
- }
847
- if (typeof frameState.time === 'number') {
848
- this.time = frameState.time;
849
- }
727
+ _renderDirectGL() {
728
+ const gl = this.gl;
729
+ if (!gl || !this.program) return;
850
730
 
851
- this.renderFrame();
731
+ gl.useProgram(this.program);
732
+ gl.enable(gl.BLEND);
733
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
734
+ gl.clearColor(0, 0, 0, 1);
735
+ gl.clear(gl.COLOR_BUFFER_BIT);
852
736
 
853
- if (this.isActive) {
854
- requestAnimationFrame(() => this.render());
737
+ // Set uniforms
738
+ const uniforms = this._buildUniforms();
739
+ for (const [name, value] of Object.entries(uniforms)) {
740
+ const loc = this._uniformLocations[name];
741
+ if (loc === null || loc === undefined) continue;
742
+ if (Array.isArray(value)) {
743
+ if (value.length === 2) gl.uniform2fv(loc, value);
744
+ else if (value.length === 3) gl.uniform3fv(loc, value);
745
+ else if (value.length === 4) gl.uniform4fv(loc, value);
746
+ } else {
747
+ gl.uniform1f(loc, value);
748
+ }
855
749
  }
856
- }
857
750
 
858
- /**
859
- * Update parameters with validation
860
- */
861
- updateParameters(params) {
862
- if (!params || typeof params !== 'object') return;
863
- for (const [key, value] of Object.entries(params)) {
864
- // Only accept finite numbers to prevent NaN/Infinity reaching shaders
865
- if (typeof value === 'number' && Number.isFinite(value)) {
866
- this.parameters[key] = value;
867
- }
751
+ // Draw fullscreen quad
752
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer);
753
+ const posLoc = gl.getAttribLocation(this.program, 'a_position');
754
+ if (posLoc >= 0) {
755
+ gl.enableVertexAttribArray(posLoc);
756
+ gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
868
757
  }
758
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
869
759
  }
870
760
 
871
- // ============================================
872
- // RendererContract Compliance Methods
873
- // ============================================
874
-
875
- /**
876
- * Initialize the renderer (RendererContract.init)
877
- * @param {Object} [context] - Optional context with canvas or canvasId
878
- * @returns {boolean|Promise<boolean>} Success status
879
- */
880
- init(context = {}) {
881
- const canvasOverride = context.canvas ||
882
- (context.canvasId ? document.getElementById(context.canvasId) : null);
883
-
884
- // If preferWebGPU is set and canvas is provided, use bridge mode
885
- if (context.preferWebGPU && canvasOverride) {
886
- return this.initWithBridge(canvasOverride, {
887
- preferWebGPU: true,
888
- debug: context.debug
889
- });
761
+ render() {
762
+ if (this._useDirectGL) {
763
+ this._renderDirectGL();
764
+ } else if (this.bridge) {
765
+ this.bridge.setUniforms(this._buildUniforms());
766
+ this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
890
767
  }
768
+ }
891
769
 
892
- return this.initialize(canvasOverride);
770
+ getBackendType() {
771
+ if (this._useDirectGL) return 'webgl';
772
+ return this.bridge ? this.bridge.getBackendType() : 'none';
893
773
  }
894
774
 
895
- /**
896
- * Handle canvas resize (RendererContract.resize)
897
- * @param {number} width
898
- * @param {number} height
899
- * @param {number} [pixelRatio=1]
900
- */
901
- resize(width, height, pixelRatio = 1) {
902
- if (!this.canvas) return;
903
-
904
- if (this._renderMode === 'bridge' && this._bridge) {
905
- this._bridge.resize(width, height, pixelRatio);
906
- } else if (this.gl) {
907
- this.canvas.width = width * pixelRatio;
908
- this.canvas.height = height * pixelRatio;
909
- this.canvas.style.width = `${width}px`;
910
- this.canvas.style.height = `${height}px`;
911
- this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
912
- }
775
+ setActive(active) {
776
+ if (active) this.start();
777
+ else this.stop();
778
+ const layer = document.getElementById('faceted-layer');
779
+ if (layer) layer.style.display = active ? 'block' : 'none';
913
780
  }
914
781
 
915
- /**
916
- * Clean up all resources (RendererContract.dispose)
917
- */
918
- dispose() {
919
- this.isActive = false;
782
+ init(context = {}) { return this.initialize(context); }
920
783
 
921
- // Remove context loss listeners
784
+ resize(width, height, pixelRatio = 1) {
785
+ const w = Math.floor(width * pixelRatio);
786
+ const h = Math.floor(height * pixelRatio);
922
787
  if (this.canvas) {
923
- if (this._onContextLost) {
924
- this.canvas.removeEventListener('webglcontextlost', this._onContextLost);
925
- }
926
- if (this._onContextRestored) {
927
- this.canvas.removeEventListener('webglcontextrestored', this._onContextRestored);
928
- }
788
+ this.canvas.width = w;
789
+ this.canvas.height = h;
929
790
  }
930
-
931
- if (this._bridge) {
932
- this._bridge.dispose();
933
- this._bridge = null;
791
+ if (this._useDirectGL && this.gl) {
792
+ this.gl.viewport(0, 0, w, h);
793
+ } else if (this.bridge && this.bridge.resize) {
794
+ this.bridge.resize(width, height, pixelRatio);
934
795
  }
796
+ }
935
797
 
936
- if (this.gl && !this.gl.isContextLost()) {
937
- if (this.program) {
938
- this.gl.deleteProgram(this.program);
939
- }
940
- }
941
- this.program = null;
798
+ dispose() { this.destroy(); }
942
799
 
943
- if (this.gl) {
944
- const loseContext = this.gl.getExtension('WEBGL_lose_context');
945
- if (loseContext) {
946
- loseContext.loseContext();
947
- }
800
+ destroy() {
801
+ this.stop();
802
+ if (this._useDirectGL && this.gl) {
803
+ if (this.program) this.gl.deleteProgram(this.program);
804
+ if (this._quadBuffer) this.gl.deleteBuffer(this._quadBuffer);
948
805
  this.gl = null;
806
+ this.program = null;
807
+ this._quadBuffer = null;
949
808
  }
950
-
951
- this.canvas = null;
952
- this._renderMode = 'direct';
953
- this._contextLost = true;
954
- console.log('Faceted System disposed');
955
- }
956
-
957
- /**
958
- * Alias for dispose (for backward compatibility)
959
- */
960
- destroy() {
961
- this.dispose();
809
+ if (this.bridge) {
810
+ this.bridge.dispose();
811
+ this.bridge = null;
812
+ }
813
+ this.initialized = false;
814
+ this._useDirectGL = false;
962
815
  }
963
816
  }