@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,3055 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trading Card Generator - Creates personalized trading cards from current visualization
|
|
3
|
+
* Allows users to export their current VIB34D state as a shareable trading card
|
|
4
|
+
*
|
|
5
|
+
* REFACTORED: Now uses modular system architecture
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { TradingCardSystemFaceted } from './systems/TradingCardSystemFaceted.js';
|
|
9
|
+
import { TradingCardSystemQuantum } from './systems/TradingCardSystemQuantum.js';
|
|
10
|
+
import { TradingCardSystemHolographic } from './systems/TradingCardSystemHolographic.js';
|
|
11
|
+
|
|
12
|
+
export class TradingCardGenerator {
|
|
13
|
+
constructor(engine) {
|
|
14
|
+
this.engine = engine;
|
|
15
|
+
// Detect current system reliably from multiple sources
|
|
16
|
+
this.currentSystem = this.detectCurrentSystem();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Reliably detect which visualization system is currently active
|
|
21
|
+
*/
|
|
22
|
+
detectCurrentSystem() {
|
|
23
|
+
// Method 1: Check active system button in UI
|
|
24
|
+
const activeSystemBtn = document.querySelector('.system-btn.active');
|
|
25
|
+
if (activeSystemBtn?.dataset.system) {
|
|
26
|
+
return activeSystemBtn.dataset.system;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Method 2: Check global variable
|
|
30
|
+
if (window.currentSystem) {
|
|
31
|
+
return window.currentSystem;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Method 3: Check which canvas layers are visible
|
|
35
|
+
const holographicLayers = document.getElementById('holographicLayers');
|
|
36
|
+
const polychoraLayers = document.getElementById('polychoraLayers');
|
|
37
|
+
const vib34dLayers = document.getElementById('vib34dLayers');
|
|
38
|
+
|
|
39
|
+
if (holographicLayers && holographicLayers.style.display !== 'none') {
|
|
40
|
+
return 'holographic';
|
|
41
|
+
} else if (polychoraLayers && polychoraLayers.style.display !== 'none') {
|
|
42
|
+
return 'polychora';
|
|
43
|
+
} else if (vib34dLayers && vib34dLayers.style.display !== 'none') {
|
|
44
|
+
return 'faceted';
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Fallback
|
|
48
|
+
console.warn('⚠️ Could not detect current system, defaulting to faceted');
|
|
49
|
+
return 'faceted';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Generate a trading card from current visualization state
|
|
54
|
+
*/
|
|
55
|
+
async generateTradingCard(format = 'classic') {
|
|
56
|
+
console.log('🎴 Generating trading card from current state...');
|
|
57
|
+
|
|
58
|
+
// Capture current parameters
|
|
59
|
+
const state = this.captureCurrentState();
|
|
60
|
+
|
|
61
|
+
// Capture the actual canvas visual as base64 image
|
|
62
|
+
const canvasImage = await this.captureCanvasImage();
|
|
63
|
+
|
|
64
|
+
// Generate card HTML based on format
|
|
65
|
+
const cardHTML = format === 'social' ?
|
|
66
|
+
this.generateSocialCard(state, canvasImage) :
|
|
67
|
+
this.generateClassicCard(state, canvasImage);
|
|
68
|
+
|
|
69
|
+
// Create blob and download
|
|
70
|
+
const blob = new Blob([cardHTML], { type: 'text/html' });
|
|
71
|
+
const url = URL.createObjectURL(blob);
|
|
72
|
+
|
|
73
|
+
// Generate filename with timestamp
|
|
74
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
75
|
+
const filename = `vib34d-card-${state.geometry.toLowerCase()}-${timestamp}.html`;
|
|
76
|
+
|
|
77
|
+
// Trigger download
|
|
78
|
+
const link = document.createElement('a');
|
|
79
|
+
link.href = url;
|
|
80
|
+
link.download = filename;
|
|
81
|
+
document.body.appendChild(link);
|
|
82
|
+
link.click();
|
|
83
|
+
document.body.removeChild(link);
|
|
84
|
+
URL.revokeObjectURL(url);
|
|
85
|
+
|
|
86
|
+
console.log(`🎴 Trading card generated: ${filename}`);
|
|
87
|
+
|
|
88
|
+
// Show success message
|
|
89
|
+
if (this.engine?.statusManager) {
|
|
90
|
+
this.engine.statusManager.success(
|
|
91
|
+
`🎴 Trading Card Created!<br>` +
|
|
92
|
+
`<strong>${state.name}</strong><br>` +
|
|
93
|
+
`Format: ${format === 'social' ? 'Social Media' : 'Classic'}<br>` +
|
|
94
|
+
`<small>File: ${filename}</small>`
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
return { success: true, filename, state };
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Generate trading card HTML without downloading (for viewer.html compatibility)
|
|
103
|
+
* @param {string} format - Card format ('classic' or 'social')
|
|
104
|
+
* @returns {Promise<{success: boolean, html: string}>} Card HTML for navigation
|
|
105
|
+
*/
|
|
106
|
+
async generateCardHTML(format = 'classic') {
|
|
107
|
+
console.log('🎴 Generating trading card HTML for navigation...');
|
|
108
|
+
|
|
109
|
+
// Capture current parameters
|
|
110
|
+
const state = this.captureCurrentState();
|
|
111
|
+
|
|
112
|
+
// Capture the actual canvas visual as base64 image
|
|
113
|
+
const canvasImage = await this.captureCanvasImage();
|
|
114
|
+
|
|
115
|
+
// Generate card HTML based on format
|
|
116
|
+
const cardHTML = format === 'social' ?
|
|
117
|
+
this.generateSocialCard(state, canvasImage) :
|
|
118
|
+
this.generateClassicCard(state, canvasImage);
|
|
119
|
+
|
|
120
|
+
return { success: true, html: cardHTML };
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Capture ALL 5 layers from the current active system and composite them properly
|
|
125
|
+
*/
|
|
126
|
+
async captureCanvasImage() {
|
|
127
|
+
console.log('📸 Capturing multi-layer visualization from system:', this.currentSystem);
|
|
128
|
+
|
|
129
|
+
// System-specific layer configuration
|
|
130
|
+
const systemLayers = {
|
|
131
|
+
'faceted': {
|
|
132
|
+
prefix: '',
|
|
133
|
+
layers: ['background-canvas', 'shadow-canvas', 'content-canvas', 'highlight-canvas', 'accent-canvas'],
|
|
134
|
+
name: 'VIB34D Faceted'
|
|
135
|
+
},
|
|
136
|
+
'holographic': {
|
|
137
|
+
prefix: 'holo-',
|
|
138
|
+
layers: ['background-canvas', 'shadow-canvas', 'content-canvas', 'highlight-canvas', 'accent-canvas'],
|
|
139
|
+
name: 'Active Holograms'
|
|
140
|
+
},
|
|
141
|
+
'polychora': {
|
|
142
|
+
prefix: 'polychora-',
|
|
143
|
+
layers: ['background-canvas', 'shadow-canvas', 'content-canvas', 'highlight-canvas', 'accent-canvas'],
|
|
144
|
+
name: 'Polychora System'
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
|
|
148
|
+
const systemConfig = systemLayers[this.currentSystem] || systemLayers['faceted'];
|
|
149
|
+
|
|
150
|
+
// Layer-specific properties matching the actual system
|
|
151
|
+
const layerProperties = {
|
|
152
|
+
'background-canvas': { alpha: 0.4, blendMode: 'normal' },
|
|
153
|
+
'shadow-canvas': { alpha: 0.6, blendMode: 'multiply' },
|
|
154
|
+
'content-canvas': { alpha: 1.0, blendMode: 'normal' },
|
|
155
|
+
'highlight-canvas': { alpha: 1.0, blendMode: 'screen' },
|
|
156
|
+
'accent-canvas': { alpha: 0.8, blendMode: 'overlay' }
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
// Create high-quality composite canvas
|
|
161
|
+
const compositeCanvas = document.createElement('canvas');
|
|
162
|
+
const targetWidth = 800;
|
|
163
|
+
const targetHeight = 600;
|
|
164
|
+
compositeCanvas.width = targetWidth;
|
|
165
|
+
compositeCanvas.height = targetHeight;
|
|
166
|
+
const ctx = compositeCanvas.getContext('2d');
|
|
167
|
+
|
|
168
|
+
// Start with black background
|
|
169
|
+
ctx.fillStyle = '#000';
|
|
170
|
+
ctx.fillRect(0, 0, targetWidth, targetHeight);
|
|
171
|
+
|
|
172
|
+
// Composite all 5 layers in correct order
|
|
173
|
+
let layersFound = 0;
|
|
174
|
+
for (const layerBase of systemConfig.layers) {
|
|
175
|
+
const layerId = systemConfig.prefix + layerBase;
|
|
176
|
+
const layerCanvas = document.getElementById(layerId);
|
|
177
|
+
|
|
178
|
+
if (layerCanvas && layerCanvas.width > 0 && layerCanvas.height > 0) {
|
|
179
|
+
const props = layerProperties[layerBase];
|
|
180
|
+
|
|
181
|
+
// Set blend mode and alpha
|
|
182
|
+
ctx.globalAlpha = props.alpha;
|
|
183
|
+
ctx.globalCompositeOperation = props.blendMode;
|
|
184
|
+
|
|
185
|
+
// Draw the layer
|
|
186
|
+
ctx.drawImage(layerCanvas, 0, 0, targetWidth, targetHeight);
|
|
187
|
+
layersFound++;
|
|
188
|
+
|
|
189
|
+
console.log(`✅ Composited ${layerId} (alpha: ${props.alpha}, blend: ${props.blendMode})`);
|
|
190
|
+
} else {
|
|
191
|
+
console.warn(`⚠️ Layer ${layerId} not found or empty`);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Reset composite operation
|
|
196
|
+
ctx.globalCompositeOperation = 'normal';
|
|
197
|
+
ctx.globalAlpha = 1.0;
|
|
198
|
+
|
|
199
|
+
if (layersFound === 0) {
|
|
200
|
+
console.error('❌ No layers captured from current system');
|
|
201
|
+
return null;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Convert to high-quality base64
|
|
205
|
+
const imageData = compositeCanvas.toDataURL('image/png', 0.95);
|
|
206
|
+
console.log(`✅ Multi-layer capture complete: ${layersFound} layers from ${systemConfig.name}`);
|
|
207
|
+
return imageData;
|
|
208
|
+
|
|
209
|
+
} catch (error) {
|
|
210
|
+
console.error('❌ Error capturing multi-layer canvas:', error);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Capture current visualization state with improved system detection
|
|
217
|
+
*/
|
|
218
|
+
captureCurrentState() {
|
|
219
|
+
// Detect current system more reliably
|
|
220
|
+
const activeSystemBtn = document.querySelector('.system-btn.active');
|
|
221
|
+
const detectedSystem = activeSystemBtn?.dataset.system || window.currentSystem || 'faceted';
|
|
222
|
+
this.currentSystem = detectedSystem;
|
|
223
|
+
|
|
224
|
+
console.log('🎯 Capturing state for system:', this.currentSystem);
|
|
225
|
+
|
|
226
|
+
// Get parameters based on current system
|
|
227
|
+
let params = {};
|
|
228
|
+
let geometryType = 0;
|
|
229
|
+
|
|
230
|
+
if (this.currentSystem === 'faceted' && this.engine) {
|
|
231
|
+
// VIB34D Faceted System
|
|
232
|
+
params = this.engine.parameterManager?.getAllParameters() || {};
|
|
233
|
+
geometryType = params.geometry || this.getActiveGeometryIndex();
|
|
234
|
+
} else if (this.currentSystem === 'holographic') {
|
|
235
|
+
// CRITICAL FIX: Use SAME parameter names as holographicSystem.getParameters()
|
|
236
|
+
// This ensures trading cards match gallery save/load system
|
|
237
|
+
params = {
|
|
238
|
+
geometry: this.getActiveGeometryIndex(),
|
|
239
|
+
gridDensity: parseFloat(document.getElementById('gridDensity')?.value || 15), // Raw value, not divided
|
|
240
|
+
morphFactor: parseFloat(document.getElementById('morphFactor')?.value || 1.0),
|
|
241
|
+
speed: parseFloat(document.getElementById('speed')?.value || 1.0),
|
|
242
|
+
chaos: parseFloat(document.getElementById('chaos')?.value || 0.2),
|
|
243
|
+
hue: parseFloat(document.getElementById('hue')?.value || 320), // Match holographic default
|
|
244
|
+
intensity: parseFloat(document.getElementById('intensity')?.value || 0.6), // Match holographic default
|
|
245
|
+
saturation: parseFloat(document.getElementById('saturation')?.value || 0.8),
|
|
246
|
+
rot4dXW: parseFloat(document.getElementById('rot4dXW')?.value || 0),
|
|
247
|
+
rot4dYW: parseFloat(document.getElementById('rot4dYW')?.value || 0),
|
|
248
|
+
rot4dZW: parseFloat(document.getElementById('rot4dZW')?.value || 0)
|
|
249
|
+
};
|
|
250
|
+
geometryType = params.geometry;
|
|
251
|
+
} else if (this.currentSystem === 'polychora') {
|
|
252
|
+
// Polychora System
|
|
253
|
+
params = {
|
|
254
|
+
polytope: this.getActiveGeometryIndex(),
|
|
255
|
+
gridDensity: parseFloat(document.getElementById('gridDensity')?.value || 15),
|
|
256
|
+
morphFactor: parseFloat(document.getElementById('morphFactor')?.value || 1.0),
|
|
257
|
+
chaos: parseFloat(document.getElementById('chaos')?.value || 0.2),
|
|
258
|
+
speed: parseFloat(document.getElementById('speed')?.value || 1.0),
|
|
259
|
+
hue: parseFloat(document.getElementById('hue')?.value || 200),
|
|
260
|
+
intensity: parseFloat(document.getElementById('intensity')?.value || 0.5),
|
|
261
|
+
saturation: parseFloat(document.getElementById('saturation')?.value || 0.8),
|
|
262
|
+
rot4dXW: parseFloat(document.getElementById('rot4dXW')?.value || 0),
|
|
263
|
+
rot4dYW: parseFloat(document.getElementById('rot4dYW')?.value || 0),
|
|
264
|
+
rot4dZW: parseFloat(document.getElementById('rot4dZW')?.value || 0)
|
|
265
|
+
};
|
|
266
|
+
geometryType = params.polytope;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
const geometryNames = ['TETRAHEDRON', 'HYPERCUBE', 'SPHERE', 'TORUS', 'KLEIN BOTTLE', 'FRACTAL', 'WAVE', 'CRYSTAL'];
|
|
270
|
+
const systemNames = {
|
|
271
|
+
faceted: 'FACETED',
|
|
272
|
+
holographic: 'HOLOGRAPHIC',
|
|
273
|
+
polychora: 'POLYCHORA'
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const state = {
|
|
277
|
+
name: `${geometryNames[geometryType] || 'QUANTUM'} ${systemNames[this.currentSystem] || 'SYSTEM'}`,
|
|
278
|
+
geometry: geometryNames[geometryType] || 'QUANTUM',
|
|
279
|
+
system: this.currentSystem,
|
|
280
|
+
dimension: (params.dimension || 3.8).toString(),
|
|
281
|
+
hue: params.hue || 200,
|
|
282
|
+
saturation: ((params.saturation || 0.8) * 100).toFixed(0),
|
|
283
|
+
intensity: ((params.intensity || 0.5) * 100).toFixed(0),
|
|
284
|
+
speed: (params.speed || 1.0).toFixed(1),
|
|
285
|
+
chaos: ((params.chaos || 0) * 100).toFixed(0),
|
|
286
|
+
rarity: this.calculateRarity(params),
|
|
287
|
+
parameters: params,
|
|
288
|
+
portalUrl: window.location.origin + '/vib34d-portal.html'
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
console.log('🎯 Captured state:', state);
|
|
292
|
+
return state;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
getActiveGeometryIndex() {
|
|
296
|
+
const activeBtn = document.querySelector('.geom-btn.active');
|
|
297
|
+
return activeBtn ? parseInt(activeBtn.dataset.index) : 0;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Calculate rarity based on parameter extremity
|
|
302
|
+
*/
|
|
303
|
+
calculateRarity(params) {
|
|
304
|
+
const extremity =
|
|
305
|
+
Math.abs(params.rot4dXW || 0) +
|
|
306
|
+
Math.abs(params.rot4dYW || 0) +
|
|
307
|
+
Math.abs(params.rot4dZW || 0) +
|
|
308
|
+
(params.chaos || 0) * 2 +
|
|
309
|
+
Math.abs((params.dimension || 3.8) - 3.8);
|
|
310
|
+
|
|
311
|
+
if (extremity > 8) return 'MYTHIC';
|
|
312
|
+
if (extremity > 6) return 'LEGENDARY';
|
|
313
|
+
if (extremity > 4) return 'EPIC';
|
|
314
|
+
if (extremity > 2) return 'RARE';
|
|
315
|
+
return 'COMMON';
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Generate classic vertical trading card HTML - ALWAYS use live WebGL
|
|
320
|
+
*/
|
|
321
|
+
generateClassicCard(state, canvasImage) {
|
|
322
|
+
// ALWAYS use live WebGL visualization, never static images
|
|
323
|
+
const visualizationContent = this.generateVisualizationCode(state);
|
|
324
|
+
|
|
325
|
+
return `<!DOCTYPE html>
|
|
326
|
+
<html lang="en">
|
|
327
|
+
<head>
|
|
328
|
+
<meta charset="UTF-8">
|
|
329
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
330
|
+
<title>VIB34D Trading Card - ${state.name}</title>
|
|
331
|
+
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
|
|
332
|
+
<style>
|
|
333
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
334
|
+
|
|
335
|
+
body {
|
|
336
|
+
background: #000;
|
|
337
|
+
color: #fff;
|
|
338
|
+
font-family: 'Orbitron', monospace;
|
|
339
|
+
overflow: hidden;
|
|
340
|
+
height: 100vh;
|
|
341
|
+
display: flex;
|
|
342
|
+
align-items: center;
|
|
343
|
+
justify-content: center;
|
|
344
|
+
background:
|
|
345
|
+
radial-gradient(circle at 20% 20%, rgba(120, 119, 198, 0.3) 0%, transparent 50%),
|
|
346
|
+
radial-gradient(circle at 80% 80%, rgba(255, 119, 198, 0.3) 0%, transparent 50%),
|
|
347
|
+
linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
.trading-card {
|
|
351
|
+
width: 400px;
|
|
352
|
+
height: auto;
|
|
353
|
+
background: rgba(0, 0, 0, 0.85);
|
|
354
|
+
border: 2px solid rgba(0, 255, 255, 0.3);
|
|
355
|
+
border-radius: 15px;
|
|
356
|
+
padding: 20px;
|
|
357
|
+
transition: all 0.4s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
358
|
+
cursor: pointer;
|
|
359
|
+
position: relative;
|
|
360
|
+
overflow: visible;
|
|
361
|
+
transform-style: preserve-3d;
|
|
362
|
+
transform-origin: 50% 50%;
|
|
363
|
+
will-change: transform;
|
|
364
|
+
/* CSS variables for mouse tracking */
|
|
365
|
+
--mouse-x: 50%;
|
|
366
|
+
--mouse-y: 50%;
|
|
367
|
+
--bend-intensity: 0;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.trading-card:hover {
|
|
371
|
+
border-color: #00ffff;
|
|
372
|
+
box-shadow:
|
|
373
|
+
0 30px 60px rgba(0, 255, 255, 0.3),
|
|
374
|
+
inset 0 2px 0 rgba(255, 255, 255, 0.2),
|
|
375
|
+
0 0 40px rgba(255, 0, 255, 0.4);
|
|
376
|
+
transform:
|
|
377
|
+
perspective(800px)
|
|
378
|
+
rotateY(calc((var(--mouse-x) - 50) * 0.25deg * var(--bend-intensity)))
|
|
379
|
+
rotateX(calc((var(--mouse-y) - 50) * 0.12deg * var(--bend-intensity)))
|
|
380
|
+
translateZ(calc(var(--bend-intensity) * 30px))
|
|
381
|
+
translateY(-10px)
|
|
382
|
+
scale(1.05);
|
|
383
|
+
backdrop-filter: blur(20px);
|
|
384
|
+
z-index: 10;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
@keyframes cardGlow {
|
|
388
|
+
0% {
|
|
389
|
+
box-shadow:
|
|
390
|
+
0 0 50px hsla(${state.hue}, 80%, 50%, 0.3),
|
|
391
|
+
inset 0 0 50px rgba(255, 255, 255, 0.05);
|
|
392
|
+
}
|
|
393
|
+
100% {
|
|
394
|
+
box-shadow:
|
|
395
|
+
0 0 80px hsla(${(state.hue + 60) % 360}, 80%, 50%, 0.4),
|
|
396
|
+
inset 0 0 80px rgba(255, 255, 255, 0.1);
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
.card-border {
|
|
401
|
+
position: absolute;
|
|
402
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
403
|
+
border-radius: 20px;
|
|
404
|
+
background: linear-gradient(45deg,
|
|
405
|
+
hsl(${state.hue}, 80%, 50%),
|
|
406
|
+
hsl(${(state.hue + 120) % 360}, 80%, 50%),
|
|
407
|
+
hsl(${(state.hue + 240) % 360}, 80%, 50%),
|
|
408
|
+
hsl(${state.hue}, 80%, 50%));
|
|
409
|
+
background-size: 300% 300%;
|
|
410
|
+
animation: borderShift 4s ease-in-out infinite;
|
|
411
|
+
z-index: -1;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
@keyframes borderShift {
|
|
415
|
+
0%, 100% { background-position: 0% 50%; }
|
|
416
|
+
50% { background-position: 100% 50%; }
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
.card-header {
|
|
420
|
+
position: relative;
|
|
421
|
+
z-index: 10;
|
|
422
|
+
padding: 20px;
|
|
423
|
+
text-align: center;
|
|
424
|
+
background: linear-gradient(180deg, rgba(0,0,0,0.8), transparent);
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.card-title {
|
|
428
|
+
font-size: 1.4rem;
|
|
429
|
+
font-weight: 900;
|
|
430
|
+
color: hsl(${state.hue}, 80%, 60%);
|
|
431
|
+
text-shadow: 0 0 20px hsla(${state.hue}, 80%, 60%, 0.8);
|
|
432
|
+
margin-bottom: 5px;
|
|
433
|
+
letter-spacing: 2px;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.card-subtitle {
|
|
437
|
+
font-size: 0.8rem;
|
|
438
|
+
color: rgba(255, 255, 255, 0.7);
|
|
439
|
+
font-weight: 400;
|
|
440
|
+
letter-spacing: 1px;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
.rarity-badge {
|
|
444
|
+
position: absolute;
|
|
445
|
+
top: 15px;
|
|
446
|
+
right: 15px;
|
|
447
|
+
background: ${state.rarity === 'MYTHIC' ? 'linear-gradient(45deg, #ff00ff, #00ffff)' :
|
|
448
|
+
state.rarity === 'LEGENDARY' ? 'linear-gradient(45deg, #ff6b35, #f7931e)' :
|
|
449
|
+
state.rarity === 'EPIC' ? 'linear-gradient(45deg, #9b59b6, #e74c3c)' :
|
|
450
|
+
state.rarity === 'RARE' ? 'linear-gradient(45deg, #3498db, #2ecc71)' :
|
|
451
|
+
'linear-gradient(45deg, #95a5a6, #7f8c8d)'};
|
|
452
|
+
color: ${state.rarity === 'COMMON' ? '#fff' : '#000'};
|
|
453
|
+
padding: 5px 15px;
|
|
454
|
+
border-radius: 15px;
|
|
455
|
+
font-size: 0.7rem;
|
|
456
|
+
font-weight: 700;
|
|
457
|
+
text-transform: uppercase;
|
|
458
|
+
letter-spacing: 1px;
|
|
459
|
+
box-shadow: 0 0 15px rgba(255, 255, 255, 0.3);
|
|
460
|
+
animation: rarityPulse 2s ease-in-out infinite;
|
|
461
|
+
}
|
|
462
|
+
|
|
463
|
+
@keyframes rarityPulse {
|
|
464
|
+
0%, 100% { transform: scale(1); }
|
|
465
|
+
50% { transform: scale(1.1); }
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
.card-preview {
|
|
469
|
+
width: 100%;
|
|
470
|
+
height: 350px;
|
|
471
|
+
aspect-ratio: 1 / 1;
|
|
472
|
+
border-radius: 12px;
|
|
473
|
+
overflow: visible;
|
|
474
|
+
margin-bottom: 15px;
|
|
475
|
+
background: #111;
|
|
476
|
+
position: relative;
|
|
477
|
+
border: 1px solid rgba(0, 255, 255, 0.2);
|
|
478
|
+
transform-style: preserve-3d;
|
|
479
|
+
transition: all 0.6s cubic-bezier(0.25, 0.46, 0.45, 0.94);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/* GALLERY-STYLE: Card preview expands and tilts based on mouse position */
|
|
483
|
+
.trading-card:hover .card-preview {
|
|
484
|
+
/* Match gallery card preview behavior exactly */
|
|
485
|
+
transform:
|
|
486
|
+
perspective(1000px)
|
|
487
|
+
translateZ(30px)
|
|
488
|
+
scale(1.1)
|
|
489
|
+
rotateY(calc((var(--mouse-x) - 50) * 0.2deg))
|
|
490
|
+
rotateX(calc((var(--mouse-y) - 50) * 0.15deg));
|
|
491
|
+
box-shadow:
|
|
492
|
+
0 0 50px rgba(0, 255, 255, 0.6),
|
|
493
|
+
0 0 100px rgba(255, 0, 255, 0.4),
|
|
494
|
+
inset 0 0 20px rgba(255, 255, 255, 0.1);
|
|
495
|
+
border: 2px solid rgba(255, 255, 255, 0.8);
|
|
496
|
+
background: rgba(17, 17, 17, 0.7);
|
|
497
|
+
backdrop-filter: blur(15px);
|
|
498
|
+
filter: brightness(1.2) contrast(1.05) saturate(1.1);
|
|
499
|
+
overflow: visible;
|
|
500
|
+
transition: transform 0.1s ease-out;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/* Canvas visualization container inside preview - EXACT MATCH */
|
|
504
|
+
.visualization-container {
|
|
505
|
+
width: 100%;
|
|
506
|
+
height: 100%;
|
|
507
|
+
position: relative;
|
|
508
|
+
border-radius: 12px;
|
|
509
|
+
overflow: hidden;
|
|
510
|
+
background: #000;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.visualizer-canvas {
|
|
514
|
+
width: 100%;
|
|
515
|
+
height: 100%;
|
|
516
|
+
display: block;
|
|
517
|
+
border-radius: 10px;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
.stats-panel {
|
|
521
|
+
padding: 0 20px;
|
|
522
|
+
margin-bottom: 20px;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
.stat-row {
|
|
526
|
+
display: flex;
|
|
527
|
+
justify-content: space-between;
|
|
528
|
+
margin-bottom: 8px;
|
|
529
|
+
font-size: 0.7rem;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
.stat-label {
|
|
533
|
+
color: rgba(255, 255, 255, 0.6);
|
|
534
|
+
text-transform: uppercase;
|
|
535
|
+
letter-spacing: 1px;
|
|
536
|
+
}
|
|
537
|
+
|
|
538
|
+
.stat-value {
|
|
539
|
+
color: hsl(${state.hue}, 80%, 60%);
|
|
540
|
+
font-weight: 700;
|
|
541
|
+
text-shadow: 0 0 10px hsla(${state.hue}, 80%, 60%, 0.5);
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
.action-panel {
|
|
545
|
+
position: absolute;
|
|
546
|
+
bottom: 0;
|
|
547
|
+
left: 0;
|
|
548
|
+
right: 0;
|
|
549
|
+
background: linear-gradient(0deg, rgba(0,0,0,0.9), transparent);
|
|
550
|
+
padding: 20px;
|
|
551
|
+
text-align: center;
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.collect-button {
|
|
555
|
+
width: 100%;
|
|
556
|
+
background: linear-gradient(45deg, #ff6b35, #f7931e);
|
|
557
|
+
border: none;
|
|
558
|
+
color: #000;
|
|
559
|
+
padding: 15px 20px;
|
|
560
|
+
border-radius: 25px;
|
|
561
|
+
font-family: 'Orbitron', monospace;
|
|
562
|
+
font-size: 1rem;
|
|
563
|
+
font-weight: 700;
|
|
564
|
+
text-transform: uppercase;
|
|
565
|
+
letter-spacing: 2px;
|
|
566
|
+
cursor: pointer;
|
|
567
|
+
transition: all 0.3s ease;
|
|
568
|
+
box-shadow: 0 0 30px rgba(255, 107, 53, 0.4);
|
|
569
|
+
position: relative;
|
|
570
|
+
overflow: hidden;
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
.collect-button:hover {
|
|
574
|
+
transform: translateY(-3px);
|
|
575
|
+
box-shadow: 0 0 50px rgba(255, 107, 53, 0.8);
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
.edition-number {
|
|
579
|
+
position: absolute;
|
|
580
|
+
bottom: 15px;
|
|
581
|
+
left: 20px;
|
|
582
|
+
font-size: 0.6rem;
|
|
583
|
+
color: rgba(255, 255, 255, 0.5);
|
|
584
|
+
font-weight: 400;
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
.hologram-effect {
|
|
588
|
+
position: absolute;
|
|
589
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
590
|
+
background: linear-gradient(45deg,
|
|
591
|
+
hsla(${state.hue}, 80%, 50%, 0.1),
|
|
592
|
+
hsla(${(state.hue + 120) % 360}, 80%, 50%, 0.1),
|
|
593
|
+
hsla(${(state.hue + 240) % 360}, 80%, 50%, 0.1));
|
|
594
|
+
background-size: 300% 300%;
|
|
595
|
+
animation: hologramShift 6s ease-in-out infinite;
|
|
596
|
+
pointer-events: none;
|
|
597
|
+
border-radius: 20px;
|
|
598
|
+
}
|
|
599
|
+
|
|
600
|
+
@keyframes hologramShift {
|
|
601
|
+
0%, 100% {
|
|
602
|
+
background-position: 0% 50%;
|
|
603
|
+
opacity: 0.3;
|
|
604
|
+
}
|
|
605
|
+
50% {
|
|
606
|
+
background-position: 100% 50%;
|
|
607
|
+
opacity: 0.6;
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
@media (max-width: 480px) {
|
|
612
|
+
.trading-card {
|
|
613
|
+
width: 350px;
|
|
614
|
+
height: 550px;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
</style>
|
|
618
|
+
</head>
|
|
619
|
+
<body>
|
|
620
|
+
<div class="trading-card">
|
|
621
|
+
<div class="card-border"></div>
|
|
622
|
+
<div class="hologram-effect"></div>
|
|
623
|
+
|
|
624
|
+
<div class="rarity-badge">${state.rarity}</div>
|
|
625
|
+
|
|
626
|
+
<div class="card-header">
|
|
627
|
+
<h1 class="card-title">${state.name}</h1>
|
|
628
|
+
<p class="card-subtitle">${state.system} System • ${state.dimension}D</p>
|
|
629
|
+
</div>
|
|
630
|
+
|
|
631
|
+
<div class="card-preview" data-preview-container>
|
|
632
|
+
<div class="visualization-container">
|
|
633
|
+
<canvas class="visualizer-canvas" id="vib34dCanvas"></canvas>
|
|
634
|
+
</div>
|
|
635
|
+
</div>
|
|
636
|
+
|
|
637
|
+
<div class="stats-panel">
|
|
638
|
+
<div class="stat-row">
|
|
639
|
+
<span class="stat-label">Dimension</span>
|
|
640
|
+
<span class="stat-value">${state.dimension}D</span>
|
|
641
|
+
</div>
|
|
642
|
+
<div class="stat-row">
|
|
643
|
+
<span class="stat-label">Geometry</span>
|
|
644
|
+
<span class="stat-value">${state.geometry}</span>
|
|
645
|
+
</div>
|
|
646
|
+
<div class="stat-row">
|
|
647
|
+
<span class="stat-label">System</span>
|
|
648
|
+
<span class="stat-value">${state.system.toUpperCase()}</span>
|
|
649
|
+
</div>
|
|
650
|
+
<div class="stat-row">
|
|
651
|
+
<span class="stat-label">Chaos</span>
|
|
652
|
+
<span class="stat-value">${state.chaos}%</span>
|
|
653
|
+
</div>
|
|
654
|
+
<div class="stat-row">
|
|
655
|
+
<span class="stat-label">Speed</span>
|
|
656
|
+
<span class="stat-value">${state.speed}x</span>
|
|
657
|
+
</div>
|
|
658
|
+
<div class="stat-row">
|
|
659
|
+
<span class="stat-label">Rarity</span>
|
|
660
|
+
<span class="stat-value">${state.rarity}</span>
|
|
661
|
+
</div>
|
|
662
|
+
</div>
|
|
663
|
+
|
|
664
|
+
<div class="action-panel">
|
|
665
|
+
<button class="collect-button" onclick="collectFullSystem()">
|
|
666
|
+
<span class="collect-text">🌌 Get VIB34D Collection</span>
|
|
667
|
+
</button>
|
|
668
|
+
</div>
|
|
669
|
+
|
|
670
|
+
<div class="edition-number">Generated ${new Date().toLocaleDateString()}</div>
|
|
671
|
+
</div>
|
|
672
|
+
|
|
673
|
+
<script>
|
|
674
|
+
${visualizationContent}
|
|
675
|
+
|
|
676
|
+
// Initialize LIVE multi-layer WebGL system
|
|
677
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
678
|
+
const canvas = document.getElementById('vib34dCanvas');
|
|
679
|
+
if (canvas) {
|
|
680
|
+
console.log('🎴 Initializing LIVE trading card system...');
|
|
681
|
+
new LiveTradingCardSystem();
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// EXACT MATCH: Add portfolio card mouse tracking behavior
|
|
685
|
+
initializeHolographicCardEffects();
|
|
686
|
+
});
|
|
687
|
+
|
|
688
|
+
// EXACT COPY from gallery.html - Mouse tracking for trading cards
|
|
689
|
+
function initializeHolographicCardEffects() {
|
|
690
|
+
console.log('🌟 Initializing trading card holographic effects...');
|
|
691
|
+
|
|
692
|
+
const card = document.querySelector('.trading-card');
|
|
693
|
+
if (!card) return;
|
|
694
|
+
|
|
695
|
+
let isHovering = false;
|
|
696
|
+
|
|
697
|
+
// Mouse enter - start holographic effect
|
|
698
|
+
card.addEventListener('mouseenter', (e) => {
|
|
699
|
+
isHovering = true;
|
|
700
|
+
card.style.setProperty('--bend-intensity', '0.8');
|
|
701
|
+
console.log('🌌 Trading card holographic effect activated');
|
|
702
|
+
});
|
|
703
|
+
|
|
704
|
+
// Mouse leave - end holographic effect
|
|
705
|
+
card.addEventListener('mouseleave', (e) => {
|
|
706
|
+
isHovering = false;
|
|
707
|
+
card.style.setProperty('--bend-intensity', '0');
|
|
708
|
+
card.style.setProperty('--mouse-x', '50%');
|
|
709
|
+
card.style.setProperty('--mouse-y', '50%');
|
|
710
|
+
console.log('🌌 Trading card holographic effect deactivated');
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
// Mouse move - track position for card bending + visual reactivity
|
|
714
|
+
card.addEventListener('mousemove', (e) => {
|
|
715
|
+
if (!isHovering) return;
|
|
716
|
+
|
|
717
|
+
const rect = card.getBoundingClientRect();
|
|
718
|
+
const cardX = ((e.clientX - rect.left) / rect.width) * 100;
|
|
719
|
+
const cardY = ((e.clientY - rect.top) / rect.height) * 100;
|
|
720
|
+
|
|
721
|
+
// Calculate distance from center for bend intensity
|
|
722
|
+
const centerX = 50;
|
|
723
|
+
const centerY = 50;
|
|
724
|
+
const distanceFromCenter = Math.sqrt(
|
|
725
|
+
Math.pow(cardX - centerX, 2) + Math.pow(cardY - centerY, 2)
|
|
726
|
+
);
|
|
727
|
+
|
|
728
|
+
// Dynamic bend intensity based on mouse position
|
|
729
|
+
const bendIntensity = Math.min(1, (distanceFromCenter / 70) + 0.3);
|
|
730
|
+
|
|
731
|
+
// Update CSS variables for real-time transformation
|
|
732
|
+
card.style.setProperty('--mouse-x', cardX);
|
|
733
|
+
card.style.setProperty('--mouse-y', cardY);
|
|
734
|
+
card.style.setProperty('--bend-intensity', bendIntensity);
|
|
735
|
+
});
|
|
736
|
+
|
|
737
|
+
console.log('✅ Trading card holographic effects initialized');
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// Collect button action - leads to VIB34D Portal
|
|
741
|
+
function collectFullSystem() {
|
|
742
|
+
const portalUrl = '${state.portalUrl}';
|
|
743
|
+
const confirmed = confirm(
|
|
744
|
+
"🌌 Ready to explore the complete VIB34D Collection?\\n\\n" +
|
|
745
|
+
"✨ 100+ Legendary Variations\\n" +
|
|
746
|
+
"🎮 3 Complete Visualization Systems\\n" +
|
|
747
|
+
"🎯 4D Mathematics & Physics\\n" +
|
|
748
|
+
"💫 Real-time Parameter Control\\n" +
|
|
749
|
+
"🎨 Create Your Own Trading Cards\\n\\n" +
|
|
750
|
+
"Click OK to visit the VIB34D Portal!"
|
|
751
|
+
);
|
|
752
|
+
|
|
753
|
+
if (confirmed) {
|
|
754
|
+
try {
|
|
755
|
+
window.location.href = portalUrl;
|
|
756
|
+
} catch (e) {
|
|
757
|
+
window.open(portalUrl, '_blank');
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
}
|
|
761
|
+
</script>
|
|
762
|
+
</body>
|
|
763
|
+
</html>`;
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
/**
|
|
767
|
+
* Generate social media card HTML
|
|
768
|
+
*/
|
|
769
|
+
generateSocialCard(state, canvasImage) {
|
|
770
|
+
const visualizationContent = canvasImage ?
|
|
771
|
+
this.generateImageVisualization(canvasImage) :
|
|
772
|
+
this.generateVisualizationCode(state);
|
|
773
|
+
|
|
774
|
+
return `<!DOCTYPE html>
|
|
775
|
+
<html lang="en">
|
|
776
|
+
<head>
|
|
777
|
+
<meta charset="UTF-8">
|
|
778
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
779
|
+
<title>VIB34D - ${state.name}</title>
|
|
780
|
+
<link href="https://fonts.googleapis.com/css2?family=Orbitron:wght@400;700;900&display=swap" rel="stylesheet">
|
|
781
|
+
<style>
|
|
782
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
783
|
+
|
|
784
|
+
body {
|
|
785
|
+
background: #000;
|
|
786
|
+
color: #fff;
|
|
787
|
+
font-family: 'Orbitron', monospace;
|
|
788
|
+
overflow: hidden;
|
|
789
|
+
height: 100vh;
|
|
790
|
+
display: flex;
|
|
791
|
+
align-items: center;
|
|
792
|
+
justify-content: center;
|
|
793
|
+
background: linear-gradient(135deg, #0a0a0a 0%, #1a1a2e 50%, #16213e 100%);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.social-card {
|
|
797
|
+
width: 500px;
|
|
798
|
+
height: 280px;
|
|
799
|
+
background: linear-gradient(145deg, rgba(0,0,0,0.9), rgba(30,30,60,0.9));
|
|
800
|
+
border-radius: 15px;
|
|
801
|
+
border: 2px solid transparent;
|
|
802
|
+
background-clip: padding-box;
|
|
803
|
+
position: relative;
|
|
804
|
+
overflow: hidden;
|
|
805
|
+
display: flex;
|
|
806
|
+
box-shadow: 0 0 40px hsla(${state.hue}, 80%, 50%, 0.3);
|
|
807
|
+
animation: cardPulse 4s ease-in-out infinite alternate;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
@keyframes cardPulse {
|
|
811
|
+
0% { box-shadow: 0 0 40px hsla(${state.hue}, 80%, 50%, 0.3); }
|
|
812
|
+
100% { box-shadow: 0 0 60px hsla(${(state.hue + 60) % 360}, 80%, 50%, 0.4); }
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
.card-visual {
|
|
816
|
+
flex: 1;
|
|
817
|
+
position: relative;
|
|
818
|
+
background: radial-gradient(ellipse at center, hsla(${state.hue}, 80%, 50%, 0.1), rgba(0, 0, 0, 0.8));
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
.visualizer-canvas {
|
|
822
|
+
width: 100%;
|
|
823
|
+
height: 100%;
|
|
824
|
+
display: block;
|
|
825
|
+
border-radius: 10px;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
.visualizer-container img {
|
|
829
|
+
width: 100%;
|
|
830
|
+
height: 100%;
|
|
831
|
+
object-fit: cover;
|
|
832
|
+
border-radius: 10px;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
.card-info {
|
|
836
|
+
flex: 1;
|
|
837
|
+
padding: 25px;
|
|
838
|
+
display: flex;
|
|
839
|
+
flex-direction: column;
|
|
840
|
+
justify-content: space-between;
|
|
841
|
+
background: linear-gradient(90deg, transparent, rgba(0,0,0,0.7));
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
.card-title {
|
|
845
|
+
font-size: 1.6rem;
|
|
846
|
+
font-weight: 900;
|
|
847
|
+
color: hsl(${state.hue}, 80%, 60%);
|
|
848
|
+
text-shadow: 0 0 20px hsla(${state.hue}, 80%, 60%, 0.8);
|
|
849
|
+
margin-bottom: 8px;
|
|
850
|
+
letter-spacing: 1px;
|
|
851
|
+
line-height: 1.2;
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
.card-subtitle {
|
|
855
|
+
font-size: 0.9rem;
|
|
856
|
+
color: rgba(255, 255, 255, 0.8);
|
|
857
|
+
margin-bottom: 20px;
|
|
858
|
+
letter-spacing: 1px;
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
.feature-list {
|
|
862
|
+
margin-bottom: 20px;
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
.feature-item {
|
|
866
|
+
font-size: 0.7rem;
|
|
867
|
+
color: rgba(255, 255, 255, 0.7);
|
|
868
|
+
margin-bottom: 5px;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
.cta-button {
|
|
872
|
+
background: linear-gradient(45deg, #ff6b35, #f7931e);
|
|
873
|
+
border: none;
|
|
874
|
+
color: #000;
|
|
875
|
+
padding: 12px 20px;
|
|
876
|
+
border-radius: 20px;
|
|
877
|
+
font-family: 'Orbitron', monospace;
|
|
878
|
+
font-size: 0.8rem;
|
|
879
|
+
font-weight: 700;
|
|
880
|
+
text-transform: uppercase;
|
|
881
|
+
letter-spacing: 1px;
|
|
882
|
+
cursor: pointer;
|
|
883
|
+
transition: all 0.3s ease;
|
|
884
|
+
box-shadow: 0 0 20px rgba(255, 107, 53, 0.4);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
.cta-button:hover {
|
|
888
|
+
transform: translateY(-2px);
|
|
889
|
+
box-shadow: 0 0 30px rgba(255, 107, 53, 0.7);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
.rarity-badge {
|
|
893
|
+
position: absolute;
|
|
894
|
+
top: 10px;
|
|
895
|
+
right: 10px;
|
|
896
|
+
background: ${state.rarity === 'MYTHIC' ? 'linear-gradient(45deg, #ff00ff, #00ffff)' :
|
|
897
|
+
state.rarity === 'LEGENDARY' ? 'linear-gradient(45deg, #ff6b35, #f7931e)' :
|
|
898
|
+
state.rarity === 'EPIC' ? 'linear-gradient(45deg, #9b59b6, #e74c3c)' :
|
|
899
|
+
state.rarity === 'RARE' ? 'linear-gradient(45deg, #3498db, #2ecc71)' :
|
|
900
|
+
'linear-gradient(45deg, #95a5a6, #7f8c8d)'};
|
|
901
|
+
color: ${state.rarity === 'COMMON' ? '#fff' : '#000'};
|
|
902
|
+
padding: 4px 12px;
|
|
903
|
+
border-radius: 10px;
|
|
904
|
+
font-size: 0.6rem;
|
|
905
|
+
font-weight: 700;
|
|
906
|
+
text-transform: uppercase;
|
|
907
|
+
letter-spacing: 1px;
|
|
908
|
+
box-shadow: 0 0 10px rgba(255, 255, 255, 0.3);
|
|
909
|
+
}
|
|
910
|
+
</style>
|
|
911
|
+
</head>
|
|
912
|
+
<body>
|
|
913
|
+
<div class="social-card">
|
|
914
|
+
<div class="rarity-badge">${state.rarity}</div>
|
|
915
|
+
|
|
916
|
+
<div class="card-visual">
|
|
917
|
+
${canvasImage ?
|
|
918
|
+
`<img src="${canvasImage}" class="visualizer-canvas" alt="${state.name}" style="width: 100%; height: 100%; object-fit: cover;" />` :
|
|
919
|
+
`<canvas class="visualizer-canvas" id="vib34dCanvas"></canvas>`
|
|
920
|
+
}
|
|
921
|
+
</div>
|
|
922
|
+
|
|
923
|
+
<div class="card-info">
|
|
924
|
+
<div>
|
|
925
|
+
<h1 class="card-title">VIB34D<br>${state.geometry}</h1>
|
|
926
|
+
<p class="card-subtitle">${state.system} • ${state.dimension}D</p>
|
|
927
|
+
|
|
928
|
+
<div class="feature-list">
|
|
929
|
+
<div class="feature-item">🌌 Dimension: ${state.dimension}D</div>
|
|
930
|
+
<div class="feature-item">⚡ Speed: ${state.speed}x</div>
|
|
931
|
+
<div class="feature-item">🎮 Chaos: ${state.chaos}%</div>
|
|
932
|
+
<div class="feature-item">✨ Rarity: ${state.rarity}</div>
|
|
933
|
+
</div>
|
|
934
|
+
</div>
|
|
935
|
+
|
|
936
|
+
<button class="cta-button" onclick="exploreCollection()">
|
|
937
|
+
🚀 Get Collection
|
|
938
|
+
</button>
|
|
939
|
+
</div>
|
|
940
|
+
</div>
|
|
941
|
+
|
|
942
|
+
<script>
|
|
943
|
+
${visualizationContent}
|
|
944
|
+
|
|
945
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
946
|
+
const canvas = document.getElementById('vib34dCanvas');
|
|
947
|
+
if (canvas) {
|
|
948
|
+
${canvasImage ? '// Using captured image, no animation needed' : 'new TradingCardVisualizer(canvas);'}
|
|
949
|
+
}
|
|
950
|
+
});
|
|
951
|
+
|
|
952
|
+
function exploreCollection() {
|
|
953
|
+
const portalUrl = '${state.portalUrl}';
|
|
954
|
+
if (confirm("🌌 Visit the VIB34D Portal to collect more variations?")) {
|
|
955
|
+
try {
|
|
956
|
+
window.location.href = portalUrl;
|
|
957
|
+
} catch (e) {
|
|
958
|
+
window.open(portalUrl, '_blank');
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
}
|
|
962
|
+
</script>
|
|
963
|
+
</body>
|
|
964
|
+
</html>`;
|
|
965
|
+
}
|
|
966
|
+
|
|
967
|
+
/**
|
|
968
|
+
* Generate LIVE multi-layer WebGL visualization code for the trading card
|
|
969
|
+
* REFACTORED: Now uses modular system architecture
|
|
970
|
+
*/
|
|
971
|
+
generateVisualizationCode(state) {
|
|
972
|
+
console.log(`🎯 Generating ${this.currentSystem} system using modular architecture`);
|
|
973
|
+
|
|
974
|
+
if (this.currentSystem === 'faceted') {
|
|
975
|
+
return TradingCardSystemFaceted.generateLiveSystem(state);
|
|
976
|
+
} else if (this.currentSystem === 'quantum') {
|
|
977
|
+
return TradingCardSystemQuantum.generateLiveSystem(state);
|
|
978
|
+
} else if (this.currentSystem === 'holographic') {
|
|
979
|
+
return TradingCardSystemHolographic.generateLiveSystem(state);
|
|
980
|
+
} else if (this.currentSystem === 'polychora') {
|
|
981
|
+
// Use faceted as fallback for polychora (placeholder system)
|
|
982
|
+
console.log('🔮 Polychora system using faceted fallback');
|
|
983
|
+
return TradingCardSystemFaceted.generateLiveSystem(state);
|
|
984
|
+
} else {
|
|
985
|
+
console.warn(`⚠️ Unknown system: ${this.currentSystem}, using faceted fallback`);
|
|
986
|
+
return TradingCardSystemFaceted.generateLiveSystem(state);
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
/**
|
|
991
|
+
* Generate LIVE 5-layer Faceted system with actual Engine code
|
|
992
|
+
*/
|
|
993
|
+
generateLiveFacetedSystem(state) {
|
|
994
|
+
return `
|
|
995
|
+
// LIVE VIB34D Faceted System - 5 Layer WebGL Rendering
|
|
996
|
+
class LiveTradingCardSystem {
|
|
997
|
+
constructor() {
|
|
998
|
+
this.layers = ['background', 'shadow', 'content', 'highlight', 'accent'];
|
|
999
|
+
this.visualizers = [];
|
|
1000
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
1001
|
+
this.startTime = Date.now();
|
|
1002
|
+
|
|
1003
|
+
this.initializeAllLayers();
|
|
1004
|
+
this.startRenderLoop();
|
|
1005
|
+
}
|
|
1006
|
+
|
|
1007
|
+
initializeAllLayers() {
|
|
1008
|
+
// Create 5 canvases dynamically
|
|
1009
|
+
this.layers.forEach((role, index) => {
|
|
1010
|
+
const canvas = document.createElement('canvas');
|
|
1011
|
+
canvas.id = 'card-' + role + '-canvas';
|
|
1012
|
+
canvas.style.position = 'absolute';
|
|
1013
|
+
canvas.style.top = '0';
|
|
1014
|
+
canvas.style.left = '0';
|
|
1015
|
+
canvas.style.width = '100%';
|
|
1016
|
+
canvas.style.height = '100%';
|
|
1017
|
+
canvas.style.zIndex = index;
|
|
1018
|
+
|
|
1019
|
+
// Set layer-specific blend modes and opacity
|
|
1020
|
+
if (role === 'background') {
|
|
1021
|
+
canvas.style.opacity = '0.4';
|
|
1022
|
+
} else if (role === 'shadow') {
|
|
1023
|
+
canvas.style.mixBlendMode = 'multiply';
|
|
1024
|
+
canvas.style.opacity = '0.6';
|
|
1025
|
+
} else if (role === 'content') {
|
|
1026
|
+
canvas.style.opacity = '1.0';
|
|
1027
|
+
} else if (role === 'highlight') {
|
|
1028
|
+
canvas.style.mixBlendMode = 'screen';
|
|
1029
|
+
} else if (role === 'accent') {
|
|
1030
|
+
canvas.style.mixBlendMode = 'overlay';
|
|
1031
|
+
canvas.style.opacity = '0.8';
|
|
1032
|
+
}
|
|
1033
|
+
|
|
1034
|
+
document.getElementById('vib34dCanvas').parentElement.appendChild(canvas);
|
|
1035
|
+
|
|
1036
|
+
// Create WebGL visualizer for this layer
|
|
1037
|
+
const visualizer = new LayerVisualizer(canvas, role, this.params);
|
|
1038
|
+
this.visualizers.push(visualizer);
|
|
1039
|
+
});
|
|
1040
|
+
|
|
1041
|
+
// Hide the original canvas
|
|
1042
|
+
document.getElementById('vib34dCanvas').style.display = 'none';
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
startRenderLoop() {
|
|
1046
|
+
const render = () => {
|
|
1047
|
+
const time = Date.now() - this.startTime;
|
|
1048
|
+
this.visualizers.forEach(visualizer => {
|
|
1049
|
+
visualizer.render(time);
|
|
1050
|
+
});
|
|
1051
|
+
requestAnimationFrame(render);
|
|
1052
|
+
};
|
|
1053
|
+
render();
|
|
1054
|
+
}
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
class LayerVisualizer {
|
|
1058
|
+
constructor(canvas, role, params) {
|
|
1059
|
+
this.canvas = canvas;
|
|
1060
|
+
this.role = role;
|
|
1061
|
+
this.params = params;
|
|
1062
|
+
this.gl = canvas.getContext('webgl');
|
|
1063
|
+
|
|
1064
|
+
const roleIntensities = {
|
|
1065
|
+
'background': 0.3, 'shadow': 0.5, 'content': 0.8,
|
|
1066
|
+
'highlight': 1.0, 'accent': 1.2
|
|
1067
|
+
};
|
|
1068
|
+
this.roleIntensity = roleIntensities[role] || 1.0;
|
|
1069
|
+
|
|
1070
|
+
this.initShaders();
|
|
1071
|
+
this.initBuffers();
|
|
1072
|
+
this.resize();
|
|
1073
|
+
}
|
|
1074
|
+
|
|
1075
|
+
resize() {
|
|
1076
|
+
this.canvas.width = this.canvas.clientWidth;
|
|
1077
|
+
this.canvas.height = this.canvas.clientHeight;
|
|
1078
|
+
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
initShaders() {
|
|
1082
|
+
const vertexShaderSource = \`attribute vec2 a_position;
|
|
1083
|
+
void main() {
|
|
1084
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
1085
|
+
}\`;
|
|
1086
|
+
|
|
1087
|
+
// EXACT FRAGMENT SHADER FROM FACETED SYSTEM
|
|
1088
|
+
const fragmentShaderSource = \`precision highp float;
|
|
1089
|
+
uniform vec2 u_resolution;
|
|
1090
|
+
uniform float u_time;
|
|
1091
|
+
uniform vec2 u_mouse;
|
|
1092
|
+
uniform float u_geometry;
|
|
1093
|
+
uniform float u_gridDensity;
|
|
1094
|
+
uniform float u_morphFactor;
|
|
1095
|
+
uniform float u_chaos;
|
|
1096
|
+
uniform float u_speed;
|
|
1097
|
+
uniform float u_hue;
|
|
1098
|
+
uniform float u_intensity;
|
|
1099
|
+
uniform float u_saturation;
|
|
1100
|
+
uniform float u_dimension;
|
|
1101
|
+
uniform float u_rot4dXW;
|
|
1102
|
+
uniform float u_rot4dYW;
|
|
1103
|
+
uniform float u_rot4dZW;
|
|
1104
|
+
uniform float u_mouseIntensity;
|
|
1105
|
+
uniform float u_clickIntensity;
|
|
1106
|
+
uniform float u_roleIntensity;
|
|
1107
|
+
|
|
1108
|
+
// 4D rotation matrices
|
|
1109
|
+
mat4 rotateXW(float theta) {
|
|
1110
|
+
float c = cos(theta);
|
|
1111
|
+
float s = sin(theta);
|
|
1112
|
+
return mat4(c, 0.0, 0.0, -s, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, s, 0.0, 0.0, c);
|
|
1113
|
+
}
|
|
1114
|
+
mat4 rotateYW(float theta) {
|
|
1115
|
+
float c = cos(theta);
|
|
1116
|
+
float s = sin(theta);
|
|
1117
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c);
|
|
1118
|
+
}
|
|
1119
|
+
mat4 rotateZW(float theta) {
|
|
1120
|
+
float c = cos(theta);
|
|
1121
|
+
float s = sin(theta);
|
|
1122
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c);
|
|
1123
|
+
}
|
|
1124
|
+
vec3 project4Dto3D(vec4 p) {
|
|
1125
|
+
float w = 2.5 / (2.5 + p.w);
|
|
1126
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
1127
|
+
}
|
|
1128
|
+
|
|
1129
|
+
float geometryFunction(vec4 p) {
|
|
1130
|
+
int geomType = int(u_geometry);
|
|
1131
|
+
|
|
1132
|
+
if (geomType == 0) {
|
|
1133
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
1134
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
1135
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
1136
|
+
}
|
|
1137
|
+
else if (geomType == 1) {
|
|
1138
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
1139
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
1140
|
+
float minDist = min(min(dist.x, dist.y), min(dist.z, dist.w));
|
|
1141
|
+
return minDist * u_morphFactor;
|
|
1142
|
+
}
|
|
1143
|
+
else if (geomType == 2) {
|
|
1144
|
+
float r = length(p);
|
|
1145
|
+
float density = u_gridDensity * 0.08;
|
|
1146
|
+
float spheres = abs(fract(r * density) - 0.5) * 2.0;
|
|
1147
|
+
float theta = atan(p.y, p.x);
|
|
1148
|
+
float harmonics = sin(theta * 3.0) * 0.2;
|
|
1149
|
+
return (spheres + harmonics) * u_morphFactor;
|
|
1150
|
+
}
|
|
1151
|
+
else if (geomType == 3) {
|
|
1152
|
+
float r1 = length(p.xy) - 2.0;
|
|
1153
|
+
float torus = length(vec2(r1, p.z)) - 0.8;
|
|
1154
|
+
float lattice = sin(p.x * u_gridDensity * 0.08) * sin(p.y * u_gridDensity * 0.08);
|
|
1155
|
+
return (torus + lattice * 0.3) * u_morphFactor;
|
|
1156
|
+
}
|
|
1157
|
+
else if (geomType == 4) {
|
|
1158
|
+
float u = atan(p.y, p.x);
|
|
1159
|
+
float v = atan(p.w, p.z);
|
|
1160
|
+
float dist = length(p) - 2.0;
|
|
1161
|
+
float lattice = sin(u * u_gridDensity * 0.08) * sin(v * u_gridDensity * 0.08);
|
|
1162
|
+
return (dist + lattice * 0.4) * u_morphFactor;
|
|
1163
|
+
}
|
|
1164
|
+
else if (geomType == 5) {
|
|
1165
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
1166
|
+
pos = abs(pos * 2.0 - 1.0);
|
|
1167
|
+
float dist = length(max(abs(pos) - 1.0, 0.0));
|
|
1168
|
+
return dist * u_morphFactor;
|
|
1169
|
+
}
|
|
1170
|
+
else if (geomType == 6) {
|
|
1171
|
+
float freq = u_gridDensity * 0.08;
|
|
1172
|
+
float time = u_time * 0.001 * u_speed;
|
|
1173
|
+
float wave1 = sin(p.x * freq + time);
|
|
1174
|
+
float wave2 = sin(p.y * freq + time * 1.3);
|
|
1175
|
+
float wave3 = sin(p.z * freq * 0.8 + time * 0.7);
|
|
1176
|
+
float interference = wave1 * wave2 * wave3;
|
|
1177
|
+
return interference * u_morphFactor;
|
|
1178
|
+
}
|
|
1179
|
+
else if (geomType == 7) {
|
|
1180
|
+
vec4 pos = fract(p * u_gridDensity * 0.08) - 0.5;
|
|
1181
|
+
float cube = max(max(abs(pos.x), abs(pos.y)), max(abs(pos.z), abs(pos.w)));
|
|
1182
|
+
return cube * u_morphFactor;
|
|
1183
|
+
}
|
|
1184
|
+
else {
|
|
1185
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
1186
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
1187
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
void main() {
|
|
1192
|
+
vec2 uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / min(u_resolution.x, u_resolution.y);
|
|
1193
|
+
|
|
1194
|
+
float timeSpeed = u_time * 0.0001 * u_speed;
|
|
1195
|
+
vec4 pos = vec4(uv * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
1196
|
+
pos.xy += (u_mouse - 0.5) * u_mouseIntensity * 2.0;
|
|
1197
|
+
|
|
1198
|
+
pos = rotateXW(u_rot4dXW) * pos;
|
|
1199
|
+
pos = rotateYW(u_rot4dYW) * pos;
|
|
1200
|
+
pos = rotateZW(u_rot4dZW) * pos;
|
|
1201
|
+
|
|
1202
|
+
float value = geometryFunction(pos);
|
|
1203
|
+
|
|
1204
|
+
float noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
1205
|
+
value += noise * u_chaos;
|
|
1206
|
+
|
|
1207
|
+
float geometryIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
1208
|
+
geometryIntensity += u_clickIntensity * 0.3;
|
|
1209
|
+
|
|
1210
|
+
float finalIntensity = geometryIntensity * u_intensity;
|
|
1211
|
+
|
|
1212
|
+
float hue = u_hue / 360.0 + value * 0.1;
|
|
1213
|
+
|
|
1214
|
+
vec3 baseColor = vec3(
|
|
1215
|
+
sin(hue * 6.28318 + 0.0) * 0.5 + 0.5,
|
|
1216
|
+
sin(hue * 6.28318 + 2.0943) * 0.5 + 0.5,
|
|
1217
|
+
sin(hue * 6.28318 + 4.1887) * 0.5 + 0.5
|
|
1218
|
+
);
|
|
1219
|
+
|
|
1220
|
+
float gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
1221
|
+
vec3 color = mix(vec3(gray), baseColor, u_saturation) * finalIntensity;
|
|
1222
|
+
|
|
1223
|
+
gl_FragColor = vec4(color, finalIntensity * u_roleIntensity);
|
|
1224
|
+
}\`;
|
|
1225
|
+
|
|
1226
|
+
this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
|
|
1227
|
+
this.uniforms = {
|
|
1228
|
+
resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
1229
|
+
time: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
1230
|
+
mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
|
|
1231
|
+
geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
|
|
1232
|
+
gridDensity: this.gl.getUniformLocation(this.program, 'u_gridDensity'),
|
|
1233
|
+
morphFactor: this.gl.getUniformLocation(this.program, 'u_morphFactor'),
|
|
1234
|
+
chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
|
|
1235
|
+
speed: this.gl.getUniformLocation(this.program, 'u_speed'),
|
|
1236
|
+
hue: this.gl.getUniformLocation(this.program, 'u_hue'),
|
|
1237
|
+
intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
1238
|
+
saturation: this.gl.getUniformLocation(this.program, 'u_saturation'),
|
|
1239
|
+
dimension: this.gl.getUniformLocation(this.program, 'u_dimension'),
|
|
1240
|
+
rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
|
|
1241
|
+
rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
|
|
1242
|
+
rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW'),
|
|
1243
|
+
mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
|
|
1244
|
+
clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
|
|
1245
|
+
roleIntensity: this.gl.getUniformLocation(this.program, 'u_roleIntensity')
|
|
1246
|
+
};
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
createProgram(vertexSource, fragmentSource) {
|
|
1250
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
|
|
1251
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
1252
|
+
|
|
1253
|
+
const program = this.gl.createProgram();
|
|
1254
|
+
this.gl.attachShader(program, vertexShader);
|
|
1255
|
+
this.gl.attachShader(program, fragmentShader);
|
|
1256
|
+
this.gl.linkProgram(program);
|
|
1257
|
+
|
|
1258
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
1259
|
+
console.error('Program linking failed:', this.gl.getProgramInfoLog(program));
|
|
1260
|
+
return null;
|
|
1261
|
+
}
|
|
1262
|
+
|
|
1263
|
+
return program;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
createShader(type, source) {
|
|
1267
|
+
const shader = this.gl.createShader(type);
|
|
1268
|
+
this.gl.shaderSource(shader, source);
|
|
1269
|
+
this.gl.compileShader(shader);
|
|
1270
|
+
|
|
1271
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
1272
|
+
console.error('Shader compilation failed:', this.gl.getShaderInfoLog(shader));
|
|
1273
|
+
return null;
|
|
1274
|
+
}
|
|
1275
|
+
|
|
1276
|
+
return shader;
|
|
1277
|
+
}
|
|
1278
|
+
|
|
1279
|
+
initBuffers() {
|
|
1280
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
1281
|
+
|
|
1282
|
+
this.buffer = this.gl.createBuffer();
|
|
1283
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
|
|
1284
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
|
1285
|
+
|
|
1286
|
+
const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
|
|
1287
|
+
this.gl.enableVertexAttribArray(positionLocation);
|
|
1288
|
+
this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
|
|
1289
|
+
}
|
|
1290
|
+
|
|
1291
|
+
render(time) {
|
|
1292
|
+
if (!this.program) return;
|
|
1293
|
+
|
|
1294
|
+
this.resize();
|
|
1295
|
+
this.gl.useProgram(this.program);
|
|
1296
|
+
|
|
1297
|
+
this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
1298
|
+
this.gl.uniform1f(this.uniforms.time, time);
|
|
1299
|
+
this.gl.uniform2f(this.uniforms.mouse, 0.5, 0.5);
|
|
1300
|
+
this.gl.uniform1f(this.uniforms.geometry, this.params.geometry || 0);
|
|
1301
|
+
this.gl.uniform1f(this.uniforms.gridDensity, this.params.gridDensity || 15);
|
|
1302
|
+
this.gl.uniform1f(this.uniforms.morphFactor, this.params.morphFactor || 1.0);
|
|
1303
|
+
this.gl.uniform1f(this.uniforms.chaos, this.params.chaos || 0.2);
|
|
1304
|
+
this.gl.uniform1f(this.uniforms.speed, this.params.speed || 1.0);
|
|
1305
|
+
this.gl.uniform1f(this.uniforms.hue, this.params.hue || 200);
|
|
1306
|
+
this.gl.uniform1f(this.uniforms.intensity, this.params.intensity || 0.5);
|
|
1307
|
+
this.gl.uniform1f(this.uniforms.saturation, this.params.saturation || 0.8);
|
|
1308
|
+
this.gl.uniform1f(this.uniforms.dimension, this.params.dimension || 3.8);
|
|
1309
|
+
this.gl.uniform1f(this.uniforms.rot4dXW, this.params.rot4dXW || 0.0);
|
|
1310
|
+
this.gl.uniform1f(this.uniforms.rot4dYW, this.params.rot4dYW || 0.0);
|
|
1311
|
+
this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
|
|
1312
|
+
this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity || 0.0);
|
|
1313
|
+
this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity || 0.0);
|
|
1314
|
+
this.gl.uniform1f(this.uniforms.roleIntensity, this.roleIntensity);
|
|
1315
|
+
|
|
1316
|
+
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// Enhanced interactivity system - FIXED CANVAS SCOPE
|
|
1321
|
+
const canvas = document.getElementById('vib34dCanvas');
|
|
1322
|
+
if (!canvas) {
|
|
1323
|
+
console.error('Canvas not found for interactivity');
|
|
1324
|
+
return;
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
let mouseX = 0.5, mouseY = 0.5, mouseIntensity = 0.0;
|
|
1328
|
+
let clickIntensity = 0.0;
|
|
1329
|
+
let currentTouch = null;
|
|
1330
|
+
|
|
1331
|
+
// Mouse interactions
|
|
1332
|
+
canvas.addEventListener('mousemove', (e) => {
|
|
1333
|
+
const rect = canvas.getBoundingClientRect();
|
|
1334
|
+
mouseX = (e.clientX - rect.left) / rect.width;
|
|
1335
|
+
mouseY = 1.0 - (e.clientY - rect.top) / rect.height;
|
|
1336
|
+
mouseIntensity = Math.min(1.0, Math.sqrt(e.movementX*e.movementX + e.movementY*e.movementY) / 40);
|
|
1337
|
+
|
|
1338
|
+
// Update all layer visualizers
|
|
1339
|
+
layers.forEach(layer => {
|
|
1340
|
+
if (layer.visualizer) {
|
|
1341
|
+
layer.visualizer.mouseX = mouseX;
|
|
1342
|
+
layer.visualizer.mouseY = mouseY;
|
|
1343
|
+
layer.visualizer.mouseIntensity = mouseIntensity;
|
|
1344
|
+
}
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1347
|
+
|
|
1348
|
+
canvas.addEventListener('click', (e) => {
|
|
1349
|
+
clickIntensity = 1.0;
|
|
1350
|
+
layers.forEach(layer => {
|
|
1351
|
+
if (layer.visualizer) {
|
|
1352
|
+
layer.visualizer.clickIntensity = clickIntensity;
|
|
1353
|
+
}
|
|
1354
|
+
});
|
|
1355
|
+
setTimeout(() => {
|
|
1356
|
+
clickIntensity = 0.0;
|
|
1357
|
+
layers.forEach(layer => {
|
|
1358
|
+
if (layer.visualizer) {
|
|
1359
|
+
layer.visualizer.clickIntensity = 0.0;
|
|
1360
|
+
}
|
|
1361
|
+
});
|
|
1362
|
+
}, 500);
|
|
1363
|
+
});
|
|
1364
|
+
|
|
1365
|
+
// Touch interactions
|
|
1366
|
+
canvas.addEventListener('touchstart', (e) => {
|
|
1367
|
+
e.preventDefault();
|
|
1368
|
+
if (e.touches.length > 0) {
|
|
1369
|
+
currentTouch = e.touches[0];
|
|
1370
|
+
const rect = canvas.getBoundingClientRect();
|
|
1371
|
+
mouseX = (currentTouch.clientX - rect.left) / rect.width;
|
|
1372
|
+
mouseY = 1.0 - (currentTouch.clientY - rect.top) / rect.height;
|
|
1373
|
+
clickIntensity = 1.0;
|
|
1374
|
+
|
|
1375
|
+
layers.forEach(layer => {
|
|
1376
|
+
if (layer.visualizer) {
|
|
1377
|
+
layer.visualizer.mouseX = mouseX;
|
|
1378
|
+
layer.visualizer.mouseY = mouseY;
|
|
1379
|
+
layer.visualizer.clickIntensity = clickIntensity;
|
|
1380
|
+
}
|
|
1381
|
+
});
|
|
1382
|
+
}
|
|
1383
|
+
}, { passive: false });
|
|
1384
|
+
|
|
1385
|
+
canvas.addEventListener('touchmove', (e) => {
|
|
1386
|
+
e.preventDefault();
|
|
1387
|
+
if (e.touches.length > 0) {
|
|
1388
|
+
const touch = e.touches[0];
|
|
1389
|
+
const rect = canvas.getBoundingClientRect();
|
|
1390
|
+
mouseX = (touch.clientX - rect.left) / rect.width;
|
|
1391
|
+
mouseY = 1.0 - (touch.clientY - rect.top) / rect.height;
|
|
1392
|
+
mouseIntensity = 0.8;
|
|
1393
|
+
currentTouch = touch;
|
|
1394
|
+
|
|
1395
|
+
layers.forEach(layer => {
|
|
1396
|
+
if (layer.visualizer) {
|
|
1397
|
+
layer.visualizer.mouseX = mouseX;
|
|
1398
|
+
layer.visualizer.mouseY = mouseY;
|
|
1399
|
+
layer.visualizer.mouseIntensity = mouseIntensity;
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1402
|
+
}
|
|
1403
|
+
}, { passive: false });
|
|
1404
|
+
|
|
1405
|
+
canvas.addEventListener('touchend', (e) => {
|
|
1406
|
+
clickIntensity = 0.0;
|
|
1407
|
+
mouseIntensity = 0.0;
|
|
1408
|
+
currentTouch = null;
|
|
1409
|
+
|
|
1410
|
+
layers.forEach(layer => {
|
|
1411
|
+
if (layer.visualizer) {
|
|
1412
|
+
layer.visualizer.clickIntensity = 0.0;
|
|
1413
|
+
layer.visualizer.mouseIntensity = 0.0;
|
|
1414
|
+
}
|
|
1415
|
+
});
|
|
1416
|
+
}, { passive: false });
|
|
1417
|
+
|
|
1418
|
+
// Scroll interactions
|
|
1419
|
+
canvas.addEventListener('wheel', (e) => {
|
|
1420
|
+
e.preventDefault();
|
|
1421
|
+
clickIntensity = Math.min(1.0, Math.abs(e.deltaY) / 100);
|
|
1422
|
+
|
|
1423
|
+
layers.forEach(layer => {
|
|
1424
|
+
if (layer.visualizer) {
|
|
1425
|
+
layer.visualizer.clickIntensity = clickIntensity;
|
|
1426
|
+
}
|
|
1427
|
+
});
|
|
1428
|
+
|
|
1429
|
+
setTimeout(() => {
|
|
1430
|
+
clickIntensity = 0.0;
|
|
1431
|
+
layers.forEach(layer => {
|
|
1432
|
+
if (layer.visualizer) {
|
|
1433
|
+
layer.visualizer.clickIntensity = 0.0;
|
|
1434
|
+
}
|
|
1435
|
+
});
|
|
1436
|
+
}, 300);
|
|
1437
|
+
}, { passive: false });`;
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
/**
|
|
1441
|
+
* Generate LIVE Quantum system with enhanced holographic effects
|
|
1442
|
+
*/
|
|
1443
|
+
generateLiveQuantumSystem(state) {
|
|
1444
|
+
return `
|
|
1445
|
+
// LIVE VIB34D Quantum System - Enhanced 5 Layer WebGL Rendering
|
|
1446
|
+
class LiveQuantumTradingCardSystem {
|
|
1447
|
+
constructor(canvas) {
|
|
1448
|
+
this.canvas = canvas;
|
|
1449
|
+
this.layers = [];
|
|
1450
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
1451
|
+
this.startTime = Date.now();
|
|
1452
|
+
|
|
1453
|
+
console.log('🌌 Initializing LIVE Quantum Trading Card System');
|
|
1454
|
+
this.initializeLayers();
|
|
1455
|
+
this.startRenderLoop();
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
initializeLayers() {
|
|
1459
|
+
const layerConfigs = [
|
|
1460
|
+
{ id: 'quantum-bg', role: 'background', blend: 'multiply', opacity: 0.4, intensity: 0.4, densityMult: 0.8, speedMult: 0.6 },
|
|
1461
|
+
{ id: 'quantum-shadow', role: 'shadow', blend: 'multiply', opacity: 0.6, intensity: 0.6, densityMult: 0.9, speedMult: 0.8 },
|
|
1462
|
+
{ id: 'quantum-content', role: 'content', blend: 'normal', opacity: 1.0, intensity: 1.0, densityMult: 1.0, speedMult: 1.0 },
|
|
1463
|
+
{ id: 'quantum-highlight', role: 'highlight', blend: 'screen', opacity: 0.8, intensity: 1.3, densityMult: 1.1, speedMult: 1.2 },
|
|
1464
|
+
{ id: 'quantum-accent', role: 'accent', blend: 'color-dodge', opacity: 0.7, intensity: 1.6, densityMult: 1.2, speedMult: 1.4 }
|
|
1465
|
+
];
|
|
1466
|
+
|
|
1467
|
+
layerConfigs.forEach(config => {
|
|
1468
|
+
const layerCanvas = document.createElement('canvas');
|
|
1469
|
+
layerCanvas.id = config.id;
|
|
1470
|
+
layerCanvas.width = this.canvas.width;
|
|
1471
|
+
layerCanvas.height = this.canvas.height;
|
|
1472
|
+
layerCanvas.style.position = 'absolute';
|
|
1473
|
+
layerCanvas.style.top = '0';
|
|
1474
|
+
layerCanvas.style.left = '0';
|
|
1475
|
+
layerCanvas.style.width = '100%';
|
|
1476
|
+
layerCanvas.style.height = '100%';
|
|
1477
|
+
layerCanvas.style.mixBlendMode = config.blend;
|
|
1478
|
+
layerCanvas.style.opacity = config.opacity;
|
|
1479
|
+
layerCanvas.style.pointerEvents = 'none';
|
|
1480
|
+
|
|
1481
|
+
this.canvas.parentNode.appendChild(layerCanvas);
|
|
1482
|
+
|
|
1483
|
+
const visualizer = new QuantumLayerVisualizer(layerCanvas, config);
|
|
1484
|
+
this.layers.push({ visualizer, config });
|
|
1485
|
+
console.log(\`🌌 Created quantum layer: \${config.role}\`);
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
startRenderLoop() {
|
|
1490
|
+
const render = () => {
|
|
1491
|
+
this.layers.forEach(({ visualizer }) => {
|
|
1492
|
+
if (visualizer && visualizer.render) {
|
|
1493
|
+
visualizer.render(Date.now());
|
|
1494
|
+
}
|
|
1495
|
+
});
|
|
1496
|
+
requestAnimationFrame(render);
|
|
1497
|
+
};
|
|
1498
|
+
render();
|
|
1499
|
+
}
|
|
1500
|
+
}
|
|
1501
|
+
|
|
1502
|
+
// Enhanced Quantum Layer Visualizer with complex 3D lattice shaders
|
|
1503
|
+
class QuantumLayerVisualizer {
|
|
1504
|
+
constructor(canvas, roleConfig) {
|
|
1505
|
+
this.canvas = canvas;
|
|
1506
|
+
this.roleConfig = roleConfig;
|
|
1507
|
+
this.gl = canvas.getContext('webgl');
|
|
1508
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
1509
|
+
this.mouseX = 0.5;
|
|
1510
|
+
this.mouseY = 0.5;
|
|
1511
|
+
this.mouseIntensity = 0.0;
|
|
1512
|
+
this.clickIntensity = 0.0;
|
|
1513
|
+
this.startTime = Date.now();
|
|
1514
|
+
|
|
1515
|
+
if (!this.gl) {
|
|
1516
|
+
console.error(\`WebGL not supported for quantum layer \${roleConfig.role}\`);
|
|
1517
|
+
return;
|
|
1518
|
+
}
|
|
1519
|
+
|
|
1520
|
+
this.initShaders();
|
|
1521
|
+
this.initBuffers();
|
|
1522
|
+
}
|
|
1523
|
+
|
|
1524
|
+
initShaders() {
|
|
1525
|
+
const vertexShader = \`
|
|
1526
|
+
attribute vec2 a_position;
|
|
1527
|
+
void main() {
|
|
1528
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
1529
|
+
}\`;
|
|
1530
|
+
|
|
1531
|
+
const fragmentShader = \`
|
|
1532
|
+
precision highp float;
|
|
1533
|
+
uniform vec2 u_resolution;
|
|
1534
|
+
uniform float u_time;
|
|
1535
|
+
uniform vec2 u_mouse;
|
|
1536
|
+
uniform float u_geometry;
|
|
1537
|
+
uniform float u_gridDensity;
|
|
1538
|
+
uniform float u_morphFactor;
|
|
1539
|
+
uniform float u_chaos;
|
|
1540
|
+
uniform float u_speed;
|
|
1541
|
+
uniform float u_hue;
|
|
1542
|
+
uniform float u_intensity;
|
|
1543
|
+
uniform float u_saturation;
|
|
1544
|
+
uniform float u_rot4dXW;
|
|
1545
|
+
uniform float u_rot4dYW;
|
|
1546
|
+
uniform float u_rot4dZW;
|
|
1547
|
+
uniform float u_mouseIntensity;
|
|
1548
|
+
uniform float u_clickIntensity;
|
|
1549
|
+
uniform float u_roleIntensity;
|
|
1550
|
+
|
|
1551
|
+
// 4D rotation matrices
|
|
1552
|
+
mat4 rotateXW(float theta) {
|
|
1553
|
+
float c = cos(theta);
|
|
1554
|
+
float s = sin(theta);
|
|
1555
|
+
return mat4(c, 0.0, 0.0, -s, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, s, 0.0, 0.0, c);
|
|
1556
|
+
}
|
|
1557
|
+
|
|
1558
|
+
mat4 rotateYW(float theta) {
|
|
1559
|
+
float c = cos(theta);
|
|
1560
|
+
float s = sin(theta);
|
|
1561
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c);
|
|
1562
|
+
}
|
|
1563
|
+
|
|
1564
|
+
mat4 rotateZW(float theta) {
|
|
1565
|
+
float c = cos(theta);
|
|
1566
|
+
float s = sin(theta);
|
|
1567
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c);
|
|
1568
|
+
}
|
|
1569
|
+
|
|
1570
|
+
vec3 project4Dto3D(vec4 p) {
|
|
1571
|
+
float w = 2.5 / (2.5 + p.w);
|
|
1572
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
// COMPLEX 3D LATTICE FUNCTIONS - QUANTUM ENHANCED
|
|
1576
|
+
float tetrahedronLattice(vec3 p, float gridSize) {
|
|
1577
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
1578
|
+
float d1 = length(q);
|
|
1579
|
+
float d2 = length(q - vec3(0.4, 0.0, 0.0));
|
|
1580
|
+
float d3 = length(q - vec3(0.0, 0.4, 0.0));
|
|
1581
|
+
float d4 = length(q - vec3(0.0, 0.0, 0.4));
|
|
1582
|
+
float vertices = 1.0 - smoothstep(0.0, 0.04, min(min(d1, d2), min(d3, d4)));
|
|
1583
|
+
float edges = 0.0;
|
|
1584
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xy) - 0.2)));
|
|
1585
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.yz) - 0.2)));
|
|
1586
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xz) - 0.2)));
|
|
1587
|
+
return max(vertices, edges * 0.5);
|
|
1588
|
+
}
|
|
1589
|
+
|
|
1590
|
+
float hypercubeLattice(vec3 p, float gridSize) {
|
|
1591
|
+
vec3 grid = fract(p * gridSize);
|
|
1592
|
+
vec3 edges = min(grid, 1.0 - grid);
|
|
1593
|
+
float minEdge = min(min(edges.x, edges.y), edges.z);
|
|
1594
|
+
float lattice = 1.0 - smoothstep(0.0, 0.03, minEdge);
|
|
1595
|
+
|
|
1596
|
+
vec3 centers = abs(grid - 0.5);
|
|
1597
|
+
float maxCenter = max(max(centers.x, centers.y), centers.z);
|
|
1598
|
+
float vertices = 1.0 - smoothstep(0.45, 0.5, maxCenter);
|
|
1599
|
+
|
|
1600
|
+
return max(lattice * 0.7, vertices);
|
|
1601
|
+
}
|
|
1602
|
+
|
|
1603
|
+
// ENHANCED GEOMETRY FUNCTION WITH QUANTUM EFFECTS
|
|
1604
|
+
float quantumGeometry(vec4 p) {
|
|
1605
|
+
int geomType = int(u_geometry);
|
|
1606
|
+
vec3 p3d = project4Dto3D(p);
|
|
1607
|
+
float gridSize = u_gridDensity * 0.08;
|
|
1608
|
+
|
|
1609
|
+
if (geomType == 0) {
|
|
1610
|
+
return tetrahedronLattice(p3d, gridSize) * u_morphFactor;
|
|
1611
|
+
} else if (geomType == 1) {
|
|
1612
|
+
return hypercubeLattice(p3d, gridSize) * u_morphFactor;
|
|
1613
|
+
} else {
|
|
1614
|
+
return hypercubeLattice(p3d, gridSize) * u_morphFactor;
|
|
1615
|
+
}
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
// HSV to RGB conversion
|
|
1619
|
+
vec3 hsv2rgb(vec3 c) {
|
|
1620
|
+
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
1621
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
1622
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
1623
|
+
}
|
|
1624
|
+
|
|
1625
|
+
// RGB Glitch effect
|
|
1626
|
+
vec3 rgbGlitch(vec3 color, vec2 uv, float intensity) {
|
|
1627
|
+
float r = color.r + sin(uv.y * 30.0 + u_time * 0.001) * intensity * 0.06;
|
|
1628
|
+
float g = color.g + sin(uv.y * 28.0 + u_time * 0.0012) * intensity * 0.06;
|
|
1629
|
+
float b = color.b + sin(uv.y * 32.0 + u_time * 0.0008) * intensity * 0.06;
|
|
1630
|
+
return vec3(r, g, b);
|
|
1631
|
+
}
|
|
1632
|
+
|
|
1633
|
+
void main() {
|
|
1634
|
+
vec2 uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / min(u_resolution.x, u_resolution.y);
|
|
1635
|
+
|
|
1636
|
+
// Enhanced 4D position with quantum effects
|
|
1637
|
+
float timeSpeed = u_time * 0.0001 * u_speed;
|
|
1638
|
+
vec4 pos = vec4(uv * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
1639
|
+
pos.xy += (u_mouse - 0.5) * u_mouseIntensity * 2.0;
|
|
1640
|
+
|
|
1641
|
+
// Apply 4D rotations
|
|
1642
|
+
pos = rotateXW(u_rot4dXW) * pos;
|
|
1643
|
+
pos = rotateYW(u_rot4dYW) * pos;
|
|
1644
|
+
pos = rotateZW(u_rot4dZW) * pos;
|
|
1645
|
+
|
|
1646
|
+
// Calculate quantum geometry value
|
|
1647
|
+
float value = quantumGeometry(pos);
|
|
1648
|
+
|
|
1649
|
+
// Enhanced chaos with quantum noise
|
|
1650
|
+
float noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
1651
|
+
value += noise * u_chaos;
|
|
1652
|
+
|
|
1653
|
+
// Quantum intensity calculation with holographic glow
|
|
1654
|
+
float geometryIntensity = 1.0 - clamp(abs(value * 0.8), 0.0, 1.0);
|
|
1655
|
+
geometryIntensity = pow(geometryIntensity, 1.5);
|
|
1656
|
+
geometryIntensity += u_clickIntensity * 0.3;
|
|
1657
|
+
|
|
1658
|
+
// Quantum shimmer effect
|
|
1659
|
+
float shimmer = sin(uv.x * 20.0 + timeSpeed * 5.0) * cos(uv.y * 15.0 + timeSpeed * 3.0) * 0.1;
|
|
1660
|
+
geometryIntensity += shimmer * geometryIntensity;
|
|
1661
|
+
|
|
1662
|
+
float finalIntensity = geometryIntensity * u_intensity;
|
|
1663
|
+
|
|
1664
|
+
// Enhanced quantum color system
|
|
1665
|
+
float baseHue = u_hue / 360.0;
|
|
1666
|
+
float hueShift = value * 0.2 + timeSpeed * 0.1;
|
|
1667
|
+
float finalHue = baseHue + hueShift;
|
|
1668
|
+
|
|
1669
|
+
vec3 hsvColor = vec3(finalHue, u_saturation, finalIntensity);
|
|
1670
|
+
vec3 baseColor = hsv2rgb(hsvColor);
|
|
1671
|
+
|
|
1672
|
+
// Add quantum particles
|
|
1673
|
+
float particles = 0.0;
|
|
1674
|
+
vec2 particleUV = uv * 8.0;
|
|
1675
|
+
vec2 particleID = floor(particleUV);
|
|
1676
|
+
vec2 particlePos = fract(particleUV) - 0.5;
|
|
1677
|
+
float particleDist = length(particlePos);
|
|
1678
|
+
|
|
1679
|
+
float particleTime = timeSpeed + dot(particleID, vec2(127.1, 311.7));
|
|
1680
|
+
float particleAlpha = sin(particleTime) * 0.5 + 0.5;
|
|
1681
|
+
particles = (1.0 - smoothstep(0.1, 0.3, particleDist)) * particleAlpha * 0.3;
|
|
1682
|
+
|
|
1683
|
+
vec3 glitchedColor = rgbGlitch(baseColor, uv, finalIntensity * 0.5);
|
|
1684
|
+
vec3 finalColor = glitchedColor + particles * vec3(1.0, 0.8, 1.0);
|
|
1685
|
+
|
|
1686
|
+
gl_FragColor = vec4(finalColor, finalIntensity * u_roleIntensity);
|
|
1687
|
+
}\`;
|
|
1688
|
+
|
|
1689
|
+
this.program = this.createProgram(vertexShader, fragmentShader);
|
|
1690
|
+
if (this.program) {
|
|
1691
|
+
this.uniforms = {
|
|
1692
|
+
resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
1693
|
+
time: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
1694
|
+
mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
|
|
1695
|
+
geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
|
|
1696
|
+
gridDensity: this.gl.getUniformLocation(this.program, 'u_gridDensity'),
|
|
1697
|
+
morphFactor: this.gl.getUniformLocation(this.program, 'u_morphFactor'),
|
|
1698
|
+
chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
|
|
1699
|
+
speed: this.gl.getUniformLocation(this.program, 'u_speed'),
|
|
1700
|
+
hue: this.gl.getUniformLocation(this.program, 'u_hue'),
|
|
1701
|
+
intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
1702
|
+
saturation: this.gl.getUniformLocation(this.program, 'u_saturation'),
|
|
1703
|
+
rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
|
|
1704
|
+
rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
|
|
1705
|
+
rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW'),
|
|
1706
|
+
mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
|
|
1707
|
+
clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
|
|
1708
|
+
roleIntensity: this.gl.getUniformLocation(this.program, 'u_roleIntensity')
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
createProgram(vertexSource, fragmentSource) {
|
|
1714
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
|
|
1715
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
1716
|
+
|
|
1717
|
+
if (!vertexShader || !fragmentShader) return null;
|
|
1718
|
+
|
|
1719
|
+
const program = this.gl.createProgram();
|
|
1720
|
+
this.gl.attachShader(program, vertexShader);
|
|
1721
|
+
this.gl.attachShader(program, fragmentShader);
|
|
1722
|
+
this.gl.linkProgram(program);
|
|
1723
|
+
|
|
1724
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
1725
|
+
console.error('Quantum program linking failed:', this.gl.getProgramInfoLog(program));
|
|
1726
|
+
return null;
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
return program;
|
|
1730
|
+
}
|
|
1731
|
+
|
|
1732
|
+
createShader(type, source) {
|
|
1733
|
+
const shader = this.gl.createShader(type);
|
|
1734
|
+
this.gl.shaderSource(shader, source);
|
|
1735
|
+
this.gl.compileShader(shader);
|
|
1736
|
+
|
|
1737
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
1738
|
+
console.error('Quantum shader compilation failed:', this.gl.getShaderInfoLog(shader));
|
|
1739
|
+
return null;
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1742
|
+
return shader;
|
|
1743
|
+
}
|
|
1744
|
+
|
|
1745
|
+
initBuffers() {
|
|
1746
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
1747
|
+
this.buffer = this.gl.createBuffer();
|
|
1748
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
|
|
1749
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
|
1750
|
+
|
|
1751
|
+
const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
|
|
1752
|
+
this.gl.enableVertexAttribArray(positionLocation);
|
|
1753
|
+
this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1756
|
+
render(time) {
|
|
1757
|
+
if (!this.program) return;
|
|
1758
|
+
|
|
1759
|
+
this.canvas.width = this.canvas.clientWidth;
|
|
1760
|
+
this.canvas.height = this.canvas.clientHeight;
|
|
1761
|
+
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
1762
|
+
this.gl.useProgram(this.program);
|
|
1763
|
+
|
|
1764
|
+
this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
1765
|
+
this.gl.uniform1f(this.uniforms.time, time);
|
|
1766
|
+
this.gl.uniform2f(this.uniforms.mouse, this.mouseX || 0.5, this.mouseY || 0.5);
|
|
1767
|
+
this.gl.uniform1f(this.uniforms.geometry, this.params.geometry || 0);
|
|
1768
|
+
this.gl.uniform1f(this.uniforms.gridDensity, (this.params.gridDensity || 15) * this.roleConfig.densityMult);
|
|
1769
|
+
this.gl.uniform1f(this.uniforms.morphFactor, this.params.morphFactor || 1.0);
|
|
1770
|
+
this.gl.uniform1f(this.uniforms.chaos, this.params.chaos || 0.2);
|
|
1771
|
+
this.gl.uniform1f(this.uniforms.speed, (this.params.speed || 1.0) * this.roleConfig.speedMult);
|
|
1772
|
+
this.gl.uniform1f(this.uniforms.hue, this.params.hue || 280); // Quantum purple-blue
|
|
1773
|
+
this.gl.uniform1f(this.uniforms.intensity, (this.params.intensity || 0.7) * this.roleConfig.intensity);
|
|
1774
|
+
this.gl.uniform1f(this.uniforms.saturation, this.params.saturation || 0.9);
|
|
1775
|
+
this.gl.uniform1f(this.uniforms.rot4dXW, this.params.rot4dXW || 0.0);
|
|
1776
|
+
this.gl.uniform1f(this.uniforms.rot4dYW, this.params.rot4dYW || 0.0);
|
|
1777
|
+
this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
|
|
1778
|
+
this.gl.uniform1f(this.uniforms.mouseIntensity, this.mouseIntensity || 0.0);
|
|
1779
|
+
this.gl.uniform1f(this.uniforms.clickIntensity, this.clickIntensity || 0.0);
|
|
1780
|
+
this.gl.uniform1f(this.uniforms.roleIntensity, this.roleConfig.intensity);
|
|
1781
|
+
|
|
1782
|
+
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
|
|
1786
|
+
// Enhanced interactivity system for Quantum cards - FIXED CANVAS SCOPE
|
|
1787
|
+
const canvas = document.getElementById('vib34dCanvas');
|
|
1788
|
+
if (!canvas) {
|
|
1789
|
+
console.error('Canvas not found for quantum interactivity');
|
|
1790
|
+
return;
|
|
1791
|
+
}
|
|
1792
|
+
|
|
1793
|
+
let mouseX = 0.5, mouseY = 0.5, mouseIntensity = 0.0;
|
|
1794
|
+
let clickIntensity = 0.0;
|
|
1795
|
+
|
|
1796
|
+
canvas.addEventListener('mousemove', (e) => {
|
|
1797
|
+
const rect = canvas.getBoundingClientRect();
|
|
1798
|
+
mouseX = (e.clientX - rect.left) / rect.width;
|
|
1799
|
+
mouseY = 1.0 - (e.clientY - rect.top) / rect.height;
|
|
1800
|
+
mouseIntensity = Math.min(1.0, Math.sqrt(e.movementX*e.movementX + e.movementY*e.movementY) / 40);
|
|
1801
|
+
|
|
1802
|
+
layers.forEach(layer => {
|
|
1803
|
+
if (layer.visualizer) {
|
|
1804
|
+
layer.visualizer.mouseX = mouseX;
|
|
1805
|
+
layer.visualizer.mouseY = mouseY;
|
|
1806
|
+
layer.visualizer.mouseIntensity = mouseIntensity;
|
|
1807
|
+
}
|
|
1808
|
+
});
|
|
1809
|
+
});
|
|
1810
|
+
|
|
1811
|
+
canvas.addEventListener('dblclick', async () => {
|
|
1812
|
+
console.log('🌌 Quantum card audio reactivity - Coming soon!');
|
|
1813
|
+
canvas.style.border = '2px solid #ff00ff';
|
|
1814
|
+
setTimeout(() => { canvas.style.border = ''; }, 2000);
|
|
1815
|
+
});`;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
/**
|
|
1819
|
+
* Generate LIVE 5-layer Holographic system with actual shader code
|
|
1820
|
+
*/
|
|
1821
|
+
generateLiveHolographicSystem(state) {
|
|
1822
|
+
return `
|
|
1823
|
+
// LIVE Active Holographic System - 5 Layer WebGL with Audio Reactivity
|
|
1824
|
+
class LiveTradingCardSystem {
|
|
1825
|
+
constructor() {
|
|
1826
|
+
this.layers = ['background', 'shadow', 'content', 'highlight', 'accent'];
|
|
1827
|
+
this.visualizers = [];
|
|
1828
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
1829
|
+
this.startTime = Date.now();
|
|
1830
|
+
|
|
1831
|
+
this.initializeAllLayers();
|
|
1832
|
+
this.startRenderLoop();
|
|
1833
|
+
}
|
|
1834
|
+
|
|
1835
|
+
initializeAllLayers() {
|
|
1836
|
+
// Create 5 canvases with holographic blend modes
|
|
1837
|
+
this.layers.forEach((role, index) => {
|
|
1838
|
+
const canvas = document.createElement('canvas');
|
|
1839
|
+
canvas.id = 'card-' + role + '-canvas';
|
|
1840
|
+
canvas.style.position = 'absolute';
|
|
1841
|
+
canvas.style.top = '0';
|
|
1842
|
+
canvas.style.left = '0';
|
|
1843
|
+
canvas.style.width = '100%';
|
|
1844
|
+
canvas.style.height = '100%';
|
|
1845
|
+
canvas.style.zIndex = index;
|
|
1846
|
+
|
|
1847
|
+
// Holographic layer blend modes for rich effects
|
|
1848
|
+
if (role === 'background') {
|
|
1849
|
+
canvas.style.opacity = '0.3';
|
|
1850
|
+
canvas.style.mixBlendMode = 'normal';
|
|
1851
|
+
} else if (role === 'shadow') {
|
|
1852
|
+
canvas.style.opacity = '0.7';
|
|
1853
|
+
canvas.style.mixBlendMode = 'multiply';
|
|
1854
|
+
} else if (role === 'content') {
|
|
1855
|
+
canvas.style.opacity = '1.0';
|
|
1856
|
+
canvas.style.mixBlendMode = 'normal';
|
|
1857
|
+
} else if (role === 'highlight') {
|
|
1858
|
+
canvas.style.opacity = '0.9';
|
|
1859
|
+
canvas.style.mixBlendMode = 'screen';
|
|
1860
|
+
} else if (role === 'accent') {
|
|
1861
|
+
canvas.style.opacity = '0.6';
|
|
1862
|
+
canvas.style.mixBlendMode = 'color-dodge';
|
|
1863
|
+
}
|
|
1864
|
+
|
|
1865
|
+
document.getElementById('vib34dCanvas').parentElement.appendChild(canvas);
|
|
1866
|
+
|
|
1867
|
+
// Create holographic visualizer for this layer
|
|
1868
|
+
const visualizer = new HolographicLayerVisualizer(canvas, role, this.params);
|
|
1869
|
+
this.visualizers.push(visualizer);
|
|
1870
|
+
});
|
|
1871
|
+
|
|
1872
|
+
// Hide the original canvas
|
|
1873
|
+
document.getElementById('vib34dCanvas').style.display = 'none';
|
|
1874
|
+
}
|
|
1875
|
+
|
|
1876
|
+
startRenderLoop() {
|
|
1877
|
+
const render = () => {
|
|
1878
|
+
const time = Date.now() - this.startTime;
|
|
1879
|
+
this.visualizers.forEach(visualizer => {
|
|
1880
|
+
visualizer.render(time);
|
|
1881
|
+
});
|
|
1882
|
+
requestAnimationFrame(render);
|
|
1883
|
+
};
|
|
1884
|
+
render();
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
|
|
1888
|
+
class HolographicLayerVisualizer {
|
|
1889
|
+
constructor(canvas, role, params) {
|
|
1890
|
+
this.canvas = canvas;
|
|
1891
|
+
this.role = role;
|
|
1892
|
+
this.params = params;
|
|
1893
|
+
this.gl = canvas.getContext('webgl');
|
|
1894
|
+
|
|
1895
|
+
const roleParams = {
|
|
1896
|
+
'background': { densityMult: 0.4, speedMult: 0.2, intensity: 0.2 },
|
|
1897
|
+
'shadow': { densityMult: 0.8, speedMult: 0.3, intensity: 0.4 },
|
|
1898
|
+
'content': { densityMult: 1.0, speedMult: 0.5, intensity: 0.8 },
|
|
1899
|
+
'highlight': { densityMult: 1.5, speedMult: 0.8, intensity: 1.0 },
|
|
1900
|
+
'accent': { densityMult: 2.0, speedMult: 0.4, intensity: 0.6 }
|
|
1901
|
+
};
|
|
1902
|
+
this.roleConfig = roleParams[role] || roleParams['content'];
|
|
1903
|
+
|
|
1904
|
+
this.initShaders();
|
|
1905
|
+
this.initBuffers();
|
|
1906
|
+
this.resize();
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
resize() {
|
|
1910
|
+
this.canvas.width = this.canvas.clientWidth;
|
|
1911
|
+
this.canvas.height = this.canvas.clientHeight;
|
|
1912
|
+
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
1913
|
+
}
|
|
1914
|
+
|
|
1915
|
+
initShaders() {
|
|
1916
|
+
const vertexShaderSource = \`
|
|
1917
|
+
attribute vec2 a_position;
|
|
1918
|
+
void main() {
|
|
1919
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
1920
|
+
}
|
|
1921
|
+
\`;
|
|
1922
|
+
|
|
1923
|
+
// EXACT HOLOGRAPHIC FRAGMENT SHADER WITH ALL EFFECTS
|
|
1924
|
+
const fragmentShaderSource = \`
|
|
1925
|
+
precision highp float;
|
|
1926
|
+
|
|
1927
|
+
uniform vec2 u_resolution;
|
|
1928
|
+
uniform float u_time;
|
|
1929
|
+
uniform vec2 u_mouse;
|
|
1930
|
+
uniform float u_geometry;
|
|
1931
|
+
uniform float u_density;
|
|
1932
|
+
uniform float u_speed;
|
|
1933
|
+
uniform vec3 u_color;
|
|
1934
|
+
uniform float u_intensity;
|
|
1935
|
+
uniform float u_roleDensity;
|
|
1936
|
+
uniform float u_roleSpeed;
|
|
1937
|
+
uniform float u_geometryType;
|
|
1938
|
+
uniform float u_chaos;
|
|
1939
|
+
uniform float u_morph;
|
|
1940
|
+
uniform float u_rot4dXW;
|
|
1941
|
+
uniform float u_rot4dYW;
|
|
1942
|
+
uniform float u_rot4dZW;
|
|
1943
|
+
|
|
1944
|
+
// 4D rotation matrices
|
|
1945
|
+
mat4 rotateXW(float theta) {
|
|
1946
|
+
float c = cos(theta);
|
|
1947
|
+
float s = sin(theta);
|
|
1948
|
+
return mat4(c, 0, 0, -s, 0, 1, 0, 0, 0, 0, 1, 0, s, 0, 0, c);
|
|
1949
|
+
}
|
|
1950
|
+
|
|
1951
|
+
mat4 rotateYW(float theta) {
|
|
1952
|
+
float c = cos(theta);
|
|
1953
|
+
float s = sin(theta);
|
|
1954
|
+
return mat4(1, 0, 0, 0, 0, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c);
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
mat4 rotateZW(float theta) {
|
|
1958
|
+
float c = cos(theta);
|
|
1959
|
+
float s = sin(theta);
|
|
1960
|
+
return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
vec3 project4Dto3D(vec4 p) {
|
|
1964
|
+
float w = 2.5 / (2.5 + p.w);
|
|
1965
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
1966
|
+
}
|
|
1967
|
+
|
|
1968
|
+
// Complete VIB3 Geometry Library
|
|
1969
|
+
float tetrahedronLattice(vec3 p, float gridSize) {
|
|
1970
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
1971
|
+
float d1 = length(q);
|
|
1972
|
+
float d2 = length(q - vec3(0.4, 0.0, 0.0));
|
|
1973
|
+
float d3 = length(q - vec3(0.0, 0.4, 0.0));
|
|
1974
|
+
float d4 = length(q - vec3(0.0, 0.0, 0.4));
|
|
1975
|
+
float vertices = 1.0 - smoothstep(0.0, 0.04, min(min(d1, d2), min(d3, d4)));
|
|
1976
|
+
float edges = 0.0;
|
|
1977
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xy) - 0.2)));
|
|
1978
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.yz) - 0.2)));
|
|
1979
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xz) - 0.2)));
|
|
1980
|
+
return max(vertices, edges * 0.5);
|
|
1981
|
+
}
|
|
1982
|
+
|
|
1983
|
+
float hypercubeLattice(vec3 p, float gridSize) {
|
|
1984
|
+
vec3 grid = fract(p * gridSize);
|
|
1985
|
+
vec3 edges = 1.0 - smoothstep(0.0, 0.03, abs(grid - 0.5));
|
|
1986
|
+
return max(max(edges.x, edges.y), edges.z);
|
|
1987
|
+
}
|
|
1988
|
+
|
|
1989
|
+
float sphereLattice(vec3 p, float gridSize) {
|
|
1990
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
1991
|
+
float r = length(q);
|
|
1992
|
+
return 1.0 - smoothstep(0.2, 0.5, r);
|
|
1993
|
+
}
|
|
1994
|
+
|
|
1995
|
+
float torusLattice(vec3 p, float gridSize) {
|
|
1996
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
1997
|
+
float r1 = sqrt(q.x*q.x + q.y*q.y);
|
|
1998
|
+
float r2 = sqrt((r1 - 0.3)*(r1 - 0.3) + q.z*q.z);
|
|
1999
|
+
return 1.0 - smoothstep(0.0, 0.1, r2);
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
float kleinLattice(vec3 p, float gridSize) {
|
|
2003
|
+
vec3 q = fract(p * gridSize);
|
|
2004
|
+
float u = q.x * 2.0 * 3.14159;
|
|
2005
|
+
float v = q.y * 2.0 * 3.14159;
|
|
2006
|
+
float x = cos(u) * (3.0 + cos(u/2.0) * sin(v) - sin(u/2.0) * sin(2.0*v));
|
|
2007
|
+
float klein = length(vec2(x, q.z)) - 0.1;
|
|
2008
|
+
return 1.0 - smoothstep(0.0, 0.05, abs(klein));
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
float fractalLattice(vec3 p, float gridSize) {
|
|
2012
|
+
vec3 q = p * gridSize;
|
|
2013
|
+
float scale = 1.0;
|
|
2014
|
+
float fractal = 0.0;
|
|
2015
|
+
for(int i = 0; i < 4; i++) {
|
|
2016
|
+
q = fract(q) - 0.5;
|
|
2017
|
+
fractal += abs(length(q)) / scale;
|
|
2018
|
+
scale *= 2.0;
|
|
2019
|
+
q *= 2.0;
|
|
2020
|
+
}
|
|
2021
|
+
return 1.0 - smoothstep(0.0, 1.0, fractal);
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
float waveLattice(vec3 p, float gridSize) {
|
|
2025
|
+
vec3 q = p * gridSize;
|
|
2026
|
+
float wave = sin(q.x * 2.0) * sin(q.y * 2.0) * sin(q.z * 2.0 + u_time);
|
|
2027
|
+
return smoothstep(-0.5, 0.5, wave);
|
|
2028
|
+
}
|
|
2029
|
+
|
|
2030
|
+
float crystalLattice(vec3 p, float gridSize) {
|
|
2031
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
2032
|
+
float d = max(max(abs(q.x), abs(q.y)), abs(q.z));
|
|
2033
|
+
return 1.0 - smoothstep(0.3, 0.5, d);
|
|
2034
|
+
}
|
|
2035
|
+
|
|
2036
|
+
float getDynamicGeometry(vec3 p, float gridSize, float geometryType) {
|
|
2037
|
+
int baseGeom = int(mod(geometryType, 8.0));
|
|
2038
|
+
float variation = floor(geometryType / 8.0) / 4.0;
|
|
2039
|
+
float variedGridSize = gridSize * (0.5 + variation * 1.5);
|
|
2040
|
+
|
|
2041
|
+
if (baseGeom == 0) return tetrahedronLattice(p, variedGridSize);
|
|
2042
|
+
else if (baseGeom == 1) return hypercubeLattice(p, variedGridSize);
|
|
2043
|
+
else if (baseGeom == 2) return sphereLattice(p, variedGridSize);
|
|
2044
|
+
else if (baseGeom == 3) return torusLattice(p, variedGridSize);
|
|
2045
|
+
else if (baseGeom == 4) return kleinLattice(p, variedGridSize);
|
|
2046
|
+
else if (baseGeom == 5) return fractalLattice(p, variedGridSize);
|
|
2047
|
+
else if (baseGeom == 6) return waveLattice(p, variedGridSize);
|
|
2048
|
+
else return crystalLattice(p, variedGridSize);
|
|
2049
|
+
}
|
|
2050
|
+
|
|
2051
|
+
vec3 rgbGlitch(vec3 color, vec2 uv, float intensity) {
|
|
2052
|
+
vec2 offset = vec2(intensity * 0.005, 0.0);
|
|
2053
|
+
float r = color.r + sin(uv.y * 30.0 + u_time * 0.001) * intensity * 0.06;
|
|
2054
|
+
float g = color.g + sin(uv.y * 28.0 + u_time * 0.0012) * intensity * 0.06;
|
|
2055
|
+
float b = color.b + sin(uv.y * 32.0 + u_time * 0.0008) * intensity * 0.06;
|
|
2056
|
+
return vec3(r, g, b);
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
float moirePattern(vec2 uv, float intensity) {
|
|
2060
|
+
float freq1 = 12.0 + intensity * 6.0;
|
|
2061
|
+
float freq2 = 14.0 + intensity * 8.0;
|
|
2062
|
+
float pattern1 = sin(uv.x * freq1) * sin(uv.y * freq1);
|
|
2063
|
+
float pattern2 = sin(uv.x * freq2) * sin(uv.y * freq2);
|
|
2064
|
+
return (pattern1 * pattern2) * intensity * 0.15;
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
void main() {
|
|
2068
|
+
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
|
2069
|
+
float aspectRatio = u_resolution.x / u_resolution.y;
|
|
2070
|
+
uv.x *= aspectRatio;
|
|
2071
|
+
uv -= 0.5;
|
|
2072
|
+
|
|
2073
|
+
float time = u_time * 0.0004 * u_speed * u_roleSpeed;
|
|
2074
|
+
|
|
2075
|
+
vec4 p4d = vec4(uv * 3.0, sin(time * 0.1) * 0.15, cos(time * 0.08) * 0.15);
|
|
2076
|
+
|
|
2077
|
+
p4d = rotateXW(u_rot4dXW + time * 0.2) * p4d;
|
|
2078
|
+
p4d = rotateYW(u_rot4dYW + time * 0.15) * p4d;
|
|
2079
|
+
p4d = rotateZW(u_rot4dZW + time * 0.25) * p4d;
|
|
2080
|
+
|
|
2081
|
+
vec3 p = project4Dto3D(p4d);
|
|
2082
|
+
|
|
2083
|
+
float roleDensity = u_density * u_roleDensity;
|
|
2084
|
+
float morphedGeometry = u_geometryType + u_morph * 3.0;
|
|
2085
|
+
float lattice = getDynamicGeometry(p, roleDensity, morphedGeometry);
|
|
2086
|
+
|
|
2087
|
+
vec3 baseColor = u_color;
|
|
2088
|
+
float latticeIntensity = lattice * u_intensity;
|
|
2089
|
+
|
|
2090
|
+
vec3 color = baseColor * (0.3 + latticeIntensity * 0.7);
|
|
2091
|
+
color += vec3(lattice * 0.4) * baseColor;
|
|
2092
|
+
|
|
2093
|
+
// Add holographic effects
|
|
2094
|
+
color += vec3(moirePattern(uv, u_chaos));
|
|
2095
|
+
color = rgbGlitch(color, uv, u_chaos);
|
|
2096
|
+
|
|
2097
|
+
gl_FragColor = vec4(color, 0.95);
|
|
2098
|
+
}
|
|
2099
|
+
\`;
|
|
2100
|
+
|
|
2101
|
+
this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
|
|
2102
|
+
this.uniforms = {
|
|
2103
|
+
resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
2104
|
+
time: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
2105
|
+
mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
|
|
2106
|
+
geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
|
|
2107
|
+
density: this.gl.getUniformLocation(this.program, 'u_density'),
|
|
2108
|
+
speed: this.gl.getUniformLocation(this.program, 'u_speed'),
|
|
2109
|
+
color: this.gl.getUniformLocation(this.program, 'u_color'),
|
|
2110
|
+
intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
2111
|
+
roleDensity: this.gl.getUniformLocation(this.program, 'u_roleDensity'),
|
|
2112
|
+
roleSpeed: this.gl.getUniformLocation(this.program, 'u_roleSpeed'),
|
|
2113
|
+
geometryType: this.gl.getUniformLocation(this.program, 'u_geometryType'),
|
|
2114
|
+
chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
|
|
2115
|
+
morph: this.gl.getUniformLocation(this.program, 'u_morph'),
|
|
2116
|
+
rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
|
|
2117
|
+
rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
|
|
2118
|
+
rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW')
|
|
2119
|
+
};
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
createProgram(vertexSource, fragmentSource) {
|
|
2123
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
|
|
2124
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
2125
|
+
|
|
2126
|
+
const program = this.gl.createProgram();
|
|
2127
|
+
this.gl.attachShader(program, vertexShader);
|
|
2128
|
+
this.gl.attachShader(program, fragmentShader);
|
|
2129
|
+
this.gl.linkProgram(program);
|
|
2130
|
+
|
|
2131
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2132
|
+
console.error('Program linking failed:', this.gl.getProgramInfoLog(program));
|
|
2133
|
+
return null;
|
|
2134
|
+
}
|
|
2135
|
+
|
|
2136
|
+
return program;
|
|
2137
|
+
}
|
|
2138
|
+
|
|
2139
|
+
createShader(type, source) {
|
|
2140
|
+
const shader = this.gl.createShader(type);
|
|
2141
|
+
this.gl.shaderSource(shader, source);
|
|
2142
|
+
this.gl.compileShader(shader);
|
|
2143
|
+
|
|
2144
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
2145
|
+
console.error('Shader compilation failed:', this.gl.getShaderInfoLog(shader));
|
|
2146
|
+
return null;
|
|
2147
|
+
}
|
|
2148
|
+
|
|
2149
|
+
return shader;
|
|
2150
|
+
}
|
|
2151
|
+
|
|
2152
|
+
initBuffers() {
|
|
2153
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
2154
|
+
|
|
2155
|
+
this.buffer = this.gl.createBuffer();
|
|
2156
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
|
|
2157
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
|
2158
|
+
|
|
2159
|
+
const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
|
|
2160
|
+
this.gl.enableVertexAttribArray(positionLocation);
|
|
2161
|
+
this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
|
|
2162
|
+
}
|
|
2163
|
+
|
|
2164
|
+
render(time) {
|
|
2165
|
+
if (!this.program) return;
|
|
2166
|
+
|
|
2167
|
+
this.resize();
|
|
2168
|
+
this.gl.useProgram(this.program);
|
|
2169
|
+
|
|
2170
|
+
const hue = (this.params.hue || 200) / 360;
|
|
2171
|
+
const saturation = this.params.saturation || 0.8;
|
|
2172
|
+
const lightness = this.params.intensity || 0.5;
|
|
2173
|
+
|
|
2174
|
+
// HSL to RGB conversion
|
|
2175
|
+
const hslToRgb = (h, s, l) => {
|
|
2176
|
+
let r, g, b;
|
|
2177
|
+
if (s === 0) {
|
|
2178
|
+
r = g = b = l;
|
|
2179
|
+
} else {
|
|
2180
|
+
const hue2rgb = (p, q, t) => {
|
|
2181
|
+
if (t < 0) t += 1;
|
|
2182
|
+
if (t > 1) t -= 1;
|
|
2183
|
+
if (t < 1/6) return p + (q - p) * 6 * t;
|
|
2184
|
+
if (t < 1/2) return q;
|
|
2185
|
+
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
2186
|
+
return p;
|
|
2187
|
+
};
|
|
2188
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
2189
|
+
const p = 2 * l - q;
|
|
2190
|
+
r = hue2rgb(p, q, h + 1/3);
|
|
2191
|
+
g = hue2rgb(p, q, h);
|
|
2192
|
+
b = hue2rgb(p, q, h - 1/3);
|
|
2193
|
+
}
|
|
2194
|
+
return [r, g, b];
|
|
2195
|
+
};
|
|
2196
|
+
|
|
2197
|
+
const rgbColor = hslToRgb(hue, saturation, lightness);
|
|
2198
|
+
|
|
2199
|
+
this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
2200
|
+
this.gl.uniform1f(this.uniforms.time, time);
|
|
2201
|
+
this.gl.uniform2f(this.uniforms.mouse, 0.5, 0.5);
|
|
2202
|
+
this.gl.uniform1f(this.uniforms.geometryType, this.params.geometryType || 0);
|
|
2203
|
+
this.gl.uniform1f(this.uniforms.density, (this.params.density || 1.0) * this.roleConfig.densityMult);
|
|
2204
|
+
this.gl.uniform1f(this.uniforms.speed, (this.params.speed || 0.5) * this.roleConfig.speedMult);
|
|
2205
|
+
this.gl.uniform3fv(this.uniforms.color, new Float32Array(rgbColor));
|
|
2206
|
+
this.gl.uniform1f(this.uniforms.intensity, (this.params.intensity || 0.5) * this.roleConfig.intensity);
|
|
2207
|
+
this.gl.uniform1f(this.uniforms.roleDensity, this.roleConfig.densityMult);
|
|
2208
|
+
this.gl.uniform1f(this.uniforms.roleSpeed, this.roleConfig.speedMult);
|
|
2209
|
+
this.gl.uniform1f(this.uniforms.chaos, this.params.chaos || 0.0);
|
|
2210
|
+
this.gl.uniform1f(this.uniforms.morph, this.params.morph || 0.0);
|
|
2211
|
+
this.gl.uniform1f(this.uniforms.rot4dXW, this.params.rot4dXW || 0.0);
|
|
2212
|
+
this.gl.uniform1f(this.uniforms.rot4dYW, this.params.rot4dYW || 0.0);
|
|
2213
|
+
this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
|
|
2214
|
+
|
|
2215
|
+
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
2216
|
+
}
|
|
2217
|
+
}
|
|
2218
|
+
|
|
2219
|
+
// Enhanced interactivity system for Holographic cards - FIXED CANVAS SCOPE
|
|
2220
|
+
const canvas = document.getElementById('vib34dCanvas');
|
|
2221
|
+
if (!canvas) {
|
|
2222
|
+
console.error('Canvas not found for holographic interactivity');
|
|
2223
|
+
return;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
let mouseX = 0.5, mouseY = 0.5, mouseIntensity = 0.0;
|
|
2227
|
+
let clickIntensity = 0.0;
|
|
2228
|
+
let currentTouch = null;
|
|
2229
|
+
|
|
2230
|
+
// Mouse interactions
|
|
2231
|
+
canvas.addEventListener('mousemove', (e) => {
|
|
2232
|
+
const rect = canvas.getBoundingClientRect();
|
|
2233
|
+
mouseX = (e.clientX - rect.left) / rect.width;
|
|
2234
|
+
mouseY = 1.0 - (e.clientY - rect.top) / rect.height;
|
|
2235
|
+
mouseIntensity = Math.min(1.0, Math.sqrt(e.movementX*e.movementX + e.movementY*e.movementY) / 40);
|
|
2236
|
+
|
|
2237
|
+
// Update all layer visualizers
|
|
2238
|
+
layers.forEach(layer => {
|
|
2239
|
+
if (layer.visualizer) {
|
|
2240
|
+
layer.visualizer.mouseX = mouseX;
|
|
2241
|
+
layer.visualizer.mouseY = mouseY;
|
|
2242
|
+
layer.visualizer.mouseIntensity = mouseIntensity;
|
|
2243
|
+
}
|
|
2244
|
+
});
|
|
2245
|
+
});
|
|
2246
|
+
|
|
2247
|
+
// Audio reactivity (double-click to enable)
|
|
2248
|
+
let audioEnabled = false;
|
|
2249
|
+
let audioContext = null;
|
|
2250
|
+
let analyser = null;
|
|
2251
|
+
let frequencyData = null;
|
|
2252
|
+
|
|
2253
|
+
canvas.addEventListener('dblclick', async () => {
|
|
2254
|
+
if (!audioEnabled) {
|
|
2255
|
+
try {
|
|
2256
|
+
audioContext = new (window.AudioContext || window.webkitAudioContext)();
|
|
2257
|
+
analyser = audioContext.createAnalyser();
|
|
2258
|
+
analyser.fftSize = 256;
|
|
2259
|
+
frequencyData = new Uint8Array(analyser.frequencyBinCount);
|
|
2260
|
+
|
|
2261
|
+
const stream = await navigator.mediaDevices.getUserMedia({
|
|
2262
|
+
audio: { echoCancellation: false, noiseSuppression: false }
|
|
2263
|
+
});
|
|
2264
|
+
|
|
2265
|
+
const source = audioContext.createMediaStreamSource(stream);
|
|
2266
|
+
source.connect(analyser);
|
|
2267
|
+
audioEnabled = true;
|
|
2268
|
+
|
|
2269
|
+
console.log('🎵 Trading card audio reactivity ENABLED');
|
|
2270
|
+
canvas.style.border = '2px solid #00ff00';
|
|
2271
|
+
setTimeout(() => { canvas.style.border = ''; }, 2000);
|
|
2272
|
+
} catch (error) {
|
|
2273
|
+
console.error('Audio failed:', error);
|
|
2274
|
+
}
|
|
2275
|
+
}
|
|
2276
|
+
});`;
|
|
2277
|
+
}
|
|
2278
|
+
|
|
2279
|
+
/**
|
|
2280
|
+
* Generate LIVE Polychora system (placeholder for now)
|
|
2281
|
+
*/
|
|
2282
|
+
generateLivePolychoraSystem(state) {
|
|
2283
|
+
// For now, use faceted system as base - will be enhanced later
|
|
2284
|
+
return this.generateLiveFacetedSystem(state);
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
/**
|
|
2288
|
+
* Generate WebGL code for Faceted system with EXACT shader from Visualizer.js
|
|
2289
|
+
*/
|
|
2290
|
+
generateFacetedVisualizationCode(state) {
|
|
2291
|
+
return `
|
|
2292
|
+
// VIB34D Faceted System Trading Card - ${state.name}
|
|
2293
|
+
// EXACT SHADER CODE FROM src/core/Visualizer.js IntegratedHolographicVisualizer
|
|
2294
|
+
class TradingCardVisualizer {
|
|
2295
|
+
constructor(canvas) {
|
|
2296
|
+
this.canvas = canvas;
|
|
2297
|
+
this.gl = canvas.getContext('webgl');
|
|
2298
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
2299
|
+
this.startTime = Date.now();
|
|
2300
|
+
|
|
2301
|
+
if (!this.gl) {
|
|
2302
|
+
console.error('WebGL not supported');
|
|
2303
|
+
return;
|
|
2304
|
+
}
|
|
2305
|
+
|
|
2306
|
+
this.initShaders();
|
|
2307
|
+
this.initBuffers();
|
|
2308
|
+
this.resize();
|
|
2309
|
+
this.animate();
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
resize() {
|
|
2313
|
+
this.canvas.width = this.canvas.clientWidth;
|
|
2314
|
+
this.canvas.height = this.canvas.clientHeight;
|
|
2315
|
+
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
2316
|
+
}
|
|
2317
|
+
|
|
2318
|
+
initShaders() {
|
|
2319
|
+
const vertexShaderSource = \`attribute vec2 a_position;
|
|
2320
|
+
void main() {
|
|
2321
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
2322
|
+
}\`;
|
|
2323
|
+
|
|
2324
|
+
// EXACT FRAGMENT SHADER FROM FACETED SYSTEM
|
|
2325
|
+
const fragmentShaderSource = \`precision highp float;
|
|
2326
|
+
uniform vec2 u_resolution;
|
|
2327
|
+
uniform float u_time;
|
|
2328
|
+
uniform vec2 u_mouse;
|
|
2329
|
+
uniform float u_geometry;
|
|
2330
|
+
uniform float u_gridDensity;
|
|
2331
|
+
uniform float u_morphFactor;
|
|
2332
|
+
uniform float u_chaos;
|
|
2333
|
+
uniform float u_speed;
|
|
2334
|
+
uniform float u_hue;
|
|
2335
|
+
uniform float u_intensity;
|
|
2336
|
+
uniform float u_saturation;
|
|
2337
|
+
uniform float u_dimension;
|
|
2338
|
+
uniform float u_rot4dXW;
|
|
2339
|
+
uniform float u_rot4dYW;
|
|
2340
|
+
uniform float u_rot4dZW;
|
|
2341
|
+
uniform float u_mouseIntensity;
|
|
2342
|
+
uniform float u_clickIntensity;
|
|
2343
|
+
uniform float u_roleIntensity;
|
|
2344
|
+
// 4D rotation matrices
|
|
2345
|
+
mat4 rotateXW(float theta) {
|
|
2346
|
+
float c = cos(theta);
|
|
2347
|
+
float s = sin(theta);
|
|
2348
|
+
return mat4(c, 0.0, 0.0, -s, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, s, 0.0, 0.0, c);
|
|
2349
|
+
}
|
|
2350
|
+
mat4 rotateYW(float theta) {
|
|
2351
|
+
float c = cos(theta);
|
|
2352
|
+
float s = sin(theta);
|
|
2353
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, c, 0.0, -s, 0.0, 0.0, 1.0, 0.0, 0.0, s, 0.0, c);
|
|
2354
|
+
}
|
|
2355
|
+
mat4 rotateZW(float theta) {
|
|
2356
|
+
float c = cos(theta);
|
|
2357
|
+
float s = sin(theta);
|
|
2358
|
+
return mat4(1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, c, -s, 0.0, 0.0, s, c);
|
|
2359
|
+
}
|
|
2360
|
+
vec3 project4Dto3D(vec4 p) {
|
|
2361
|
+
float w = 2.5 / (2.5 + p.w);
|
|
2362
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
2363
|
+
}
|
|
2364
|
+
// Simplified geometry functions for WebGL 1.0 compatibility
|
|
2365
|
+
float geometryFunction(vec4 p) {
|
|
2366
|
+
int geomType = int(u_geometry);
|
|
2367
|
+
|
|
2368
|
+
if (geomType == 0) {
|
|
2369
|
+
// Tetrahedron lattice - UNIFORM GRID DENSITY
|
|
2370
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
2371
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
2372
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
2373
|
+
}
|
|
2374
|
+
else if (geomType == 1) {
|
|
2375
|
+
// Hypercube lattice - UNIFORM GRID DENSITY
|
|
2376
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
2377
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
2378
|
+
float minDist = min(min(dist.x, dist.y), min(dist.z, dist.w));
|
|
2379
|
+
return minDist * u_morphFactor;
|
|
2380
|
+
}
|
|
2381
|
+
else if (geomType == 2) {
|
|
2382
|
+
// Sphere lattice - UNIFORM GRID DENSITY
|
|
2383
|
+
float r = length(p);
|
|
2384
|
+
float density = u_gridDensity * 0.08;
|
|
2385
|
+
float spheres = abs(fract(r * density) - 0.5) * 2.0;
|
|
2386
|
+
float theta = atan(p.y, p.x);
|
|
2387
|
+
float harmonics = sin(theta * 3.0) * 0.2;
|
|
2388
|
+
return (spheres + harmonics) * u_morphFactor;
|
|
2389
|
+
}
|
|
2390
|
+
else if (geomType == 3) {
|
|
2391
|
+
// Torus lattice - UNIFORM GRID DENSITY
|
|
2392
|
+
float r1 = length(p.xy) - 2.0;
|
|
2393
|
+
float torus = length(vec2(r1, p.z)) - 0.8;
|
|
2394
|
+
float lattice = sin(p.x * u_gridDensity * 0.08) * sin(p.y * u_gridDensity * 0.08);
|
|
2395
|
+
return (torus + lattice * 0.3) * u_morphFactor;
|
|
2396
|
+
}
|
|
2397
|
+
else if (geomType == 4) {
|
|
2398
|
+
// Klein bottle lattice - UNIFORM GRID DENSITY
|
|
2399
|
+
float u = atan(p.y, p.x);
|
|
2400
|
+
float v = atan(p.w, p.z);
|
|
2401
|
+
float dist = length(p) - 2.0;
|
|
2402
|
+
float lattice = sin(u * u_gridDensity * 0.08) * sin(v * u_gridDensity * 0.08);
|
|
2403
|
+
return (dist + lattice * 0.4) * u_morphFactor;
|
|
2404
|
+
}
|
|
2405
|
+
else if (geomType == 5) {
|
|
2406
|
+
// Fractal lattice - NOW WITH UNIFORM GRID DENSITY
|
|
2407
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
2408
|
+
pos = abs(pos * 2.0 - 1.0);
|
|
2409
|
+
float dist = length(max(abs(pos) - 1.0, 0.0));
|
|
2410
|
+
return dist * u_morphFactor;
|
|
2411
|
+
}
|
|
2412
|
+
else if (geomType == 6) {
|
|
2413
|
+
// Wave lattice - UNIFORM GRID DENSITY
|
|
2414
|
+
float freq = u_gridDensity * 0.08;
|
|
2415
|
+
float time = u_time * 0.001 * u_speed;
|
|
2416
|
+
float wave1 = sin(p.x * freq + time);
|
|
2417
|
+
float wave2 = sin(p.y * freq + time * 1.3);
|
|
2418
|
+
float wave3 = sin(p.z * freq * 0.8 + time * 0.7); // Add Z-dimension waves
|
|
2419
|
+
float interference = wave1 * wave2 * wave3;
|
|
2420
|
+
return interference * u_morphFactor;
|
|
2421
|
+
}
|
|
2422
|
+
else if (geomType == 7) {
|
|
2423
|
+
// Crystal lattice - UNIFORM GRID DENSITY
|
|
2424
|
+
vec4 pos = fract(p * u_gridDensity * 0.08) - 0.5;
|
|
2425
|
+
float cube = max(max(abs(pos.x), abs(pos.y)), max(abs(pos.z), abs(pos.w)));
|
|
2426
|
+
return cube * u_morphFactor;
|
|
2427
|
+
}
|
|
2428
|
+
else {
|
|
2429
|
+
// Default hypercube - UNIFORM GRID DENSITY
|
|
2430
|
+
vec4 pos = fract(p * u_gridDensity * 0.08);
|
|
2431
|
+
vec4 dist = min(pos, 1.0 - pos);
|
|
2432
|
+
return min(min(dist.x, dist.y), min(dist.z, dist.w)) * u_morphFactor;
|
|
2433
|
+
}
|
|
2434
|
+
}
|
|
2435
|
+
void main() {
|
|
2436
|
+
vec2 uv = (gl_FragCoord.xy - u_resolution.xy * 0.5) / min(u_resolution.x, u_resolution.y);
|
|
2437
|
+
|
|
2438
|
+
// 4D position with mouse interaction - NOW USING SPEED PARAMETER
|
|
2439
|
+
float timeSpeed = u_time * 0.0001 * u_speed;
|
|
2440
|
+
vec4 pos = vec4(uv * 3.0, sin(timeSpeed * 3.0), cos(timeSpeed * 2.0));
|
|
2441
|
+
pos.xy += (u_mouse - 0.5) * u_mouseIntensity * 2.0;
|
|
2442
|
+
|
|
2443
|
+
// Apply 4D rotations
|
|
2444
|
+
pos = rotateXW(u_rot4dXW) * pos;
|
|
2445
|
+
pos = rotateYW(u_rot4dYW) * pos;
|
|
2446
|
+
pos = rotateZW(u_rot4dZW) * pos;
|
|
2447
|
+
|
|
2448
|
+
// Calculate geometry value
|
|
2449
|
+
float value = geometryFunction(pos);
|
|
2450
|
+
|
|
2451
|
+
// Apply chaos
|
|
2452
|
+
float noise = sin(pos.x * 7.0) * cos(pos.y * 11.0) * sin(pos.z * 13.0);
|
|
2453
|
+
value += noise * u_chaos;
|
|
2454
|
+
|
|
2455
|
+
// Color based on geometry value and hue with user-controlled intensity/saturation
|
|
2456
|
+
float geometryIntensity = 1.0 - clamp(abs(value), 0.0, 1.0);
|
|
2457
|
+
geometryIntensity += u_clickIntensity * 0.3;
|
|
2458
|
+
|
|
2459
|
+
// Apply user intensity control
|
|
2460
|
+
float finalIntensity = geometryIntensity * u_intensity;
|
|
2461
|
+
|
|
2462
|
+
float hue = u_hue / 360.0 + value * 0.1;
|
|
2463
|
+
|
|
2464
|
+
// Create color with saturation control
|
|
2465
|
+
vec3 baseColor = vec3(
|
|
2466
|
+
sin(hue * 6.28318 + 0.0) * 0.5 + 0.5,
|
|
2467
|
+
sin(hue * 6.28318 + 2.0943) * 0.5 + 0.5,
|
|
2468
|
+
sin(hue * 6.28318 + 4.1887) * 0.5 + 0.5
|
|
2469
|
+
);
|
|
2470
|
+
|
|
2471
|
+
// Apply saturation (mix with grayscale)
|
|
2472
|
+
float gray = (baseColor.r + baseColor.g + baseColor.b) / 3.0;
|
|
2473
|
+
vec3 color = mix(vec3(gray), baseColor, u_saturation) * finalIntensity;
|
|
2474
|
+
|
|
2475
|
+
gl_FragColor = vec4(color, finalIntensity * u_roleIntensity);
|
|
2476
|
+
}\`;
|
|
2477
|
+
|
|
2478
|
+
this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
|
|
2479
|
+
this.uniforms = {
|
|
2480
|
+
resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
2481
|
+
time: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
2482
|
+
mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
|
|
2483
|
+
geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
|
|
2484
|
+
gridDensity: this.gl.getUniformLocation(this.program, 'u_gridDensity'),
|
|
2485
|
+
morphFactor: this.gl.getUniformLocation(this.program, 'u_morphFactor'),
|
|
2486
|
+
chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
|
|
2487
|
+
speed: this.gl.getUniformLocation(this.program, 'u_speed'),
|
|
2488
|
+
hue: this.gl.getUniformLocation(this.program, 'u_hue'),
|
|
2489
|
+
intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
2490
|
+
saturation: this.gl.getUniformLocation(this.program, 'u_saturation'),
|
|
2491
|
+
dimension: this.gl.getUniformLocation(this.program, 'u_dimension'),
|
|
2492
|
+
rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
|
|
2493
|
+
rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
|
|
2494
|
+
rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW'),
|
|
2495
|
+
mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
|
|
2496
|
+
clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
|
|
2497
|
+
roleIntensity: this.gl.getUniformLocation(this.program, 'u_roleIntensity')
|
|
2498
|
+
};
|
|
2499
|
+
}
|
|
2500
|
+
|
|
2501
|
+
createProgram(vertexSource, fragmentSource) {
|
|
2502
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
|
|
2503
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
2504
|
+
|
|
2505
|
+
const program = this.gl.createProgram();
|
|
2506
|
+
this.gl.attachShader(program, vertexShader);
|
|
2507
|
+
this.gl.attachShader(program, fragmentShader);
|
|
2508
|
+
this.gl.linkProgram(program);
|
|
2509
|
+
|
|
2510
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2511
|
+
console.error('Program linking failed:', this.gl.getProgramInfoLog(program));
|
|
2512
|
+
return null;
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
return program;
|
|
2516
|
+
}
|
|
2517
|
+
|
|
2518
|
+
createShader(type, source) {
|
|
2519
|
+
const shader = this.gl.createShader(type);
|
|
2520
|
+
this.gl.shaderSource(shader, source);
|
|
2521
|
+
this.gl.compileShader(shader);
|
|
2522
|
+
|
|
2523
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
2524
|
+
console.error('Shader compilation failed:', this.gl.getShaderInfoLog(shader));
|
|
2525
|
+
return null;
|
|
2526
|
+
}
|
|
2527
|
+
|
|
2528
|
+
return shader;
|
|
2529
|
+
}
|
|
2530
|
+
|
|
2531
|
+
initBuffers() {
|
|
2532
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
2533
|
+
|
|
2534
|
+
this.buffer = this.gl.createBuffer();
|
|
2535
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
|
|
2536
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
|
2537
|
+
|
|
2538
|
+
const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
|
|
2539
|
+
this.gl.enableVertexAttribArray(positionLocation);
|
|
2540
|
+
this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
|
|
2541
|
+
}
|
|
2542
|
+
|
|
2543
|
+
animate() {
|
|
2544
|
+
this.render();
|
|
2545
|
+
requestAnimationFrame(() => this.animate());
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2548
|
+
render() {
|
|
2549
|
+
if (!this.program) return;
|
|
2550
|
+
|
|
2551
|
+
this.resize();
|
|
2552
|
+
this.gl.useProgram(this.program);
|
|
2553
|
+
|
|
2554
|
+
const time = Date.now() - this.startTime;
|
|
2555
|
+
|
|
2556
|
+
this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
2557
|
+
this.gl.uniform1f(this.uniforms.time, time);
|
|
2558
|
+
this.gl.uniform2f(this.uniforms.mouse, 0.5, 0.5);
|
|
2559
|
+
this.gl.uniform1f(this.uniforms.geometry, this.params.geometry || 0);
|
|
2560
|
+
this.gl.uniform1f(this.uniforms.gridDensity, this.params.gridDensity || 15);
|
|
2561
|
+
this.gl.uniform1f(this.uniforms.morphFactor, this.params.morphFactor || 1.0);
|
|
2562
|
+
this.gl.uniform1f(this.uniforms.chaos, this.params.chaos || 0.2);
|
|
2563
|
+
this.gl.uniform1f(this.uniforms.speed, this.params.speed || 1.0);
|
|
2564
|
+
this.gl.uniform1f(this.uniforms.hue, this.params.hue || 200);
|
|
2565
|
+
this.gl.uniform1f(this.uniforms.intensity, this.params.intensity || 0.5);
|
|
2566
|
+
this.gl.uniform1f(this.uniforms.saturation, this.params.saturation || 0.8);
|
|
2567
|
+
this.gl.uniform1f(this.uniforms.dimension, this.params.dimension || 3.8);
|
|
2568
|
+
this.gl.uniform1f(this.uniforms.rot4dXW, this.params.rot4dXW || 0.0);
|
|
2569
|
+
this.gl.uniform1f(this.uniforms.rot4dYW, this.params.rot4dYW || 0.0);
|
|
2570
|
+
this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
|
|
2571
|
+
this.gl.uniform1f(this.uniforms.mouseIntensity, 0.0);
|
|
2572
|
+
this.gl.uniform1f(this.uniforms.clickIntensity, 0.0);
|
|
2573
|
+
this.gl.uniform1f(this.uniforms.roleIntensity, 1.0);
|
|
2574
|
+
|
|
2575
|
+
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
2576
|
+
}
|
|
2577
|
+
}`;
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
/**
|
|
2581
|
+
* Generate WebGL code for Holographic system with EXACT shader from HolographicVisualizer.js
|
|
2582
|
+
*/
|
|
2583
|
+
generateHolographicVisualizationCode(state) {
|
|
2584
|
+
return `
|
|
2585
|
+
// VIB34D Holographic System Trading Card - ${state.name}
|
|
2586
|
+
// EXACT SHADER CODE FROM src/holograms/HolographicVisualizer.js
|
|
2587
|
+
class TradingCardVisualizer {
|
|
2588
|
+
constructor(canvas) {
|
|
2589
|
+
this.canvas = canvas;
|
|
2590
|
+
this.gl = canvas.getContext('webgl');
|
|
2591
|
+
this.params = ${JSON.stringify(state.parameters)};
|
|
2592
|
+
this.startTime = Date.now();
|
|
2593
|
+
|
|
2594
|
+
if (!this.gl) {
|
|
2595
|
+
console.error('WebGL not supported');
|
|
2596
|
+
return;
|
|
2597
|
+
}
|
|
2598
|
+
|
|
2599
|
+
this.initHolographicShaders();
|
|
2600
|
+
this.initBuffers();
|
|
2601
|
+
this.resize();
|
|
2602
|
+
this.animate();
|
|
2603
|
+
}
|
|
2604
|
+
|
|
2605
|
+
initHolographicShaders() {
|
|
2606
|
+
const vertexShaderSource = \`
|
|
2607
|
+
attribute vec2 a_position;
|
|
2608
|
+
void main() {
|
|
2609
|
+
gl_Position = vec4(a_position, 0.0, 1.0);
|
|
2610
|
+
}
|
|
2611
|
+
\`;
|
|
2612
|
+
|
|
2613
|
+
// EXACT FRAGMENT SHADER FROM HOLOGRAPHIC SYSTEM
|
|
2614
|
+
const fragmentShaderSource = \`
|
|
2615
|
+
precision highp float;
|
|
2616
|
+
|
|
2617
|
+
uniform vec2 u_resolution;
|
|
2618
|
+
uniform float u_time;
|
|
2619
|
+
uniform vec2 u_mouse;
|
|
2620
|
+
uniform float u_geometry;
|
|
2621
|
+
uniform float u_density;
|
|
2622
|
+
uniform float u_speed;
|
|
2623
|
+
uniform vec3 u_color;
|
|
2624
|
+
uniform float u_intensity;
|
|
2625
|
+
uniform float u_roleDensity;
|
|
2626
|
+
uniform float u_roleSpeed;
|
|
2627
|
+
uniform float u_colorShift;
|
|
2628
|
+
uniform float u_chaosIntensity;
|
|
2629
|
+
uniform float u_mouseIntensity;
|
|
2630
|
+
uniform float u_clickIntensity;
|
|
2631
|
+
uniform float u_densityVariation;
|
|
2632
|
+
uniform float u_geometryType;
|
|
2633
|
+
uniform float u_chaos;
|
|
2634
|
+
uniform float u_morph;
|
|
2635
|
+
uniform float u_touchMorph;
|
|
2636
|
+
uniform float u_touchChaos;
|
|
2637
|
+
uniform float u_scrollParallax;
|
|
2638
|
+
uniform float u_gridDensityShift;
|
|
2639
|
+
uniform float u_colorScrollShift;
|
|
2640
|
+
uniform float u_audioDensityBoost;
|
|
2641
|
+
uniform float u_audioMorphBoost;
|
|
2642
|
+
uniform float u_audioSpeedBoost;
|
|
2643
|
+
uniform float u_audioChaosBoost;
|
|
2644
|
+
uniform float u_audioColorShift;
|
|
2645
|
+
uniform float u_rot4dXW;
|
|
2646
|
+
uniform float u_rot4dYW;
|
|
2647
|
+
uniform float u_rot4dZW;
|
|
2648
|
+
|
|
2649
|
+
// 4D rotation matrices
|
|
2650
|
+
mat4 rotateXW(float theta) {
|
|
2651
|
+
float c = cos(theta);
|
|
2652
|
+
float s = sin(theta);
|
|
2653
|
+
return mat4(c, 0, 0, -s, 0, 1, 0, 0, 0, 0, 1, 0, s, 0, 0, c);
|
|
2654
|
+
}
|
|
2655
|
+
|
|
2656
|
+
mat4 rotateYW(float theta) {
|
|
2657
|
+
float c = cos(theta);
|
|
2658
|
+
float s = sin(theta);
|
|
2659
|
+
return mat4(1, 0, 0, 0, 0, c, 0, -s, 0, 0, 1, 0, 0, s, 0, c);
|
|
2660
|
+
}
|
|
2661
|
+
|
|
2662
|
+
mat4 rotateZW(float theta) {
|
|
2663
|
+
float c = cos(theta);
|
|
2664
|
+
float s = sin(theta);
|
|
2665
|
+
return mat4(1, 0, 0, 0, 0, 1, 0, 0, 0, 0, c, -s, 0, 0, s, c);
|
|
2666
|
+
}
|
|
2667
|
+
|
|
2668
|
+
// 4D to 3D projection
|
|
2669
|
+
vec3 project4Dto3D(vec4 p) {
|
|
2670
|
+
float w = 2.5 / (2.5 + p.w);
|
|
2671
|
+
return vec3(p.x * w, p.y * w, p.z * w);
|
|
2672
|
+
}
|
|
2673
|
+
|
|
2674
|
+
// VIB3 Geometry Library
|
|
2675
|
+
float tetrahedronLattice(vec3 p, float gridSize) {
|
|
2676
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
2677
|
+
float d1 = length(q);
|
|
2678
|
+
float d2 = length(q - vec3(0.4, 0.0, 0.0));
|
|
2679
|
+
float d3 = length(q - vec3(0.0, 0.4, 0.0));
|
|
2680
|
+
float d4 = length(q - vec3(0.0, 0.0, 0.4));
|
|
2681
|
+
float vertices = 1.0 - smoothstep(0.0, 0.04, min(min(d1, d2), min(d3, d4)));
|
|
2682
|
+
float edges = 0.0;
|
|
2683
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xy) - 0.2)));
|
|
2684
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.yz) - 0.2)));
|
|
2685
|
+
edges = max(edges, 1.0 - smoothstep(0.0, 0.02, abs(length(q.xz) - 0.2)));
|
|
2686
|
+
return max(vertices, edges * 0.5);
|
|
2687
|
+
}
|
|
2688
|
+
|
|
2689
|
+
float hypercubeLattice(vec3 p, float gridSize) {
|
|
2690
|
+
vec3 grid = fract(p * gridSize);
|
|
2691
|
+
vec3 edges = 1.0 - smoothstep(0.0, 0.03, abs(grid - 0.5));
|
|
2692
|
+
return max(max(edges.x, edges.y), edges.z);
|
|
2693
|
+
}
|
|
2694
|
+
|
|
2695
|
+
float sphereLattice(vec3 p, float gridSize) {
|
|
2696
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
2697
|
+
float r = length(q);
|
|
2698
|
+
return 1.0 - smoothstep(0.2, 0.5, r);
|
|
2699
|
+
}
|
|
2700
|
+
|
|
2701
|
+
float torusLattice(vec3 p, float gridSize) {
|
|
2702
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
2703
|
+
float r1 = sqrt(q.x*q.x + q.y*q.y);
|
|
2704
|
+
float r2 = sqrt((r1 - 0.3)*(r1 - 0.3) + q.z*q.z);
|
|
2705
|
+
return 1.0 - smoothstep(0.0, 0.1, r2);
|
|
2706
|
+
}
|
|
2707
|
+
|
|
2708
|
+
float kleinLattice(vec3 p, float gridSize) {
|
|
2709
|
+
vec3 q = fract(p * gridSize);
|
|
2710
|
+
float u = q.x * 2.0 * 3.14159;
|
|
2711
|
+
float v = q.y * 2.0 * 3.14159;
|
|
2712
|
+
float x = cos(u) * (3.0 + cos(u/2.0) * sin(v) - sin(u/2.0) * sin(2.0*v));
|
|
2713
|
+
float klein = length(vec2(x, q.z)) - 0.1;
|
|
2714
|
+
return 1.0 - smoothstep(0.0, 0.05, abs(klein));
|
|
2715
|
+
}
|
|
2716
|
+
|
|
2717
|
+
float fractalLattice(vec3 p, float gridSize) {
|
|
2718
|
+
vec3 q = p * gridSize;
|
|
2719
|
+
float scale = 1.0;
|
|
2720
|
+
float fractal = 0.0;
|
|
2721
|
+
for(int i = 0; i < 4; i++) {
|
|
2722
|
+
q = fract(q) - 0.5;
|
|
2723
|
+
fractal += abs(length(q)) / scale;
|
|
2724
|
+
scale *= 2.0;
|
|
2725
|
+
q *= 2.0;
|
|
2726
|
+
}
|
|
2727
|
+
return 1.0 - smoothstep(0.0, 1.0, fractal);
|
|
2728
|
+
}
|
|
2729
|
+
|
|
2730
|
+
float waveLattice(vec3 p, float gridSize) {
|
|
2731
|
+
vec3 q = p * gridSize;
|
|
2732
|
+
float wave = sin(q.x * 2.0) * sin(q.y * 2.0) * sin(q.z * 2.0 + u_time);
|
|
2733
|
+
return smoothstep(-0.5, 0.5, wave);
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
float crystalLattice(vec3 p, float gridSize) {
|
|
2737
|
+
vec3 q = fract(p * gridSize) - 0.5;
|
|
2738
|
+
float d = max(max(abs(q.x), abs(q.y)), abs(q.z));
|
|
2739
|
+
return 1.0 - smoothstep(0.3, 0.5, d);
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
float getDynamicGeometry(vec3 p, float gridSize, float geometryType) {
|
|
2743
|
+
int baseGeom = int(mod(geometryType, 8.0));
|
|
2744
|
+
float variation = floor(geometryType / 8.0) / 4.0;
|
|
2745
|
+
float variedGridSize = gridSize * (0.5 + variation * 1.5);
|
|
2746
|
+
|
|
2747
|
+
if (baseGeom == 0) return tetrahedronLattice(p, variedGridSize);
|
|
2748
|
+
else if (baseGeom == 1) return hypercubeLattice(p, variedGridSize);
|
|
2749
|
+
else if (baseGeom == 2) return sphereLattice(p, variedGridSize);
|
|
2750
|
+
else if (baseGeom == 3) return torusLattice(p, variedGridSize);
|
|
2751
|
+
else if (baseGeom == 4) return kleinLattice(p, variedGridSize);
|
|
2752
|
+
else if (baseGeom == 5) return fractalLattice(p, variedGridSize);
|
|
2753
|
+
else if (baseGeom == 6) return waveLattice(p, variedGridSize);
|
|
2754
|
+
else return crystalLattice(p, variedGridSize);
|
|
2755
|
+
}
|
|
2756
|
+
|
|
2757
|
+
vec3 hsv2rgb(vec3 c) {
|
|
2758
|
+
vec4 K = vec4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
|
|
2759
|
+
vec3 p = abs(fract(c.xxx + K.xyz) * 6.0 - K.www);
|
|
2760
|
+
return c.z * mix(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
|
|
2761
|
+
}
|
|
2762
|
+
|
|
2763
|
+
vec3 rgbGlitch(vec3 color, vec2 uv, float intensity) {
|
|
2764
|
+
vec2 offset = vec2(intensity * 0.005, 0.0);
|
|
2765
|
+
float r = color.r + sin(uv.y * 30.0 + u_time * 0.001) * intensity * 0.06;
|
|
2766
|
+
float g = color.g + sin(uv.y * 28.0 + u_time * 0.0012) * intensity * 0.06;
|
|
2767
|
+
float b = color.b + sin(uv.y * 32.0 + u_time * 0.0008) * intensity * 0.06;
|
|
2768
|
+
return vec3(r, g, b);
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
float moirePattern(vec2 uv, float intensity) {
|
|
2772
|
+
float freq1 = 12.0 + intensity * 6.0 + u_densityVariation * 3.0;
|
|
2773
|
+
float freq2 = 14.0 + intensity * 8.0 + u_densityVariation * 4.0;
|
|
2774
|
+
float pattern1 = sin(uv.x * freq1) * sin(uv.y * freq1);
|
|
2775
|
+
float pattern2 = sin(uv.x * freq2) * sin(uv.y * freq2);
|
|
2776
|
+
return (pattern1 * pattern2) * intensity * 0.15;
|
|
2777
|
+
}
|
|
2778
|
+
|
|
2779
|
+
float gridOverlay(vec2 uv, float intensity) {
|
|
2780
|
+
vec2 grid = fract(uv * (8.0 + u_densityVariation * 4.0));
|
|
2781
|
+
float lines = 0.0;
|
|
2782
|
+
lines = max(lines, 1.0 - smoothstep(0.0, 0.02, abs(grid.x - 0.5)));
|
|
2783
|
+
lines = max(lines, 1.0 - smoothstep(0.0, 0.02, abs(grid.y - 0.5)));
|
|
2784
|
+
return lines * intensity * 0.1;
|
|
2785
|
+
}
|
|
2786
|
+
|
|
2787
|
+
void main() {
|
|
2788
|
+
vec2 uv = gl_FragCoord.xy / u_resolution.xy;
|
|
2789
|
+
float aspectRatio = u_resolution.x / u_resolution.y;
|
|
2790
|
+
uv.x *= aspectRatio;
|
|
2791
|
+
uv -= 0.5;
|
|
2792
|
+
|
|
2793
|
+
float time = u_time * 0.0004 * u_speed * u_roleSpeed;
|
|
2794
|
+
|
|
2795
|
+
float mouseInfluence = u_mouseIntensity * 0.5;
|
|
2796
|
+
vec2 mouseOffset = (u_mouse - 0.5) * mouseInfluence;
|
|
2797
|
+
|
|
2798
|
+
float parallaxOffset = u_scrollParallax * 0.2;
|
|
2799
|
+
vec2 scrollOffset = vec2(parallaxOffset * 0.1, parallaxOffset * 0.05);
|
|
2800
|
+
|
|
2801
|
+
float morphOffset = u_touchMorph * 0.3;
|
|
2802
|
+
|
|
2803
|
+
vec4 p4d = vec4(uv + mouseOffset * 0.1 + scrollOffset,
|
|
2804
|
+
sin(time * 0.1 + morphOffset) * 0.15,
|
|
2805
|
+
cos(time * 0.08 + morphOffset * 0.5) * 0.15);
|
|
2806
|
+
|
|
2807
|
+
float scrollRotation = u_scrollParallax * 0.1;
|
|
2808
|
+
float touchRotation = u_touchMorph * 0.2;
|
|
2809
|
+
|
|
2810
|
+
// Combine manual rotation with automatic/interactive rotation
|
|
2811
|
+
p4d = rotateXW(u_rot4dXW + time * 0.2 + mouseOffset.y * 0.5 + scrollRotation) * p4d;
|
|
2812
|
+
p4d = rotateYW(u_rot4dYW + time * 0.15 + mouseOffset.x * 0.5 + touchRotation) * p4d;
|
|
2813
|
+
p4d = rotateZW(u_rot4dZW + time * 0.25 + u_clickIntensity * 0.3 + u_touchChaos * 0.4) * p4d;
|
|
2814
|
+
|
|
2815
|
+
vec3 p = project4Dto3D(p4d);
|
|
2816
|
+
|
|
2817
|
+
float scrollDensityMod = 1.0 + u_gridDensityShift * 0.3;
|
|
2818
|
+
float audioDensityMod = 1.0 + u_audioDensityBoost * 0.5;
|
|
2819
|
+
float roleDensity = ((u_density + u_densityVariation) * u_roleDensity) * scrollDensityMod * audioDensityMod;
|
|
2820
|
+
|
|
2821
|
+
float morphedGeometry = u_geometryType + u_morph * 3.0 + u_touchMorph * 2.0 + u_audioMorphBoost * 1.5;
|
|
2822
|
+
float lattice = getDynamicGeometry(p, roleDensity, morphedGeometry);
|
|
2823
|
+
|
|
2824
|
+
// Use the passed RGB as base color and modulate with lattice patterns
|
|
2825
|
+
vec3 baseColor = u_color;
|
|
2826
|
+
float latticeIntensity = lattice * u_intensity;
|
|
2827
|
+
|
|
2828
|
+
vec3 color = baseColor * (0.3 + latticeIntensity * 0.7);
|
|
2829
|
+
|
|
2830
|
+
// Add lattice-based brightness variations
|
|
2831
|
+
color += vec3(lattice * 0.4) * baseColor;
|
|
2832
|
+
|
|
2833
|
+
float enhancedChaos = u_chaos + u_chaosIntensity + u_touchChaos * 0.3 + u_audioChaosBoost * 0.4;
|
|
2834
|
+
color += vec3(moirePattern(uv + scrollOffset, enhancedChaos));
|
|
2835
|
+
color += vec3(gridOverlay(uv, u_mouseIntensity + u_scrollParallax * 0.1));
|
|
2836
|
+
color = rgbGlitch(color, uv, enhancedChaos);
|
|
2837
|
+
|
|
2838
|
+
// Apply morph distortion to position
|
|
2839
|
+
vec2 morphDistortion = vec2(sin(uv.y * 10.0 + u_time * 0.001) * u_morph * 0.1,
|
|
2840
|
+
cos(uv.x * 10.0 + u_time * 0.001) * u_morph * 0.1);
|
|
2841
|
+
color = mix(color, color * (1.0 + length(morphDistortion)), u_morph * 0.5);
|
|
2842
|
+
|
|
2843
|
+
float mouseDist = length(uv - (u_mouse - 0.5) * vec2(aspectRatio, 1.0));
|
|
2844
|
+
float mouseGlow = exp(-mouseDist * 1.5) * u_mouseIntensity * 0.2;
|
|
2845
|
+
color += vec3(mouseGlow) * baseColor * 0.6;
|
|
2846
|
+
|
|
2847
|
+
float clickPulse = u_clickIntensity * exp(-mouseDist * 2.0) * 0.3;
|
|
2848
|
+
color += vec3(clickPulse, clickPulse * 0.5, clickPulse * 1.5);
|
|
2849
|
+
|
|
2850
|
+
gl_FragColor = vec4(color, 0.95);
|
|
2851
|
+
}
|
|
2852
|
+
\`;
|
|
2853
|
+
|
|
2854
|
+
this.program = this.createProgram(vertexShaderSource, fragmentShaderSource);
|
|
2855
|
+
this.uniforms = {
|
|
2856
|
+
resolution: this.gl.getUniformLocation(this.program, 'u_resolution'),
|
|
2857
|
+
time: this.gl.getUniformLocation(this.program, 'u_time'),
|
|
2858
|
+
mouse: this.gl.getUniformLocation(this.program, 'u_mouse'),
|
|
2859
|
+
geometry: this.gl.getUniformLocation(this.program, 'u_geometry'),
|
|
2860
|
+
density: this.gl.getUniformLocation(this.program, 'u_density'),
|
|
2861
|
+
speed: this.gl.getUniformLocation(this.program, 'u_speed'),
|
|
2862
|
+
color: this.gl.getUniformLocation(this.program, 'u_color'),
|
|
2863
|
+
intensity: this.gl.getUniformLocation(this.program, 'u_intensity'),
|
|
2864
|
+
roleDensity: this.gl.getUniformLocation(this.program, 'u_roleDensity'),
|
|
2865
|
+
roleSpeed: this.gl.getUniformLocation(this.program, 'u_roleSpeed'),
|
|
2866
|
+
colorShift: this.gl.getUniformLocation(this.program, 'u_colorShift'),
|
|
2867
|
+
chaosIntensity: this.gl.getUniformLocation(this.program, 'u_chaosIntensity'),
|
|
2868
|
+
mouseIntensity: this.gl.getUniformLocation(this.program, 'u_mouseIntensity'),
|
|
2869
|
+
clickIntensity: this.gl.getUniformLocation(this.program, 'u_clickIntensity'),
|
|
2870
|
+
densityVariation: this.gl.getUniformLocation(this.program, 'u_densityVariation'),
|
|
2871
|
+
geometryType: this.gl.getUniformLocation(this.program, 'u_geometryType'),
|
|
2872
|
+
chaos: this.gl.getUniformLocation(this.program, 'u_chaos'),
|
|
2873
|
+
morph: this.gl.getUniformLocation(this.program, 'u_morph'),
|
|
2874
|
+
touchMorph: this.gl.getUniformLocation(this.program, 'u_touchMorph'),
|
|
2875
|
+
touchChaos: this.gl.getUniformLocation(this.program, 'u_touchChaos'),
|
|
2876
|
+
scrollParallax: this.gl.getUniformLocation(this.program, 'u_scrollParallax'),
|
|
2877
|
+
gridDensityShift: this.gl.getUniformLocation(this.program, 'u_gridDensityShift'),
|
|
2878
|
+
colorScrollShift: this.gl.getUniformLocation(this.program, 'u_colorScrollShift'),
|
|
2879
|
+
audioDensityBoost: this.gl.getUniformLocation(this.program, 'u_audioDensityBoost'),
|
|
2880
|
+
audioMorphBoost: this.gl.getUniformLocation(this.program, 'u_audioMorphBoost'),
|
|
2881
|
+
audioSpeedBoost: this.gl.getUniformLocation(this.program, 'u_audioSpeedBoost'),
|
|
2882
|
+
audioChaosBoost: this.gl.getUniformLocation(this.program, 'u_audioChaosBoost'),
|
|
2883
|
+
audioColorShift: this.gl.getUniformLocation(this.program, 'u_audioColorShift'),
|
|
2884
|
+
rot4dXW: this.gl.getUniformLocation(this.program, 'u_rot4dXW'),
|
|
2885
|
+
rot4dYW: this.gl.getUniformLocation(this.program, 'u_rot4dYW'),
|
|
2886
|
+
rot4dZW: this.gl.getUniformLocation(this.program, 'u_rot4dZW')
|
|
2887
|
+
};
|
|
2888
|
+
}
|
|
2889
|
+
|
|
2890
|
+
createProgram(vertexSource, fragmentSource) {
|
|
2891
|
+
const vertexShader = this.createShader(this.gl.VERTEX_SHADER, vertexSource);
|
|
2892
|
+
const fragmentShader = this.createShader(this.gl.FRAGMENT_SHADER, fragmentSource);
|
|
2893
|
+
|
|
2894
|
+
const program = this.gl.createProgram();
|
|
2895
|
+
this.gl.attachShader(program, vertexShader);
|
|
2896
|
+
this.gl.attachShader(program, fragmentShader);
|
|
2897
|
+
this.gl.linkProgram(program);
|
|
2898
|
+
|
|
2899
|
+
if (!this.gl.getProgramParameter(program, this.gl.LINK_STATUS)) {
|
|
2900
|
+
console.error('Program linking failed:', this.gl.getProgramInfoLog(program));
|
|
2901
|
+
return null;
|
|
2902
|
+
}
|
|
2903
|
+
|
|
2904
|
+
return program;
|
|
2905
|
+
}
|
|
2906
|
+
|
|
2907
|
+
createShader(type, source) {
|
|
2908
|
+
const shader = this.gl.createShader(type);
|
|
2909
|
+
this.gl.shaderSource(shader, source);
|
|
2910
|
+
this.gl.compileShader(shader);
|
|
2911
|
+
|
|
2912
|
+
if (!this.gl.getShaderParameter(shader, this.gl.COMPILE_STATUS)) {
|
|
2913
|
+
console.error('Shader compilation failed:', this.gl.getShaderInfoLog(shader));
|
|
2914
|
+
return null;
|
|
2915
|
+
}
|
|
2916
|
+
|
|
2917
|
+
return shader;
|
|
2918
|
+
}
|
|
2919
|
+
|
|
2920
|
+
initBuffers() {
|
|
2921
|
+
const positions = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]);
|
|
2922
|
+
|
|
2923
|
+
this.buffer = this.gl.createBuffer();
|
|
2924
|
+
this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
|
|
2925
|
+
this.gl.bufferData(this.gl.ARRAY_BUFFER, positions, this.gl.STATIC_DRAW);
|
|
2926
|
+
|
|
2927
|
+
const positionLocation = this.gl.getAttribLocation(this.program, 'a_position');
|
|
2928
|
+
this.gl.enableVertexAttribArray(positionLocation);
|
|
2929
|
+
this.gl.vertexAttribPointer(positionLocation, 2, this.gl.FLOAT, false, 0, 0);
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
resize() {
|
|
2933
|
+
this.canvas.width = this.canvas.clientWidth;
|
|
2934
|
+
this.canvas.height = this.canvas.clientHeight;
|
|
2935
|
+
this.gl.viewport(0, 0, this.canvas.width, this.canvas.height);
|
|
2936
|
+
}
|
|
2937
|
+
|
|
2938
|
+
animate() {
|
|
2939
|
+
this.render();
|
|
2940
|
+
requestAnimationFrame(() => this.animate());
|
|
2941
|
+
}
|
|
2942
|
+
|
|
2943
|
+
render() {
|
|
2944
|
+
if (!this.program) return;
|
|
2945
|
+
|
|
2946
|
+
this.resize();
|
|
2947
|
+
this.gl.useProgram(this.program);
|
|
2948
|
+
|
|
2949
|
+
const time = Date.now() - this.startTime;
|
|
2950
|
+
const hue = (this.params.hue || 200) / 360;
|
|
2951
|
+
|
|
2952
|
+
// Convert hue to RGB
|
|
2953
|
+
const hslToRgb = (h, s, l) => {
|
|
2954
|
+
let r, g, b;
|
|
2955
|
+
if (s === 0) {
|
|
2956
|
+
r = g = b = l;
|
|
2957
|
+
} else {
|
|
2958
|
+
const hue2rgb = (p, q, t) => {
|
|
2959
|
+
if (t < 0) t += 1;
|
|
2960
|
+
if (t > 1) t -= 1;
|
|
2961
|
+
if (t < 1/6) return p + (q - p) * 6 * t;
|
|
2962
|
+
if (t < 1/2) return q;
|
|
2963
|
+
if (t < 2/3) return p + (q - p) * (2/3 - t) * 6;
|
|
2964
|
+
return p;
|
|
2965
|
+
};
|
|
2966
|
+
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
|
|
2967
|
+
const p = 2 * l - q;
|
|
2968
|
+
r = hue2rgb(p, q, h + 1/3);
|
|
2969
|
+
g = hue2rgb(p, q, h);
|
|
2970
|
+
b = hue2rgb(p, q, h - 1/3);
|
|
2971
|
+
}
|
|
2972
|
+
return [r, g, b];
|
|
2973
|
+
};
|
|
2974
|
+
|
|
2975
|
+
const rgbColor = hslToRgb(hue, this.params.saturation || 0.8, this.params.intensity || 0.5);
|
|
2976
|
+
|
|
2977
|
+
this.gl.uniform2f(this.uniforms.resolution, this.canvas.width, this.canvas.height);
|
|
2978
|
+
this.gl.uniform1f(this.uniforms.time, time);
|
|
2979
|
+
this.gl.uniform2f(this.uniforms.mouse, 0.5, 0.5);
|
|
2980
|
+
this.gl.uniform1f(this.uniforms.geometryType, this.params.geometryType || 0);
|
|
2981
|
+
this.gl.uniform1f(this.uniforms.density, this.params.density || 1.0);
|
|
2982
|
+
this.gl.uniform1f(this.uniforms.speed, this.params.speed || 0.5);
|
|
2983
|
+
this.gl.uniform3fv(this.uniforms.color, new Float32Array(rgbColor));
|
|
2984
|
+
this.gl.uniform1f(this.uniforms.intensity, this.params.intensity || 0.5);
|
|
2985
|
+
this.gl.uniform1f(this.uniforms.roleDensity, 1.0);
|
|
2986
|
+
this.gl.uniform1f(this.uniforms.roleSpeed, 1.0);
|
|
2987
|
+
this.gl.uniform1f(this.uniforms.colorShift, 0.0);
|
|
2988
|
+
this.gl.uniform1f(this.uniforms.chaosIntensity, this.params.chaos || 0.0);
|
|
2989
|
+
this.gl.uniform1f(this.uniforms.mouseIntensity, 0.0);
|
|
2990
|
+
this.gl.uniform1f(this.uniforms.clickIntensity, 0.0);
|
|
2991
|
+
this.gl.uniform1f(this.uniforms.densityVariation, 0.0);
|
|
2992
|
+
this.gl.uniform1f(this.uniforms.chaos, this.params.chaos || 0.0);
|
|
2993
|
+
this.gl.uniform1f(this.uniforms.morph, this.params.morph || 0.0);
|
|
2994
|
+
this.gl.uniform1f(this.uniforms.touchMorph, 0.0);
|
|
2995
|
+
this.gl.uniform1f(this.uniforms.touchChaos, 0.0);
|
|
2996
|
+
this.gl.uniform1f(this.uniforms.scrollParallax, 0.0);
|
|
2997
|
+
this.gl.uniform1f(this.uniforms.gridDensityShift, 0.0);
|
|
2998
|
+
this.gl.uniform1f(this.uniforms.colorScrollShift, 0.0);
|
|
2999
|
+
this.gl.uniform1f(this.uniforms.audioDensityBoost, 0.0);
|
|
3000
|
+
this.gl.uniform1f(this.uniforms.audioMorphBoost, 0.0);
|
|
3001
|
+
this.gl.uniform1f(this.uniforms.audioSpeedBoost, 0.0);
|
|
3002
|
+
this.gl.uniform1f(this.uniforms.audioChaosBoost, 0.0);
|
|
3003
|
+
this.gl.uniform1f(this.uniforms.audioColorShift, 0.0);
|
|
3004
|
+
this.gl.uniform1f(this.uniforms.rot4dXW, this.params.rot4dXW || 0.0);
|
|
3005
|
+
this.gl.uniform1f(this.uniforms.rot4dYW, this.params.rot4dYW || 0.0);
|
|
3006
|
+
this.gl.uniform1f(this.uniforms.rot4dZW, this.params.rot4dZW || 0.0);
|
|
3007
|
+
|
|
3008
|
+
this.gl.drawArrays(this.gl.TRIANGLE_STRIP, 0, 4);
|
|
3009
|
+
}
|
|
3010
|
+
}`;
|
|
3011
|
+
}
|
|
3012
|
+
|
|
3013
|
+
/**
|
|
3014
|
+
* Generate fallback visualization code
|
|
3015
|
+
*/
|
|
3016
|
+
generateFallbackVisualizationCode(state) {
|
|
3017
|
+
return `
|
|
3018
|
+
// VIB34D Trading Card - Fallback Canvas Renderer
|
|
3019
|
+
class TradingCardVisualizer {
|
|
3020
|
+
constructor(canvas) {
|
|
3021
|
+
console.log('🎴 Trading card using fallback 2D renderer');
|
|
3022
|
+
// Simple 2D fallback if WebGL fails
|
|
3023
|
+
this.canvas = canvas;
|
|
3024
|
+
this.ctx = canvas.getContext('2d');
|
|
3025
|
+
this.animate();
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
animate() {
|
|
3029
|
+
if (this.ctx) {
|
|
3030
|
+
this.ctx.fillStyle = '#000';
|
|
3031
|
+
this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height);
|
|
3032
|
+
this.ctx.fillStyle = '#00ffff';
|
|
3033
|
+
this.ctx.font = '20px Orbitron';
|
|
3034
|
+
this.ctx.textAlign = 'center';
|
|
3035
|
+
this.ctx.fillText('VIB34D', this.canvas.width/2, this.canvas.height/2);
|
|
3036
|
+
}
|
|
3037
|
+
requestAnimationFrame(() => this.animate());
|
|
3038
|
+
}
|
|
3039
|
+
}`;
|
|
3040
|
+
}
|
|
3041
|
+
|
|
3042
|
+
/**
|
|
3043
|
+
* Generate simple image display code for captured canvas
|
|
3044
|
+
*/
|
|
3045
|
+
generateImageVisualization(imageData) {
|
|
3046
|
+
return `
|
|
3047
|
+
// VIB34D Trading Card - Captured Visualization
|
|
3048
|
+
// This card contains the exact visual state from when it was created
|
|
3049
|
+
console.log('🎴 Trading card using captured visualization');
|
|
3050
|
+
|
|
3051
|
+
// The visualization is embedded as an image
|
|
3052
|
+
// Original state preserved perfectly
|
|
3053
|
+
`;
|
|
3054
|
+
}
|
|
3055
|
+
}
|