@vib3code/sdk 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +118 -0
- package/DOCS/BLUEPRINT_EXECUTION_PLAN_2026-01-07.md +34 -0
- package/DOCS/CI_TESTING.md +38 -0
- package/DOCS/CLI_ONBOARDING.md +75 -0
- package/DOCS/CONTROL_REFERENCE.md +64 -0
- package/DOCS/DEV_TRACK_ANALYSIS.md +77 -0
- package/DOCS/DEV_TRACK_PLAN_2026-01-07.md +42 -0
- package/DOCS/DEV_TRACK_SESSION_2026-01-31.md +220 -0
- package/DOCS/ENV_SETUP.md +189 -0
- package/DOCS/EXPORT_FORMATS.md +417 -0
- package/DOCS/GPU_DISPOSAL_GUIDE.md +21 -0
- package/DOCS/LICENSING_TIERS.md +275 -0
- package/DOCS/MASTER_PLAN_2026-01-31.md +570 -0
- package/DOCS/OBS_SETUP_GUIDE.md +98 -0
- package/DOCS/PROJECT_SETUP.md +66 -0
- package/DOCS/RENDERER_LIFECYCLE.md +40 -0
- package/DOCS/REPO_MANIFEST.md +121 -0
- package/DOCS/SESSION_014_PLAN.md +195 -0
- package/DOCS/SESSION_LOG_2026-01-07.md +56 -0
- package/DOCS/STRATEGIC_BLUEPRINT_2026-01-07.md +72 -0
- package/DOCS/SYSTEM_AUDIT_2026-01-30.md +738 -0
- package/DOCS/SYSTEM_INVENTORY.md +520 -0
- package/DOCS/TELEMETRY_EXPORTS.md +34 -0
- package/DOCS/WEBGPU_STATUS.md +38 -0
- package/DOCS/XR_BENCHMARKS.md +608 -0
- package/LICENSE +21 -0
- package/README.md +426 -0
- package/docs/.nojekyll +0 -0
- package/docs/01-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/02-hyperspatial_ego_death.html +346 -0
- package/docs/03-post_cartesian_sublime.html +346 -0
- package/docs/04-crystalline_void_meditation.html +346 -0
- package/docs/05-quantum_decoherence_ballet.html +346 -0
- package/docs/06-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/07-hyperspatial_ego_death.html +346 -0
- package/docs/08-post_cartesian_sublime.html +346 -0
- package/docs/09-crystalline_void_meditation.html +346 -0
- package/docs/10-quantum_decoherence_ballet.html +346 -0
- package/docs/11-dissolution_of_euclidean_hegemony.html +346 -0
- package/docs/12-hyperspatial_ego_death.html +346 -0
- package/docs/13-post_cartesian_sublime.html +346 -0
- package/docs/index.html +794 -0
- package/docs/test-hub.html +441 -0
- package/docs/url-state.js +102 -0
- package/docs/vib3-exports/01-quantum-quantum-tetrahedron-lattice.html +489 -0
- package/docs/vib3-exports/02-quantum-quantum-hypersphere-matrix.html +489 -0
- package/docs/vib3-exports/03-quantum-quantum-hypertetra-fractal.html +489 -0
- package/docs/vib3-exports/04-faceted-faceted-crystal-structure.html +407 -0
- package/docs/vib3-exports/05-faceted-faceted-klein-bottle.html +407 -0
- package/docs/vib3-exports/06-faceted-faceted-hypertetra-torus.html +407 -0
- package/docs/vib3-exports/07-holographic-holographic-wave-field.html +457 -0
- package/docs/vib3-exports/08-holographic-holographic-hypersphere-sphere.html +457 -0
- package/docs/vib3-exports/09-holographic-holographic-hypertetra-crystal.html +457 -0
- package/docs/vib3-exports/index.html +238 -0
- package/docs/webgpu-live.html +702 -0
- package/package.json +367 -0
- package/src/advanced/AIPresetGenerator.js +777 -0
- package/src/advanced/MIDIController.js +703 -0
- package/src/advanced/OffscreenWorker.js +1051 -0
- package/src/advanced/WebGPUCompute.js +1051 -0
- package/src/advanced/WebXRRenderer.js +680 -0
- package/src/agent/cli/AgentCLI.js +615 -0
- package/src/agent/cli/index.js +14 -0
- package/src/agent/index.js +73 -0
- package/src/agent/mcp/MCPServer.js +950 -0
- package/src/agent/mcp/index.js +9 -0
- package/src/agent/mcp/tools.js +548 -0
- package/src/agent/telemetry/EventStream.js +669 -0
- package/src/agent/telemetry/Instrumentation.js +618 -0
- package/src/agent/telemetry/TelemetryExporters.js +427 -0
- package/src/agent/telemetry/TelemetryService.js +464 -0
- package/src/agent/telemetry/index.js +52 -0
- package/src/benchmarks/BenchmarkRunner.js +381 -0
- package/src/benchmarks/MetricsCollector.js +299 -0
- package/src/benchmarks/index.js +9 -0
- package/src/benchmarks/scenes.js +259 -0
- package/src/cli/index.js +675 -0
- package/src/config/ApiConfig.js +88 -0
- package/src/core/CanvasManager.js +217 -0
- package/src/core/ErrorReporter.js +117 -0
- package/src/core/ParameterMapper.js +333 -0
- package/src/core/Parameters.js +396 -0
- package/src/core/RendererContracts.js +200 -0
- package/src/core/UnifiedResourceManager.js +370 -0
- package/src/core/VIB3Engine.js +636 -0
- package/src/core/renderers/FacetedRendererAdapter.js +32 -0
- package/src/core/renderers/HolographicRendererAdapter.js +29 -0
- package/src/core/renderers/QuantumRendererAdapter.js +29 -0
- package/src/core/renderers/RendererLifecycleManager.js +63 -0
- package/src/creative/ColorPresetsSystem.js +980 -0
- package/src/creative/ParameterTimeline.js +1061 -0
- package/src/creative/PostProcessingPipeline.js +1113 -0
- package/src/creative/TransitionAnimator.js +683 -0
- package/src/export/CSSExporter.js +226 -0
- package/src/export/CardGeneratorBase.js +279 -0
- package/src/export/ExportManager.js +580 -0
- package/src/export/FacetedCardGenerator.js +279 -0
- package/src/export/HolographicCardGenerator.js +543 -0
- package/src/export/LottieExporter.js +552 -0
- package/src/export/QuantumCardGenerator.js +315 -0
- package/src/export/SVGExporter.js +519 -0
- package/src/export/ShaderExporter.js +903 -0
- package/src/export/TradingCardGenerator.js +3055 -0
- package/src/export/TradingCardManager.js +181 -0
- package/src/export/VIB3PackageExporter.js +559 -0
- package/src/export/index.js +14 -0
- package/src/export/systems/TradingCardSystemFaceted.js +494 -0
- package/src/export/systems/TradingCardSystemHolographic.js +452 -0
- package/src/export/systems/TradingCardSystemQuantum.js +411 -0
- package/src/faceted/FacetedSystem.js +963 -0
- package/src/features/CollectionManager.js +433 -0
- package/src/gallery/CollectionManager.js +240 -0
- package/src/gallery/GallerySystem.js +485 -0
- package/src/geometry/GeometryFactory.js +314 -0
- package/src/geometry/GeometryLibrary.js +72 -0
- package/src/geometry/buffers/BufferBuilder.js +338 -0
- package/src/geometry/buffers/index.js +18 -0
- package/src/geometry/generators/Crystal.js +420 -0
- package/src/geometry/generators/Fractal.js +298 -0
- package/src/geometry/generators/KleinBottle.js +197 -0
- package/src/geometry/generators/Sphere.js +192 -0
- package/src/geometry/generators/Tesseract.js +160 -0
- package/src/geometry/generators/Tetrahedron.js +225 -0
- package/src/geometry/generators/Torus.js +304 -0
- package/src/geometry/generators/Wave.js +341 -0
- package/src/geometry/index.js +142 -0
- package/src/geometry/warp/HypersphereCore.js +211 -0
- package/src/geometry/warp/HypertetraCore.js +386 -0
- package/src/geometry/warp/index.js +57 -0
- package/src/holograms/HolographicVisualizer.js +1073 -0
- package/src/holograms/RealHolographicSystem.js +966 -0
- package/src/holograms/variantRegistry.js +69 -0
- package/src/integrations/FigmaPlugin.js +854 -0
- package/src/integrations/OBSMode.js +754 -0
- package/src/integrations/ThreeJsPackage.js +660 -0
- package/src/integrations/TouchDesignerExport.js +552 -0
- package/src/integrations/frameworks/Vib3React.js +591 -0
- package/src/integrations/frameworks/Vib3Svelte.js +654 -0
- package/src/integrations/frameworks/Vib3Vue.js +628 -0
- package/src/llm/LLMParameterInterface.js +240 -0
- package/src/llm/LLMParameterUI.js +577 -0
- package/src/math/Mat4x4.js +708 -0
- package/src/math/Projection.js +341 -0
- package/src/math/Rotor4D.js +637 -0
- package/src/math/Vec4.js +476 -0
- package/src/math/constants.js +164 -0
- package/src/math/index.js +68 -0
- package/src/math/projections.js +54 -0
- package/src/math/rotations.js +196 -0
- package/src/quantum/QuantumEngine.js +906 -0
- package/src/quantum/QuantumVisualizer.js +1103 -0
- package/src/reactivity/ReactivityConfig.js +499 -0
- package/src/reactivity/ReactivityManager.js +586 -0
- package/src/reactivity/SpatialInputSystem.js +1783 -0
- package/src/reactivity/index.js +93 -0
- package/src/render/CommandBuffer.js +465 -0
- package/src/render/MultiCanvasBridge.js +340 -0
- package/src/render/RenderCommand.js +514 -0
- package/src/render/RenderResourceRegistry.js +523 -0
- package/src/render/RenderState.js +552 -0
- package/src/render/RenderTarget.js +512 -0
- package/src/render/ShaderLoader.js +253 -0
- package/src/render/ShaderProgram.js +599 -0
- package/src/render/UnifiedRenderBridge.js +496 -0
- package/src/render/backends/WebGLBackend.js +1108 -0
- package/src/render/backends/WebGPUBackend.js +1409 -0
- package/src/render/commands/CommandBufferExecutor.js +607 -0
- package/src/render/commands/RenderCommandBuffer.js +661 -0
- package/src/render/commands/index.js +17 -0
- package/src/render/index.js +367 -0
- package/src/scene/Disposable.js +498 -0
- package/src/scene/MemoryPool.js +618 -0
- package/src/scene/Node4D.js +697 -0
- package/src/scene/ResourceManager.js +599 -0
- package/src/scene/Scene4D.js +540 -0
- package/src/scene/index.js +98 -0
- package/src/schemas/error.schema.json +84 -0
- package/src/schemas/extension.schema.json +88 -0
- package/src/schemas/index.js +214 -0
- package/src/schemas/parameters.schema.json +142 -0
- package/src/schemas/tool-pack.schema.json +44 -0
- package/src/schemas/tool-response.schema.json +127 -0
- package/src/shaders/common/fullscreen.vert.glsl +5 -0
- package/src/shaders/common/fullscreen.vert.wgsl +17 -0
- package/src/shaders/common/geometry24.glsl +65 -0
- package/src/shaders/common/geometry24.wgsl +54 -0
- package/src/shaders/common/rotation4d.glsl +85 -0
- package/src/shaders/common/rotation4d.wgsl +86 -0
- package/src/shaders/common/uniforms.glsl +44 -0
- package/src/shaders/common/uniforms.wgsl +48 -0
- package/src/shaders/faceted/faceted.frag.glsl +129 -0
- package/src/shaders/faceted/faceted.frag.wgsl +164 -0
- package/src/shaders/holographic/holographic.frag.glsl +406 -0
- package/src/shaders/holographic/holographic.frag.wgsl +185 -0
- package/src/shaders/quantum/quantum.frag.glsl +513 -0
- package/src/shaders/quantum/quantum.frag.wgsl +361 -0
- package/src/testing/ParallelTestFramework.js +519 -0
- package/src/testing/__snapshots__/exportFormats.test.js.snap +24 -0
- package/src/testing/exportFormats.test.js +8 -0
- package/src/testing/projections.test.js +14 -0
- package/src/testing/rotations.test.js +37 -0
- package/src/ui/InteractivityMenu.js +516 -0
- package/src/ui/StatusManager.js +96 -0
- package/src/ui/adaptive/renderers/webgpu/BufferLayout.ts +252 -0
- package/src/ui/adaptive/renderers/webgpu/PolytopeInstanceBuffer.ts +144 -0
- package/src/ui/adaptive/renderers/webgpu/TripleBufferedUniform.ts +170 -0
- package/src/ui/adaptive/renderers/webgpu/WebGPURenderer.ts +735 -0
- package/src/ui/adaptive/renderers/webgpu/index.ts +112 -0
- package/src/variations/VariationManager.js +431 -0
- package/src/viewer/AudioReactivity.js +505 -0
- package/src/viewer/CardBending.js +481 -0
- package/src/viewer/GalleryUI.js +832 -0
- package/src/viewer/ReactivityManager.js +590 -0
- package/src/viewer/TradingCardExporter.js +600 -0
- package/src/viewer/ViewerPortal.js +374 -0
- package/src/viewer/index.js +12 -0
- package/src/wasm/WasmLoader.js +296 -0
- package/src/wasm/index.js +132 -0
- package/tools/agentic/mcpTools.js +88 -0
- package/tools/cli/agent-cli.js +92 -0
- package/tools/export/formats.js +24 -0
- package/tools/math/rotation-baseline.mjs +64 -0
- package/tools/shader-sync-verify.js +937 -0
- package/tools/telemetry/manifestPipeline.js +141 -0
- package/tools/telemetry/telemetryEvents.js +35 -0
- package/types/adaptive-sdk.d.ts +185 -0
- package/types/advanced/AIPresetGenerator.d.ts +81 -0
- package/types/advanced/MIDIController.d.ts +100 -0
- package/types/advanced/OffscreenWorker.d.ts +82 -0
- package/types/advanced/WebGPUCompute.d.ts +52 -0
- package/types/advanced/WebXRRenderer.d.ts +77 -0
- package/types/advanced/index.d.ts +46 -0
- package/types/core/ErrorReporter.d.ts +50 -0
- package/types/core/VIB3Engine.d.ts +204 -0
- package/types/creative/ColorPresetsSystem.d.ts +91 -0
- package/types/creative/ParameterTimeline.d.ts +74 -0
- package/types/creative/PostProcessingPipeline.d.ts +109 -0
- package/types/creative/TransitionAnimator.d.ts +71 -0
- package/types/creative/index.d.ts +35 -0
- package/types/integrations/FigmaPlugin.d.ts +46 -0
- package/types/integrations/OBSMode.d.ts +74 -0
- package/types/integrations/ThreeJsPackage.d.ts +62 -0
- package/types/integrations/TouchDesignerExport.d.ts +36 -0
- package/types/integrations/Vib3React.d.ts +74 -0
- package/types/integrations/Vib3Svelte.d.ts +63 -0
- package/types/integrations/Vib3Vue.d.ts +55 -0
- package/types/integrations/index.d.ts +52 -0
- package/types/reactivity/SpatialInputSystem.d.ts +173 -0
- package/types/reactivity/index.d.ts +394 -0
- package/types/render/CommandBuffer.d.ts +169 -0
- package/types/render/RenderCommand.d.ts +312 -0
- package/types/render/RenderState.d.ts +279 -0
- package/types/render/RenderTarget.d.ts +254 -0
- package/types/render/ShaderProgram.d.ts +277 -0
- package/types/render/UnifiedRenderBridge.d.ts +143 -0
- package/types/render/WebGLBackend.d.ts +168 -0
- package/types/render/WebGPUBackend.d.ts +186 -0
- package/types/render/index.d.ts +141 -0
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Faceted System - Clean 2D Geometric Patterns with 4D Rotation
|
|
3
|
+
* Supports 24 geometry variants: 8 base + 8 Hypersphere Core + 8 Hypertetrahedron Core
|
|
4
|
+
* Full 6D rotation mathematics (XY, XZ, YZ, XW, YW, ZW)
|
|
5
|
+
*
|
|
6
|
+
* Supports both WebGL (direct) and WebGPU (via UnifiedRenderBridge).
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { UnifiedRenderBridge } from '../render/UnifiedRenderBridge.js';
|
|
10
|
+
import { shaderLoader } from '../render/ShaderLoader.js';
|
|
11
|
+
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Shader Sources
|
|
14
|
+
// ============================================================================
|
|
15
|
+
|
|
16
|
+
const VERTEX_SHADER_GLSL = `
|
|
17
|
+
attribute vec2 a_position;
|
|
18
|
+
void main() {
|
|
19
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
20
|
+
}
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const FRAGMENT_SHADER_GLSL = `
|
|
24
|
+
precision highp float;
|
|
25
|
+
|
|
26
|
+
uniform float u_time;
|
|
27
|
+
uniform vec2 u_resolution;
|
|
28
|
+
uniform vec2 u_mouse;
|
|
29
|
+
uniform float u_geometry; // 0-23
|
|
30
|
+
|
|
31
|
+
// 6D Rotation uniforms
|
|
32
|
+
uniform float u_rot4dXY;
|
|
33
|
+
uniform float u_rot4dXZ;
|
|
34
|
+
uniform float u_rot4dYZ;
|
|
35
|
+
uniform float u_rot4dXW;
|
|
36
|
+
uniform float u_rot4dYW;
|
|
37
|
+
uniform float u_rot4dZW;
|
|
38
|
+
|
|
39
|
+
uniform float u_dimension;
|
|
40
|
+
uniform float u_gridDensity;
|
|
41
|
+
uniform float u_morphFactor;
|
|
42
|
+
uniform float u_chaos;
|
|
43
|
+
uniform float u_speed;
|
|
44
|
+
uniform float u_hue;
|
|
45
|
+
uniform float u_intensity;
|
|
46
|
+
uniform float u_saturation;
|
|
47
|
+
uniform float u_mouseIntensity;
|
|
48
|
+
uniform float u_clickIntensity;
|
|
49
|
+
uniform float u_roleIntensity;
|
|
50
|
+
uniform float u_bass;
|
|
51
|
+
uniform float u_mid;
|
|
52
|
+
uniform float u_high;
|
|
53
|
+
|
|
54
|
+
// ── 6D Rotation Matrices ──
|
|
55
|
+
|
|
56
|
+
mat4 rotateXY(float theta) {
|
|
57
|
+
float c = cos(theta); float s = sin(theta);
|
|
58
|
+
return mat4(c, -s, 0, 0, s, c, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1);
|
|
59
|
+
}
|
|
60
|
+
mat4 rotateXZ(float theta) {
|
|
61
|
+
float c = cos(theta); float s = sin(theta);
|
|
62
|
+
return mat4(c, 0, s, 0, 0, 1, 0, 0, -s, 0, c, 0, 0, 0, 0, 1);
|
|
63
|
+
}
|
|
64
|
+
mat4 rotateYZ(float theta) {
|
|
65
|
+
float c = cos(theta); float s = sin(theta);
|
|
66
|
+
return mat4(1, 0, 0, 0, 0, c, -s, 0, 0, s, c, 0, 0, 0, 0, 1);
|
|
67
|
+
}
|
|
68
|
+
mat4 rotateXW(float theta) {
|
|
69
|
+
float c = cos(theta); float s = sin(theta);
|
|
70
|
+
return mat4(c, 0, 0, -s, 0, 1, 0, 0, 0, 0, 1, 0, s, 0, 0, c);
|
|
71
|
+
}
|
|
72
|
+
mat4 rotateYW(float theta) {
|
|
73
|
+
float c = cos(theta); float s = sin(theta);
|
|
74
|
+
return mat4(1, 0, 0, 0, 0, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c);
|
|
75
|
+
}
|
|
76
|
+
mat4 rotateZW(float theta) {
|
|
77
|
+
float c = cos(theta); float s = sin(theta);
|
|
78
|
+
return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// ── 4D → 3D Projection ──
|
|
82
|
+
|
|
83
|
+
vec3 project4Dto3D(vec4 p) {
|
|
84
|
+
float w = 2.5 / (2.5 + p.w);
|
|
85
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// ── Polytope Core Warp Functions (24 Geometries) ──
|
|
89
|
+
|
|
90
|
+
vec3 warpHypersphereCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
|
|
91
|
+
float radius = length(p);
|
|
92
|
+
float morphBlend = clamp(u_morphFactor * 0.6 + (u_dimension - 3.0) * 0.25, 0.0, 2.0);
|
|
93
|
+
float w = sin(radius * (1.3 + float(geometryIndex) * 0.12) + u_time * 0.0008 * u_speed);
|
|
94
|
+
w *= (0.4 + morphBlend * 0.45);
|
|
95
|
+
|
|
96
|
+
vec4 p4d = vec4(p * (1.0 + morphBlend * 0.2), w);
|
|
97
|
+
p4d = rotateXY(u_rot4dXY) * p4d;
|
|
98
|
+
p4d = rotateXZ(u_rot4dXZ) * p4d;
|
|
99
|
+
p4d = rotateYZ(u_rot4dYZ) * p4d;
|
|
100
|
+
p4d = rotateXW(u_rot4dXW) * p4d;
|
|
101
|
+
p4d = rotateYW(u_rot4dYW) * p4d;
|
|
102
|
+
p4d = rotateZW(u_rot4dZW) * p4d;
|
|
103
|
+
|
|
104
|
+
vec3 projected = project4Dto3D(p4d);
|
|
105
|
+
return mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
vec3 warpHypertetraCore(vec3 p, int geometryIndex, vec2 mouseDelta) {
|
|
109
|
+
vec3 c1 = normalize(vec3(1.0, 1.0, 1.0));
|
|
110
|
+
vec3 c2 = normalize(vec3(-1.0, -1.0, 1.0));
|
|
111
|
+
vec3 c3 = normalize(vec3(-1.0, 1.0, -1.0));
|
|
112
|
+
vec3 c4 = normalize(vec3(1.0, -1.0, -1.0));
|
|
113
|
+
|
|
114
|
+
float morphBlend = clamp(u_morphFactor * 0.8 + (u_dimension - 3.0) * 0.2, 0.0, 2.0);
|
|
115
|
+
float basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
|
|
116
|
+
float w = sin(basisMix * 5.5 + u_time * 0.0009 * u_speed);
|
|
117
|
+
w *= cos(dot(p, c4) * 4.2 - u_time * 0.0007 * u_speed);
|
|
118
|
+
w *= (0.5 + morphBlend * 0.4);
|
|
119
|
+
|
|
120
|
+
vec3 offset = vec3(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
|
|
121
|
+
vec4 p4d = vec4(p + offset, w);
|
|
122
|
+
p4d = rotateXY(u_rot4dXY) * p4d;
|
|
123
|
+
p4d = rotateXZ(u_rot4dXZ) * p4d;
|
|
124
|
+
p4d = rotateYZ(u_rot4dYZ) * p4d;
|
|
125
|
+
p4d = rotateXW(u_rot4dXW) * p4d;
|
|
126
|
+
p4d = rotateYW(u_rot4dYW) * p4d;
|
|
127
|
+
p4d = rotateZW(u_rot4dZW) * p4d;
|
|
128
|
+
|
|
129
|
+
vec3 projected = project4Dto3D(p4d);
|
|
130
|
+
float planeInfluence = min(min(abs(dot(p, c1)), abs(dot(p, c2))),
|
|
131
|
+
min(abs(dot(p, c3)), abs(dot(p, c4))));
|
|
132
|
+
vec3 blended = mix(p, projected, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
133
|
+
return mix(blended, blended * (1.0 - planeInfluence * 0.55), 0.2 + morphBlend * 0.2);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
vec3 applyCoreWarp(vec3 p, float geometryType, vec2 mouseDelta) {
|
|
137
|
+
float totalBase = 8.0;
|
|
138
|
+
float coreFloat = floor(geometryType / totalBase);
|
|
139
|
+
int coreIndex = int(clamp(coreFloat, 0.0, 2.0));
|
|
140
|
+
// WebGL 1.0 compatible modulus
|
|
141
|
+
float baseGeomFloat = geometryType - floor(geometryType / totalBase) * totalBase;
|
|
142
|
+
int geometryIndex = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
|
|
143
|
+
|
|
144
|
+
if (coreIndex == 1) {
|
|
145
|
+
return warpHypersphereCore(p, geometryIndex, mouseDelta);
|
|
146
|
+
}
|
|
147
|
+
if (coreIndex == 2) {
|
|
148
|
+
return warpHypertetraCore(p, geometryIndex, mouseDelta);
|
|
149
|
+
}
|
|
150
|
+
return p;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ── 8 Lattice Geometry Functions ──
|
|
154
|
+
|
|
155
|
+
float geometryFunction(vec4 p) {
|
|
156
|
+
float totalBase = 8.0;
|
|
157
|
+
// WebGL 1.0 compatible modulus
|
|
158
|
+
float baseGeomFloat = u_geometry - floor(u_geometry / totalBase) * totalBase;
|
|
159
|
+
int geomType = int(clamp(floor(baseGeomFloat + 0.5), 0.0, totalBase - 1.0));
|
|
160
|
+
|
|
161
|
+
if (geomType == 0) {
|
|
162
|
+
// Tetrahedron lattice
|
|
163
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
164
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
165
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
166
|
+
}
|
|
167
|
+
else if (geomType == 1) {
|
|
168
|
+
// Hypercube lattice
|
|
169
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
170
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
171
|
+
float minDist = min(min(dist.x, dist.y), min(dist.z, dist.w));
|
|
172
|
+
return minDist * u_morphFactor;
|
|
173
|
+
}
|
|
174
|
+
else if (geomType == 2) {
|
|
175
|
+
// Sphere lattice
|
|
176
|
+
float r = length(p);
|
|
177
|
+
float density = u_gridDensity * 0.08;
|
|
178
|
+
float spheres = abs(fract(r * density) - 0.5) * 2.0;
|
|
179
|
+
float theta = atan(p.y, p.x);
|
|
180
|
+
float harmonics = sin(theta * 3.0) * 0.2;
|
|
181
|
+
return (spheres + harmonics) * u_morphFactor;
|
|
182
|
+
}
|
|
183
|
+
else if (geomType == 3) {
|
|
184
|
+
// Torus lattice
|
|
185
|
+
float r1 = length(p.xy) - 2.0;
|
|
186
|
+
float torus = length(vec2(r1, p.z)) - 0.8;
|
|
187
|
+
float lattice = sin(p.x * u_gridDensity * 0.08) * sin(p.y * u_gridDensity * 0.08);
|
|
188
|
+
return (torus + lattice * 0.3) * u_morphFactor;
|
|
189
|
+
}
|
|
190
|
+
else if (geomType == 4) {
|
|
191
|
+
// Klein bottle lattice
|
|
192
|
+
float u_ang = atan(p.y, p.x);
|
|
193
|
+
float v_ang = atan(p.w, p.z);
|
|
194
|
+
float dist = length(p) - 2.0;
|
|
195
|
+
float lattice = sin(u_ang * u_gridDensity * 0.08) * sin(v_ang * u_gridDensity * 0.08);
|
|
196
|
+
return (dist + lattice * 0.4) * u_morphFactor;
|
|
197
|
+
}
|
|
198
|
+
else if (geomType == 5) {
|
|
199
|
+
// Fractal lattice
|
|
200
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
201
|
+
pos = abs(pos * 2.0 - 1.0);
|
|
202
|
+
float dist = length(max(abs(pos) - 1.0, 0.0));
|
|
203
|
+
return dist * u_morphFactor;
|
|
204
|
+
}
|
|
205
|
+
else if (geomType == 6) {
|
|
206
|
+
// Wave lattice
|
|
207
|
+
float freq = u_gridDensity * 0.08;
|
|
208
|
+
float time = u_time * 0.001 * u_speed;
|
|
209
|
+
float wave1 = sin(p.x * freq + time);
|
|
210
|
+
float wave2 = sin(p.y * freq + time * 1.3);
|
|
211
|
+
float wave3 = sin(p.z * freq * 0.8 + time * 0.7);
|
|
212
|
+
float interference = wave1 * wave2 * wave3;
|
|
213
|
+
return interference * u_morphFactor;
|
|
214
|
+
}
|
|
215
|
+
else if (geomType == 7) {
|
|
216
|
+
// Crystal lattice
|
|
217
|
+
vec4 pos = fract(p * u_gridDensity * 0.08) - 0.5;
|
|
218
|
+
float cube = max(max(abs(pos.x), abs(pos.y)), max(abs(pos.z), abs(pos.w)));
|
|
219
|
+
return cube * u_morphFactor;
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
// Default hypercube
|
|
223
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
224
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
225
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
// ── Main ──
|
|
230
|
+
|
|
231
|
+
void main() {
|
|
232
|
+
vec2 uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / min(u_resolution.x, u_resolution.y);
|
|
233
|
+
float timeSpeed = u_time * 0.0001 * u_speed;
|
|
234
|
+
|
|
235
|
+
// Create 4D point
|
|
236
|
+
vec4 pos = vec4(uv * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
237
|
+
|
|
238
|
+
// Mouse influence
|
|
239
|
+
pos.xy += (u_mouse - 0.5) * u_mouseIntensity * 2.0;
|
|
240
|
+
|
|
241
|
+
// Audio-reactive density and morph
|
|
242
|
+
float audioDensityMod = 1.0 + u_bass * 0.3;
|
|
243
|
+
float audioMorphMod = 1.0 + u_mid * 0.2;
|
|
244
|
+
|
|
245
|
+
// Apply full 6D rotation
|
|
246
|
+
pos = rotateXY(u_rot4dXY) * pos;
|
|
247
|
+
pos = rotateXZ(u_rot4dXZ) * pos;
|
|
248
|
+
pos = rotateYZ(u_rot4dYZ) * pos;
|
|
249
|
+
pos = rotateXW(u_rot4dXW) * pos;
|
|
250
|
+
pos = rotateYW(u_rot4dYW) * pos;
|
|
251
|
+
pos = rotateZW(u_rot4dZW) * pos;
|
|
252
|
+
|
|
253
|
+
// 4D → 3D projection
|
|
254
|
+
vec3 basePoint = project4Dto3D(pos);
|
|
255
|
+
|
|
256
|
+
// Apply polytope core warp (types 8-23)
|
|
257
|
+
vec3 warpedPoint = applyCoreWarp(basePoint, u_geometry, u_mouse - 0.5);
|
|
258
|
+
|
|
259
|
+
// Evaluate lattice geometry
|
|
260
|
+
vec4 warpedPos = vec4(warpedPoint, pos.w);
|
|
261
|
+
float value = geometryFunction(warpedPos);
|
|
262
|
+
|
|
263
|
+
// Chaos noise
|
|
264
|
+
float noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
265
|
+
value += noise * u_chaos;
|
|
266
|
+
|
|
267
|
+
// Intensity from lattice
|
|
268
|
+
float geometryIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
269
|
+
geometryIntensity += u_clickIntensity * 0.3;
|
|
270
|
+
float finalIntensity = geometryIntensity * u_intensity;
|
|
271
|
+
|
|
272
|
+
// Audio-reactive hue shift
|
|
273
|
+
float hue = u_hue / 360.0 + value * 0.1 + u_high * 0.08;
|
|
274
|
+
|
|
275
|
+
// Color via sin-wave HSL
|
|
276
|
+
vec3 baseColor = vec3(
|
|
277
|
+
sin(hue * 6.28318 + 0.0) * 0.5 + 0.5,
|
|
278
|
+
sin(hue * 6.28318 + 2.0943) * 0.5 + 0.5,
|
|
279
|
+
sin(hue * 6.28318 + 4.1887) * 0.5 + 0.5
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
// Saturation control (mix to gray)
|
|
283
|
+
float gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
284
|
+
vec3 color = mix(vec3(gray), baseColor, u_saturation) * finalIntensity;
|
|
285
|
+
|
|
286
|
+
gl_FragColor = vec4(color, finalIntensity * u_roleIntensity);
|
|
287
|
+
}
|
|
288
|
+
`;
|
|
289
|
+
|
|
290
|
+
// WGSL version of the faceted fragment shader for WebGPU
|
|
291
|
+
const FRAGMENT_SHADER_WGSL = `
|
|
292
|
+
struct VIB3Uniforms {
|
|
293
|
+
time: f32,
|
|
294
|
+
speed: f32,
|
|
295
|
+
resolution: vec2<f32>,
|
|
296
|
+
geometry: f32,
|
|
297
|
+
rot4dXY: f32,
|
|
298
|
+
rot4dXZ: f32,
|
|
299
|
+
rot4dYZ: f32,
|
|
300
|
+
rot4dXW: f32,
|
|
301
|
+
rot4dYW: f32,
|
|
302
|
+
rot4dZW: f32,
|
|
303
|
+
dimension: f32,
|
|
304
|
+
gridDensity: f32,
|
|
305
|
+
morphFactor: f32,
|
|
306
|
+
chaos: f32,
|
|
307
|
+
hue: f32,
|
|
308
|
+
intensity: f32,
|
|
309
|
+
saturation: f32,
|
|
310
|
+
mouseIntensity: f32,
|
|
311
|
+
clickIntensity: f32,
|
|
312
|
+
roleIntensity: f32,
|
|
313
|
+
bass: f32,
|
|
314
|
+
mid: f32,
|
|
315
|
+
high: f32,
|
|
316
|
+
_pad0: f32,
|
|
317
|
+
mouse: vec2<f32>,
|
|
318
|
+
_pad1: vec2<f32>,
|
|
319
|
+
};
|
|
320
|
+
|
|
321
|
+
@group(0) @binding(0) var<uniform> u: VIB3Uniforms;
|
|
322
|
+
|
|
323
|
+
fn rotateXY_w(theta: f32) -> mat4x4<f32> {
|
|
324
|
+
let c = cos(theta); let s = sin(theta);
|
|
325
|
+
return mat4x4<f32>(
|
|
326
|
+
vec4<f32>(c, -s, 0.0, 0.0), vec4<f32>(s, c, 0.0, 0.0),
|
|
327
|
+
vec4<f32>(0.0, 0.0, 1.0, 0.0), vec4<f32>(0.0, 0.0, 0.0, 1.0));
|
|
328
|
+
}
|
|
329
|
+
fn rotateXZ_w(theta: f32) -> mat4x4<f32> {
|
|
330
|
+
let c = cos(theta); let s = sin(theta);
|
|
331
|
+
return mat4x4<f32>(
|
|
332
|
+
vec4<f32>(c, 0.0, s, 0.0), vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
|
333
|
+
vec4<f32>(-s, 0.0, c, 0.0), vec4<f32>(0.0, 0.0, 0.0, 1.0));
|
|
334
|
+
}
|
|
335
|
+
fn rotateYZ_w(theta: f32) -> mat4x4<f32> {
|
|
336
|
+
let c = cos(theta); let s = sin(theta);
|
|
337
|
+
return mat4x4<f32>(
|
|
338
|
+
vec4<f32>(1.0, 0.0, 0.0, 0.0), vec4<f32>(0.0, c, -s, 0.0),
|
|
339
|
+
vec4<f32>(0.0, s, c, 0.0), vec4<f32>(0.0, 0.0, 0.0, 1.0));
|
|
340
|
+
}
|
|
341
|
+
fn rotateXW_w(theta: f32) -> mat4x4<f32> {
|
|
342
|
+
let c = cos(theta); let s = sin(theta);
|
|
343
|
+
return mat4x4<f32>(
|
|
344
|
+
vec4<f32>(c, 0.0, 0.0, -s), vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
|
345
|
+
vec4<f32>(0.0, 0.0, 1.0, 0.0), vec4<f32>(s, 0.0, 0.0, c));
|
|
346
|
+
}
|
|
347
|
+
fn rotateYW_w(theta: f32) -> mat4x4<f32> {
|
|
348
|
+
let c = cos(theta); let s = sin(theta);
|
|
349
|
+
return mat4x4<f32>(
|
|
350
|
+
vec4<f32>(1.0, 0.0, 0.0, 0.0), vec4<f32>(0.0, c, 0.0, -s),
|
|
351
|
+
vec4<f32>(0.0, 0.0, 1.0, 0.0), vec4<f32>(0.0, s, 0.0, c));
|
|
352
|
+
}
|
|
353
|
+
fn rotateZW_w(theta: f32) -> mat4x4<f32> {
|
|
354
|
+
let c = cos(theta); let s = sin(theta);
|
|
355
|
+
return mat4x4<f32>(
|
|
356
|
+
vec4<f32>(1.0, 0.0, 0.0, 0.0), vec4<f32>(0.0, 1.0, 0.0, 0.0),
|
|
357
|
+
vec4<f32>(0.0, 0.0, c, -s), vec4<f32>(0.0, 0.0, s, c));
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
fn project4Dto3D_w(p: vec4<f32>) -> vec3<f32> {
|
|
361
|
+
let w = 2.5 / (2.5 + p.w);
|
|
362
|
+
return vec3<f32>(p.x * w, p.y * w, p.z * w);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
fn warpHypersphereCore_w(p: vec3<f32>, geomIdx: i32) -> vec3<f32> {
|
|
366
|
+
let radius = length(p);
|
|
367
|
+
let morphBlend = clamp(u.morphFactor * 0.6 + (u.dimension - 3.0) * 0.25, 0.0, 2.0);
|
|
368
|
+
let w = sin(radius * (1.3 + f32(geomIdx) * 0.12) + u.time * 0.0008 * u.speed)
|
|
369
|
+
* (0.4 + morphBlend * 0.45);
|
|
370
|
+
var p4d = vec4<f32>(p * (1.0 + morphBlend * 0.2), w);
|
|
371
|
+
p4d = rotateXY_w(u.rot4dXY) * p4d;
|
|
372
|
+
p4d = rotateXZ_w(u.rot4dXZ) * p4d;
|
|
373
|
+
p4d = rotateYZ_w(u.rot4dYZ) * p4d;
|
|
374
|
+
p4d = rotateXW_w(u.rot4dXW) * p4d;
|
|
375
|
+
p4d = rotateYW_w(u.rot4dYW) * p4d;
|
|
376
|
+
p4d = rotateZW_w(u.rot4dZW) * p4d;
|
|
377
|
+
let proj = project4Dto3D_w(p4d);
|
|
378
|
+
return mix(p, proj, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
fn warpHypertetraCore_w(p: vec3<f32>, geomIdx: i32) -> vec3<f32> {
|
|
382
|
+
let c1 = normalize(vec3<f32>(1.0, 1.0, 1.0));
|
|
383
|
+
let c2 = normalize(vec3<f32>(-1.0, -1.0, 1.0));
|
|
384
|
+
let c3 = normalize(vec3<f32>(-1.0, 1.0, -1.0));
|
|
385
|
+
let c4 = normalize(vec3<f32>(1.0, -1.0, -1.0));
|
|
386
|
+
let morphBlend = clamp(u.morphFactor * 0.8 + (u.dimension - 3.0) * 0.2, 0.0, 2.0);
|
|
387
|
+
let basisMix = dot(p, c1) * 0.14 + dot(p, c2) * 0.1 + dot(p, c3) * 0.08;
|
|
388
|
+
let w = sin(basisMix * 5.5 + u.time * 0.0009 * u.speed)
|
|
389
|
+
* cos(dot(p, c4) * 4.2 - u.time * 0.0007 * u.speed)
|
|
390
|
+
* (0.5 + morphBlend * 0.4);
|
|
391
|
+
let offset = vec3<f32>(dot(p, c1), dot(p, c2), dot(p, c3)) * 0.1 * morphBlend;
|
|
392
|
+
var p4d = vec4<f32>(p + offset, w);
|
|
393
|
+
p4d = rotateXY_w(u.rot4dXY) * p4d;
|
|
394
|
+
p4d = rotateXZ_w(u.rot4dXZ) * p4d;
|
|
395
|
+
p4d = rotateYZ_w(u.rot4dYZ) * p4d;
|
|
396
|
+
p4d = rotateXW_w(u.rot4dXW) * p4d;
|
|
397
|
+
p4d = rotateYW_w(u.rot4dYW) * p4d;
|
|
398
|
+
p4d = rotateZW_w(u.rot4dZW) * p4d;
|
|
399
|
+
let proj = project4Dto3D_w(p4d);
|
|
400
|
+
let planeInf = min(min(abs(dot(p, c1)), abs(dot(p, c2))),
|
|
401
|
+
min(abs(dot(p, c3)), abs(dot(p, c4))));
|
|
402
|
+
let blended = mix(p, proj, clamp(0.45 + morphBlend * 0.35, 0.0, 1.0));
|
|
403
|
+
return mix(blended, blended * (1.0 - planeInf * 0.55), 0.2 + morphBlend * 0.2);
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
fn applyCoreWarp_w(p: vec3<f32>, geomType: f32, mouseDelta: vec2<f32>) -> vec3<f32> {
|
|
407
|
+
let coreFloat = floor(geomType / 8.0);
|
|
408
|
+
let coreIndex = i32(clamp(coreFloat, 0.0, 2.0));
|
|
409
|
+
let baseFloat = geomType - coreFloat * 8.0;
|
|
410
|
+
let geomIdx = i32(clamp(floor(baseFloat + 0.5), 0.0, 7.0));
|
|
411
|
+
if (coreIndex == 1) { return warpHypersphereCore_w(p, geomIdx); }
|
|
412
|
+
if (coreIndex == 2) { return warpHypertetraCore_w(p, geomIdx); }
|
|
413
|
+
return p;
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
fn geometryFunction_w(p: vec4<f32>) -> f32 {
|
|
417
|
+
let baseFloat = u.geometry - floor(u.geometry / 8.0) * 8.0;
|
|
418
|
+
let gt = i32(clamp(floor(baseFloat + 0.5), 0.0, 7.0));
|
|
419
|
+
let d = u.gridDensity * 0.08;
|
|
420
|
+
if (gt == 0) {
|
|
421
|
+
let pos = fract(p * d); let dist = min(pos, 1.0 - pos);
|
|
422
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u.morphFactor;
|
|
423
|
+
} else if (gt == 1) {
|
|
424
|
+
let pos = fract(p * d); let dist = min(pos, 1.0 - pos);
|
|
425
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u.morphFactor;
|
|
426
|
+
} else if (gt == 2) {
|
|
427
|
+
let r = length(p); let sph = abs(fract(r * d) - 0.5) * 2.0;
|
|
428
|
+
let harm = sin(atan2(p.y, p.x) * 3.0) * 0.2;
|
|
429
|
+
return (sph + harm) * u.morphFactor;
|
|
430
|
+
} else if (gt == 3) {
|
|
431
|
+
let r1 = length(p.xy) - 2.0; let tor = length(vec2<f32>(r1, p.z)) - 0.8;
|
|
432
|
+
let lat = sin(p.x * d) * sin(p.y * d);
|
|
433
|
+
return (tor + lat * 0.3) * u.morphFactor;
|
|
434
|
+
} else if (gt == 4) {
|
|
435
|
+
let ua = atan2(p.y, p.x); let va = atan2(p.w, p.z);
|
|
436
|
+
let dist = length(p) - 2.0; let lat = sin(ua * d) * sin(va * d);
|
|
437
|
+
return (dist + lat * 0.4) * u.morphFactor;
|
|
438
|
+
} else if (gt == 5) {
|
|
439
|
+
var pos = fract(p * d); pos = abs(pos * 2.0 - 1.0);
|
|
440
|
+
return length(max(abs(pos) - 1.0, vec4<f32>(0.0))) * u.morphFactor;
|
|
441
|
+
} else if (gt == 6) {
|
|
442
|
+
let t = u.time * 0.001 * u.speed;
|
|
443
|
+
return sin(p.x * d + t) * sin(p.y * d + t * 1.3) * sin(p.z * d * 0.8 + t * 0.7) * u.morphFactor;
|
|
444
|
+
} else {
|
|
445
|
+
let pos = fract(p * d) - 0.5;
|
|
446
|
+
return max(max(abs(pos.x), abs(pos.y)), max(abs(pos.z), abs(pos.w))) * u.morphFactor;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
struct VertexOutput {
|
|
451
|
+
@builtin(position) position: vec4<f32>,
|
|
452
|
+
@location(0) uv: vec2<f32>,
|
|
453
|
+
};
|
|
454
|
+
|
|
455
|
+
@fragment
|
|
456
|
+
fn main(input: VertexOutput) -> @location(0) vec4<f32> {
|
|
457
|
+
let fragCoord = input.position.xy;
|
|
458
|
+
let uv2 = (fragCoord - u.resolution * 0.5) / min(u.resolution.x, u.resolution.y);
|
|
459
|
+
let timeSpeed = u.time * 0.0001 * u.speed;
|
|
460
|
+
|
|
461
|
+
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);
|
|
463
|
+
|
|
464
|
+
pos = rotateXY_w(u.rot4dXY) * pos;
|
|
465
|
+
pos = rotateXZ_w(u.rot4dXZ) * pos;
|
|
466
|
+
pos = rotateYZ_w(u.rot4dYZ) * pos;
|
|
467
|
+
pos = rotateXW_w(u.rot4dXW) * pos;
|
|
468
|
+
pos = rotateYW_w(u.rot4dYW) * pos;
|
|
469
|
+
pos = rotateZW_w(u.rot4dZW) * pos;
|
|
470
|
+
|
|
471
|
+
let basePoint = project4Dto3D_w(pos);
|
|
472
|
+
let warpedPoint = applyCoreWarp_w(basePoint, u.geometry, u.mouse - 0.5);
|
|
473
|
+
let warpedPos = vec4<f32>(warpedPoint, pos.w);
|
|
474
|
+
var value = geometryFunction_w(warpedPos);
|
|
475
|
+
|
|
476
|
+
let noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
477
|
+
value += noise * u.chaos;
|
|
478
|
+
|
|
479
|
+
var geomIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
480
|
+
geomIntensity += u.clickIntensity * 0.3;
|
|
481
|
+
let finalIntensity = geomIntensity * u.intensity;
|
|
482
|
+
|
|
483
|
+
let hueVal = u.hue / 360.0 + value * 0.1 + u.high * 0.08;
|
|
484
|
+
let baseColor = vec3<f32>(
|
|
485
|
+
sin(hueVal * 6.28318 + 0.0) * 0.5 + 0.5,
|
|
486
|
+
sin(hueVal * 6.28318 + 2.0943) * 0.5 + 0.5,
|
|
487
|
+
sin(hueVal * 6.28318 + 4.1887) * 0.5 + 0.5);
|
|
488
|
+
let gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
489
|
+
let color = mix(vec3<f32>(gray), baseColor, u.saturation) * finalIntensity;
|
|
490
|
+
|
|
491
|
+
return vec4<f32>(color, finalIntensity * u.roleIntensity);
|
|
492
|
+
}
|
|
493
|
+
`;
|
|
494
|
+
|
|
495
|
+
// ============================================================================
|
|
496
|
+
// FacetedSystem Class
|
|
497
|
+
// ============================================================================
|
|
498
|
+
|
|
499
|
+
export class FacetedSystem {
|
|
500
|
+
constructor() {
|
|
501
|
+
this.canvas = null;
|
|
502
|
+
this.gl = null;
|
|
503
|
+
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';
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
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>}
|
|
542
|
+
*/
|
|
543
|
+
async initWithBridge(canvas, options = {}) {
|
|
544
|
+
this.canvas = canvas;
|
|
545
|
+
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;
|
|
580
|
+
} 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']);
|
|
595
|
+
return false;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
this.gl = this.canvas.getContext('webgl');
|
|
599
|
+
if (!this.gl) {
|
|
600
|
+
console.error('WebGL not available for Faceted System');
|
|
601
|
+
return false;
|
|
602
|
+
}
|
|
603
|
+
|
|
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');
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
|
|
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);
|
|
642
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, vertices, this.gl.STATIC_DRAW);
|
|
643
|
+
|
|
644
|
+
return true;
|
|
645
|
+
}
|
|
646
|
+
|
|
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;
|
|
655
|
+
|
|
656
|
+
const program = this.gl.createProgram();
|
|
657
|
+
this.gl.attachShader(program, vertexShader);
|
|
658
|
+
this.gl.attachShader(program, fragmentShader);
|
|
659
|
+
this.gl.linkProgram(program);
|
|
660
|
+
|
|
661
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
662
|
+
console.error('Shader program link error:', this.gl.getProgramInfoLog(program));
|
|
663
|
+
return null;
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
return program;
|
|
667
|
+
}
|
|
668
|
+
|
|
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));
|
|
679
|
+
return null;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
return shader;
|
|
683
|
+
}
|
|
684
|
+
|
|
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
|
+
}
|
|
696
|
+
|
|
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');
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Set active state
|
|
716
|
+
*/
|
|
717
|
+
setActive(active) {
|
|
718
|
+
if (active) {
|
|
719
|
+
this.start();
|
|
720
|
+
} else {
|
|
721
|
+
this.stop();
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
|
|
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';
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Build uniform object for current parameters
|
|
738
|
+
* @private
|
|
739
|
+
*/
|
|
740
|
+
_buildUniforms() {
|
|
741
|
+
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
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
|
|
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');
|
|
777
|
+
}
|
|
778
|
+
|
|
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;
|
|
788
|
+
}
|
|
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
|
+
}
|
|
816
|
+
|
|
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
|
+
}
|
|
829
|
+
|
|
830
|
+
this.time += 0.016 * this.parameters.speed;
|
|
831
|
+
|
|
832
|
+
if (this._renderMode === 'bridge') {
|
|
833
|
+
this._renderBridgeFrame();
|
|
834
|
+
} else {
|
|
835
|
+
this._renderDirectFrame();
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* Render loop
|
|
841
|
+
*/
|
|
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
|
+
}
|
|
850
|
+
|
|
851
|
+
this.renderFrame();
|
|
852
|
+
|
|
853
|
+
if (this.isActive) {
|
|
854
|
+
requestAnimationFrame(() => this.render());
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
|
|
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
|
+
}
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
|
|
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
|
+
});
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
return this.initialize(canvasOverride);
|
|
893
|
+
}
|
|
894
|
+
|
|
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
|
+
}
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Clean up all resources (RendererContract.dispose)
|
|
917
|
+
*/
|
|
918
|
+
dispose() {
|
|
919
|
+
this.isActive = false;
|
|
920
|
+
|
|
921
|
+
// Remove context loss listeners
|
|
922
|
+
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
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
if (this._bridge) {
|
|
932
|
+
this._bridge.dispose();
|
|
933
|
+
this._bridge = null;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
if (this.gl && !this.gl.isContextLost()) {
|
|
937
|
+
if (this.program) {
|
|
938
|
+
this.gl.deleteProgram(this.program);
|
|
939
|
+
}
|
|
940
|
+
}
|
|
941
|
+
this.program = null;
|
|
942
|
+
|
|
943
|
+
if (this.gl) {
|
|
944
|
+
const loseContext = this.gl.getExtension('WEBGL_lose_context');
|
|
945
|
+
if (loseContext) {
|
|
946
|
+
loseContext.loseContext();
|
|
947
|
+
}
|
|
948
|
+
this.gl = null;
|
|
949
|
+
}
|
|
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();
|
|
962
|
+
}
|
|
963
|
+
}
|