@vib3code/sdk 2.0.1 → 2.0.3-canary.0a63e71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +36 -0
- package/DOCS/AGENT_HARNESS_ARCHITECTURE.md +245 -0
- package/DOCS/ANDROID_DEPLOYMENT.md +59 -0
- package/DOCS/ARCHITECTURE.md +1 -0
- package/DOCS/CI_TESTING.md +2 -0
- package/DOCS/CLI_ONBOARDING.md +3 -1
- package/DOCS/CONTROL_REFERENCE.md +2 -0
- package/DOCS/CROSS_SITE_DESIGN_PATTERNS.md +119 -0
- package/DOCS/ENV_SETUP.md +2 -0
- package/DOCS/EPIC_SCROLL_EVENTS.md +775 -0
- package/DOCS/EXPANSION_DESIGN.md +979 -0
- package/DOCS/EXPANSION_DESIGN_ULTRA.md +389 -0
- package/DOCS/EXPORT_FORMATS.md +2 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +2 -0
- package/DOCS/HANDOFF_LANDING_PAGE.md +156 -0
- package/DOCS/HANDOFF_SDK_DEVELOPMENT.md +495 -0
- package/DOCS/LICENSING_TIERS.md +2 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +4 -2
- package/DOCS/MULTIVIZ_CHOREOGRAPHY_PATTERNS.md +939 -0
- package/DOCS/OBS_SETUP_GUIDE.md +2 -0
- package/DOCS/OPTIMIZATION_PLAN_MATH.md +119 -0
- package/DOCS/PRODUCT_STRATEGY.md +65 -0
- package/DOCS/PROJECT_SETUP.md +2 -0
- package/DOCS/README.md +105 -0
- package/DOCS/REFERENCE_SCROLL_ANALYSIS.md +99 -0
- package/DOCS/RENDERER_LIFECYCLE.md +2 -0
- package/DOCS/REPO_MANIFEST.md +2 -0
- package/DOCS/ROADMAP.md +113 -0
- package/DOCS/SCROLL_TIMELINE_v3.md +271 -0
- package/DOCS/SITE_REFACTOR_PLAN.md +102 -0
- package/DOCS/STATUS.md +26 -0
- package/DOCS/SYSTEM_INVENTORY.md +37 -32
- package/DOCS/TELEMETRY_EXPORTS.md +2 -0
- package/DOCS/VISUAL_ANALYSIS_CLICKERSS.md +87 -0
- package/DOCS/VISUAL_ANALYSIS_FACETAD.md +135 -0
- package/DOCS/VISUAL_ANALYSIS_SIMONE.md +97 -0
- package/DOCS/VISUAL_ANALYSIS_TABLESIDE.md +88 -0
- package/DOCS/WEBGPU_STATUS.md +121 -38
- package/DOCS/XR_BENCHMARKS.md +2 -0
- package/DOCS/archive/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/DEV_TRACK_ANALYSIS.md +1 -0
- package/DOCS/archive/DEV_TRACK_PLAN_2026-01-07.md +1 -0
- package/DOCS/archive/SESSION_014_PLAN.md +1 -0
- package/DOCS/archive/SESSION_LOG_2026-01-07.md +1 -0
- package/DOCS/archive/STRATEGIC_BLUEPRINT_2026-01-07.md +1 -0
- package/DOCS/archive/SYSTEM_AUDIT_2026-01-30.md +1 -0
- package/DOCS/archive/WEBGPU_STATUS_2026-02-15_STALE.md +1 -0
- package/DOCS/{DEV_TRACK_SESSION_2026-01-31.md → dev-tracks/DEV_TRACK_SESSION_2026-01-31.md} +3 -1
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-06.md +233 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-13.md +129 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-15.md +144 -0
- package/DOCS/dev-tracks/DEV_TRACK_SESSION_2026-02-16.md +110 -0
- package/DOCS/dev-tracks/PERF_UPGRADE_2026-02-16.md +310 -0
- package/DOCS/dev-tracks/README.md +12 -0
- package/README.md +26 -13
- package/cpp/CMakeLists.txt +236 -0
- package/cpp/bindings/embind.cpp +269 -0
- package/cpp/build.sh +129 -0
- package/cpp/geometry/Crystal.cpp +103 -0
- package/cpp/geometry/Fractal.cpp +136 -0
- package/cpp/geometry/GeometryGenerator.cpp +262 -0
- package/cpp/geometry/KleinBottle.cpp +71 -0
- package/cpp/geometry/Sphere.cpp +134 -0
- package/cpp/geometry/Tesseract.cpp +94 -0
- package/cpp/geometry/Tetrahedron.cpp +83 -0
- package/cpp/geometry/Torus.cpp +65 -0
- package/cpp/geometry/WarpFunctions.cpp +238 -0
- package/cpp/geometry/Wave.cpp +85 -0
- package/cpp/include/vib3_ffi.h +238 -0
- package/cpp/math/Mat4x4.cpp +409 -0
- package/cpp/math/Mat4x4.hpp +209 -0
- package/cpp/math/Projection.cpp +142 -0
- package/cpp/math/Projection.hpp +148 -0
- package/cpp/math/Rotor4D.cpp +322 -0
- package/cpp/math/Rotor4D.hpp +204 -0
- package/cpp/math/Vec4.cpp +303 -0
- package/cpp/math/Vec4.hpp +225 -0
- package/cpp/src/vib3_ffi.cpp +607 -0
- package/cpp/tests/Geometry_test.cpp +213 -0
- package/cpp/tests/Mat4x4_test.cpp +494 -0
- package/cpp/tests/Projection_test.cpp +298 -0
- package/cpp/tests/Rotor4D_test.cpp +423 -0
- package/cpp/tests/Vec4_test.cpp +489 -0
- package/docs/webgpu-live.html +1 -1
- package/package.json +41 -30
- package/src/agent/index.js +1 -3
- package/src/agent/mcp/MCPServer.js +1220 -144
- package/src/agent/mcp/index.js +1 -1
- package/src/agent/mcp/stdio-server.js +264 -0
- package/src/agent/mcp/tools.js +498 -31
- package/src/cli/index.js +431 -47
- package/src/core/CanvasManager.js +97 -204
- package/src/core/ErrorReporter.js +1 -1
- package/src/core/Parameters.js +1 -1
- package/src/core/VIB3Engine.js +93 -4
- package/src/core/VitalitySystem.js +53 -0
- package/src/core/index.js +18 -0
- package/src/core/renderers/FacetedRendererAdapter.js +10 -9
- package/src/core/renderers/HolographicRendererAdapter.js +13 -9
- package/src/core/renderers/QuantumRendererAdapter.js +11 -7
- package/src/creative/AestheticMapper.js +628 -0
- package/src/creative/ChoreographyPlayer.js +481 -0
- package/src/creative/index.js +11 -0
- package/src/experimental/GameLoop.js +72 -0
- package/src/experimental/LatticePhysics.js +100 -0
- package/src/experimental/LiveDirector.js +143 -0
- package/src/experimental/PlayerController4D.js +154 -0
- package/src/experimental/VIB3Actor.js +138 -0
- package/src/experimental/VIB3Compositor.js +117 -0
- package/src/experimental/VIB3Link.js +122 -0
- package/src/experimental/VIB3Orchestrator.js +146 -0
- package/src/experimental/VIB3Universe.js +109 -0
- package/src/experimental/demos/CrystalLabyrinth.js +202 -0
- package/src/export/TradingCardManager.js +3 -4
- package/src/export/index.js +11 -1
- package/src/faceted/FacetedSystem.js +260 -394
- package/src/games/glyph-war/GlyphWarVisualizer.js +641 -0
- package/src/geometry/generators/Crystal.js +2 -2
- package/src/geometry/warp/HypersphereCore.js +53 -24
- package/src/holograms/HolographicVisualizer.js +84 -98
- package/src/holograms/RealHolographicSystem.js +194 -43
- package/src/math/Mat4x4.js +308 -105
- package/src/math/Rotor4D.js +124 -40
- package/src/math/Vec4.js +200 -103
- package/src/math/index.js +7 -7
- package/src/polychora/PolychoraSystem.js +77 -0
- package/src/quantum/QuantumEngine.js +103 -66
- package/src/quantum/QuantumVisualizer.js +31 -22
- package/src/reactivity/index.js +3 -5
- package/src/render/LayerPresetManager.js +372 -0
- package/src/render/LayerReactivityBridge.js +344 -0
- package/src/render/LayerRelationshipGraph.js +610 -0
- package/src/render/MultiCanvasBridge.js +148 -25
- package/src/render/ShaderLoader.js +38 -0
- package/src/render/ShaderProgram.js +4 -4
- package/src/render/UnifiedRenderBridge.js +4 -1
- package/src/render/backends/WebGPUBackend.js +8 -4
- package/src/render/index.js +27 -2
- package/src/scene/Node4D.js +74 -24
- package/src/scene/index.js +4 -4
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +4 -4
- package/src/shaders/common/rotation4d.wgsl +2 -2
- package/src/shaders/common/uniforms.wgsl +15 -8
- package/src/shaders/faceted/faceted.frag.glsl +220 -80
- package/src/shaders/faceted/faceted.frag.wgsl +144 -90
- package/src/shaders/holographic/holographic.frag.glsl +28 -9
- package/src/shaders/holographic/holographic.frag.wgsl +112 -41
- package/src/shaders/quantum/quantum.frag.glsl +1 -0
- package/src/shaders/quantum/quantum.frag.wgsl +6 -4
- package/src/testing/ParallelTestFramework.js +2 -2
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +2 -2
- package/src/viewer/GalleryUI.js +17 -0
- package/src/viewer/ViewerPortal.js +2 -2
- package/src/viewer/index.js +1 -1
- package/tools/headless-renderer.js +258 -0
- package/tools/shader-sync-verify.js +14 -8
- package/tools/site-analysis/all-reports.json +32 -0
- package/tools/site-analysis/combined-analysis.md +50 -0
- package/tools/site-analyzer.mjs +779 -0
- package/tools/visual-catalog/capture.js +276 -0
- package/tools/visual-catalog/composite.js +138 -0
- package/types/adaptive-sdk.d.ts +204 -5
- package/types/agent/cli.d.ts +78 -0
- package/types/agent/index.d.ts +18 -0
- package/types/agent/mcp.d.ts +87 -0
- package/types/agent/telemetry.d.ts +190 -0
- package/types/core/VIB3Engine.d.ts +26 -0
- package/types/core/index.d.ts +261 -0
- package/types/creative/AestheticMapper.d.ts +72 -0
- package/types/creative/ChoreographyPlayer.d.ts +96 -0
- package/types/creative/index.d.ts +17 -0
- package/types/export/index.d.ts +243 -0
- package/types/geometry/index.d.ts +164 -0
- package/types/math/index.d.ts +214 -0
- package/types/render/LayerPresetManager.d.ts +78 -0
- package/types/render/LayerReactivityBridge.d.ts +85 -0
- package/types/render/LayerRelationshipGraph.d.ts +174 -0
- package/types/render/index.d.ts +3 -0
- package/types/scene/index.d.ts +204 -0
- package/types/systems/index.d.ts +244 -0
- package/types/variations/index.d.ts +62 -0
- package/types/viewer/index.d.ts +225 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +0 -34
- package/DOCS/DEV_TRACK_ANALYSIS.md +0 -77
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +0 -42
- package/DOCS/SESSION_014_PLAN.md +0 -195
- package/DOCS/SESSION_LOG_2026-01-07.md +0 -56
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +0 -72
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +0 -738
- /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
|
|
|
@@ -159,10 +160,16 @@ const FRAGMENT_SHADER_GLSL = `
|
|
|
159
160
|
int geomType = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
|
|
160
161
|
|
|
161
162
|
if (geomType == 0) {
|
|
162
|
-
// Tetrahedron lattice
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
163
|
+
// Tetrahedron lattice — tetrahedral symmetry planes
|
|
164
|
+
float d = u_gridDensity * 0.08;
|
|
165
|
+
vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
|
|
166
|
+
vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
|
|
167
|
+
vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
|
|
168
|
+
vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
|
|
169
|
+
vec3 q = fract(p.xyz * d + 0.5) - 0.5;
|
|
170
|
+
float minPlane = min(min(abs(dot(q, c1)), abs(dot(q, c2))),
|
|
171
|
+
min(abs(dot(q, c3)), abs(dot(q, c4))));
|
|
172
|
+
return (1.0 - smoothstep(0.0, 0.05, minPlane)) * u_morphFactor;
|
|
166
173
|
}
|
|
167
174
|
else if (geomType == 1) {
|
|
168
175
|
// Hypercube lattice
|
|
@@ -267,7 +274,11 @@ const FRAGMENT_SHADER_GLSL = `
|
|
|
267
274
|
// Intensity from lattice
|
|
268
275
|
float geometryIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
269
276
|
geometryIntensity += u_clickIntensity * 0.3;
|
|
270
|
-
|
|
277
|
+
|
|
278
|
+
// Exhale: Vitality Breath Modulation
|
|
279
|
+
float breathMod = 1.0 + (u_breath * 0.3); // +30% intensity at full breath
|
|
280
|
+
|
|
281
|
+
float finalIntensity = geometryIntensity * u_intensity * breathMod;
|
|
271
282
|
|
|
272
283
|
// Audio-reactive hue shift
|
|
273
284
|
float hue = u_hue / 360.0 + value * 0.1 + u_high * 0.08;
|
|
@@ -283,7 +294,7 @@ const FRAGMENT_SHADER_GLSL = `
|
|
|
283
294
|
float gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
284
295
|
vec3 color = mix(vec3(gray), baseColor, u_saturation) * finalIntensity;
|
|
285
296
|
|
|
286
|
-
gl_FragColor = vec4(color, finalIntensity
|
|
297
|
+
gl_FragColor = vec4(color, finalIntensity);
|
|
287
298
|
}
|
|
288
299
|
`;
|
|
289
300
|
|
|
@@ -291,7 +302,7 @@ const FRAGMENT_SHADER_GLSL = `
|
|
|
291
302
|
const FRAGMENT_SHADER_WGSL = `
|
|
292
303
|
struct VIB3Uniforms {
|
|
293
304
|
time: f32,
|
|
294
|
-
|
|
305
|
+
_pad0: f32,
|
|
295
306
|
resolution: vec2<f32>,
|
|
296
307
|
geometry: f32,
|
|
297
308
|
rot4dXY: f32,
|
|
@@ -304,18 +315,24 @@ struct VIB3Uniforms {
|
|
|
304
315
|
gridDensity: f32,
|
|
305
316
|
morphFactor: f32,
|
|
306
317
|
chaos: f32,
|
|
318
|
+
speed: f32,
|
|
307
319
|
hue: f32,
|
|
308
320
|
intensity: f32,
|
|
309
321
|
saturation: f32,
|
|
310
322
|
mouseIntensity: f32,
|
|
311
323
|
clickIntensity: f32,
|
|
312
|
-
roleIntensity: f32,
|
|
313
324
|
bass: f32,
|
|
314
325
|
mid: f32,
|
|
315
326
|
high: f32,
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
_pad1:
|
|
327
|
+
layerScale: f32,
|
|
328
|
+
layerOpacity: f32,
|
|
329
|
+
_pad1: f32,
|
|
330
|
+
layerColorR: f32,
|
|
331
|
+
layerColorG: f32,
|
|
332
|
+
layerColorB: f32,
|
|
333
|
+
densityMult: f32,
|
|
334
|
+
speedMult: f32,
|
|
335
|
+
breath: f32, // Index 32
|
|
319
336
|
};
|
|
320
337
|
|
|
321
338
|
@group(0) @binding(0) var<uniform> u: VIB3Uniforms;
|
|
@@ -406,7 +423,7 @@ fn warpHypertetraCore_w(p: vec3<f32>, geomIdx: i32) -> vec3<f32> {
|
|
|
406
423
|
fn applyCoreWarp_w(p: vec3<f32>, geomType: f32, mouseDelta: vec2<f32>) -> vec3<f32> {
|
|
407
424
|
let coreFloat = floor(geomType / 8.0);
|
|
408
425
|
let coreIndex = i32(clamp(coreFloat, 0.0, 2.0));
|
|
409
|
-
let baseFloat = geomType -
|
|
426
|
+
let baseFloat = geomType - floor(geomType / 8.0) * 8.0;
|
|
410
427
|
let geomIdx = i32(clamp(floor(baseFloat + 0.5), 0.0, 7.0));
|
|
411
428
|
if (coreIndex == 1) { return warpHypersphereCore_w(p, geomIdx); }
|
|
412
429
|
if (coreIndex == 2) { return warpHypertetraCore_w(p, geomIdx); }
|
|
@@ -418,8 +435,15 @@ fn geometryFunction_w(p: vec4<f32>) -> f32 {
|
|
|
418
435
|
let gt = i32(clamp(floor(baseFloat + 0.5), 0.0, 7.0));
|
|
419
436
|
let d = u.gridDensity * 0.08;
|
|
420
437
|
if (gt == 0) {
|
|
421
|
-
|
|
422
|
-
|
|
438
|
+
// Tetrahedron — tetrahedral symmetry planes
|
|
439
|
+
let c1 = normalize(vec3<f32>(1.0, 1.0, 1.0));
|
|
440
|
+
let c2 = normalize(vec3<f32>(-1.0, -1.0, 1.0));
|
|
441
|
+
let c3 = normalize(vec3<f32>(-1.0, 1.0, -1.0));
|
|
442
|
+
let c4 = normalize(vec3<f32>(1.0, -1.0, -1.0));
|
|
443
|
+
let q = fract(p.xyz * d + 0.5) - 0.5;
|
|
444
|
+
let minPlane = min(min(abs(dot(q, c1)), abs(dot(q, c2))),
|
|
445
|
+
min(abs(dot(q, c3)), abs(dot(q, c4))));
|
|
446
|
+
return (1.0 - smoothstep(0.0, 0.05, minPlane)) * u.morphFactor;
|
|
423
447
|
} else if (gt == 1) {
|
|
424
448
|
let pos = fract(p * d); let dist = min(pos, 1.0 - pos);
|
|
425
449
|
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u.morphFactor;
|
|
@@ -459,7 +483,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
459
483
|
let timeSpeed = u.time * 0.0001 * u.speed;
|
|
460
484
|
|
|
461
485
|
var pos = vec4<f32>(uv2 * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
462
|
-
pos = vec4<f32>(pos.xy + (
|
|
486
|
+
pos = vec4<f32>(pos.xy + (vec2<f32>(0.5, 0.5) - 0.5) * u.mouseIntensity * 2.0, pos.z, pos.w);
|
|
463
487
|
|
|
464
488
|
pos = rotateXY_w(u.rot4dXY) * pos;
|
|
465
489
|
pos = rotateXZ_w(u.rot4dXZ) * pos;
|
|
@@ -469,7 +493,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
469
493
|
pos = rotateZW_w(u.rot4dZW) * pos;
|
|
470
494
|
|
|
471
495
|
let basePoint = project4Dto3D_w(pos);
|
|
472
|
-
let warpedPoint = applyCoreWarp_w(basePoint, u.geometry,
|
|
496
|
+
let warpedPoint = applyCoreWarp_w(basePoint, u.geometry, vec2<f32>(0.0, 0.0));
|
|
473
497
|
let warpedPos = vec4<f32>(warpedPoint, pos.w);
|
|
474
498
|
var value = geometryFunction_w(warpedPos);
|
|
475
499
|
|
|
@@ -478,7 +502,10 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
478
502
|
|
|
479
503
|
var geomIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
480
504
|
geomIntensity += u.clickIntensity * 0.3;
|
|
481
|
-
|
|
505
|
+
|
|
506
|
+
// Vitality (Breath) modulation
|
|
507
|
+
let breathMod = 1.0 + (u.breath * 0.3);
|
|
508
|
+
let finalIntensity = geomIntensity * u.intensity * breathMod;
|
|
482
509
|
|
|
483
510
|
let hueVal = u.hue / 360.0 + value * 0.1 + u.high * 0.08;
|
|
484
511
|
let baseColor = vec3<f32>(
|
|
@@ -488,7 +515,7 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
488
515
|
let gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
489
516
|
let color = mix(vec3<f32>(gray), baseColor, u.saturation) * finalIntensity;
|
|
490
517
|
|
|
491
|
-
return vec4<f32>(color, finalIntensity
|
|
518
|
+
return vec4<f32>(color, finalIntensity);
|
|
492
519
|
}
|
|
493
520
|
`;
|
|
494
521
|
|
|
@@ -498,466 +525,305 @@ fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
|
498
525
|
|
|
499
526
|
export class FacetedSystem {
|
|
500
527
|
constructor() {
|
|
528
|
+
this.bridge = null;
|
|
501
529
|
this.canvas = null;
|
|
502
530
|
this.gl = null;
|
|
503
531
|
this.program = null;
|
|
504
|
-
this.
|
|
505
|
-
this.
|
|
506
|
-
this.
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
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';
|
|
532
|
+
this.params = {};
|
|
533
|
+
this.initialized = false;
|
|
534
|
+
this.contextLost = false;
|
|
535
|
+
this._animFrame = null;
|
|
536
|
+
this._time = 0;
|
|
537
|
+
this._running = false;
|
|
538
|
+
this._quadBuffer = null;
|
|
539
|
+
this._uniformLocations = {};
|
|
540
|
+
this._useDirectGL = false;
|
|
533
541
|
}
|
|
534
542
|
|
|
543
|
+
// ─── Synchronous Direct WebGL Init (matches Quantum/Holographic pattern) ───
|
|
544
|
+
|
|
535
545
|
/**
|
|
536
|
-
* Initialize with
|
|
537
|
-
*
|
|
538
|
-
*
|
|
539
|
-
* @param {boolean} [options.preferWebGPU=true]
|
|
540
|
-
* @param {boolean} [options.debug=false]
|
|
541
|
-
* @returns {Promise<boolean>}
|
|
546
|
+
* Initialize directly with WebGL on a given canvas.
|
|
547
|
+
* Synchronous — no async bridge, no WebGPU.
|
|
548
|
+
* This is the preferred path for the landing page and adapters.
|
|
542
549
|
*/
|
|
543
|
-
|
|
550
|
+
initDirect(canvas) {
|
|
544
551
|
this.canvas = canvas;
|
|
545
552
|
try {
|
|
546
|
-
this.
|
|
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;
|
|
553
|
+
this.gl = canvas.getContext('webgl2') || canvas.getContext('webgl');
|
|
580
554
|
} catch (e) {
|
|
581
|
-
console.
|
|
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']);
|
|
555
|
+
console.warn('FacetedSystem: WebGL context creation failed', e);
|
|
595
556
|
return false;
|
|
596
557
|
}
|
|
597
|
-
|
|
598
|
-
this.gl = this.canvas.getContext('webgl');
|
|
599
558
|
if (!this.gl) {
|
|
600
|
-
console.
|
|
559
|
+
console.warn('FacetedSystem: WebGL not available');
|
|
601
560
|
return false;
|
|
602
561
|
}
|
|
603
562
|
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
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');
|
|
563
|
+
// Compile shader program
|
|
564
|
+
this.program = this._compileProgram(this.gl, VERTEX_SHADER_GLSL, FRAGMENT_SHADER_GLSL);
|
|
565
|
+
if (!this.program) {
|
|
566
|
+
console.error('FacetedSystem: Shader compilation failed');
|
|
622
567
|
return false;
|
|
623
568
|
}
|
|
624
569
|
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
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);
|
|
570
|
+
// Create fullscreen quad buffer
|
|
571
|
+
const vertices = new Float32Array([-1,-1, 1,-1, -1,1, -1,1, 1,-1, 1,1]);
|
|
572
|
+
this._quadBuffer = this.gl.createBuffer();
|
|
573
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this._quadBuffer);
|
|
642
574
|
this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
|
|
643
575
|
|
|
576
|
+
// Cache uniform locations
|
|
577
|
+
const gl = this.gl;
|
|
578
|
+
const numUniforms = gl.getProgramParameter(this.program, gl.ACTIVE_UNIFORMS);
|
|
579
|
+
for (let i = 0; i < numUniforms; i++) {
|
|
580
|
+
const info = gl.getActiveUniform(this.program, i);
|
|
581
|
+
if (info) {
|
|
582
|
+
this._uniformLocations[info.name] = gl.getUniformLocation(this.program, info.name);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
this._useDirectGL = true;
|
|
587
|
+
this.initialized = true;
|
|
588
|
+
this.start();
|
|
644
589
|
return true;
|
|
645
590
|
}
|
|
646
591
|
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
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;
|
|
592
|
+
_compileProgram(gl, vertexSrc, fragmentSrc) {
|
|
593
|
+
const vs = this._compileShader(gl, gl.VERTEX_SHADER, vertexSrc);
|
|
594
|
+
const fs = this._compileShader(gl, gl.FRAGMENT_SHADER, fragmentSrc);
|
|
595
|
+
if (!vs || !fs) return null;
|
|
655
596
|
|
|
656
|
-
const program =
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
597
|
+
const program = gl.createProgram();
|
|
598
|
+
gl.attachShader(program, vs);
|
|
599
|
+
gl.attachShader(program, fs);
|
|
600
|
+
gl.linkProgram(program);
|
|
660
601
|
|
|
661
|
-
if (!
|
|
662
|
-
console.error('
|
|
602
|
+
if (!gl.getProgramParameter(program, gl.LINK_STATUS)) {
|
|
603
|
+
console.error('FacetedSystem link error:', gl.getProgramInfoLog(program));
|
|
663
604
|
return null;
|
|
664
605
|
}
|
|
665
606
|
|
|
607
|
+
gl.deleteShader(vs);
|
|
608
|
+
gl.deleteShader(fs);
|
|
666
609
|
return program;
|
|
667
610
|
}
|
|
668
611
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
678
|
-
console.error('Shader compile error:', this.gl.getShaderInfoLog(shader));
|
|
612
|
+
_compileShader(gl, type, source) {
|
|
613
|
+
const shader = gl.createShader(type);
|
|
614
|
+
gl.shaderSource(shader, source);
|
|
615
|
+
gl.compileShader(shader);
|
|
616
|
+
if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) {
|
|
617
|
+
console.error('FacetedSystem shader error:', gl.getShaderInfoLog(shader));
|
|
618
|
+
gl.deleteShader(shader);
|
|
679
619
|
return null;
|
|
680
620
|
}
|
|
681
|
-
|
|
682
621
|
return shader;
|
|
683
622
|
}
|
|
684
623
|
|
|
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
|
-
}
|
|
624
|
+
// ─── Async Bridge Init (for SDK/WebGPU usage) ───
|
|
696
625
|
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
626
|
+
async initWithBridge(canvas, options) {
|
|
627
|
+
this.canvas = canvas;
|
|
628
|
+
try {
|
|
629
|
+
this.bridge = await UnifiedRenderBridge.create(canvas, options);
|
|
630
|
+
if (this.bridge) {
|
|
631
|
+
const success = this.bridge.compileShader('faceted', {
|
|
632
|
+
glslVertex: VERTEX_SHADER_GLSL,
|
|
633
|
+
glslFragment: FRAGMENT_SHADER_GLSL,
|
|
634
|
+
wgslFragment: FRAGMENT_SHADER_WGSL
|
|
635
|
+
});
|
|
636
|
+
if (!success) {
|
|
637
|
+
console.error("Faceted shader compilation failed");
|
|
638
|
+
return false;
|
|
639
|
+
}
|
|
640
|
+
this.initialized = true;
|
|
641
|
+
this.start();
|
|
642
|
+
return true;
|
|
643
|
+
}
|
|
644
|
+
} catch (e) {
|
|
645
|
+
console.error("Faceted initWithBridge failed:", e);
|
|
646
|
+
}
|
|
647
|
+
return false;
|
|
712
648
|
}
|
|
713
649
|
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
650
|
+
async initialize(options = {}) {
|
|
651
|
+
if (this.initialized) return true;
|
|
652
|
+
const canvas = options.canvas ||
|
|
653
|
+
document.getElementById('faceted-content-canvas') ||
|
|
654
|
+
document.getElementById('content-canvas');
|
|
655
|
+
if (!canvas) {
|
|
656
|
+
console.warn("FacetedSystem: No canvas found for initialize()");
|
|
657
|
+
return false;
|
|
722
658
|
}
|
|
659
|
+
return this.initWithBridge(canvas, {
|
|
660
|
+
preferWebGPU: options.preferWebGPU !== undefined ? options.preferWebGPU : true,
|
|
661
|
+
debug: options.debug || false
|
|
662
|
+
});
|
|
723
663
|
}
|
|
724
664
|
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
if (this._renderMode === 'bridge' && this._bridge) {
|
|
731
|
-
return this._bridge.getBackendType();
|
|
732
|
-
}
|
|
733
|
-
return 'direct-webgl';
|
|
665
|
+
// ─── Parameters ───
|
|
666
|
+
|
|
667
|
+
updateParameters(params) {
|
|
668
|
+
if (!params) return;
|
|
669
|
+
this.params = { ...this.params, ...params };
|
|
734
670
|
}
|
|
735
671
|
|
|
736
672
|
/**
|
|
737
|
-
* Build uniform object for
|
|
738
|
-
* @private
|
|
673
|
+
* Build the uniform object with proper u_ prefixed names for the shader.
|
|
739
674
|
*/
|
|
740
675
|
_buildUniforms() {
|
|
676
|
+
const p = this.params;
|
|
741
677
|
return {
|
|
742
|
-
u_time: this.
|
|
743
|
-
u_resolution: [this.canvas
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
678
|
+
u_time: this._time,
|
|
679
|
+
u_resolution: [this.canvas?.width || 800, this.canvas?.height || 600],
|
|
680
|
+
u_geometry: p.geometry ?? 0,
|
|
681
|
+
u_rot4dXY: p.rot4dXY ?? 0,
|
|
682
|
+
u_rot4dXZ: p.rot4dXZ ?? 0,
|
|
683
|
+
u_rot4dYZ: p.rot4dYZ ?? 0,
|
|
684
|
+
u_rot4dXW: p.rot4dXW ?? 0,
|
|
685
|
+
u_rot4dYW: p.rot4dYW ?? 0,
|
|
686
|
+
u_rot4dZW: p.rot4dZW ?? 0,
|
|
687
|
+
u_dimension: p.dimension ?? 3.5,
|
|
688
|
+
u_gridDensity: p.gridDensity ?? 15,
|
|
689
|
+
u_morphFactor: p.morphFactor ?? 1.0,
|
|
690
|
+
u_chaos: p.chaos ?? 0.2,
|
|
691
|
+
u_speed: p.speed ?? 1.0,
|
|
692
|
+
u_hue: p.hue ?? 200,
|
|
693
|
+
u_intensity: p.intensity ?? 0.7,
|
|
694
|
+
u_saturation: p.saturation ?? 0.8,
|
|
695
|
+
u_mouseIntensity: p.mouseIntensity ?? 0,
|
|
696
|
+
u_clickIntensity: p.clickIntensity ?? 0,
|
|
697
|
+
u_bass: p.bass ?? 0,
|
|
698
|
+
u_mid: p.mid ?? 0,
|
|
699
|
+
u_high: p.high ?? 0,
|
|
700
|
+
u_breath: p.breath ?? 0,
|
|
701
|
+
u_mouse: p.mouse ?? [0.5, 0.5],
|
|
766
702
|
};
|
|
767
703
|
}
|
|
768
704
|
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
this._bridge.setUniforms(this._buildUniforms());
|
|
776
|
-
this._bridge.render('faceted');
|
|
705
|
+
// ─── Render Loop ───
|
|
706
|
+
|
|
707
|
+
start() {
|
|
708
|
+
if (this._running) return;
|
|
709
|
+
this._running = true;
|
|
710
|
+
this._renderLoop();
|
|
777
711
|
}
|
|
778
712
|
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
if (!this.gl || !this.program || this._contextLost) return;
|
|
785
|
-
if (this.gl.isContextLost()) {
|
|
786
|
-
this._contextLost = true;
|
|
787
|
-
return;
|
|
713
|
+
stop() {
|
|
714
|
+
this._running = false;
|
|
715
|
+
if (this._animFrame) {
|
|
716
|
+
cancelAnimationFrame(this._animFrame);
|
|
717
|
+
this._animFrame = null;
|
|
788
718
|
}
|
|
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
719
|
}
|
|
816
720
|
|
|
817
|
-
|
|
818
|
-
|
|
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
|
-
}
|
|
721
|
+
_renderLoop() {
|
|
722
|
+
if (!this._running) return;
|
|
829
723
|
|
|
830
|
-
this.
|
|
724
|
+
this._time += 16.0 * (this.params.speed ?? 1.0);
|
|
831
725
|
|
|
832
|
-
if (this.
|
|
833
|
-
this.
|
|
834
|
-
} else {
|
|
835
|
-
this.
|
|
726
|
+
if (this._useDirectGL) {
|
|
727
|
+
this._renderDirectGL();
|
|
728
|
+
} else if (this.bridge) {
|
|
729
|
+
this.bridge.setUniforms(this._buildUniforms());
|
|
730
|
+
this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
|
|
836
731
|
}
|
|
732
|
+
|
|
733
|
+
this._animFrame = requestAnimationFrame(() => this._renderLoop());
|
|
837
734
|
}
|
|
838
735
|
|
|
839
736
|
/**
|
|
840
|
-
*
|
|
737
|
+
* Direct WebGL rendering — no bridge, just raw GL calls.
|
|
738
|
+
* Matches the original working FacetedSystem pattern.
|
|
841
739
|
*/
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
if (
|
|
845
|
-
Object.assign(this.parameters, frameState.params);
|
|
846
|
-
}
|
|
847
|
-
if (typeof frameState.time === 'number') {
|
|
848
|
-
this.time = frameState.time;
|
|
849
|
-
}
|
|
740
|
+
_renderDirectGL() {
|
|
741
|
+
const gl = this.gl;
|
|
742
|
+
if (!gl || !this.program) return;
|
|
850
743
|
|
|
851
|
-
this.
|
|
744
|
+
gl.useProgram(this.program);
|
|
745
|
+
gl.enable(gl.BLEND);
|
|
746
|
+
gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA);
|
|
747
|
+
gl.clearColor(0, 0, 0, 1);
|
|
748
|
+
gl.clear(gl.COLOR_BUFFER_BIT);
|
|
852
749
|
|
|
853
|
-
|
|
854
|
-
|
|
750
|
+
// Set uniforms
|
|
751
|
+
const uniforms = this._buildUniforms();
|
|
752
|
+
for (const [name, value] of Object.entries(uniforms)) {
|
|
753
|
+
const loc = this._uniformLocations[name];
|
|
754
|
+
if (loc === null || loc === undefined) continue;
|
|
755
|
+
if (Array.isArray(value)) {
|
|
756
|
+
if (value.length === 2) gl.uniform2fv(loc, value);
|
|
757
|
+
else if (value.length === 3) gl.uniform3fv(loc, value);
|
|
758
|
+
else if (value.length === 4) gl.uniform4fv(loc, value);
|
|
759
|
+
} else {
|
|
760
|
+
gl.uniform1f(loc, value);
|
|
761
|
+
}
|
|
855
762
|
}
|
|
856
|
-
}
|
|
857
763
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
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
|
-
}
|
|
764
|
+
// Draw fullscreen quad
|
|
765
|
+
gl.bindBuffer(gl.ARRAY_BUFFER, this._quadBuffer);
|
|
766
|
+
const posLoc = gl.getAttribLocation(this.program, 'a_position');
|
|
767
|
+
if (posLoc >= 0) {
|
|
768
|
+
gl.enableVertexAttribArray(posLoc);
|
|
769
|
+
gl.vertexAttribPointer(posLoc, 2, gl.FLOAT, false, 0, 0);
|
|
868
770
|
}
|
|
771
|
+
gl.drawArrays(gl.TRIANGLES, 0, 6);
|
|
869
772
|
}
|
|
870
773
|
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
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
|
-
});
|
|
774
|
+
render() {
|
|
775
|
+
if (this._useDirectGL) {
|
|
776
|
+
this._renderDirectGL();
|
|
777
|
+
} else if (this.bridge) {
|
|
778
|
+
this.bridge.setUniforms(this._buildUniforms());
|
|
779
|
+
this.bridge.render('faceted', { clear: true, clearColor: [0, 0, 0, 1] });
|
|
890
780
|
}
|
|
781
|
+
}
|
|
891
782
|
|
|
892
|
-
|
|
783
|
+
getBackendType() {
|
|
784
|
+
if (this._useDirectGL) return 'webgl';
|
|
785
|
+
return this.bridge ? this.bridge.getBackendType() : 'none';
|
|
893
786
|
}
|
|
894
787
|
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
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
|
-
}
|
|
788
|
+
setActive(active) {
|
|
789
|
+
if (active) this.start();
|
|
790
|
+
else this.stop();
|
|
791
|
+
const layer = document.getElementById('faceted-layer');
|
|
792
|
+
if (layer) layer.style.display = active ? 'block' : 'none';
|
|
913
793
|
}
|
|
914
794
|
|
|
915
|
-
|
|
916
|
-
* Clean up all resources (RendererContract.dispose)
|
|
917
|
-
*/
|
|
918
|
-
dispose() {
|
|
919
|
-
this.isActive = false;
|
|
795
|
+
init(context = {}) { return this.initialize(context); }
|
|
920
796
|
|
|
921
|
-
|
|
797
|
+
resize(width, height, pixelRatio = 1) {
|
|
798
|
+
const w = Math.floor(width * pixelRatio);
|
|
799
|
+
const h = Math.floor(height * pixelRatio);
|
|
922
800
|
if (this.canvas) {
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
}
|
|
926
|
-
if (this._onContextRestored) {
|
|
927
|
-
this.canvas.removeEventListener('webglcontextrestored', this._onContextRestored);
|
|
928
|
-
}
|
|
801
|
+
this.canvas.width = w;
|
|
802
|
+
this.canvas.height = h;
|
|
929
803
|
}
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
this.
|
|
804
|
+
if (this._useDirectGL && this.gl) {
|
|
805
|
+
this.gl.viewport(0, 0, w, h);
|
|
806
|
+
} else if (this.bridge && this.bridge.resize) {
|
|
807
|
+
this.bridge.resize(width, height, pixelRatio);
|
|
934
808
|
}
|
|
809
|
+
}
|
|
935
810
|
|
|
936
|
-
|
|
937
|
-
if (this.program) {
|
|
938
|
-
this.gl.deleteProgram(this.program);
|
|
939
|
-
}
|
|
940
|
-
}
|
|
941
|
-
this.program = null;
|
|
811
|
+
dispose() { this.destroy(); }
|
|
942
812
|
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
813
|
+
destroy() {
|
|
814
|
+
this.stop();
|
|
815
|
+
if (this._useDirectGL && this.gl) {
|
|
816
|
+
if (this.program) this.gl.deleteProgram(this.program);
|
|
817
|
+
if (this._quadBuffer) this.gl.deleteBuffer(this._quadBuffer);
|
|
948
818
|
this.gl = null;
|
|
819
|
+
this.program = null;
|
|
820
|
+
this._quadBuffer = null;
|
|
949
821
|
}
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
/**
|
|
958
|
-
* Alias for dispose (for backward compatibility)
|
|
959
|
-
*/
|
|
960
|
-
destroy() {
|
|
961
|
-
this.dispose();
|
|
822
|
+
if (this.bridge) {
|
|
823
|
+
this.bridge.dispose();
|
|
824
|
+
this.bridge = null;
|
|
825
|
+
}
|
|
826
|
+
this.initialized = false;
|
|
827
|
+
this._useDirectGL = false;
|
|
962
828
|
}
|
|
963
829
|
}
|