diff options
Diffstat (limited to 'src/gpu/effect.h')
| -rw-r--r-- | src/gpu/effect.h | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/src/gpu/effect.h b/src/gpu/effect.h new file mode 100644 index 0000000..50b2d72 --- /dev/null +++ b/src/gpu/effect.h @@ -0,0 +1,117 @@ +// This file is part of the 64k demo project. +// It defines the Effect interface and Sequence management system. +// Used for choreographing visual effects. + +#pragma once + +#include <vector> +#include <memory> +#include <algorithm> + +#if defined(DEMO_CROSS_COMPILE_WIN32) +#include <webgpu/webgpu.h> +#else +#include <webgpu.h> +#endif + +class MainSequence; + +// Abstract base class for all visual effects +class Effect { +public: + virtual ~Effect() = default; + + // One-time setup (load assets, create buffers). + // Idempotent: safe to call multiple times if effect is shared. + virtual void init(MainSequence *demo) { (void)demo; } + + // Called when the effect starts playing in a sequence segment. + virtual void start() {} + + // Dispatch compute shaders. + virtual void compute(WGPUCommandEncoder encoder, float time, float beat, + float intensity, float aspect_ratio) { + (void)encoder; + (void)time; + (void)beat; + (void)intensity; + (void)aspect_ratio; + } + + // Record render commands. + virtual void render(WGPURenderPassEncoder pass, float time, float beat, + float intensity, float aspect_ratio) = 0; + + // Called when the effect finishes in a sequence segment. + virtual void end() {} + + bool is_initialized = false; +}; + +struct SequenceItem { + std::shared_ptr<Effect> effect; + float start_time; // Relative to Sequence start + float end_time; // Relative to Sequence start + int priority; // Render order within sequence (higher = later/top) + bool active; +}; + +class Sequence { +public: + int priority = 0; // Render order of this sequence (higher = later/top) + + void init(MainSequence *demo); + + // Add an effect to the sequence. + // start_time, end_time: Relative to sequence start. + // priority: Drawing order within this sequence. + void add_effect(std::shared_ptr<Effect> effect, float start_time, + float end_time, int priority = 0); + + // Updates active state of effects based on sequence-local time. + // seq_time: Time relative to sequence start. + void update_active_list(float seq_time); + + // Calls compute() on all active effects (sorted by priority). + void dispatch_compute(WGPUCommandEncoder encoder, float seq_time, float beat, + float intensity, float aspect_ratio); + + // Calls render() on all active effects (sorted by priority). + void dispatch_render(WGPURenderPassEncoder pass, float seq_time, float beat, + float intensity, float aspect_ratio); + + void reset(); + +private: + std::vector<SequenceItem> items_; + bool is_sorted_ = false; + void sort_items(); +}; + +class MainSequence { +public: + WGPUDevice device; + WGPUQueue queue; + WGPUTextureFormat format; + + void init(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format); + + // Add a sequence to the demo. + // start_time: Global time when this sequence starts. + // priority: Layering order (higher = on top). + void add_sequence(std::shared_ptr<Sequence> seq, float start_time, int priority = 0); + + // Renders the full frame: updates sequences, runs compute, runs render pass. + void render_frame(float global_time, float beat, float peak, + float aspect_ratio, WGPUSurface surface); + + void shutdown(); + +private: + struct ActiveSequence { + std::shared_ptr<Sequence> seq; + float start_time; + int priority; + }; + std::vector<ActiveSequence> sequences_; +}; |
