@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,937 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* VIB3+ Shader Sync Verification Tool
|
|
3
|
+
* Ensures uniform consistency across all visualization systems
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* Node.js (static analysis):
|
|
7
|
+
* node tools/shader-sync-verify.js
|
|
8
|
+
*
|
|
9
|
+
* Browser console (runtime):
|
|
10
|
+
* import { ShaderSyncVerifier } from './tools/shader-sync-verify.js';
|
|
11
|
+
* const verifier = new ShaderSyncVerifier();
|
|
12
|
+
* verifier.runFullAudit();
|
|
13
|
+
*
|
|
14
|
+
* This tool parses GLSL and WGSL shader source to extract uniform declarations,
|
|
15
|
+
* then compares across the Quantum, Faceted, and Holographic systems to flag
|
|
16
|
+
* missing, mismatched, or extra uniforms relative to the VIB3+ standard set.
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// ShaderSyncVerifier
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
|
|
23
|
+
export class ShaderSyncVerifier {
|
|
24
|
+
constructor() {
|
|
25
|
+
/**
|
|
26
|
+
* The canonical VIB3+ uniform contract.
|
|
27
|
+
* Every system MUST declare the "required" set.
|
|
28
|
+
* "recommended" uniforms enable full audio/interaction reactivity.
|
|
29
|
+
* "optional" uniforms are system-specific extensions.
|
|
30
|
+
*/
|
|
31
|
+
this.STANDARD_UNIFORMS = {
|
|
32
|
+
required: [
|
|
33
|
+
'u_time', 'u_resolution', 'u_geometry',
|
|
34
|
+
'u_rot4dXY', 'u_rot4dXZ', 'u_rot4dYZ',
|
|
35
|
+
'u_rot4dXW', 'u_rot4dYW', 'u_rot4dZW',
|
|
36
|
+
'u_gridDensity', 'u_morphFactor', 'u_chaos',
|
|
37
|
+
'u_speed', 'u_hue', 'u_intensity', 'u_dimension'
|
|
38
|
+
],
|
|
39
|
+
recommended: [
|
|
40
|
+
'u_saturation', 'u_mouseIntensity', 'u_clickIntensity',
|
|
41
|
+
'u_bass', 'u_mid', 'u_high'
|
|
42
|
+
],
|
|
43
|
+
optional: [
|
|
44
|
+
'u_mouse', 'u_roleIntensity', 'u_layerScale',
|
|
45
|
+
'u_layerOpacity', 'u_layerColor', 'u_densityMult', 'u_speedMult'
|
|
46
|
+
]
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
/** Map of system name -> { glslUniforms, wgslUniforms, sources } */
|
|
50
|
+
this.systems = new Map();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// -----------------------------------------------------------------------
|
|
54
|
+
// GLSL uniform parser
|
|
55
|
+
// -----------------------------------------------------------------------
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Parse GLSL source code and extract all uniform declarations.
|
|
59
|
+
* Handles `uniform float u_foo;`, `uniform vec2 u_bar;`, etc.
|
|
60
|
+
* Returns an array of { name, type, qualifiers } objects.
|
|
61
|
+
*
|
|
62
|
+
* @param {string} source - GLSL shader source code
|
|
63
|
+
* @returns {{ name: string, type: string, qualifiers: string }[]}
|
|
64
|
+
*/
|
|
65
|
+
parseGLSLUniforms(source) {
|
|
66
|
+
if (!source || typeof source !== 'string') return [];
|
|
67
|
+
|
|
68
|
+
const uniforms = [];
|
|
69
|
+
// Match: uniform <optional qualifiers> <type> <name> ;
|
|
70
|
+
// Handles optional precision qualifiers like `uniform highp float u_time;`
|
|
71
|
+
const uniformRegex = /uniform\s+((?:(?:lowp|mediump|highp)\s+)?)(float|int|bool|[ui]?vec[234]|mat[234](?:x[234])?|sampler(?:2D|3D|Cube))\s+(\w+)\s*;/g;
|
|
72
|
+
|
|
73
|
+
let match;
|
|
74
|
+
while ((match = uniformRegex.exec(source)) !== null) {
|
|
75
|
+
uniforms.push({
|
|
76
|
+
name: match[3],
|
|
77
|
+
type: match[2],
|
|
78
|
+
qualifiers: match[1].trim() || ''
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return uniforms;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// -----------------------------------------------------------------------
|
|
86
|
+
// WGSL uniform parser
|
|
87
|
+
// -----------------------------------------------------------------------
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Parse WGSL source code and extract struct fields used as uniforms.
|
|
91
|
+
* Looks for a struct definition (typically VIB3Uniforms) bound via
|
|
92
|
+
* `@group(0) @binding(0) var<uniform>`, then extracts its fields.
|
|
93
|
+
*
|
|
94
|
+
* Returns an array of { name, type } objects with names prefixed by `u_`
|
|
95
|
+
* so they can be compared against the GLSL convention. Padding fields
|
|
96
|
+
* (names starting with `_`) are excluded.
|
|
97
|
+
*
|
|
98
|
+
* @param {string} source - WGSL shader source code
|
|
99
|
+
* @returns {{ name: string, type: string }[]}
|
|
100
|
+
*/
|
|
101
|
+
parseWGSLUniforms(source) {
|
|
102
|
+
if (!source || typeof source !== 'string') return [];
|
|
103
|
+
|
|
104
|
+
const uniforms = [];
|
|
105
|
+
|
|
106
|
+
// Step 1 - Find the struct name referenced by the uniform binding
|
|
107
|
+
const bindingRegex = /@group\s*\(\s*0\s*\)\s*@binding\s*\(\s*0\s*\)\s*var\s*<\s*uniform\s*>\s*\w+\s*:\s*(\w+)\s*;/;
|
|
108
|
+
const bindingMatch = bindingRegex.exec(source);
|
|
109
|
+
const structName = bindingMatch ? bindingMatch[1] : 'VIB3Uniforms';
|
|
110
|
+
|
|
111
|
+
// Step 2 - Extract the struct body
|
|
112
|
+
const structRegex = new RegExp(
|
|
113
|
+
`struct\\s+${structName}\\s*\\{([^}]+)\\}`,
|
|
114
|
+
's'
|
|
115
|
+
);
|
|
116
|
+
const structMatch = structRegex.exec(source);
|
|
117
|
+
if (!structMatch) return uniforms;
|
|
118
|
+
|
|
119
|
+
const body = structMatch[1];
|
|
120
|
+
|
|
121
|
+
// Step 3 - Parse each field: name: type,
|
|
122
|
+
// Use a non-greedy type match that stops at comma, semicolon, or newline
|
|
123
|
+
const fieldRegex = /(\w+)\s*:\s*([^,}\n]+)/g;
|
|
124
|
+
let fieldMatch;
|
|
125
|
+
while ((fieldMatch = fieldRegex.exec(body)) !== null) {
|
|
126
|
+
const fieldName = fieldMatch[1].trim();
|
|
127
|
+
const fieldType = fieldMatch[2].trim().replace(/,\s*$/, '');
|
|
128
|
+
|
|
129
|
+
// Skip padding fields
|
|
130
|
+
if (fieldName.startsWith('_')) continue;
|
|
131
|
+
|
|
132
|
+
// Convert WGSL field name to u_ prefix for comparison
|
|
133
|
+
const uniformName = this._wgslFieldToUniform(fieldName);
|
|
134
|
+
uniforms.push({ name: uniformName, type: fieldType });
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return uniforms;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Convert a WGSL struct field name to the GLSL u_ convention.
|
|
142
|
+
* e.g. "time" -> "u_time", "rot4dXY" -> "u_rot4dXY"
|
|
143
|
+
* @private
|
|
144
|
+
*/
|
|
145
|
+
_wgslFieldToUniform(fieldName) {
|
|
146
|
+
if (fieldName.startsWith('u_')) return fieldName;
|
|
147
|
+
return 'u_' + fieldName;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// -----------------------------------------------------------------------
|
|
151
|
+
// System registration
|
|
152
|
+
// -----------------------------------------------------------------------
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Register a visualization system's shader sources for verification.
|
|
156
|
+
*
|
|
157
|
+
* @param {string} name - System name (e.g. 'quantum', 'faceted', 'holographic')
|
|
158
|
+
* @param {object} sources
|
|
159
|
+
* @param {string} [sources.glslVertex] - GLSL vertex shader source
|
|
160
|
+
* @param {string} [sources.glslFragment] - GLSL fragment shader source
|
|
161
|
+
* @param {string} [sources.wgslVertex] - WGSL vertex shader source
|
|
162
|
+
* @param {string} [sources.wgslFragment] - WGSL fragment shader source
|
|
163
|
+
*/
|
|
164
|
+
registerSystem(name, sources = {}) {
|
|
165
|
+
const glslUniforms = [
|
|
166
|
+
...this.parseGLSLUniforms(sources.glslVertex || ''),
|
|
167
|
+
...this.parseGLSLUniforms(sources.glslFragment || '')
|
|
168
|
+
];
|
|
169
|
+
|
|
170
|
+
// Deduplicate by name (vertex + fragment may both declare same uniform)
|
|
171
|
+
const glslMap = new Map();
|
|
172
|
+
for (const u of glslUniforms) {
|
|
173
|
+
if (!glslMap.has(u.name)) glslMap.set(u.name, u);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const wgslUniforms = [
|
|
177
|
+
...this.parseWGSLUniforms(sources.wgslVertex || ''),
|
|
178
|
+
...this.parseWGSLUniforms(sources.wgslFragment || '')
|
|
179
|
+
];
|
|
180
|
+
const wgslMap = new Map();
|
|
181
|
+
for (const u of wgslUniforms) {
|
|
182
|
+
if (!wgslMap.has(u.name)) wgslMap.set(u.name, u);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
this.systems.set(name, {
|
|
186
|
+
glslUniforms: glslMap,
|
|
187
|
+
wgslUniforms: wgslMap,
|
|
188
|
+
sources
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// -----------------------------------------------------------------------
|
|
193
|
+
// Verification
|
|
194
|
+
// -----------------------------------------------------------------------
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Run verification across all registered systems.
|
|
198
|
+
*
|
|
199
|
+
* @returns {{
|
|
200
|
+
* systems: Object.<string, {
|
|
201
|
+
* glslUniforms: string[],
|
|
202
|
+
* wgslUniforms: string[],
|
|
203
|
+
* missingRequired: string[],
|
|
204
|
+
* missingRecommended: string[],
|
|
205
|
+
* extraUniforms: string[],
|
|
206
|
+
* glslWgslMismatch: { glslOnly: string[], wgslOnly: string[] }
|
|
207
|
+
* }>,
|
|
208
|
+
* crossSystemMismatch: { uniform: string, presentIn: string[], missingFrom: string[] }[],
|
|
209
|
+
* summary: string,
|
|
210
|
+
* passed: boolean
|
|
211
|
+
* }}
|
|
212
|
+
*/
|
|
213
|
+
verify() {
|
|
214
|
+
const allRequired = new Set(this.STANDARD_UNIFORMS.required);
|
|
215
|
+
const allRecommended = new Set(this.STANDARD_UNIFORMS.recommended);
|
|
216
|
+
const allOptional = new Set(this.STANDARD_UNIFORMS.optional);
|
|
217
|
+
const allKnown = new Set([...allRequired, ...allRecommended, ...allOptional]);
|
|
218
|
+
|
|
219
|
+
const systemResults = {};
|
|
220
|
+
let overallPassed = true;
|
|
221
|
+
|
|
222
|
+
for (const [name, data] of this.systems) {
|
|
223
|
+
const glslNames = new Set(data.glslUniforms.keys());
|
|
224
|
+
const wgslNames = new Set(data.wgslUniforms.keys());
|
|
225
|
+
const allNames = new Set([...glslNames, ...wgslNames]);
|
|
226
|
+
|
|
227
|
+
// Required uniforms missing from GLSL fragment
|
|
228
|
+
const missingRequired = [...allRequired].filter(u => !glslNames.has(u));
|
|
229
|
+
|
|
230
|
+
// Recommended uniforms missing from GLSL fragment
|
|
231
|
+
const missingRecommended = [...allRecommended].filter(u => !glslNames.has(u));
|
|
232
|
+
|
|
233
|
+
// Extra uniforms not in any standard category
|
|
234
|
+
const extraUniforms = [...allNames].filter(u => !allKnown.has(u));
|
|
235
|
+
|
|
236
|
+
// GLSL vs WGSL mismatch (if both backends exist)
|
|
237
|
+
const glslOnly = [...glslNames].filter(u => wgslNames.size > 0 && !wgslNames.has(u));
|
|
238
|
+
const wgslOnly = [...wgslNames].filter(u => glslNames.size > 0 && !glslNames.has(u));
|
|
239
|
+
|
|
240
|
+
if (missingRequired.length > 0) overallPassed = false;
|
|
241
|
+
|
|
242
|
+
systemResults[name] = {
|
|
243
|
+
glslUniforms: [...glslNames].sort(),
|
|
244
|
+
wgslUniforms: [...wgslNames].sort(),
|
|
245
|
+
missingRequired,
|
|
246
|
+
missingRecommended,
|
|
247
|
+
extraUniforms,
|
|
248
|
+
glslWgslMismatch: { glslOnly, wgslOnly }
|
|
249
|
+
};
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Cross-system comparison: check which required/recommended uniforms
|
|
253
|
+
// are present in some systems but missing from others
|
|
254
|
+
const systemNames = [...this.systems.keys()];
|
|
255
|
+
const crossSystemMismatch = [];
|
|
256
|
+
|
|
257
|
+
const checkSet = [...allRequired, ...allRecommended];
|
|
258
|
+
for (const uniform of checkSet) {
|
|
259
|
+
const presentIn = [];
|
|
260
|
+
const missingFrom = [];
|
|
261
|
+
|
|
262
|
+
for (const sysName of systemNames) {
|
|
263
|
+
const data = this.systems.get(sysName);
|
|
264
|
+
const glslNames = new Set(data.glslUniforms.keys());
|
|
265
|
+
if (glslNames.has(uniform)) {
|
|
266
|
+
presentIn.push(sysName);
|
|
267
|
+
} else {
|
|
268
|
+
missingFrom.push(sysName);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
if (presentIn.length > 0 && missingFrom.length > 0) {
|
|
273
|
+
crossSystemMismatch.push({ uniform, presentIn, missingFrom });
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
if (crossSystemMismatch.length > 0) overallPassed = false;
|
|
278
|
+
|
|
279
|
+
// Build summary
|
|
280
|
+
const summaryLines = [];
|
|
281
|
+
summaryLines.push(`VIB3+ Shader Sync Verification Report`);
|
|
282
|
+
summaryLines.push(`Systems checked: ${systemNames.join(', ')}`);
|
|
283
|
+
summaryLines.push(`Overall status: ${overallPassed ? 'PASSED' : 'FAILED'}`);
|
|
284
|
+
summaryLines.push('');
|
|
285
|
+
|
|
286
|
+
for (const [sysName, result] of Object.entries(systemResults)) {
|
|
287
|
+
summaryLines.push(`[${sysName}]`);
|
|
288
|
+
summaryLines.push(` GLSL uniforms: ${result.glslUniforms.length}`);
|
|
289
|
+
summaryLines.push(` WGSL uniforms: ${result.wgslUniforms.length}`);
|
|
290
|
+
if (result.missingRequired.length > 0) {
|
|
291
|
+
summaryLines.push(` MISSING REQUIRED: ${result.missingRequired.join(', ')}`);
|
|
292
|
+
}
|
|
293
|
+
if (result.missingRecommended.length > 0) {
|
|
294
|
+
summaryLines.push(` Missing recommended: ${result.missingRecommended.join(', ')}`);
|
|
295
|
+
}
|
|
296
|
+
if (result.extraUniforms.length > 0) {
|
|
297
|
+
summaryLines.push(` Extra (system-specific): ${result.extraUniforms.join(', ')}`);
|
|
298
|
+
}
|
|
299
|
+
if (result.glslWgslMismatch.glslOnly.length > 0) {
|
|
300
|
+
summaryLines.push(` GLSL only (no WGSL): ${result.glslWgslMismatch.glslOnly.join(', ')}`);
|
|
301
|
+
}
|
|
302
|
+
if (result.glslWgslMismatch.wgslOnly.length > 0) {
|
|
303
|
+
summaryLines.push(` WGSL only (no GLSL): ${result.glslWgslMismatch.wgslOnly.join(', ')}`);
|
|
304
|
+
}
|
|
305
|
+
summaryLines.push('');
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
if (crossSystemMismatch.length > 0) {
|
|
309
|
+
summaryLines.push('[Cross-System Inconsistencies]');
|
|
310
|
+
for (const m of crossSystemMismatch) {
|
|
311
|
+
summaryLines.push(` ${m.uniform}: present in [${m.presentIn.join(', ')}], missing from [${m.missingFrom.join(', ')}]`);
|
|
312
|
+
}
|
|
313
|
+
summaryLines.push('');
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
return {
|
|
317
|
+
systems: systemResults,
|
|
318
|
+
crossSystemMismatch,
|
|
319
|
+
summary: summaryLines.join('\n'),
|
|
320
|
+
passed: overallPassed
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// -----------------------------------------------------------------------
|
|
325
|
+
// Console report
|
|
326
|
+
// -----------------------------------------------------------------------
|
|
327
|
+
|
|
328
|
+
/**
|
|
329
|
+
* Print a colour-coded report to the console.
|
|
330
|
+
* Works in both Node.js (ANSI codes) and browser (console.log styles).
|
|
331
|
+
*/
|
|
332
|
+
printReport() {
|
|
333
|
+
const report = this.verify();
|
|
334
|
+
const isBrowser = typeof window !== 'undefined';
|
|
335
|
+
|
|
336
|
+
if (isBrowser) {
|
|
337
|
+
this._printBrowserReport(report);
|
|
338
|
+
} else {
|
|
339
|
+
this._printNodeReport(report);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
return report;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
/** @private */
|
|
346
|
+
_printBrowserReport(report) {
|
|
347
|
+
const headerStyle = 'font-weight:bold;font-size:14px;color:#64ff96;';
|
|
348
|
+
const sysStyle = 'font-weight:bold;font-size:12px;color:#00bfff;';
|
|
349
|
+
const okStyle = 'color:#64ff96;';
|
|
350
|
+
const warnStyle = 'color:#ffa500;';
|
|
351
|
+
const errStyle = 'color:#ff4444;font-weight:bold;';
|
|
352
|
+
const dimStyle = 'color:#888;';
|
|
353
|
+
|
|
354
|
+
console.log('%c=== VIB3+ Shader Sync Verification ===', headerStyle);
|
|
355
|
+
console.log('%cSystems: %s', dimStyle, [...this.systems.keys()].join(', '));
|
|
356
|
+
console.log(
|
|
357
|
+
`%c${report.passed ? 'PASSED' : 'FAILED'}`,
|
|
358
|
+
report.passed ? okStyle : errStyle
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
for (const [sysName, result] of Object.entries(report.systems)) {
|
|
362
|
+
console.log('%c--- %s ---', sysStyle, sysName);
|
|
363
|
+
console.log('%cGLSL uniforms (%d): %s', dimStyle,
|
|
364
|
+
result.glslUniforms.length, result.glslUniforms.join(', '));
|
|
365
|
+
console.log('%cWGSL uniforms (%d): %s', dimStyle,
|
|
366
|
+
result.wgslUniforms.length, result.wgslUniforms.join(', '));
|
|
367
|
+
|
|
368
|
+
if (result.missingRequired.length > 0) {
|
|
369
|
+
console.log('%cMISSING REQUIRED: %s', errStyle,
|
|
370
|
+
result.missingRequired.join(', '));
|
|
371
|
+
} else {
|
|
372
|
+
console.log('%cAll required uniforms present', okStyle);
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
if (result.missingRecommended.length > 0) {
|
|
376
|
+
console.log('%cMissing recommended: %s', warnStyle,
|
|
377
|
+
result.missingRecommended.join(', '));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
if (result.extraUniforms.length > 0) {
|
|
381
|
+
console.log('%cExtra (system-specific): %s', dimStyle,
|
|
382
|
+
result.extraUniforms.join(', '));
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
if (result.glslWgslMismatch.glslOnly.length > 0) {
|
|
386
|
+
console.log('%cGLSL only (no WGSL): %s', warnStyle,
|
|
387
|
+
result.glslWgslMismatch.glslOnly.join(', '));
|
|
388
|
+
}
|
|
389
|
+
if (result.glslWgslMismatch.wgslOnly.length > 0) {
|
|
390
|
+
console.log('%cWGSL only (no GLSL): %s', warnStyle,
|
|
391
|
+
result.glslWgslMismatch.wgslOnly.join(', '));
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (report.crossSystemMismatch.length > 0) {
|
|
396
|
+
console.log('%c--- Cross-System Inconsistencies ---', errStyle);
|
|
397
|
+
for (const m of report.crossSystemMismatch) {
|
|
398
|
+
console.log(
|
|
399
|
+
'%c %s: present in [%s], missing from [%s]',
|
|
400
|
+
warnStyle, m.uniform,
|
|
401
|
+
m.presentIn.join(', '), m.missingFrom.join(', ')
|
|
402
|
+
);
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
/** @private */
|
|
408
|
+
_printNodeReport(report) {
|
|
409
|
+
const R = '\x1b[31m'; // red
|
|
410
|
+
const G = '\x1b[32m'; // green
|
|
411
|
+
const Y = '\x1b[33m'; // yellow
|
|
412
|
+
const C = '\x1b[36m'; // cyan
|
|
413
|
+
const D = '\x1b[90m'; // dim
|
|
414
|
+
const B = '\x1b[1m'; // bold
|
|
415
|
+
const X = '\x1b[0m'; // reset
|
|
416
|
+
|
|
417
|
+
console.log(`${B}${G}=== VIB3+ Shader Sync Verification ===${X}`);
|
|
418
|
+
console.log(`${D}Systems: ${[...this.systems.keys()].join(', ')}${X}`);
|
|
419
|
+
console.log(
|
|
420
|
+
report.passed
|
|
421
|
+
? `${B}${G}PASSED${X}`
|
|
422
|
+
: `${B}${R}FAILED${X}`
|
|
423
|
+
);
|
|
424
|
+
console.log('');
|
|
425
|
+
|
|
426
|
+
for (const [sysName, result] of Object.entries(report.systems)) {
|
|
427
|
+
console.log(`${B}${C}--- ${sysName} ---${X}`);
|
|
428
|
+
console.log(`${D} GLSL uniforms (${result.glslUniforms.length}): ${result.glslUniforms.join(', ')}${X}`);
|
|
429
|
+
console.log(`${D} WGSL uniforms (${result.wgslUniforms.length}): ${result.wgslUniforms.join(', ')}${X}`);
|
|
430
|
+
|
|
431
|
+
if (result.missingRequired.length > 0) {
|
|
432
|
+
console.log(`${R} MISSING REQUIRED: ${result.missingRequired.join(', ')}${X}`);
|
|
433
|
+
} else {
|
|
434
|
+
console.log(`${G} All required uniforms present${X}`);
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
if (result.missingRecommended.length > 0) {
|
|
438
|
+
console.log(`${Y} Missing recommended: ${result.missingRecommended.join(', ')}${X}`);
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (result.extraUniforms.length > 0) {
|
|
442
|
+
console.log(`${D} Extra (system-specific): ${result.extraUniforms.join(', ')}${X}`);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (result.glslWgslMismatch.glslOnly.length > 0) {
|
|
446
|
+
console.log(`${Y} GLSL only (no WGSL): ${result.glslWgslMismatch.glslOnly.join(', ')}${X}`);
|
|
447
|
+
}
|
|
448
|
+
if (result.glslWgslMismatch.wgslOnly.length > 0) {
|
|
449
|
+
console.log(`${Y} WGSL only (no GLSL): ${result.glslWgslMismatch.wgslOnly.join(', ')}${X}`);
|
|
450
|
+
}
|
|
451
|
+
console.log('');
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (report.crossSystemMismatch.length > 0) {
|
|
455
|
+
console.log(`${B}${R}--- Cross-System Inconsistencies ---${X}`);
|
|
456
|
+
for (const m of report.crossSystemMismatch) {
|
|
457
|
+
console.log(
|
|
458
|
+
`${Y} ${m.uniform}: present in [${m.presentIn.join(', ')}], missing from [${m.missingFrom.join(', ')}]${X}`
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
console.log('');
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// -----------------------------------------------------------------------
|
|
466
|
+
// Runtime verification (browser only - live WebGL programs)
|
|
467
|
+
// -----------------------------------------------------------------------
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* Verify a live WebGL program's active uniforms against the standard set.
|
|
471
|
+
* Call from browser console after shaders are compiled and linked.
|
|
472
|
+
*
|
|
473
|
+
* @param {WebGLRenderingContext|WebGL2RenderingContext} gl - GL context
|
|
474
|
+
* @param {WebGLProgram} program - Compiled and linked shader program
|
|
475
|
+
* @param {string} [systemName='unknown'] - Name for reporting
|
|
476
|
+
* @returns {{ activeUniforms: string[], missingRequired: string[], missingRecommended: string[], passed: boolean }}
|
|
477
|
+
*/
|
|
478
|
+
verifyRuntime(gl, program, systemName = 'unknown') {
|
|
479
|
+
if (!gl || !program) {
|
|
480
|
+
console.error('ShaderSyncVerifier.verifyRuntime: gl and program are required');
|
|
481
|
+
return { activeUniforms: [], missingRequired: [], missingRecommended: [], passed: false };
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
const numUniforms = gl.getProgramParameter(program, gl.ACTIVE_UNIFORMS);
|
|
485
|
+
const activeUniforms = [];
|
|
486
|
+
|
|
487
|
+
for (let i = 0; i < numUniforms; i++) {
|
|
488
|
+
const info = gl.getActiveUniform(program, i);
|
|
489
|
+
if (info) {
|
|
490
|
+
activeUniforms.push(info.name);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
const activeSet = new Set(activeUniforms);
|
|
495
|
+
|
|
496
|
+
const missingRequired = this.STANDARD_UNIFORMS.required.filter(
|
|
497
|
+
u => !activeSet.has(u)
|
|
498
|
+
);
|
|
499
|
+
const missingRecommended = this.STANDARD_UNIFORMS.recommended.filter(
|
|
500
|
+
u => !activeSet.has(u)
|
|
501
|
+
);
|
|
502
|
+
|
|
503
|
+
const passed = missingRequired.length === 0;
|
|
504
|
+
|
|
505
|
+
// Console output
|
|
506
|
+
const isBrowser = typeof window !== 'undefined';
|
|
507
|
+
if (isBrowser) {
|
|
508
|
+
const style = passed
|
|
509
|
+
? 'color:#64ff96;font-weight:bold;'
|
|
510
|
+
: 'color:#ff4444;font-weight:bold;';
|
|
511
|
+
console.log(`%cRuntime verification [${systemName}]: ${passed ? 'PASSED' : 'FAILED'}`, style);
|
|
512
|
+
console.log(` Active uniforms (${activeUniforms.length}):`, activeUniforms.sort().join(', '));
|
|
513
|
+
if (missingRequired.length > 0) {
|
|
514
|
+
console.log('%c MISSING REQUIRED: ' + missingRequired.join(', '), 'color:#ff4444;');
|
|
515
|
+
}
|
|
516
|
+
if (missingRecommended.length > 0) {
|
|
517
|
+
console.log('%c Missing recommended: ' + missingRecommended.join(', '), 'color:#ffa500;');
|
|
518
|
+
}
|
|
519
|
+
} else {
|
|
520
|
+
console.log(`Runtime verification [${systemName}]: ${passed ? 'PASSED' : 'FAILED'}`);
|
|
521
|
+
console.log(` Active uniforms (${activeUniforms.length}):`, activeUniforms.sort().join(', '));
|
|
522
|
+
if (missingRequired.length > 0) {
|
|
523
|
+
console.log(' MISSING REQUIRED:', missingRequired.join(', '));
|
|
524
|
+
}
|
|
525
|
+
if (missingRecommended.length > 0) {
|
|
526
|
+
console.log(' Missing recommended:', missingRecommended.join(', '));
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
return { activeUniforms, missingRequired, missingRecommended, passed };
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
// -----------------------------------------------------------------------
|
|
534
|
+
// Static analysis (no GL context needed)
|
|
535
|
+
// -----------------------------------------------------------------------
|
|
536
|
+
|
|
537
|
+
/**
|
|
538
|
+
* Analyse a single shader source without instantiating a verifier.
|
|
539
|
+
*
|
|
540
|
+
* @param {string} source - Shader source code (GLSL or WGSL)
|
|
541
|
+
* @param {'glsl'|'wgsl'} [language='glsl'] - Shader language
|
|
542
|
+
* @returns {{ uniforms: { name: string, type: string }[], language: string }}
|
|
543
|
+
*/
|
|
544
|
+
static analyzeSource(source, language = 'glsl') {
|
|
545
|
+
const verifier = new ShaderSyncVerifier();
|
|
546
|
+
let uniforms;
|
|
547
|
+
|
|
548
|
+
if (language === 'wgsl') {
|
|
549
|
+
uniforms = verifier.parseWGSLUniforms(source);
|
|
550
|
+
} else {
|
|
551
|
+
uniforms = verifier.parseGLSLUniforms(source);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
return { uniforms, language };
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
|
|
559
|
+
// ---------------------------------------------------------------------------
|
|
560
|
+
// Embedded shader sources for the three active VIB3+ systems
|
|
561
|
+
// ---------------------------------------------------------------------------
|
|
562
|
+
// These are extracted from the inline GLSL in each system's .js file so the
|
|
563
|
+
// tool can run as a standalone Node.js script without a browser.
|
|
564
|
+
// ---------------------------------------------------------------------------
|
|
565
|
+
|
|
566
|
+
/**
|
|
567
|
+
* Quantum system GLSL fragment shader uniforms (from QuantumVisualizer.js).
|
|
568
|
+
* The shader is defined inline in initShaders().
|
|
569
|
+
*/
|
|
570
|
+
const QUANTUM_GLSL_FRAGMENT = `
|
|
571
|
+
precision highp float;
|
|
572
|
+
uniform vec2 u_resolution;
|
|
573
|
+
uniform float u_time;
|
|
574
|
+
uniform vec2 u_mouse;
|
|
575
|
+
uniform float u_geometry;
|
|
576
|
+
uniform float u_gridDensity;
|
|
577
|
+
uniform float u_morphFactor;
|
|
578
|
+
uniform float u_chaos;
|
|
579
|
+
uniform float u_speed;
|
|
580
|
+
uniform float u_hue;
|
|
581
|
+
uniform float u_intensity;
|
|
582
|
+
uniform float u_saturation;
|
|
583
|
+
uniform float u_dimension;
|
|
584
|
+
uniform float u_rot4dXY;
|
|
585
|
+
uniform float u_rot4dXZ;
|
|
586
|
+
uniform float u_rot4dYZ;
|
|
587
|
+
uniform float u_rot4dXW;
|
|
588
|
+
uniform float u_rot4dYW;
|
|
589
|
+
uniform float u_rot4dZW;
|
|
590
|
+
uniform float u_mouseIntensity;
|
|
591
|
+
uniform float u_clickIntensity;
|
|
592
|
+
uniform float u_roleIntensity;
|
|
593
|
+
void main() { gl_FragColor = vec4(0.0); }
|
|
594
|
+
`;
|
|
595
|
+
|
|
596
|
+
/**
|
|
597
|
+
* Faceted system GLSL fragment shader uniforms (from FacetedSystem.js).
|
|
598
|
+
*/
|
|
599
|
+
const FACETED_GLSL_FRAGMENT = `
|
|
600
|
+
precision highp float;
|
|
601
|
+
uniform float u_time;
|
|
602
|
+
uniform vec2 u_resolution;
|
|
603
|
+
uniform float u_geometry;
|
|
604
|
+
uniform float u_rot4dXY;
|
|
605
|
+
uniform float u_rot4dXZ;
|
|
606
|
+
uniform float u_rot4dYZ;
|
|
607
|
+
uniform float u_rot4dXW;
|
|
608
|
+
uniform float u_rot4dYW;
|
|
609
|
+
uniform float u_rot4dZW;
|
|
610
|
+
uniform float u_dimension;
|
|
611
|
+
uniform float u_gridDensity;
|
|
612
|
+
uniform float u_morphFactor;
|
|
613
|
+
uniform float u_chaos;
|
|
614
|
+
uniform float u_hue;
|
|
615
|
+
uniform float u_intensity;
|
|
616
|
+
uniform float u_saturation;
|
|
617
|
+
uniform float u_speed;
|
|
618
|
+
uniform float u_mouseIntensity;
|
|
619
|
+
uniform float u_clickIntensity;
|
|
620
|
+
uniform float u_bass;
|
|
621
|
+
uniform float u_mid;
|
|
622
|
+
uniform float u_high;
|
|
623
|
+
void main() { gl_FragColor = vec4(0.0); }
|
|
624
|
+
`;
|
|
625
|
+
|
|
626
|
+
/**
|
|
627
|
+
* Faceted system WGSL fragment shader (from FacetedSystem.js inline).
|
|
628
|
+
*/
|
|
629
|
+
const FACETED_WGSL_FRAGMENT = `
|
|
630
|
+
struct VIB3Uniforms {
|
|
631
|
+
time: f32,
|
|
632
|
+
_pad0: f32,
|
|
633
|
+
resolution: vec2<f32>,
|
|
634
|
+
geometry: f32,
|
|
635
|
+
rot4dXY: f32,
|
|
636
|
+
rot4dXZ: f32,
|
|
637
|
+
rot4dYZ: f32,
|
|
638
|
+
rot4dXW: f32,
|
|
639
|
+
rot4dYW: f32,
|
|
640
|
+
rot4dZW: f32,
|
|
641
|
+
dimension: f32,
|
|
642
|
+
gridDensity: f32,
|
|
643
|
+
morphFactor: f32,
|
|
644
|
+
chaos: f32,
|
|
645
|
+
speed: f32,
|
|
646
|
+
hue: f32,
|
|
647
|
+
intensity: f32,
|
|
648
|
+
saturation: f32,
|
|
649
|
+
mouseIntensity: f32,
|
|
650
|
+
clickIntensity: f32,
|
|
651
|
+
bass: f32,
|
|
652
|
+
mid: f32,
|
|
653
|
+
high: f32,
|
|
654
|
+
layerScale: f32,
|
|
655
|
+
layerOpacity: f32,
|
|
656
|
+
_pad1: f32,
|
|
657
|
+
layerColor: vec3<f32>,
|
|
658
|
+
densityMult: f32,
|
|
659
|
+
speedMult: f32,
|
|
660
|
+
_pad2: vec3<f32>,
|
|
661
|
+
};
|
|
662
|
+
@group(0) @binding(0) var<uniform> u: VIB3Uniforms;
|
|
663
|
+
`;
|
|
664
|
+
|
|
665
|
+
/**
|
|
666
|
+
* Holographic system GLSL fragment shader uniforms (from HolographicVisualizer.js).
|
|
667
|
+
* This system uses non-standard names for several uniforms.
|
|
668
|
+
*/
|
|
669
|
+
const HOLOGRAPHIC_GLSL_FRAGMENT = `
|
|
670
|
+
precision highp float;
|
|
671
|
+
uniform vec2 u_resolution;
|
|
672
|
+
uniform float u_time;
|
|
673
|
+
uniform vec2 u_mouse;
|
|
674
|
+
uniform float u_geometry;
|
|
675
|
+
uniform float u_density;
|
|
676
|
+
uniform float u_speed;
|
|
677
|
+
uniform vec3 u_color;
|
|
678
|
+
uniform float u_intensity;
|
|
679
|
+
uniform float u_roleDensity;
|
|
680
|
+
uniform float u_roleSpeed;
|
|
681
|
+
uniform float u_colorShift;
|
|
682
|
+
uniform float u_chaosIntensity;
|
|
683
|
+
uniform float u_mouseIntensity;
|
|
684
|
+
uniform float u_clickIntensity;
|
|
685
|
+
uniform float u_densityVariation;
|
|
686
|
+
uniform float u_geometryType;
|
|
687
|
+
uniform float u_chaos;
|
|
688
|
+
uniform float u_morph;
|
|
689
|
+
uniform float u_touchMorph;
|
|
690
|
+
uniform float u_touchChaos;
|
|
691
|
+
uniform float u_scrollParallax;
|
|
692
|
+
uniform float u_gridDensityShift;
|
|
693
|
+
uniform float u_colorScrollShift;
|
|
694
|
+
uniform float u_audioDensityBoost;
|
|
695
|
+
uniform float u_audioMorphBoost;
|
|
696
|
+
uniform float u_audioSpeedBoost;
|
|
697
|
+
uniform float u_audioChaosBoost;
|
|
698
|
+
uniform float u_audioColorShift;
|
|
699
|
+
uniform float u_rot4dXY;
|
|
700
|
+
uniform float u_rot4dXZ;
|
|
701
|
+
uniform float u_rot4dYZ;
|
|
702
|
+
uniform float u_rot4dXW;
|
|
703
|
+
uniform float u_rot4dYW;
|
|
704
|
+
uniform float u_rot4dZW;
|
|
705
|
+
void main() { gl_FragColor = vec4(0.0); }
|
|
706
|
+
`;
|
|
707
|
+
|
|
708
|
+
/**
|
|
709
|
+
* Holographic system WGSL fragment shader (from holographic.frag.wgsl).
|
|
710
|
+
*/
|
|
711
|
+
const HOLOGRAPHIC_WGSL_FRAGMENT = `
|
|
712
|
+
struct VIB3Uniforms {
|
|
713
|
+
time: f32,
|
|
714
|
+
_pad0: f32,
|
|
715
|
+
resolution: vec2<f32>,
|
|
716
|
+
geometry: f32,
|
|
717
|
+
rot4dXY: f32,
|
|
718
|
+
rot4dXZ: f32,
|
|
719
|
+
rot4dYZ: f32,
|
|
720
|
+
rot4dXW: f32,
|
|
721
|
+
rot4dYW: f32,
|
|
722
|
+
rot4dZW: f32,
|
|
723
|
+
dimension: f32,
|
|
724
|
+
gridDensity: f32,
|
|
725
|
+
morphFactor: f32,
|
|
726
|
+
chaos: f32,
|
|
727
|
+
speed: f32,
|
|
728
|
+
hue: f32,
|
|
729
|
+
intensity: f32,
|
|
730
|
+
saturation: f32,
|
|
731
|
+
mouseIntensity: f32,
|
|
732
|
+
clickIntensity: f32,
|
|
733
|
+
bass: f32,
|
|
734
|
+
mid: f32,
|
|
735
|
+
high: f32,
|
|
736
|
+
layerScale: f32,
|
|
737
|
+
layerOpacity: f32,
|
|
738
|
+
_pad1: f32,
|
|
739
|
+
layerColor: vec3<f32>,
|
|
740
|
+
densityMult: f32,
|
|
741
|
+
speedMult: f32,
|
|
742
|
+
_pad2: vec3<f32>,
|
|
743
|
+
};
|
|
744
|
+
@group(0) @binding(0) var<uniform> u: VIB3Uniforms;
|
|
745
|
+
`;
|
|
746
|
+
|
|
747
|
+
/**
|
|
748
|
+
* Quantum system WGSL fragment shader (from quantum.frag.wgsl).
|
|
749
|
+
*/
|
|
750
|
+
const QUANTUM_WGSL_FRAGMENT = `
|
|
751
|
+
struct VIB3Uniforms {
|
|
752
|
+
time: f32,
|
|
753
|
+
_pad0: f32,
|
|
754
|
+
resolution: vec2<f32>,
|
|
755
|
+
geometry: f32,
|
|
756
|
+
rot4dXY: f32,
|
|
757
|
+
rot4dXZ: f32,
|
|
758
|
+
rot4dYZ: f32,
|
|
759
|
+
rot4dXW: f32,
|
|
760
|
+
rot4dYW: f32,
|
|
761
|
+
rot4dZW: f32,
|
|
762
|
+
dimension: f32,
|
|
763
|
+
gridDensity: f32,
|
|
764
|
+
morphFactor: f32,
|
|
765
|
+
chaos: f32,
|
|
766
|
+
speed: f32,
|
|
767
|
+
hue: f32,
|
|
768
|
+
intensity: f32,
|
|
769
|
+
saturation: f32,
|
|
770
|
+
mouseIntensity: f32,
|
|
771
|
+
clickIntensity: f32,
|
|
772
|
+
bass: f32,
|
|
773
|
+
mid: f32,
|
|
774
|
+
high: f32,
|
|
775
|
+
layerScale: f32,
|
|
776
|
+
layerOpacity: f32,
|
|
777
|
+
_pad1: f32,
|
|
778
|
+
layerColor: vec3<f32>,
|
|
779
|
+
densityMult: f32,
|
|
780
|
+
speedMult: f32,
|
|
781
|
+
_pad2: vec3<f32>,
|
|
782
|
+
};
|
|
783
|
+
@group(0) @binding(0) var<uniform> u: VIB3Uniforms;
|
|
784
|
+
`;
|
|
785
|
+
|
|
786
|
+
|
|
787
|
+
// ---------------------------------------------------------------------------
|
|
788
|
+
// runFullAudit - registers all 3 systems and runs verification
|
|
789
|
+
// ---------------------------------------------------------------------------
|
|
790
|
+
|
|
791
|
+
/**
|
|
792
|
+
* Register all three VIB3+ visualization systems and run a full audit.
|
|
793
|
+
* Returns the verification report object and prints to console.
|
|
794
|
+
*
|
|
795
|
+
* @returns {{ systems: object, crossSystemMismatch: object[], summary: string, passed: boolean }}
|
|
796
|
+
*/
|
|
797
|
+
export function runFullAudit() {
|
|
798
|
+
const verifier = new ShaderSyncVerifier();
|
|
799
|
+
|
|
800
|
+
// Register Quantum system
|
|
801
|
+
verifier.registerSystem('quantum', {
|
|
802
|
+
glslFragment: QUANTUM_GLSL_FRAGMENT,
|
|
803
|
+
wgslFragment: QUANTUM_WGSL_FRAGMENT
|
|
804
|
+
});
|
|
805
|
+
|
|
806
|
+
// Register Faceted system
|
|
807
|
+
verifier.registerSystem('faceted', {
|
|
808
|
+
glslFragment: FACETED_GLSL_FRAGMENT,
|
|
809
|
+
wgslFragment: FACETED_WGSL_FRAGMENT
|
|
810
|
+
});
|
|
811
|
+
|
|
812
|
+
// Register Holographic system
|
|
813
|
+
verifier.registerSystem('holographic', {
|
|
814
|
+
glslFragment: HOLOGRAPHIC_GLSL_FRAGMENT,
|
|
815
|
+
wgslFragment: HOLOGRAPHIC_WGSL_FRAGMENT
|
|
816
|
+
});
|
|
817
|
+
|
|
818
|
+
const report = verifier.printReport();
|
|
819
|
+
|
|
820
|
+
// Generate the uniform matrix table
|
|
821
|
+
_printUniformMatrix(verifier, report);
|
|
822
|
+
|
|
823
|
+
return report;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
|
|
827
|
+
/**
|
|
828
|
+
* Print a matrix showing which uniforms are present in which systems.
|
|
829
|
+
* @private
|
|
830
|
+
*/
|
|
831
|
+
function _printUniformMatrix(verifier, report) {
|
|
832
|
+
const isBrowser = typeof window !== 'undefined';
|
|
833
|
+
|
|
834
|
+
// Collect every uniform name across all systems
|
|
835
|
+
const allUniforms = new Set();
|
|
836
|
+
for (const result of Object.values(report.systems)) {
|
|
837
|
+
for (const u of result.glslUniforms) allUniforms.add(u);
|
|
838
|
+
for (const u of result.wgslUniforms) allUniforms.add(u);
|
|
839
|
+
}
|
|
840
|
+
// Also include standard uniforms even if missing everywhere
|
|
841
|
+
for (const u of verifier.STANDARD_UNIFORMS.required) allUniforms.add(u);
|
|
842
|
+
for (const u of verifier.STANDARD_UNIFORMS.recommended) allUniforms.add(u);
|
|
843
|
+
|
|
844
|
+
const sortedUniforms = [...allUniforms].sort();
|
|
845
|
+
const systemNames = Object.keys(report.systems);
|
|
846
|
+
|
|
847
|
+
// Categorize
|
|
848
|
+
const requiredSet = new Set(verifier.STANDARD_UNIFORMS.required);
|
|
849
|
+
const recommendedSet = new Set(verifier.STANDARD_UNIFORMS.recommended);
|
|
850
|
+
|
|
851
|
+
if (isBrowser) {
|
|
852
|
+
console.log('%c=== Uniform Coverage Matrix ===', 'font-weight:bold;font-size:12px;color:#64ff96;');
|
|
853
|
+
console.table(
|
|
854
|
+
sortedUniforms.reduce((table, uniform) => {
|
|
855
|
+
const row = { uniform, category: requiredSet.has(uniform) ? 'required' : (recommendedSet.has(uniform) ? 'recommended' : 'extra') };
|
|
856
|
+
for (const sysName of systemNames) {
|
|
857
|
+
const result = report.systems[sysName];
|
|
858
|
+
const inGlsl = result.glslUniforms.includes(uniform);
|
|
859
|
+
const inWgsl = result.wgslUniforms.includes(uniform);
|
|
860
|
+
if (inGlsl && inWgsl) row[sysName] = 'GLSL+WGSL';
|
|
861
|
+
else if (inGlsl) row[sysName] = 'GLSL';
|
|
862
|
+
else if (inWgsl) row[sysName] = 'WGSL';
|
|
863
|
+
else row[sysName] = '---';
|
|
864
|
+
}
|
|
865
|
+
table.push(row);
|
|
866
|
+
return table;
|
|
867
|
+
}, [])
|
|
868
|
+
);
|
|
869
|
+
} else {
|
|
870
|
+
const G = '\x1b[32m';
|
|
871
|
+
const Y = '\x1b[33m';
|
|
872
|
+
const R = '\x1b[31m';
|
|
873
|
+
const D = '\x1b[90m';
|
|
874
|
+
const B = '\x1b[1m';
|
|
875
|
+
const X = '\x1b[0m';
|
|
876
|
+
|
|
877
|
+
console.log(`\n${B}${G}=== Uniform Coverage Matrix ===${X}\n`);
|
|
878
|
+
|
|
879
|
+
// Header
|
|
880
|
+
const nameCol = 28;
|
|
881
|
+
const catCol = 14;
|
|
882
|
+
const sysCol = 16;
|
|
883
|
+
|
|
884
|
+
let header = 'Uniform'.padEnd(nameCol) + 'Category'.padEnd(catCol);
|
|
885
|
+
for (const sysName of systemNames) {
|
|
886
|
+
header += sysName.padEnd(sysCol);
|
|
887
|
+
}
|
|
888
|
+
console.log(`${B}${header}${X}`);
|
|
889
|
+
console.log('-'.repeat(nameCol + catCol + sysCol * systemNames.length));
|
|
890
|
+
|
|
891
|
+
for (const uniform of sortedUniforms) {
|
|
892
|
+
const category = requiredSet.has(uniform) ? 'required'
|
|
893
|
+
: (recommendedSet.has(uniform) ? 'recommended' : 'extra');
|
|
894
|
+
|
|
895
|
+
let line = uniform.padEnd(nameCol);
|
|
896
|
+
|
|
897
|
+
if (category === 'required') line += `${R}${category.padEnd(catCol)}${X}`;
|
|
898
|
+
else if (category === 'recommended') line += `${Y}${category.padEnd(catCol)}${X}`;
|
|
899
|
+
else line += `${D}${category.padEnd(catCol)}${X}`;
|
|
900
|
+
|
|
901
|
+
for (const sysName of systemNames) {
|
|
902
|
+
const result = report.systems[sysName];
|
|
903
|
+
const inGlsl = result.glslUniforms.includes(uniform);
|
|
904
|
+
const inWgsl = result.wgslUniforms.includes(uniform);
|
|
905
|
+
|
|
906
|
+
let cell;
|
|
907
|
+
if (inGlsl && inWgsl) cell = `${G}GLSL+WGSL${X}`;
|
|
908
|
+
else if (inGlsl) cell = `${Y}GLSL${X}`;
|
|
909
|
+
else if (inWgsl) cell = `${Y}WGSL${X}`;
|
|
910
|
+
else cell = `${R}---${X}`;
|
|
911
|
+
|
|
912
|
+
// Pad accounting for ANSI codes
|
|
913
|
+
const visibleLen = cell.replace(/\x1b\[\d+m/g, '').length;
|
|
914
|
+
line += cell + ' '.repeat(Math.max(0, sysCol - visibleLen));
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
console.log(line);
|
|
918
|
+
}
|
|
919
|
+
console.log('');
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
|
|
924
|
+
// ---------------------------------------------------------------------------
|
|
925
|
+
// CLI entry point (Node.js)
|
|
926
|
+
// ---------------------------------------------------------------------------
|
|
927
|
+
|
|
928
|
+
const isNodeMain = typeof process !== 'undefined'
|
|
929
|
+
&& typeof process.argv !== 'undefined'
|
|
930
|
+
&& process.argv[1]
|
|
931
|
+
&& (process.argv[1].endsWith('shader-sync-verify.js')
|
|
932
|
+
|| process.argv[1].endsWith('shader-sync-verify'));
|
|
933
|
+
|
|
934
|
+
if (isNodeMain) {
|
|
935
|
+
const report = runFullAudit();
|
|
936
|
+
process.exit(report.passed ? 0 : 1);
|
|
937
|
+
}
|