Transition from a single-visualizer architecture to a compositing engine. This allows users to stack multiple effects (e.g., a background spiral, a foreground spectrum analyzer, and a particle overlay) with independent controls and transparency.
- Define Layer Structure: Create a standard data structure for a "Layer" (id, type, visible, opacity, blendMode, params).
- Global vs. Layer State: Separate global settings (Canvas Background Color, Resolution) from Layer settings (Stroke Color, Rotation, Scale).
- Update State Management: Refactor
currentParamsto be aCompositionStateobject containing an array oflayers.
- Enable Blending: Configure WebGL for transparency (
gl.enable(gl.BLEND),gl.blendFunc). - Render Loop Refactor:
- Rename
drawSpiraltorenderLayer. - Create
renderComposition:- Clear Canvas (using global background color).
- Loop through
layers. - If layer is visible, call
renderLayerwith that layer's params.
- Rename
- Layer Manager UI: Create a new panel to list active layers.
- Controls: Add, Remove, Duplicate, Visibility Toggle.
- Context-Aware Controls: When a layer is selected in the list, update the main control panel inputs to reflect that layer's parameters.
- Global Controls: Move "Background Color" to a global settings area.
Implement a real-time frequency spectrum analyzer using WebGL. The visualization will consist of vertical bars that react to audio frequency data.
- Update
initAudio: IncreasefftSize(currently 64) to 256 or 512 to get higher resolution frequency data (128 or 256 bars). - Add
getAudioSpectrum: Create a function to exposeanalyser.getByteFrequencyData.
- Refactor
setupWebGL: The current function returns a single program. It needs to be refactored to support/return multiple programs (Spiral Program vs. Spectrum Program). - Define Spectrum Shaders:
- Vertex Shader: Needs a new attribute
a_barIndexand a uniform arrayu_audioData[]. It will calculate vertex Y-positions based on the audio value for that bar index. - Fragment Shader: Simple color handling, potentially with gradients based on bar height.
- Vertex Shader: Needs a new attribute
-
initSpectrumMesh: Create a function to generate static geometry (quads) for the bars. This runs once (or on resize), not every frame.- Optimization: Store
barIndexas a vertex attribute so the shader knows which audio value applies to which vertex.
- Optimization: Store
-
drawSpectrum: The render function that:- Binds the spectrum shader program.
- Uploads the audio data array to the
u_audioDatauniform. - Draws the static mesh.
- State: Add
visualizerMode('spiral' | 'spectrum') tocurrentParamsandstate.js. - UI: Add a control (dropdown or toggle) to switch between modes.
- Loop: Update the main animation loop in
script.js(orui.jswhere the loop lives) to conditionally calldrawSpiralordrawSpectrum.
- Uniform Limits: We need to check
MAX_VERTEX_UNIFORM_VECTORS. A float array of size 64 or 128 is usually safe on modern devices. - Performance: The "Vertex Displacement" method is chosen here. We upload geometry once, and only upload a small array of floats (audio data) per frame. This is significantly faster than rebuilding the mesh on the CPU every frame.
- Execute Phase 1 (Audio updates).
- Execute Phase 2 (Shader creation).