@vib3code/sdk 2.0.1 → 2.0.3-canary.6f35b4c

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 (96) 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/README.md +10 -0
  28. package/README.md +26 -13
  29. package/cpp/CMakeLists.txt +236 -0
  30. package/cpp/bindings/embind.cpp +269 -0
  31. package/cpp/build.sh +129 -0
  32. package/cpp/geometry/Crystal.cpp +103 -0
  33. package/cpp/geometry/Fractal.cpp +136 -0
  34. package/cpp/geometry/GeometryGenerator.cpp +262 -0
  35. package/cpp/geometry/KleinBottle.cpp +71 -0
  36. package/cpp/geometry/Sphere.cpp +134 -0
  37. package/cpp/geometry/Tesseract.cpp +94 -0
  38. package/cpp/geometry/Tetrahedron.cpp +83 -0
  39. package/cpp/geometry/Torus.cpp +65 -0
  40. package/cpp/geometry/WarpFunctions.cpp +238 -0
  41. package/cpp/geometry/Wave.cpp +85 -0
  42. package/cpp/include/vib3_ffi.h +238 -0
  43. package/cpp/math/Mat4x4.cpp +409 -0
  44. package/cpp/math/Mat4x4.hpp +209 -0
  45. package/cpp/math/Projection.cpp +142 -0
  46. package/cpp/math/Projection.hpp +148 -0
  47. package/cpp/math/Rotor4D.cpp +322 -0
  48. package/cpp/math/Rotor4D.hpp +204 -0
  49. package/cpp/math/Vec4.cpp +303 -0
  50. package/cpp/math/Vec4.hpp +225 -0
  51. package/cpp/src/vib3_ffi.cpp +607 -0
  52. package/cpp/tests/Geometry_test.cpp +213 -0
  53. package/cpp/tests/Mat4x4_test.cpp +494 -0
  54. package/cpp/tests/Projection_test.cpp +298 -0
  55. package/cpp/tests/Rotor4D_test.cpp +423 -0
  56. package/cpp/tests/Vec4_test.cpp +489 -0
  57. package/package.json +31 -27
  58. package/src/agent/mcp/MCPServer.js +722 -0
  59. package/src/agent/mcp/stdio-server.js +264 -0
  60. package/src/agent/mcp/tools.js +367 -0
  61. package/src/cli/index.js +0 -0
  62. package/src/core/CanvasManager.js +97 -204
  63. package/src/core/ErrorReporter.js +1 -1
  64. package/src/core/Parameters.js +1 -1
  65. package/src/core/VIB3Engine.js +38 -1
  66. package/src/core/VitalitySystem.js +53 -0
  67. package/src/core/renderers/HolographicRendererAdapter.js +2 -2
  68. package/src/creative/AestheticMapper.js +628 -0
  69. package/src/creative/ChoreographyPlayer.js +481 -0
  70. package/src/export/TradingCardManager.js +3 -4
  71. package/src/faceted/FacetedSystem.js +237 -388
  72. package/src/holograms/HolographicVisualizer.js +29 -12
  73. package/src/holograms/RealHolographicSystem.js +68 -12
  74. package/src/polychora/PolychoraSystem.js +77 -0
  75. package/src/quantum/QuantumEngine.js +103 -66
  76. package/src/quantum/QuantumVisualizer.js +7 -2
  77. package/src/render/UnifiedRenderBridge.js +3 -0
  78. package/src/shaders/faceted/faceted.frag.glsl +220 -80
  79. package/src/shaders/faceted/faceted.frag.wgsl +138 -97
  80. package/src/shaders/holographic/holographic.frag.glsl +28 -9
  81. package/src/shaders/holographic/holographic.frag.wgsl +107 -38
  82. package/src/shaders/quantum/quantum.frag.glsl +1 -0
  83. package/src/shaders/quantum/quantum.frag.wgsl +1 -1
  84. package/src/viewer/index.js +1 -1
  85. package/tools/headless-renderer.js +258 -0
  86. package/tools/shader-sync-verify.js +8 -4
  87. package/tools/site-analysis/all-reports.json +32 -0
  88. package/tools/site-analysis/combined-analysis.md +50 -0
  89. package/tools/site-analyzer.mjs +779 -0
  90. package/tools/visual-catalog/capture.js +276 -0
  91. package/tools/visual-catalog/composite.js +138 -0
  92. /package/DOCS/{DEV_TRACK_PLAN_2026-01-07.md → archive/DEV_TRACK_PLAN_2026-01-07.md} +0 -0
  93. /package/DOCS/{SESSION_014_PLAN.md → archive/SESSION_014_PLAN.md} +0 -0
  94. /package/DOCS/{SESSION_LOG_2026-01-07.md → archive/SESSION_LOG_2026-01-07.md} +0 -0
  95. /package/DOCS/{STRATEGIC_BLUEPRINT_2026-01-07.md → archive/STRATEGIC_BLUEPRINT_2026-01-07.md} +0 -0
  96. /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,301 @@ 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);
653
-
654
- if (!vertexShader || !fragmentShader) return null;
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;
655
583
 
656
- const program = this.gl.createProgram();
657
- this.gl.attachShader(program, vertexShader);
658
- this.gl.attachShader(program, fragmentShader);
659
- this.gl.linkProgram(program);
584
+ const program = gl.createProgram();
585
+ gl.attachShader(program, vs);
586
+ gl.attachShader(program, fs);
587
+ gl.linkProgram(program);
660
588
 
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() {
638
+ if (this.initialized) return true;
639
+ const canvas = document.getElementById('faceted-content-canvas') ||
640
+ document.getElementById('content-canvas');
641
+ if (!canvas) {
642
+ console.warn("FacetedSystem: No canvas found for initialize()");
643
+ return false;
722
644
  }
645
+ return this.initWithBridge(canvas, { preferWebGPU: false });
723
646
  }
724
647
 
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';
648
+ // ─── Parameters ───
649
+
650
+ updateParameters(params) {
651
+ if (!params) return;
652
+ this.params = { ...this.params, ...params };
734
653
  }
735
654
 
736
655
  /**
737
- * Build uniform object for current parameters
738
- * @private
656
+ * Build the uniform object with proper u_ prefixed names for the shader.
739
657
  */
740
658
  _buildUniforms() {
659
+ const p = this.params;
741
660
  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
661
+ u_time: this._time,
662
+ u_resolution: [this.canvas?.width || 800, this.canvas?.height || 600],
663
+ u_geometry: p.geometry ?? 0,
664
+ u_rot4dXY: p.rot4dXY ?? 0,
665
+ u_rot4dXZ: p.rot4dXZ ?? 0,
666
+ u_rot4dYZ: p.rot4dYZ ?? 0,
667
+ u_rot4dXW: p.rot4dXW ?? 0,
668
+ u_rot4dYW: p.rot4dYW ?? 0,
669
+ u_rot4dZW: p.rot4dZW ?? 0,
670
+ u_dimension: p.dimension ?? 3.5,
671
+ u_gridDensity: p.gridDensity ?? 15,
672
+ u_morphFactor: p.morphFactor ?? 1.0,
673
+ u_chaos: p.chaos ?? 0.2,
674
+ u_speed: p.speed ?? 1.0,
675
+ u_hue: p.hue ?? 200,
676
+ u_intensity: p.intensity ?? 0.7,
677
+ u_saturation: p.saturation ?? 0.8,
678
+ u_mouseIntensity: p.mouseIntensity ?? 0,
679
+ u_clickIntensity: p.clickIntensity ?? 0,
680
+ u_bass: p.bass ?? 0,
681
+ u_mid: p.mid ?? 0,
682
+ u_high: p.high ?? 0,
683
+ u_breath: p.breath ?? 0,
684
+ u_mouse: p.mouse ?? [0.5, 0.5],
766
685
  };
767
686
  }
768
687
 
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');
688
+ // ─── Render Loop ───
689
+
690
+ start() {
691
+ if (this._running) return;
692
+ this._running = true;
693
+ this._renderLoop();
777
694
  }
778
695
 
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;
696
+ stop() {
697
+ this._running = false;
698
+ if (this._animFrame) {
699
+ cancelAnimationFrame(this._animFrame);
700
+ this._animFrame = null;
788
701
  }
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
702
  }
816
703
 
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
- }
704
+ _renderLoop() {
705
+ if (!this._running) return;
829
706
 
830
- this.time += 0.016 * this.parameters.speed;
707
+ this._time += 16.0 * (this.params.speed ?? 1.0);
831
708
 
832
- if (this._renderMode === 'bridge') {
833
- this._renderBridgeFrame();
834
- } else {
835
- this._renderDirectFrame();
709
+ if (this._useDirectGL) {
710
+ this._renderDirectGL();
711
+ } else if (this.bridge) {
712
+ this.bridge.setUniforms(this._buildUniforms());
713
+ this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
836
714
  }
715
+
716
+ this._animFrame = requestAnimationFrame(() => this._renderLoop());
837
717
  }
838
718
 
839
719
  /**
840
- * Render loop
720
+ * Direct WebGL rendering — no bridge, just raw GL calls.
721
+ * Matches the original working FacetedSystem pattern.
841
722
  */
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
- }
723
+ _renderDirectGL() {
724
+ const gl = this.gl;
725
+ if (!gl || !this.program) return;
850
726
 
851
- this.renderFrame();
727
+ gl.useProgram(this.program);
728
+ gl.enable(gl.BLEND);
729
+ gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
730
+ gl.clearColor(0, 0, 0, 1);
731
+ gl.clear(gl.COLOR_BUFFER_BIT);
852
732
 
853
- if (this.isActive) {
854
- requestAnimationFrame(() => this.render());
733
+ // Set uniforms
734
+ const uniforms = this._buildUniforms();
735
+ for (const [name, value] of Object.entries(uniforms)) {
736
+ const loc = this._uniformLocations[name];
737
+ if (loc === null || loc === undefined) continue;
738
+ if (Array.isArray(value)) {
739
+ if (value.length === 2) gl.uniform2fv(loc, value);
740
+ else if (value.length === 3) gl.uniform3fv(loc, value);
741
+ else if (value.length === 4) gl.uniform4fv(loc, value);
742
+ } else {
743
+ gl.uniform1f(loc, value);
744
+ }
855
745
  }
856
- }
857
746
 
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
- }
747
+ // Draw fullscreen quad
748
+ gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer);
749
+ const posLoc = gl.getAttribLocation(this.program, 'a_position');
750
+ if (posLoc >= 0) {
751
+ gl.enableVertexAttribArray(posLoc);
752
+ gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
868
753
  }
754
+ gl.drawArrays(gl.TRIANGLES, 0, 6);
869
755
  }
870
756
 
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
- });
757
+ render() {
758
+ if (this._useDirectGL) {
759
+ this._renderDirectGL();
760
+ } else if (this.bridge) {
761
+ this.bridge.setUniforms(this._buildUniforms());
762
+ this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
890
763
  }
764
+ }
891
765
 
892
- return this.initialize(canvasOverride);
766
+ getBackendType() {
767
+ if (this._useDirectGL) return 'webgl';
768
+ return this.bridge ? this.bridge.getBackendType() : 'none';
893
769
  }
894
770
 
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
- }
771
+ setActive(active) {
772
+ if (active) this.start();
773
+ else this.stop();
774
+ const layer = document.getElementById('faceted-layer');
775
+ if (layer) layer.style.display = active ? 'block' : 'none';
913
776
  }
914
777
 
915
- /**
916
- * Clean up all resources (RendererContract.dispose)
917
- */
918
- dispose() {
919
- this.isActive = false;
778
+ init(context) { return this.initialize(); }
920
779
 
921
- // Remove context loss listeners
780
+ resize(width, height, pixelRatio = 1) {
781
+ const w = Math.floor(width * pixelRatio);
782
+ const h = Math.floor(height * pixelRatio);
922
783
  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
- }
784
+ this.canvas.width = w;
785
+ this.canvas.height = h;
929
786
  }
930
-
931
- if (this._bridge) {
932
- this._bridge.dispose();
933
- this._bridge = null;
787
+ if (this._useDirectGL && this.gl) {
788
+ this.gl.viewport(0, 0, w, h);
789
+ } else if (this.bridge && this.bridge.resize) {
790
+ this.bridge.resize(width, height, pixelRatio);
934
791
  }
792
+ }
935
793
 
936
- if (this.gl && !this.gl.isContextLost()) {
937
- if (this.program) {
938
- this.gl.deleteProgram(this.program);
939
- }
940
- }
941
- this.program = null;
794
+ dispose() { this.destroy(); }
942
795
 
943
- if (this.gl) {
944
- const loseContext = this.gl.getExtension('WEBGL_lose_context');
945
- if (loseContext) {
946
- loseContext.loseContext();
947
- }
796
+ destroy() {
797
+ this.stop();
798
+ if (this._useDirectGL && this.gl) {
799
+ if (this.program) this.gl.deleteProgram(this.program);
800
+ if (this._quadBuffer) this.gl.deleteBuffer(this._quadBuffer);
948
801
  this.gl = null;
802
+ this.program = null;
803
+ this._quadBuffer = null;
949
804
  }
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();
805
+ if (this.bridge) {
806
+ this.bridge.dispose();
807
+ this.bridge = null;
808
+ }
809
+ this.initialized = false;
810
+ this._useDirectGL = false;
962
811
  }
963
812
  }