summaryrefslogtreecommitdiff
path: root/src/gpu/effect.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/effect.h')
-rw-r--r--src/gpu/effect.h117
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_;
+};