diff options
Diffstat (limited to 'src/effects/flash_cube_effect.cc')
| -rw-r--r-- | src/effects/flash_cube_effect.cc | 104 |
1 files changed, 104 insertions, 0 deletions
diff --git a/src/effects/flash_cube_effect.cc b/src/effects/flash_cube_effect.cc new file mode 100644 index 0000000..29e9897 --- /dev/null +++ b/src/effects/flash_cube_effect.cc @@ -0,0 +1,104 @@ +// This file is part of the 64k demo project. +// It implements the FlashCubeEffect - a flashing background cube with Perlin +// noise. + +#include "effects/flash_cube_effect.h" +#include "generated/assets.h" +#include "util/asset_manager_utils.h" +#include <cmath> +#include <iostream> + +FlashCubeEffect::FlashCubeEffect(const GpuContext& ctx) : Effect(ctx) { +} + +void FlashCubeEffect::resize(int width, int height) { + if (width == width_ && height == height_) + return; + + Effect::resize(width, height); + + if (!initialized_) + return; + + renderer_.resize(width_, height_); +} + +void FlashCubeEffect::init(MainSequence* demo) { + (void)demo; + WGPUTextureFormat format = demo->gpu_ctx.format; + + renderer_.init(ctx_.device, ctx_.queue, ctx_.format); + renderer_.resize(width_, height_); + initialized_ = true; + + // Texture Manager + texture_manager_.init(ctx_.device, ctx_.queue); + + // Load Perlin noise texture + TextureAsset noise_tex = GetTextureAsset(AssetId::ASSET_NOISE_TEX); + if (noise_tex.pixels && noise_tex.width == 256 && noise_tex.height == 256) { + texture_manager_.create_texture("noise", noise_tex.width, noise_tex.height, + noise_tex.pixels); + renderer_.set_noise_texture(texture_manager_.get_texture_view("noise")); + } else { + std::cerr << "Failed to load NOISE_TEX asset for FlashCubeEffect." + << std::endl; + } + + // Create a very large background cube + // Scale and distance ensure it's clearly behind foreground objects + scene_.clear(); + Object3D cube(ObjectType::BOX); + cube.position = vec3(0, 0, 0); + cube.scale = vec3(100.0f, 100.0f, 100.0f); // Much larger cube + cube.color = vec4(0.3f, 0.3f, 0.5f, 1.0f); // Dark blue base color + scene_.add_object(cube); +} + +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 (uniforms.audio_intensity > 0.5f && + flash_intensity_ < 0.3f) { // High intensity + flash cooled down + flash_intensity_ = 1.0f; // Trigger full flash + } + + // Exponential decay of flash + flash_intensity_ *= 0.90f; // Slower fade for more visible effect + + // Always have base brightness, add flash on top + float base_brightness = 0.2f; + float flash_boost = + base_brightness + flash_intensity_ * 0.8f; // 0.2 to 1.0 range + + scene_.objects[0].color = + vec4(0.4f * flash_boost, // Reddish tint + 0.6f * flash_boost, // More green + 1.0f * flash_boost, // Strong blue for background feel + 1.0f); + + // Slowly rotate the cube for visual interest + scene_.objects[0].rotation = + 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 = uniforms.time * 0.1f; + + camera_.set_look_at( + vec3(std::sin(orbit_angle) * cam_distance, + std::cos(orbit_angle * 0.3f) * 30.0f, + std::cos(orbit_angle) * cam_distance), // Camera orbits around + vec3(0, 0, 0), // Look at cube center + vec3(0, 1, 0)); + + 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_, uniforms.time); +} |
