From d378da77eec4d506bc01e4c08c38644d72969cc7 Mon Sep 17 00:00:00 2001 From: skal Date: Wed, 11 Feb 2026 11:34:08 +0100 Subject: refactor: Simplify effect render API and fix uniform initialization MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: Uniform buffers created but not initialized before bind group creation, causing undefined UV coordinates in circle_mask_compute.wgsl. Changes: - Add get_common_uniforms() helper to Effect base class - Refactor render()/compute() signatures: 5 params → CommonPostProcessUniforms& - Fix uninitialized uniforms in CircleMaskEffect and CNNEffect - Update all 19 effect implementations and headers - Fix WGSL syntax error in FlashEffect (u.audio_intensity → audio_intensity) - Update test files (test_sequence.cc) Benefits: - Cleaner API: construct uniforms once per frame, reuse across effects - More maintainable: CommonPostProcessUniforms changes need no call site updates - Fixes UV coordinate bug in circle_mask_compute.wgsl All 36 tests passing (100%) handoff(Claude): Effect API refactor complete --- src/gpu/demo_effects.h | 44 ++++++++++++++--------------- src/gpu/effect.cc | 44 +++++++++++++++++++++-------- src/gpu/effect.h | 34 ++++++++++++++-------- src/gpu/effects/chroma_aberration_effect.cc | 14 ++------- src/gpu/effects/circle_mask_effect.cc | 26 +++++------------ src/gpu/effects/circle_mask_effect.h | 8 +++--- src/gpu/effects/cnn_effect.cc | 17 +++++------ src/gpu/effects/cnn_effect.h | 4 +-- src/gpu/effects/distort_effect.cc | 15 +++------- src/gpu/effects/fade_effect.cc | 21 +++++--------- src/gpu/effects/fade_effect.h | 4 +-- src/gpu/effects/flash_cube_effect.cc | 14 ++++----- src/gpu/effects/flash_cube_effect.h | 4 +-- src/gpu/effects/flash_effect.cc | 20 ++++++------- src/gpu/effects/flash_effect.h | 4 +-- src/gpu/effects/gaussian_blur_effect.cc | 14 ++------- src/gpu/effects/heptagon_effect.cc | 14 ++------- src/gpu/effects/hybrid_3d_effect.cc | 22 +++++++-------- src/gpu/effects/hybrid_3d_effect.h | 4 +-- src/gpu/effects/moving_ellipse_effect.cc | 14 ++------- src/gpu/effects/particle_spray_effect.cc | 18 ++++-------- src/gpu/effects/particles_effect.cc | 18 ++++-------- src/gpu/effects/passthrough_effect.cc | 9 +----- src/gpu/effects/rotating_cube_effect.cc | 9 +++--- src/gpu/effects/rotating_cube_effect.h | 4 +-- src/gpu/effects/scene1_effect.cc | 14 ++------- src/gpu/effects/scene1_effect.h | 4 +-- src/gpu/effects/solarize_effect.cc | 15 +++------- src/gpu/effects/theme_modulation_effect.cc | 18 ++++-------- src/gpu/effects/theme_modulation_effect.h | 4 +-- src/gpu/effects/vignette_effect.cc | 15 +++------- src/tests/assets/test_sequence.cc | 27 ++++++------------ 32 files changed, 203 insertions(+), 293 deletions(-) (limited to 'src') diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h index 1ccf930..8cdf557 100644 --- a/src/gpu/demo_effects.h +++ b/src/gpu/demo_effects.h @@ -33,8 +33,8 @@ struct Particle { class HeptagonEffect : public Effect { public: HeptagonEffect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: RenderPass pass_; @@ -43,10 +43,10 @@ class HeptagonEffect : public Effect { class ParticlesEffect : public Effect { public: ParticlesEffect(const GpuContext& ctx); - void compute(WGPUCommandEncoder encoder, float time, float beat, - float intensity, float aspect_ratio) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: ComputePass compute_pass_; @@ -65,8 +65,8 @@ class PassthroughEffect : public PostProcessEffect { class MovingEllipseEffect : public Effect { public: MovingEllipseEffect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: RenderPass pass_; @@ -75,10 +75,10 @@ class MovingEllipseEffect : public Effect { class ParticleSprayEffect : public Effect { public: ParticleSprayEffect(const GpuContext& ctx); - void compute(WGPUCommandEncoder encoder, float time, float beat, - float intensity, float aspect_ratio) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: ComputePass compute_pass_; @@ -100,8 +100,8 @@ class GaussianBlurEffect : public PostProcessEffect { GaussianBlurEffect(const GpuContext& ctx); // New parameterized constructor GaussianBlurEffect(const GpuContext& ctx, const GaussianBlurParams& params); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: @@ -112,8 +112,8 @@ class GaussianBlurEffect : public PostProcessEffect { class SolarizeEffect : public PostProcessEffect { public: SolarizeEffect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: @@ -129,8 +129,8 @@ class VignetteEffect : public PostProcessEffect { public: VignetteEffect(const GpuContext& ctx); VignetteEffect(const GpuContext& ctx, const VignetteParams& params); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: @@ -151,8 +151,8 @@ class ChromaAberrationEffect : public PostProcessEffect { // New parameterized constructor ChromaAberrationEffect(const GpuContext& ctx, const ChromaAberrationParams& params); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: @@ -171,8 +171,8 @@ class DistortEffect : public PostProcessEffect { public: DistortEffect(const GpuContext& ctx); DistortEffect(const GpuContext& ctx, const DistortParams& params); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: diff --git a/src/gpu/effect.cc b/src/gpu/effect.cc index fba3353..528d7fc 100644 --- a/src/gpu/effect.cc +++ b/src/gpu/effect.cc @@ -12,8 +12,9 @@ #include // --- PostProcessEffect --- -void PostProcessEffect::render(WGPURenderPassEncoder pass, float, float, float, - float) { +void PostProcessEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + (void)uniforms; // Base implementation doesn't use uniforms if (pipeline_ && bind_group_) { wgpuRenderPassEncoderSetPipeline(pass, pipeline_); wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_, 0, nullptr); @@ -256,9 +257,19 @@ void MainSequence::render_frame(float global_time, float beat, float peak, }); // 1. Compute + // Construct common uniforms once (reused for all effects) + CommonPostProcessUniforms base_uniforms = { + .resolution = {static_cast(width_), static_cast(height_)}, + ._pad = {0.0f, 0.0f}, + .aspect_ratio = aspect_ratio, + .time = 0.0f, // Will be set per-effect + .beat = beat, + .audio_intensity = peak, + }; + for (const SequenceItem* item : scene_effects) { - item->effect->compute(encoder, global_time - item->start_time, beat, peak, - aspect_ratio); + base_uniforms.time = global_time - item->start_time; + item->effect->compute(encoder, base_uniforms); } // 2. Scene Pass (to A) @@ -287,8 +298,8 @@ void MainSequence::render_frame(float global_time, float beat, float peak, wgpuRenderPassEncoderSetViewport(scene_pass, 0.0f, 0.0f, (float)width_, (float)height_, 0.0f, 1.0f); for (const SequenceItem* item : scene_effects) { - item->effect->render(scene_pass, global_time - item->start_time, beat, peak, - aspect_ratio); + base_uniforms.time = global_time - item->start_time; + item->effect->render(scene_pass, base_uniforms); } wgpuRenderPassEncoderEnd(scene_pass); @@ -326,7 +337,8 @@ void MainSequence::render_frame(float global_time, float beat, float peak, PostProcessEffect* passthrough = (PostProcessEffect*)passthrough_effect_.get(); passthrough->update_bind_group(framebuffer_view_a_); - passthrough->render(capture_pass, 0, 0, 0, aspect_ratio); + base_uniforms.time = 0.0f; + passthrough->render(capture_pass, base_uniforms); wgpuRenderPassEncoderEnd(capture_pass); } @@ -358,7 +370,8 @@ void MainSequence::render_frame(float global_time, float beat, float peak, wgpuCommandEncoderBeginRenderPass(encoder, &final_desc); wgpuRenderPassEncoderSetViewport(final_pass, 0.0f, 0.0f, (float)width_, (float)height_, 0.0f, 1.0f); - passthrough_effect_->render(final_pass, 0, 0, 0, aspect_ratio); + base_uniforms.time = 0.0f; + passthrough_effect_->render(final_pass, base_uniforms); wgpuRenderPassEncoderEnd(final_pass); } else { WGPUTextureView current_input = framebuffer_view_a_; @@ -395,8 +408,8 @@ void MainSequence::render_frame(float global_time, float beat, float peak, wgpuCommandEncoderBeginRenderPass(encoder, &pp_desc); wgpuRenderPassEncoderSetViewport(pp_pass, 0.0f, 0.0f, (float)width_, (float)height_, 0.0f, 1.0f); - pp->render(pp_pass, global_time - post_effects[i]->start_time, beat, peak, - aspect_ratio); + base_uniforms.time = global_time - post_effects[i]->start_time; + pp->render(pp_pass, base_uniforms); wgpuRenderPassEncoderEnd(pp_pass); current_input = current_output; } @@ -511,8 +524,15 @@ void MainSequence::simulate_until(float target_time, float step_rate, } } for (const SequenceItem* item : scene_effects) { - item->effect->compute(encoder, t - item->start_time, beat, 0.0f, - aspect_ratio); + CommonPostProcessUniforms test_uniforms = { + .resolution = {static_cast(width_), static_cast(height_)}, + ._pad = {0.0f, 0.0f}, + .aspect_ratio = aspect_ratio, + .time = t - item->start_time, + .beat = beat, + .audio_intensity = 0.0f, + }; + item->effect->compute(encoder, test_uniforms); } WGPUCommandBuffer commands = wgpuCommandEncoderFinish(encoder, nullptr); wgpuQueueSubmit(gpu_ctx.queue, 1, &commands); diff --git a/src/gpu/effect.h b/src/gpu/effect.h index f008c8d..7991700 100644 --- a/src/gpu/effect.h +++ b/src/gpu/effect.h @@ -22,16 +22,13 @@ class Effect { } virtual void start() { } - virtual void compute(WGPUCommandEncoder encoder, float time, float beat, - float intensity, float aspect_ratio) { + virtual void compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) { (void)encoder; - (void)time; - (void)beat; - (void)intensity; - (void)aspect_ratio; + (void)uniforms; } - virtual void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) = 0; + virtual void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) = 0; virtual void resize(int width, int height) { width_ = width; height_ = height; @@ -50,6 +47,21 @@ class Effect { return false; } + // Helper: get initialized CommonPostProcessUniforms based on current dimensions + // If aspect_ratio < 0, computes from width_/height_ + CommonPostProcessUniforms get_common_uniforms(float time = 0.0f, float beat = 0.0f, + float intensity = 0.0f, + float aspect_ratio = -1.0f) const { + return { + .resolution = {static_cast(width_), static_cast(height_)}, + ._pad = {0.0f, 0.0f}, + .aspect_ratio = aspect_ratio < 0.0f ? static_cast(width_) / static_cast(height_) : aspect_ratio, + .time = time, + .beat = beat, + .audio_intensity = intensity, + }; + } + protected: const GpuContext& ctx_; UniformBuffer uniforms_; @@ -64,10 +76,10 @@ class PostProcessEffect : public Effect { bool is_post_process() const override { return true; } - void compute(WGPUCommandEncoder, float, float, float, float) override { + void compute(WGPUCommandEncoder, const CommonPostProcessUniforms&) override { } - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; virtual void update_bind_group(WGPUTextureView input_view) = 0; protected: diff --git a/src/gpu/effects/chroma_aberration_effect.cc b/src/gpu/effects/chroma_aberration_effect.cc index af3acc5..3a51965 100644 --- a/src/gpu/effects/chroma_aberration_effect.cc +++ b/src/gpu/effects/chroma_aberration_effect.cc @@ -21,18 +21,10 @@ ChromaAberrationEffect::ChromaAberrationEffect( params_buffer_.init(ctx_.device); } -void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, float time, - float beat, float intensity, - float aspect_ratio) { +void ChromaAberrationEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Update uniforms with current state and parameters - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; - uniforms_.update(ctx_.queue, u); + uniforms_.update(ctx_.queue, uniforms); params_buffer_.update(ctx_.queue, params_); wgpuRenderPassEncoderSetPipeline(pass, pipeline_); diff --git a/src/gpu/effects/circle_mask_effect.cc b/src/gpu/effects/circle_mask_effect.cc index ca80cf9..d2645d6 100644 --- a/src/gpu/effects/circle_mask_effect.cc +++ b/src/gpu/effects/circle_mask_effect.cc @@ -33,6 +33,9 @@ void CircleMaskEffect::init(MainSequence* demo) { compute_params_.init(ctx_.device); + // Initialize uniforms BEFORE bind group creation + uniforms_.update(ctx_.queue, get_common_uniforms()); + WGPUSamplerDescriptor sampler_desc = {}; sampler_desc.addressModeU = WGPUAddressMode_ClampToEdge; sampler_desc.addressModeV = WGPUAddressMode_ClampToEdge; @@ -154,16 +157,8 @@ void CircleMaskEffect::init(MainSequence* demo) { render_bind_group_ = wgpuDeviceCreateBindGroup(ctx_.device, &render_bg_desc); } -void CircleMaskEffect::compute(WGPUCommandEncoder encoder, float time, - float beat, float intensity, - float aspect_ratio) { - const CommonPostProcessUniforms uniforms = { - .resolution = {static_cast(width_), static_cast(height_)}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; +void CircleMaskEffect::compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) { uniforms_.update(ctx_.queue, uniforms); const CircleMaskParams params = { @@ -194,15 +189,8 @@ void CircleMaskEffect::compute(WGPUCommandEncoder encoder, float time, wgpuRenderPassEncoderRelease(pass); } -void CircleMaskEffect::render(WGPURenderPassEncoder pass, float time, - float beat, float intensity, float aspect_ratio) { - const CommonPostProcessUniforms uniforms = { - .resolution = {static_cast(width_), static_cast(height_)}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; +void CircleMaskEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { uniforms_.update(ctx_.queue, uniforms); wgpuRenderPassEncoderSetPipeline(pass, render_pipeline_); diff --git a/src/gpu/effects/circle_mask_effect.h b/src/gpu/effects/circle_mask_effect.h index 2ddbb11..e52371d 100644 --- a/src/gpu/effects/circle_mask_effect.h +++ b/src/gpu/effects/circle_mask_effect.h @@ -15,10 +15,10 @@ class CircleMaskEffect : public Effect { ~CircleMaskEffect() override; void init(MainSequence* demo) override; - void compute(WGPUCommandEncoder encoder, float time, float beat, - float intensity, float aspect_ratio) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: struct CircleMaskParams { diff --git a/src/gpu/effects/cnn_effect.cc b/src/gpu/effects/cnn_effect.cc index e12c26f..3f6d3b3 100644 --- a/src/gpu/effects/cnn_effect.cc +++ b/src/gpu/effects/cnn_effect.cc @@ -53,6 +53,9 @@ void CNNEffect::init(MainSequence* demo) { demo_ = demo; params_buffer_.init(ctx_.device); + // Initialize uniforms BEFORE any bind group creation + uniforms_.update(ctx_.queue, get_common_uniforms()); + // Register captured_frame texture (used by all layers for original input) if (layer_index_ == 0) { demo_->register_auxiliary_texture("captured_frame", width_, height_); @@ -62,8 +65,9 @@ void CNNEffect::init(MainSequence* demo) { params_buffer_.update(ctx_.queue, params); } -void CNNEffect::render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) { +void CNNEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + (void)uniforms; if (!bind_group_) { fprintf(stderr, "CNN render: no bind_group\n"); return; @@ -78,14 +82,7 @@ void CNNEffect::update_bind_group(WGPUTextureView input_view) { input_view_ = input_view; // Update common uniforms (CRITICAL for UV calculation!) - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = (float)width_ / (float)height_, - .time = 0.0f, - .beat = 0.0f, - .audio_intensity = 0.0f, - }; - uniforms_.update(ctx_.queue, u); + uniforms_.update(ctx_.queue, get_common_uniforms()); // All layers: get captured frame (original input from layer 0) if (demo_) { diff --git a/src/gpu/effects/cnn_effect.h b/src/gpu/effects/cnn_effect.h index bc074d2..f9a982b 100644 --- a/src/gpu/effects/cnn_effect.h +++ b/src/gpu/effects/cnn_effect.h @@ -24,8 +24,8 @@ class CNNEffect : public PostProcessEffect { explicit CNNEffect(const GpuContext& ctx, const CNNEffectParams& params); void init(MainSequence* demo) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; // Layer 0 needs framebuffer capture for original input diff --git a/src/gpu/effects/distort_effect.cc b/src/gpu/effects/distort_effect.cc index 52a8ec7..97622b2 100644 --- a/src/gpu/effects/distort_effect.cc +++ b/src/gpu/effects/distort_effect.cc @@ -16,17 +16,10 @@ DistortEffect::DistortEffect(const GpuContext& ctx, const DistortParams& params) distort_shader_wgsl); } -void DistortEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { +void DistortEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Populate CommonPostProcessUniforms - const CommonPostProcessUniforms common_u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, common_u); + uniforms_.update(ctx_.queue, uniforms); // Populate DistortParams const DistortParams distort_p = { @@ -35,7 +28,7 @@ void DistortEffect::render(WGPURenderPassEncoder pass, float t, float b, }; params_buffer_.update(ctx_.queue, distort_p); - PostProcessEffect::render(pass, t, b, i, a); + PostProcessEffect::render(pass, uniforms); } void DistortEffect::update_bind_group(WGPUTextureView v) { diff --git a/src/gpu/effects/fade_effect.cc b/src/gpu/effects/fade_effect.cc index 39b54e0..93684d8 100644 --- a/src/gpu/effects/fade_effect.cc +++ b/src/gpu/effects/fade_effect.cc @@ -72,26 +72,19 @@ void FadeEffect::update_bind_group(WGPUTextureView input_view) { uniforms_.get(), params_buffer_); } -void FadeEffect::render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; - uniforms_.update(ctx_.queue, u); +void FadeEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); // Example fade pattern: fade in at start, fade out at end // Customize this based on your needs float fade_amount = 1.0f; - if (time < 2.0f) { + if (uniforms.time < 2.0f) { // Fade in from black over first 2 seconds - fade_amount = time / 2.0f; - } else if (time > 36.0f) { + fade_amount = uniforms.time / 2.0f; + } else if (uniforms.time > 36.0f) { // Fade out to black after 36 seconds - fade_amount = 1.0f - ((time - 36.0f) / 4.0f); + fade_amount = 1.0f - ((uniforms.time - 36.0f) / 4.0f); fade_amount = fmaxf(fade_amount, 0.0f); } diff --git a/src/gpu/effects/fade_effect.h b/src/gpu/effects/fade_effect.h index 178c360..3360a5f 100644 --- a/src/gpu/effects/fade_effect.h +++ b/src/gpu/effects/fade_effect.h @@ -11,8 +11,8 @@ class FadeEffect : public PostProcessEffect { public: FadeEffect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: diff --git a/src/gpu/effects/flash_cube_effect.cc b/src/gpu/effects/flash_cube_effect.cc index f01bbd1..ee25408 100644 --- a/src/gpu/effects/flash_cube_effect.cc +++ b/src/gpu/effects/flash_cube_effect.cc @@ -48,11 +48,11 @@ void FlashCubeEffect::init(MainSequence* demo) { scene_.add_object(cube); } -void FlashCubeEffect::render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) { +void FlashCubeEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Detect beat changes for flash trigger (using intensity as proxy for beat // hits) Intensity spikes on beats, so we can use it to trigger flashes - if (intensity > 0.5f && + if (uniforms.audio_intensity > 0.5f && flash_intensity_ < 0.3f) { // High intensity + flash cooled down flash_intensity_ = 1.0f; // Trigger full flash } @@ -73,12 +73,12 @@ void FlashCubeEffect::render(WGPURenderPassEncoder pass, float time, float beat, // Slowly rotate the cube for visual interest scene_.objects[0].rotation = - quat::from_axis(vec3(0.3f, 1, 0.2f), time * 0.05f); + quat::from_axis(vec3(0.3f, 1, 0.2f), uniforms.time * 0.05f); // Position camera OUTSIDE the cube looking at it from a distance // This way we see the cube as a background element float cam_distance = 150.0f; // Much farther to ensure it's behind everything - float orbit_angle = time * 0.1f; + float orbit_angle = uniforms.time * 0.1f; camera_.set_look_at( vec3(std::sin(orbit_angle) * cam_distance, @@ -87,11 +87,11 @@ void FlashCubeEffect::render(WGPURenderPassEncoder pass, float time, float beat, vec3(0, 0, 0), // Look at cube center vec3(0, 1, 0)); - camera_.aspect_ratio = aspect_ratio; + camera_.aspect_ratio = uniforms.aspect_ratio; // Extend far plane to accommodate distant camera position (150 units + cube // size) camera_.far_plane = 300.0f; // Draw the cube - renderer_.draw(pass, scene_, camera_, time); + renderer_.draw(pass, scene_, camera_, uniforms.time); } diff --git a/src/gpu/effects/flash_cube_effect.h b/src/gpu/effects/flash_cube_effect.h index 5faeb00..1c71164 100644 --- a/src/gpu/effects/flash_cube_effect.h +++ b/src/gpu/effects/flash_cube_effect.h @@ -14,8 +14,8 @@ class FlashCubeEffect : public Effect { FlashCubeEffect(const GpuContext& ctx); void init(MainSequence* demo) override; void resize(int width, int height) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: Renderer3D renderer_; diff --git a/src/gpu/effects/flash_effect.cc b/src/gpu/effects/flash_effect.cc index 57c1d73..4357c34 100644 --- a/src/gpu/effects/flash_effect.cc +++ b/src/gpu/effects/flash_effect.cc @@ -1,5 +1,5 @@ // This file is part of the 64k demo project. -// It implements the FlashEffect - brief flash on beat hits. +// It implements the FlashEffect - brief flash on u.beat hits. // Now supports parameterized color with per-frame animation. #include "gpu/effects/flash_effect.h" @@ -22,7 +22,7 @@ FlashEffect::FlashEffect(const GpuContext& ctx, const FlashEffectParams& params) struct Uniforms { flash_intensity: f32, - intensity: f32, + audio_intensity: f32, flash_color: vec3, // Parameterized color _pad: f32, }; @@ -63,12 +63,10 @@ void FlashEffect::update_bind_group(WGPUTextureView input_view) { flash_uniforms_.get(), {}); } -void FlashEffect::render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) { - (void)aspect_ratio; - +void FlashEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Trigger flash based on configured threshold - if (intensity > params_.trigger_threshold && flash_intensity_ < 0.2f) { + if (uniforms.audio_intensity > params_.trigger_threshold && flash_intensity_ < 0.2f) { flash_intensity_ = 0.8f; // Trigger flash } @@ -77,14 +75,14 @@ void FlashEffect::render(WGPURenderPassEncoder pass, float time, float beat, // *** PER-FRAME PARAMETER COMPUTATION *** // Animate color based on time and beat - const float r = params_.color[0] * (0.5f + 0.5f * sinf(time * 0.5f)); - const float g = params_.color[1] * (0.5f + 0.5f * cosf(time * 0.7f)); - const float b = params_.color[2] * (1.0f + 0.3f * beat); + const float r = params_.color[0] * (0.5f + 0.5f * sinf(uniforms.time * 0.5f)); + const float g = params_.color[1] * (0.5f + 0.5f * cosf(uniforms.time * 0.7f)); + const float b = params_.color[2] * (1.0f + 0.3f * uniforms.beat); // Update uniforms with computed (animated) values const FlashUniforms u = { .flash_intensity = flash_intensity_, - .intensity = intensity, + .intensity = uniforms.audio_intensity, ._pad1 = {0.0f, 0.0f}, // Padding for vec3 alignment .color = {r, g, b}, // Time-dependent, computed every frame ._pad2 = 0.0f}; diff --git a/src/gpu/effects/flash_effect.h b/src/gpu/effects/flash_effect.h index 55bad7b..1ac75a4 100644 --- a/src/gpu/effects/flash_effect.h +++ b/src/gpu/effects/flash_effect.h @@ -33,8 +33,8 @@ class FlashEffect : public PostProcessEffect { FlashEffect(const GpuContext& ctx); // New parameterized constructor FlashEffect(const GpuContext& ctx, const FlashEffectParams& params); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: diff --git a/src/gpu/effects/gaussian_blur_effect.cc b/src/gpu/effects/gaussian_blur_effect.cc index 697be88..4421e33 100644 --- a/src/gpu/effects/gaussian_blur_effect.cc +++ b/src/gpu/effects/gaussian_blur_effect.cc @@ -21,18 +21,10 @@ GaussianBlurEffect::GaussianBlurEffect(const GpuContext& ctx, params_buffer_.init(ctx_.device); } -void GaussianBlurEffect::render(WGPURenderPassEncoder pass, float time, - float beat, float intensity, - float aspect_ratio) { +void GaussianBlurEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Update uniforms with current state and parameters - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; - uniforms_.update(ctx_.queue, u); + uniforms_.update(ctx_.queue, uniforms); params_buffer_.update(ctx_.queue, params_); wgpuRenderPassEncoderSetPipeline(pass, pipeline_); diff --git a/src/gpu/effects/heptagon_effect.cc b/src/gpu/effects/heptagon_effect.cc index 7b0702d..724eabb 100644 --- a/src/gpu/effects/heptagon_effect.cc +++ b/src/gpu/effects/heptagon_effect.cc @@ -13,17 +13,9 @@ HeptagonEffect::HeptagonEffect(const GpuContext& ctx) : Effect(ctx) { bindings, 1); pass_.vertex_count = 21; } -void HeptagonEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { - CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - ._pad = {0.0f, 0.0f}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void HeptagonEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline); wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr); wgpuRenderPassEncoderDraw(pass, pass_.vertex_count, 1, 0, 0); diff --git a/src/gpu/effects/hybrid_3d_effect.cc b/src/gpu/effects/hybrid_3d_effect.cc index 17fef25..d580471 100644 --- a/src/gpu/effects/hybrid_3d_effect.cc +++ b/src/gpu/effects/hybrid_3d_effect.cc @@ -87,19 +87,19 @@ static float ease_in_out_cubic(float t) { return 0.5f * (t * t * t + 2.0f); } -void Hybrid3DEffect::render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) { +void Hybrid3DEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { // Animate Objects for (size_t i = 1; i < scene_.objects.size(); ++i) { scene_.objects[i].rotation = - quat::from_axis(vec3(0, 1, 0), time * 2.0f + i); + quat::from_axis(vec3(0, 1, 0), uniforms.time * 2.0f + i); - scene_.objects[i].position.y = std::sin(time * 3.0f + i) * 1.5f; + scene_.objects[i].position.y = std::sin(uniforms.time * 3.0f + i) * 1.5f; } // Camera jumps every other pattern (2 seconds) for dramatic effect - int pattern_num = (int)(time / 2.0f); + int pattern_num = (int)(uniforms.time / 2.0f); int camera_preset = pattern_num % 4; // Cycle through 4 different angles vec3 cam_pos, cam_target; @@ -107,34 +107,34 @@ void Hybrid3DEffect::render(WGPURenderPassEncoder pass, float time, float beat, switch (camera_preset) { case 0: // High angle, orbiting { - float angle = time * 0.5f; + float angle = uniforms.time * 0.5f; cam_pos = vec3(std::sin(angle) * 12.0f, 8.0f, std::cos(angle) * 12.0f); cam_target = vec3(0, 0, 0); } break; case 1: // Low angle, close-up { - float angle = time * 0.3f + 1.57f; // Offset angle + float angle = uniforms.time * 0.3f + 1.57f; // Offset angle cam_pos = vec3(std::sin(angle) * 6.0f, 2.0f, std::cos(angle) * 6.0f); cam_target = vec3(0, 1, 0); } break; case 2: // Side view, sweeping { - float sweep = std::sin(time * 0.4f) * 10.0f; + float sweep = std::sin(uniforms.time * 0.4f) * 10.0f; cam_pos = vec3(sweep, 5.0f, 8.0f); cam_target = vec3(0, 0, 0); } break; case 3: // Top-down, rotating { - float angle = time * 0.6f; + float angle = uniforms.time * 0.6f; cam_pos = vec3(std::sin(angle) * 5.0f, 12.0f, std::cos(angle) * 5.0f); cam_target = vec3(0, 0, 0); } break; } camera_.set_look_at(cam_pos, cam_target, vec3(0, 1, 0)); - camera_.aspect_ratio = aspect_ratio; + camera_.aspect_ratio = uniforms.aspect_ratio; // Draw - renderer_.draw(pass, scene_, camera_, time); + renderer_.draw(pass, scene_, camera_, uniforms.time); } diff --git a/src/gpu/effects/hybrid_3d_effect.h b/src/gpu/effects/hybrid_3d_effect.h index 3a4e87c..ea8285b 100644 --- a/src/gpu/effects/hybrid_3d_effect.h +++ b/src/gpu/effects/hybrid_3d_effect.h @@ -16,8 +16,8 @@ class Hybrid3DEffect : public Effect { virtual ~Hybrid3DEffect() override = default; void init(MainSequence* demo) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void resize(int width, int height) override; private: diff --git a/src/gpu/effects/moving_ellipse_effect.cc b/src/gpu/effects/moving_ellipse_effect.cc index 9866f20..bbd3c08 100644 --- a/src/gpu/effects/moving_ellipse_effect.cc +++ b/src/gpu/effects/moving_ellipse_effect.cc @@ -13,17 +13,9 @@ MovingEllipseEffect::MovingEllipseEffect(const GpuContext& ctx) : Effect(ctx) { bindings, 1); pass_.vertex_count = 3; } -void MovingEllipseEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - ._pad = {0.0f, 0.0f}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void MovingEllipseEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline); wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr); wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0); diff --git a/src/gpu/effects/particle_spray_effect.cc b/src/gpu/effects/particle_spray_effect.cc index a435884..9b615d0 100644 --- a/src/gpu/effects/particle_spray_effect.cc +++ b/src/gpu/effects/particle_spray_effect.cc @@ -27,16 +27,9 @@ ParticleSprayEffect::ParticleSprayEffect(const GpuContext& ctx) : Effect(ctx) { render_pass_.vertex_count = 6; render_pass_.instance_count = NUM_PARTICLES; } -void ParticleSprayEffect::compute(WGPUCommandEncoder e, float t, float b, - float i, float a) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void ParticleSprayEffect::compute(WGPUCommandEncoder e, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(e, nullptr); wgpuComputePassEncoderSetPipeline(pass, compute_pass_.pipeline); wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0, @@ -45,8 +38,9 @@ void ParticleSprayEffect::compute(WGPUCommandEncoder e, float t, float b, 1, 1); wgpuComputePassEncoderEnd(pass); } -void ParticleSprayEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { +void ParticleSprayEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + (void)uniforms; wgpuRenderPassEncoderSetPipeline(pass, render_pass_.pipeline); wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0, nullptr); diff --git a/src/gpu/effects/particles_effect.cc b/src/gpu/effects/particles_effect.cc index cd0df74..f8c18f0 100644 --- a/src/gpu/effects/particles_effect.cc +++ b/src/gpu/effects/particles_effect.cc @@ -25,16 +25,9 @@ ParticlesEffect::ParticlesEffect(const GpuContext& ctx) : Effect(ctx) { render_pass_.vertex_count = 6; render_pass_.instance_count = NUM_PARTICLES; } -void ParticlesEffect::compute(WGPUCommandEncoder e, float t, float b, float i, - float a) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void ParticlesEffect::compute(WGPUCommandEncoder e, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); WGPUComputePassEncoder pass = wgpuCommandEncoderBeginComputePass(e, nullptr); wgpuComputePassEncoderSetPipeline(pass, compute_pass_.pipeline); wgpuComputePassEncoderSetBindGroup(pass, 0, compute_pass_.bind_group, 0, @@ -43,8 +36,9 @@ void ParticlesEffect::compute(WGPUCommandEncoder e, float t, float b, float i, 1, 1); wgpuComputePassEncoderEnd(pass); } -void ParticlesEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { +void ParticlesEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + (void)uniforms; wgpuRenderPassEncoderSetPipeline(pass, render_pass_.pipeline); wgpuRenderPassEncoderSetBindGroup(pass, 0, render_pass_.bind_group, 0, nullptr); diff --git a/src/gpu/effects/passthrough_effect.cc b/src/gpu/effects/passthrough_effect.cc index 01d557a..aedb387 100644 --- a/src/gpu/effects/passthrough_effect.cc +++ b/src/gpu/effects/passthrough_effect.cc @@ -11,14 +11,7 @@ PassthroughEffect::PassthroughEffect(const GpuContext& ctx) passthrough_shader_wgsl); } void PassthroughEffect::update_bind_group(WGPUTextureView input_view) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = 1.0f, - .time = 0.0f, - .beat = 0.0f, - .audio_intensity = 0.0f, - }; - uniforms_.update(ctx_.queue, u); + uniforms_.update(ctx_.queue, get_common_uniforms()); pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, input_view, uniforms_.get(), {}); } diff --git a/src/gpu/effects/rotating_cube_effect.cc b/src/gpu/effects/rotating_cube_effect.cc index da973e5..79a540b 100644 --- a/src/gpu/effects/rotating_cube_effect.cc +++ b/src/gpu/effects/rotating_cube_effect.cc @@ -182,9 +182,8 @@ void RotatingCubeEffect::init(MainSequence* demo) { wgpuBindGroupLayoutRelease(bgl_1); } -void RotatingCubeEffect::render(WGPURenderPassEncoder pass, float time, - float beat, float intensity, - float aspect_ratio) { +void RotatingCubeEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& u) { rotation_ += 0.016f * 1.5f; const vec3 camera_pos = vec3(0, 0, 5); @@ -193,7 +192,7 @@ void RotatingCubeEffect::render(WGPURenderPassEncoder pass, float time, const mat4 view = mat4::look_at(camera_pos, target, up); const float fov = 60.0f * 3.14159f / 180.0f; - const mat4 proj = mat4::perspective(fov, aspect_ratio, 0.1f, 100.0f); + const mat4 proj = mat4::perspective(fov, u.aspect_ratio, 0.1f, 100.0f); const mat4 view_proj = proj * view; const quat rot = quat::from_axis(vec3(0.3f, 1.0f, 0.2f), rotation_); @@ -206,7 +205,7 @@ void RotatingCubeEffect::render(WGPURenderPassEncoder pass, float time, const Uniforms uniforms = { .view_proj = view_proj, .inv_view_proj = view_proj.inverse(), - .camera_pos_time = vec4(camera_pos.x, camera_pos.y, camera_pos.z, time), + .camera_pos_time = vec4(camera_pos.x, camera_pos.y, camera_pos.z, u.time), .params = vec4(1.0f, 0.0f, 0.0f, 0.0f), .resolution = vec2(1280.0f, 720.0f), }; diff --git a/src/gpu/effects/rotating_cube_effect.h b/src/gpu/effects/rotating_cube_effect.h index 89b3fa6..fdf67ab 100644 --- a/src/gpu/effects/rotating_cube_effect.h +++ b/src/gpu/effects/rotating_cube_effect.h @@ -16,8 +16,8 @@ class RotatingCubeEffect : public Effect { ~RotatingCubeEffect() override; void init(MainSequence* demo) override; - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: struct Uniforms { diff --git a/src/gpu/effects/scene1_effect.cc b/src/gpu/effects/scene1_effect.cc index a6733b7..c75e511 100644 --- a/src/gpu/effects/scene1_effect.cc +++ b/src/gpu/effects/scene1_effect.cc @@ -11,17 +11,9 @@ Scene1Effect::Scene1Effect(const GpuContext& ctx) : Effect(ctx) { pass_.vertex_count = 3; } -void Scene1Effect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { - CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - ._pad = {0.0f, 0.0f}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void Scene1Effect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); wgpuRenderPassEncoderSetPipeline(pass, pass_.pipeline); wgpuRenderPassEncoderSetBindGroup(pass, 0, pass_.bind_group, 0, nullptr); wgpuRenderPassEncoderDraw(pass, pass_.vertex_count, 1, 0, 0); diff --git a/src/gpu/effects/scene1_effect.h b/src/gpu/effects/scene1_effect.h index dc5c747..190ffa9 100644 --- a/src/gpu/effects/scene1_effect.h +++ b/src/gpu/effects/scene1_effect.h @@ -9,8 +9,8 @@ class Scene1Effect : public Effect { public: Scene1Effect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; private: RenderPass pass_; diff --git a/src/gpu/effects/solarize_effect.cc b/src/gpu/effects/solarize_effect.cc index 4f47218..cdb9354 100644 --- a/src/gpu/effects/solarize_effect.cc +++ b/src/gpu/effects/solarize_effect.cc @@ -9,17 +9,10 @@ SolarizeEffect::SolarizeEffect(const GpuContext& ctx) : PostProcessEffect(ctx) { pipeline_ = create_post_process_pipeline(ctx_.device, ctx_.format, solarize_shader_wgsl); } -void SolarizeEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); - PostProcessEffect::render(pass, t, b, i, a); +void SolarizeEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); + PostProcessEffect::render(pass, uniforms); } void SolarizeEffect::update_bind_group(WGPUTextureView v) { pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, v, uniforms_.get(), diff --git a/src/gpu/effects/theme_modulation_effect.cc b/src/gpu/effects/theme_modulation_effect.cc index b1eff90..aff6bce 100644 --- a/src/gpu/effects/theme_modulation_effect.cc +++ b/src/gpu/effects/theme_modulation_effect.cc @@ -76,26 +76,18 @@ void ThemeModulationEffect::update_bind_group(WGPUTextureView input_view) { uniforms_.get(), params_buffer_); } -void ThemeModulationEffect::render(WGPURenderPassEncoder pass, float time, - float beat, float intensity, - float aspect_ratio) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = aspect_ratio, - .time = time, - .beat = beat, - .audio_intensity = intensity, - }; - uniforms_.update(ctx_.queue, u); +void ThemeModulationEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); // Alternate between bright and dark every 4 seconds (2 pattern changes) // Music patterns change every 2 seconds at 120 BPM - float cycle_time = fmodf(time, 8.0f); // 8 second cycle (4 patterns) + float cycle_time = fmodf(uniforms.time, 8.0f); // 8 second cycle (4 patterns) bool is_dark_section = (cycle_time >= 4.0f); // Dark for second half // Smooth transition between themes using a sine wave float transition = - (std::sin(time * 3.14159f / 4.0f) + 1.0f) * 0.5f; // 0.0 to 1.0 + (std::sin(uniforms.time * 3.14159f / 4.0f) + 1.0f) * 0.5f; // 0.0 to 1.0 float bright_value = 1.0f; float dark_value = 0.35f; float theme_brightness = diff --git a/src/gpu/effects/theme_modulation_effect.h b/src/gpu/effects/theme_modulation_effect.h index 713347b..31e96e6 100644 --- a/src/gpu/effects/theme_modulation_effect.h +++ b/src/gpu/effects/theme_modulation_effect.h @@ -11,8 +11,8 @@ class ThemeModulationEffect : public PostProcessEffect { public: ThemeModulationEffect(const GpuContext& ctx); - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override; + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override; void update_bind_group(WGPUTextureView input_view) override; private: diff --git a/src/gpu/effects/vignette_effect.cc b/src/gpu/effects/vignette_effect.cc index bba0372..4b0ffe2 100644 --- a/src/gpu/effects/vignette_effect.cc +++ b/src/gpu/effects/vignette_effect.cc @@ -17,18 +17,11 @@ VignetteEffect::VignetteEffect(const GpuContext& ctx, vignette_shader_wgsl); } -void VignetteEffect::render(WGPURenderPassEncoder pass, float t, float b, - float i, float a) { - const CommonPostProcessUniforms u = { - .resolution = {(float)width_, (float)height_}, - .aspect_ratio = a, - .time = t, - .beat = b, - .audio_intensity = i, - }; - uniforms_.update(ctx_.queue, u); +void VignetteEffect::render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) { + uniforms_.update(ctx_.queue, uniforms); params_buffer_.update(ctx_.queue, params_); - PostProcessEffect::render(pass, t, b, i, a); + PostProcessEffect::render(pass, uniforms); } void VignetteEffect::update_bind_group(WGPUTextureView v) { diff --git a/src/tests/assets/test_sequence.cc b/src/tests/assets/test_sequence.cc index d79ec1d..44aac46 100644 --- a/src/tests/assets/test_sequence.cc +++ b/src/tests/assets/test_sequence.cc @@ -38,22 +38,16 @@ class DummyEffect : public Effect { void start() override { ++start_calls; } - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override { + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override { ++render_calls; (void)pass; - (void)time; - (void)beat; - (void)intensity; - (void)aspect_ratio; + (void)uniforms; } - void compute(WGPUCommandEncoder encoder, float time, float beat, - float intensity, float aspect_ratio) override { + void compute(WGPUCommandEncoder encoder, + const CommonPostProcessUniforms& uniforms) override { (void)encoder; - (void)time; - (void)beat; - (void)intensity; - (void)aspect_ratio; + (void)uniforms; } void end() override { ++end_calls; @@ -77,14 +71,11 @@ class DummyPostProcessEffect : public PostProcessEffect { ++init_calls; (void)demo; } - void render(WGPURenderPassEncoder pass, float time, float beat, - float intensity, float aspect_ratio) override { + void render(WGPURenderPassEncoder pass, + const CommonPostProcessUniforms& uniforms) override { ++render_calls; (void)pass; - (void)time; - (void)beat; - (void)intensity; - (void)aspect_ratio; + (void)uniforms; } void update_bind_group(WGPUTextureView input_view) override { ++update_bind_group_calls; -- cgit v1.2.3