// This file is part of the 64k demo project. // It implements the FlashCubeEffect - a flashing background cube with Perlin noise. #include "gpu/effects/flash_cube_effect.h" #include "generated/assets.h" #include "util/asset_manager.h" #include #include FlashCubeEffect::FlashCubeEffect(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format) : Effect(device, queue) { (void)format; } void FlashCubeEffect::resize(int width, int height) { width_ = width; height_ = height; renderer_.resize(width_, height_); } void FlashCubeEffect::init(MainSequence* demo) { (void)demo; WGPUTextureFormat format = demo->format; renderer_.init(device_, queue_, format); renderer_.resize(width_, height_); // Texture Manager texture_manager_.init(device_, queue_); // Load Perlin noise texture size_t size = 0; const uint8_t* noise_data = GetAsset(AssetId::ASSET_NOISE_TEX, &size); if (noise_data && size == 256 * 256 * 4) { texture_manager_.create_texture("noise", 256, 256, noise_data); 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, float time, float beat, float intensity, float aspect_ratio) { // 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 && 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), 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; 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 = 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); }