@vib3code/sdk 2.0.3-canary.60bc0f0 → 2.0.3-canary.74aebb4

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 (44) hide show
  1. package/DOCS/EXPANSION_DESIGN.md +977 -0
  2. package/DOCS/EXPANSION_DESIGN_ULTRA.md +387 -0
  3. package/DOCS/MASTER_PLAN_2026-01-31.md +2 -2
  4. package/DOCS/OPTIMIZATION_PLAN_MATH.md +118 -0
  5. package/DOCS/SYSTEM_INVENTORY.md +2 -2
  6. package/DOCS/WEBGPU_STATUS.md +119 -38
  7. package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +38 -0
  8. package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +108 -0
  9. package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +308 -0
  10. package/docs/webgpu-live.html +1 -1
  11. package/package.json +1 -1
  12. package/src/agent/mcp/MCPServer.js +195 -136
  13. package/src/agent/mcp/tools.js +45 -32
  14. package/src/experimental/GameLoop.js +72 -0
  15. package/src/experimental/LatticePhysics.js +100 -0
  16. package/src/experimental/LiveDirector.js +143 -0
  17. package/src/experimental/PlayerController4D.js +154 -0
  18. package/src/experimental/VIB3Actor.js +138 -0
  19. package/src/experimental/VIB3Compositor.js +117 -0
  20. package/src/experimental/VIB3Link.js +122 -0
  21. package/src/experimental/VIB3Orchestrator.js +146 -0
  22. package/src/experimental/VIB3Universe.js +109 -0
  23. package/src/experimental/demos/CrystalLabyrinth.js +202 -0
  24. package/src/faceted/FacetedSystem.js +19 -6
  25. package/src/geometry/generators/Crystal.js +2 -2
  26. package/src/holograms/HolographicVisualizer.js +58 -89
  27. package/src/math/Mat4x4.js +122 -6
  28. package/src/math/Rotor4D.js +93 -39
  29. package/src/math/Vec4.js +119 -78
  30. package/src/quantum/QuantumVisualizer.js +24 -20
  31. package/src/render/ShaderLoader.js +38 -0
  32. package/src/render/ShaderProgram.js +4 -4
  33. package/src/render/UnifiedRenderBridge.js +1 -1
  34. package/src/render/backends/WebGPUBackend.js +8 -4
  35. package/src/shaders/common/geometry24.glsl +65 -0
  36. package/src/shaders/common/geometry24.wgsl +54 -0
  37. package/src/shaders/common/rotation4d.glsl +4 -4
  38. package/src/shaders/common/rotation4d.wgsl +2 -2
  39. package/src/shaders/common/uniforms.wgsl +15 -8
  40. package/src/shaders/faceted/faceted.frag.wgsl +19 -6
  41. package/src/shaders/holographic/holographic.frag.wgsl +7 -5
  42. package/src/shaders/quantum/quantum.frag.wgsl +7 -5
  43. package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
  44. package/tools/shader-sync-verify.js +6 -4
package/src/math/Vec4.js CHANGED
@@ -2,7 +2,8 @@
2
2
  * Vec4 - 4D Vector Class
3
3
  *
4
4
  * Represents a point or direction in 4-dimensional space.
5
- * Uses Float32Array for GPU compatibility and potential SIMD optimization.
5
+ * Uses plain numeric properties internally for minimal allocation overhead.
6
+ * GPU-compatible Float32Array created on demand via toFloat32Array().
6
7
  *
7
8
  * @example
8
9
  * const v = new Vec4(1, 2, 3, 0.5);
@@ -19,26 +20,66 @@ export class Vec4 {
19
20
  * @param {number} w - W component (4th dimension)
20
21
  */
21
22
  constructor(x = 0, y = 0, z = 0, w = 0) {
22
- // Use Float32Array for GPU compatibility
23
- this.data = new Float32Array(4);
24
- this.data[0] = x;
25
- this.data[1] = y;
26
- this.data[2] = z;
27
- this.data[3] = w;
23
+ this._x = x;
24
+ this._y = y;
25
+ this._z = z;
26
+ this._w = w;
28
27
  }
29
28
 
30
- // Property accessors for readability
31
- get x() { return this.data[0]; }
32
- set x(v) { this.data[0] = v; }
29
+ // Property accessors
30
+ get x() { return this._x; }
31
+ set x(v) { this._x = v; }
33
32
 
34
- get y() { return this.data[1]; }
35
- set y(v) { this.data[1] = v; }
33
+ get y() { return this._y; }
34
+ set y(v) { this._y = v; }
36
35
 
37
- get z() { return this.data[2]; }
38
- set z(v) { this.data[2] = v; }
36
+ get z() { return this._z; }
37
+ set z(v) { this._z = v; }
39
38
 
40
- get w() { return this.data[3]; }
41
- set w(v) { this.data[3] = v; }
39
+ get w() { return this._w; }
40
+ set w(v) { this._w = v; }
41
+
42
+ /**
43
+ * Backward-compatible .data getter.
44
+ * Returns a Float32Array snapshot of current values.
45
+ * Note: writes to the returned array do NOT propagate back.
46
+ * Use setComponent(index, value) for index-based mutation.
47
+ * @returns {Float32Array}
48
+ */
49
+ get data() {
50
+ return new Float32Array([this._x, this._y, this._z, this._w]);
51
+ }
52
+
53
+ /**
54
+ * Set a component by index (0=x, 1=y, 2=z, 3=w)
55
+ * @param {number} index - Component index (0-3)
56
+ * @param {number} value - New value
57
+ * @returns {Vec4} this
58
+ */
59
+ setComponent(index, value) {
60
+ switch (index) {
61
+ case 0: this._x = value; break;
62
+ case 1: this._y = value; break;
63
+ case 2: this._z = value; break;
64
+ case 3: this._w = value; break;
65
+ }
66
+ return this;
67
+ }
68
+
69
+ /**
70
+ * Get a component by index (0=x, 1=y, 2=z, 3=w)
71
+ * @param {number} index - Component index (0-3)
72
+ * @returns {number}
73
+ */
74
+ getComponent(index) {
75
+ switch (index) {
76
+ case 0: return this._x;
77
+ case 1: return this._y;
78
+ case 2: return this._z;
79
+ case 3: return this._w;
80
+ default: return 0;
81
+ }
82
+ }
42
83
 
43
84
  /**
44
85
  * Create a Vec4 from an array
@@ -54,7 +95,7 @@ export class Vec4 {
54
95
  * @returns {Vec4}
55
96
  */
56
97
  clone() {
57
- return new Vec4(this.x, this.y, this.z, this.w);
98
+ return new Vec4(this._x, this._y, this._z, this._w);
58
99
  }
59
100
 
60
101
  /**
@@ -63,10 +104,10 @@ export class Vec4 {
63
104
  * @returns {Vec4} this (for chaining)
64
105
  */
65
106
  copy(v) {
66
- this.data[0] = v.data[0];
67
- this.data[1] = v.data[1];
68
- this.data[2] = v.data[2];
69
- this.data[3] = v.data[3];
107
+ this._x = v._x;
108
+ this._y = v._y;
109
+ this._z = v._z;
110
+ this._w = v._w;
70
111
  return this;
71
112
  }
72
113
 
@@ -79,10 +120,10 @@ export class Vec4 {
79
120
  * @returns {Vec4} this
80
121
  */
81
122
  set(x, y, z, w) {
82
- this.data[0] = x;
83
- this.data[1] = y;
84
- this.data[2] = z;
85
- this.data[3] = w;
123
+ this._x = x;
124
+ this._y = y;
125
+ this._z = z;
126
+ this._w = w;
86
127
  return this;
87
128
  }
88
129
 
@@ -93,10 +134,10 @@ export class Vec4 {
93
134
  */
94
135
  add(v) {
95
136
  return new Vec4(
96
- this.x + v.x,
97
- this.y + v.y,
98
- this.z + v.z,
99
- this.w + v.w
137
+ this._x + v._x,
138
+ this._y + v._y,
139
+ this._z + v._z,
140
+ this._w + v._w
100
141
  );
101
142
  }
102
143
 
@@ -106,10 +147,10 @@ export class Vec4 {
106
147
  * @returns {Vec4} this
107
148
  */
108
149
  addInPlace(v) {
109
- this.data[0] += v.data[0];
110
- this.data[1] += v.data[1];
111
- this.data[2] += v.data[2];
112
- this.data[3] += v.data[3];
150
+ this._x += v._x;
151
+ this._y += v._y;
152
+ this._z += v._z;
153
+ this._w += v._w;
113
154
  return this;
114
155
  }
115
156
 
@@ -120,10 +161,10 @@ export class Vec4 {
120
161
  */
121
162
  sub(v) {
122
163
  return new Vec4(
123
- this.x - v.x,
124
- this.y - v.y,
125
- this.z - v.z,
126
- this.w - v.w
164
+ this._x - v._x,
165
+ this._y - v._y,
166
+ this._z - v._z,
167
+ this._w - v._w
127
168
  );
128
169
  }
129
170
 
@@ -133,10 +174,10 @@ export class Vec4 {
133
174
  * @returns {Vec4} this
134
175
  */
135
176
  subInPlace(v) {
136
- this.data[0] -= v.data[0];
137
- this.data[1] -= v.data[1];
138
- this.data[2] -= v.data[2];
139
- this.data[3] -= v.data[3];
177
+ this._x -= v._x;
178
+ this._y -= v._y;
179
+ this._z -= v._z;
180
+ this._w -= v._w;
140
181
  return this;
141
182
  }
142
183
 
@@ -147,10 +188,10 @@ export class Vec4 {
147
188
  */
148
189
  scale(s) {
149
190
  return new Vec4(
150
- this.x * s,
151
- this.y * s,
152
- this.z * s,
153
- this.w * s
191
+ this._x * s,
192
+ this._y * s,
193
+ this._z * s,
194
+ this._w * s
154
195
  );
155
196
  }
156
197
 
@@ -160,10 +201,10 @@ export class Vec4 {
160
201
  * @returns {Vec4} this
161
202
  */
162
203
  scaleInPlace(s) {
163
- this.data[0] *= s;
164
- this.data[1] *= s;
165
- this.data[2] *= s;
166
- this.data[3] *= s;
204
+ this._x *= s;
205
+ this._y *= s;
206
+ this._z *= s;
207
+ this._w *= s;
167
208
  return this;
168
209
  }
169
210
 
@@ -174,10 +215,10 @@ export class Vec4 {
174
215
  */
175
216
  multiply(v) {
176
217
  return new Vec4(
177
- this.x * v.x,
178
- this.y * v.y,
179
- this.z * v.z,
180
- this.w * v.w
218
+ this._x * v._x,
219
+ this._y * v._y,
220
+ this._z * v._z,
221
+ this._w * v._w
181
222
  );
182
223
  }
183
224
 
@@ -186,7 +227,7 @@ export class Vec4 {
186
227
  * @returns {Vec4} New vector
187
228
  */
188
229
  negate() {
189
- return new Vec4(-this.x, -this.y, -this.z, -this.w);
230
+ return new Vec4(-this._x, -this._y, -this._z, -this._w);
190
231
  }
191
232
 
192
233
  /**
@@ -194,10 +235,10 @@ export class Vec4 {
194
235
  * @returns {Vec4} this
195
236
  */
196
237
  negateInPlace() {
197
- this.data[0] = -this.data[0];
198
- this.data[1] = -this.data[1];
199
- this.data[2] = -this.data[2];
200
- this.data[3] = -this.data[3];
238
+ this._x = -this._x;
239
+ this._y = -this._y;
240
+ this._z = -this._z;
241
+ this._w = -this._w;
201
242
  return this;
202
243
  }
203
244
 
@@ -207,7 +248,7 @@ export class Vec4 {
207
248
  * @returns {number}
208
249
  */
209
250
  dot(v) {
210
- return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.w;
251
+ return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._w;
211
252
  }
212
253
 
213
254
  /**
@@ -215,7 +256,7 @@ export class Vec4 {
215
256
  * @returns {number}
216
257
  */
217
258
  lengthSquared() {
218
- return this.x * this.x + this.y * this.y + this.z * this.z + this.w * this.w;
259
+ return this._x * this._x + this._y * this._y + this._z * this._z + this._w * this._w;
219
260
  }
220
261
 
221
262
  /**
@@ -277,10 +318,10 @@ export class Vec4 {
277
318
  */
278
319
  lerp(v, t) {
279
320
  return new Vec4(
280
- this.x + (v.x - this.x) * t,
281
- this.y + (v.y - this.y) * t,
282
- this.z + (v.z - this.z) * t,
283
- this.w + (v.w - this.w) * t
321
+ this._x + (v._x - this._x) * t,
322
+ this._y + (v._y - this._y) * t,
323
+ this._z + (v._z - this._z) * t,
324
+ this._w + (v._w - this._w) * t
284
325
  );
285
326
  }
286
327
 
@@ -292,10 +333,10 @@ export class Vec4 {
292
333
  */
293
334
  equals(v, epsilon = 1e-6) {
294
335
  return (
295
- Math.abs(this.x - v.x) < epsilon &&
296
- Math.abs(this.y - v.y) < epsilon &&
297
- Math.abs(this.z - v.z) < epsilon &&
298
- Math.abs(this.w - v.w) < epsilon
336
+ Math.abs(this._x - v._x) < epsilon &&
337
+ Math.abs(this._y - v._y) < epsilon &&
338
+ Math.abs(this._z - v._z) < epsilon &&
339
+ Math.abs(this._w - v._w) < epsilon
299
340
  );
300
341
  }
301
342
 
@@ -321,10 +362,10 @@ export class Vec4 {
321
362
  d = options.distance ?? options.d ?? 2;
322
363
  }
323
364
  const epsilon = options.epsilon ?? 1e-5;
324
- const denom = d - this.w;
365
+ const denom = d - this._w;
325
366
  const clamped = Math.abs(denom) < epsilon ? (denom >= 0 ? epsilon : -epsilon) : denom;
326
367
  const scale = 1 / clamped;
327
- return new Vec4(this.x * scale, this.y * scale, this.z * scale, 0);
368
+ return new Vec4(this._x * scale, this._y * scale, this._z * scale, 0);
328
369
  }
329
370
 
330
371
  /**
@@ -335,10 +376,10 @@ export class Vec4 {
335
376
  */
336
377
  projectStereographic(options = {}) {
337
378
  const epsilon = options.epsilon ?? 1e-5;
338
- const denom = 1 - this.w;
379
+ const denom = 1 - this._w;
339
380
  const clamped = Math.abs(denom) < epsilon ? (denom >= 0 ? epsilon : -epsilon) : denom;
340
381
  const scale = 1 / clamped;
341
- return new Vec4(this.x * scale, this.y * scale, this.z * scale, 0);
382
+ return new Vec4(this._x * scale, this._y * scale, this._z * scale, 0);
342
383
  }
343
384
 
344
385
  /**
@@ -347,7 +388,7 @@ export class Vec4 {
347
388
  * @returns {Vec4} Projected point (w component is 0)
348
389
  */
349
390
  projectOrthographic() {
350
- return new Vec4(this.x, this.y, this.z, 0);
391
+ return new Vec4(this._x, this._y, this._z, 0);
351
392
  }
352
393
 
353
394
  /**
@@ -355,7 +396,7 @@ export class Vec4 {
355
396
  * @returns {number[]}
356
397
  */
357
398
  toArray() {
358
- return [this.x, this.y, this.z, this.w];
399
+ return [this._x, this._y, this._z, this._w];
359
400
  }
360
401
 
361
402
  /**
@@ -363,7 +404,7 @@ export class Vec4 {
363
404
  * @returns {Float32Array}
364
405
  */
365
406
  toFloat32Array() {
366
- return new Float32Array(this.data);
407
+ return new Float32Array([this._x, this._y, this._z, this._w]);
367
408
  }
368
409
 
369
410
  /**
@@ -371,7 +412,7 @@ export class Vec4 {
371
412
  * @returns {number[]}
372
413
  */
373
414
  toArray3() {
374
- return [this.x, this.y, this.z];
415
+ return [this._x, this._y, this._z];
375
416
  }
376
417
 
377
418
  /**
@@ -380,7 +421,7 @@ export class Vec4 {
380
421
  * @returns {string}
381
422
  */
382
423
  toString(precision = 3) {
383
- return `Vec4(${this.x.toFixed(precision)}, ${this.y.toFixed(precision)}, ${this.z.toFixed(precision)}, ${this.w.toFixed(precision)})`;
424
+ return `Vec4(${this._x.toFixed(precision)}, ${this._y.toFixed(precision)}, ${this._z.toFixed(precision)}, ${this._w.toFixed(precision)})`;
384
425
  }
385
426
 
386
427
  /**
@@ -388,7 +429,7 @@ export class Vec4 {
388
429
  * @returns {object}
389
430
  */
390
431
  toJSON() {
391
- return { x: this.x, y: this.y, z: this.z, w: this.w };
432
+ return { x: this._x, y: this._y, z: this._z, w: this._w };
392
433
  }
393
434
 
394
435
  // Static factory methods for common vectors
@@ -6,6 +6,17 @@
6
6
 
7
7
  import { GeometryLibrary } from '../geometry/GeometryLibrary.js';
8
8
 
9
+ // Role-specific intensity values for 5-layer canvas architecture.
10
+ // IMPORTANT: Must stay in sync with shader epsilon comparisons in the fragment shader
11
+ // at the "LAYER-BY-LAYER COLOR SYSTEM" section (search for layerIndex).
12
+ const ROLE_INTENSITIES = {
13
+ 'background': 0.4,
14
+ 'shadow': 0.6,
15
+ 'content': 1.0,
16
+ 'highlight': 1.3,
17
+ 'accent': 1.6
18
+ };
19
+
9
20
  export class QuantumHolographicVisualizer {
10
21
  constructor(canvasIdOrElement, role, reactivity, variant) {
11
22
  this.canvas = (canvasIdOrElement instanceof HTMLCanvasElement)
@@ -14,6 +25,7 @@ export class QuantumHolographicVisualizer {
14
25
  this.role = role;
15
26
  this.reactivity = reactivity;
16
27
  this.variant = variant;
28
+ this._canvasLabel = typeof canvasIdOrElement === 'string' ? canvasIdOrElement : canvasIdOrElement?.id || 'unknown';
17
29
 
18
30
  // CRITICAL FIX: Define contextOptions as instance property to match SmartCanvasPool
19
31
  this.contextOptions = {
@@ -34,9 +46,9 @@ export class QuantumHolographicVisualizer {
34
46
  this.canvas.getContext('experimental-webgl', this.contextOptions);
35
47
 
36
48
  if (!this.gl) {
37
- console.error(`WebGL not supported for ${canvasId}`);
49
+ console.error(`WebGL not supported for ${this._canvasLabel}`);
38
50
  if (window.mobileDebug) {
39
- window.mobileDebug.log(`❌ ${canvasId}: WebGL context creation failed`);
51
+ window.mobileDebug.log(`❌ ${this._canvasLabel}: WebGL context creation failed`);
40
52
  }
41
53
  // Show user-friendly error instead of white screen
42
54
  this.showWebGLError();
@@ -44,7 +56,7 @@ export class QuantumHolographicVisualizer {
44
56
  } else {
45
57
  if (window.mobileDebug) {
46
58
  const version = this.gl.getParameter(this.gl.VERSION);
47
- window.mobileDebug.log(`✅ ${canvasId}: WebGL context created - ${version}`);
59
+ window.mobileDebug.log(`✅ ${this._canvasLabel}: WebGL context created - ${version}`);
48
60
  }
49
61
  }
50
62
 
@@ -59,15 +71,15 @@ export class QuantumHolographicVisualizer {
59
71
  this._onContextLost = (e) => {
60
72
  e.preventDefault();
61
73
  this._contextLost = true;
62
- console.warn(`WebGL context lost for ${canvasId}`);
74
+ console.warn(`WebGL context lost for ${this._canvasLabel}`);
63
75
  };
64
76
  this._onContextRestored = () => {
65
- console.log(`WebGL context restored for ${canvasId}`);
77
+ console.log(`WebGL context restored for ${this._canvasLabel}`);
66
78
  this._contextLost = false;
67
79
  try {
68
80
  this.init();
69
81
  } catch (err) {
70
- console.error(`Failed to reinit after context restore for ${canvasId}:`, err);
82
+ console.error(`Failed to reinit after context restore for ${this._canvasLabel}:`, err);
71
83
  }
72
84
  };
73
85
  this.canvas.addEventListener('webglcontextlost', this._onContextLost);
@@ -688,11 +700,12 @@ void main() {
688
700
 
689
701
  // LAYER-BY-LAYER COLOR SYSTEM with user hue/saturation/intensity controls
690
702
  // Determine canvas layer from role/variant (0=background, 1=shadow, 2=content, 3=highlight, 4=accent)
703
+ // Values must match ROLE_INTENSITIES in JS: bg=0.4, shadow=0.6, content=1.0, highlight=1.3, accent=1.6
691
704
  int layerIndex = 0;
692
- if (u_roleIntensity == 0.7) layerIndex = 1; // shadow layer
693
- else if (u_roleIntensity == 1.0) layerIndex = 2; // content layer
694
- else if (u_roleIntensity == 0.85) layerIndex = 3; // highlight layer
695
- else if (u_roleIntensity == 0.6) layerIndex = 4; // accent layer
705
+ if (abs(u_roleIntensity - 0.6) < 0.05) layerIndex = 1; // shadow layer
706
+ else if (abs(u_roleIntensity - 1.0) < 0.05) layerIndex = 2; // content layer
707
+ else if (abs(u_roleIntensity - 1.3) < 0.05) layerIndex = 3; // highlight layer
708
+ else if (abs(u_roleIntensity - 1.6) < 0.05) layerIndex = 4; // accent layer
696
709
 
697
710
  // Get layer-specific base color using user hue/saturation controls
698
711
  float colorTime = timeSpeed * 2.0 + value * 3.0;
@@ -1016,15 +1029,6 @@ void main() {
1016
1029
  this._renderParamsLogged = true;
1017
1030
  }
1018
1031
 
1019
- // Role-specific intensity for quantum effects
1020
- const roleIntensities = {
1021
- 'background': 0.4,
1022
- 'shadow': 0.6,
1023
- 'content': 1.0,
1024
- 'highlight': 1.3,
1025
- 'accent': 1.6
1026
- };
1027
-
1028
1032
  const time = Date.now() - this.startTime;
1029
1033
 
1030
1034
  // Set uniforms
@@ -1068,7 +1072,7 @@ void main() {
1068
1072
  this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
1069
1073
  this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity);
1070
1074
  this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity);
1071
- this.gl.uniform1f(this.uniforms.roleIntensity, roleIntensities[this.role] || 1.0);
1075
+ this.gl.uniform1f(this.uniforms.roleIntensity, ROLE_INTENSITIES[this.role] || 1.0);
1072
1076
  this.gl.uniform1f(this.uniforms.breath, this.params.breath || 0.0);
1073
1077
 
1074
1078
  this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
@@ -199,6 +199,44 @@ export class ShaderLoader {
199
199
  return results;
200
200
  }
201
201
 
202
+ /**
203
+ * Resolve #include directives in shader source.
204
+ * GLSL: #include "common/rotation4d.glsl"
205
+ * WGSL: // @include "common/rotation4d.wgsl"
206
+ *
207
+ * Includes are resolved from the loader's cache (call loadCommonLibrary() first).
208
+ * Non-recursive — only resolves one level of includes.
209
+ *
210
+ * @param {string} source - Shader source with include directives
211
+ * @returns {string} Resolved shader source
212
+ */
213
+ resolveIncludes(source) {
214
+ if (!source) return source;
215
+
216
+ // GLSL: #include "path"
217
+ // WGSL: // @include "path"
218
+ const includeRegex = /(?:^|\n)\s*(?:#include|\/\/\s*@include)\s+"([^"]+)"\s*(?:\n|$)/g;
219
+
220
+ return source.replace(includeRegex, (match, path) => {
221
+ const cached = this._cache.get(path);
222
+ if (cached) {
223
+ return '\n// --- included from ' + path + ' ---\n' + cached + '\n// --- end ' + path + ' ---\n';
224
+ }
225
+ console.warn(`ShaderLoader: Include not found in cache: "${path}" — load it first via loadCommonLibrary()`);
226
+ return match; // Leave directive in place if not found
227
+ });
228
+ }
229
+
230
+ /**
231
+ * Load a shader file and resolve includes.
232
+ * @param {string} relativePath
233
+ * @returns {Promise<string|null>}
234
+ */
235
+ async loadAndResolve(relativePath) {
236
+ const source = await this.load(relativePath);
237
+ return source ? this.resolveIncludes(source) : null;
238
+ }
239
+
202
240
  /**
203
241
  * Clear all cached shaders.
204
242
  */
@@ -384,10 +384,10 @@ export const ShaderLib = {
384
384
  mat4 rotateXZ(float angle) {
385
385
  float c = cos(angle), s = sin(angle);
386
386
  return mat4(
387
- c, 0, -s, 0,
388
- 0, 1, 0, 0,
389
- s, 0, c, 0,
390
- 0, 0, 0, 1
387
+ c, 0, s, 0,
388
+ 0, 1, 0, 0,
389
+ -s, 0, c, 0,
390
+ 0, 0, 0, 1
391
391
  );
392
392
  }
393
393
 
@@ -25,7 +25,7 @@ import { createWebGPUBackend, isWebGPUSupported, WGSLShaderLib } from './backend
25
25
  * @returns {Float32Array}
26
26
  */
27
27
  function packVIB3Uniforms(uniforms) {
28
- // Total: 32 floats = 128 bytes → aligned to 256 bytes in buffer
28
+ // Total: 33 floats (indices 0-32) = 132 bytes → padded to 256 bytes in buffer
29
29
  const data = new Float32Array(64); // 256 bytes
30
30
 
31
31
  data[0] = uniforms.u_time || 0;
@@ -152,10 +152,14 @@ struct VIB3Uniforms {
152
152
  layerScale: f32,
153
153
  layerOpacity: f32,
154
154
  _pad1: f32,
155
- layerColor: vec3<f32>,
155
+ layerColorR: f32,
156
+ layerColorG: f32,
157
+ layerColorB: f32,
156
158
  densityMult: f32,
157
159
  speedMult: f32,
158
- _pad2: vec3<f32>,
160
+
161
+ // Vitality
162
+ breath: f32,
159
163
  };
160
164
  `;
161
165
 
@@ -178,9 +182,9 @@ fn rotateXZ(angle: f32) -> mat4x4<f32> {
178
182
  let c = cos(angle);
179
183
  let s = sin(angle);
180
184
  return mat4x4<f32>(
181
- vec4<f32>(c, 0.0, -s, 0.0),
185
+ vec4<f32>( c, 0.0, s, 0.0),
182
186
  vec4<f32>(0.0, 1.0, 0.0, 0.0),
183
- vec4<f32>(s, 0.0, c, 0.0),
187
+ vec4<f32>(-s, 0.0, c, 0.0),
184
188
  vec4<f32>(0.0, 0.0, 0.0, 1.0)
185
189
  );
186
190
  }
@@ -53,6 +53,71 @@ float hypertetrahedronCore(vec4 p, float baseType) {
53
53
  return max(baseShape, tetraField);
54
54
  }
55
55
 
56
+ // ── Polytope Core Warp Functions ──
57
+ // Requires: rotation matrices from rotation4d.glsl, project4Dto3D, and u_* uniforms
58
+
59
+ vec3 warpHypersphereCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
60
+ float radius = length(p);
61
+ float morphBlend = clamp(u_morphFactor * 0.6 + (u_dimension - 3.0) * 0.25, 0.0, 2.0);
62
+ float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
63
+ w *= (0.4 + morphBlend * 0.45);
64
+
65
+ vec4 p4d = vec4(p * (1.0 + morphBlend * 0.2), w);
66
+ p4d = rotateXY(u_rot4dXY) * p4d;
67
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
68
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
69
+ p4d = rotateXW(u_rot4dXW) * p4d;
70
+ p4d = rotateYW(u_rot4dYW) * p4d;
71
+ p4d = rotateZW(u_rot4dZW) * p4d;
72
+
73
+ vec3 projected = project4Dto3D(p4d);
74
+ return mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
75
+ }
76
+
77
+ vec3 warpHypertetraCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
78
+ vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
79
+ vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
80
+ vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
81
+ vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
82
+
83
+ float morphBlend = clamp(u_morphFactor * 0.8 + (u_dimension - 3.0) * 0.2, 0.0, 2.0);
84
+ float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
85
+ float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed);
86
+ w *= cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
87
+ w *= (0.5 + morphBlend * 0.4);
88
+
89
+ vec3 offset = vec3(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
90
+ vec4 p4d = vec4(p + offset, w);
91
+ p4d = rotateXY(u_rot4dXY) * p4d;
92
+ p4d = rotateXZ(u_rot4dXZ) * p4d;
93
+ p4d = rotateYZ(u_rot4dYZ) * p4d;
94
+ p4d = rotateXW(u_rot4dXW) * p4d;
95
+ p4d = rotateYW(u_rot4dYW) * p4d;
96
+ p4d = rotateZW(u_rot4dZW) * p4d;
97
+
98
+ vec3 projected = project4Dto3D(p4d);
99
+ float planeInfluence = min(min(abs(dot(p, c1)), abs(dot(p, c2))),
100
+ min(abs(dot(p, c3)), abs(dot(p, c4))));
101
+ vec3 blended = mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
102
+ return mix(blended, blended * (1.0 - planeInfluence * 0.55), 0.2 + morphBlend * 0.2);
103
+ }
104
+
105
+ vec3 applyCoreWarp(vec3 p, float geometryType, vec2 mouseDelta) {
106
+ float totalBase = 8.0;
107
+ float coreFloat = floor(geometryType / totalBase);
108
+ int coreIndex = int(clamp(coreFloat, 0.0, 2.0));
109
+ float baseGeomFloat = geometryType - floor(geometryType / totalBase) * totalBase;
110
+ int geometryIndex = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
111
+
112
+ if (coreIndex == 1) {
113
+ return warpHypersphereCore(p, geometryIndex, mouseDelta);
114
+ }
115
+ if (coreIndex == 2) {
116
+ return warpHypertetraCore(p, geometryIndex, mouseDelta);
117
+ }
118
+ return p;
119
+ }
120
+
56
121
  // Main geometry dispatcher (0-23)
57
122
  float geometry(vec4 p, float type) {
58
123
  if (type < 8.0) {