summaryrefslogtreecommitdiff
path: root/src/effects/hybrid_3d_effect.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/effects/hybrid_3d_effect.cc')
-rw-r--r--src/effects/hybrid_3d_effect.cc147
1 files changed, 147 insertions, 0 deletions
diff --git a/src/effects/hybrid_3d_effect.cc b/src/effects/hybrid_3d_effect.cc
new file mode 100644
index 0000000..1cd773d
--- /dev/null
+++ b/src/effects/hybrid_3d_effect.cc
@@ -0,0 +1,147 @@
+// This file is part of the 64k demo project.
+// It implements the Hybrid3DEffect.
+
+#include "effects/hybrid_3d_effect.h"
+#include "generated/assets.h"
+#include "util/asset_manager_utils.h"
+#include <cassert>
+#include <cmath>
+#include <iostream>
+
+Hybrid3DEffect::Hybrid3DEffect(const GpuContext& ctx) : Effect(ctx) {
+}
+
+void Hybrid3DEffect::resize(int width, int height) {
+ if (width == width_ && height == height_)
+ return;
+
+ Effect::resize(width, height);
+
+ if (!initialized_)
+ return;
+
+ renderer_.resize(width_, height_);
+}
+
+void Hybrid3DEffect::init(MainSequence* demo) {
+ (void)demo;
+ WGPUTextureFormat format =
+ demo->gpu_ctx.format; // Get current format from MainSequence (might be
+ // different than constructor if resized)
+
+ renderer_.init(ctx_.device, ctx_.queue, ctx_.format);
+ renderer_.resize(width_, height_);
+ initialized_ = true;
+
+ // Texture Manager
+ texture_manager_.init(ctx_.device, ctx_.queue);
+
+ // Load Noise Asset
+ 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." << std::endl;
+ }
+
+ // Setup Scene
+ scene_.clear();
+ Object3D center(ObjectType::BOX); // Use BOX for bumps
+ center.position = vec3(0, 0, 0);
+ center.color = vec4(1, 0, 0, 1);
+ scene_.add_object(center);
+
+ for (int i = 0; i < 8; ++i) {
+ ObjectType type = ObjectType::SPHERE;
+ if (i % 3 == 1)
+ type = ObjectType::TORUS;
+ if (i % 3 == 2)
+ type = ObjectType::BOX;
+
+ Object3D obj(type);
+
+ float angle = (i / 8.0f) * 6.28318f;
+
+ obj.position = vec3(std::cos(angle) * 4.0f, 0, std::sin(angle) * 4.0f);
+
+ obj.scale = vec3(0.7f, 0.7f, 0.7f); // Increased scale by 40%
+
+ if (type == ObjectType::SPHERE)
+ obj.color = vec4(0, 1, 0, 1);
+
+ else if (type == ObjectType::TORUS)
+ obj.color = vec4(0, 0.5, 1, 1);
+ else
+ obj.color = vec4(1, 1, 0, 1);
+
+ scene_.add_object(obj);
+ }
+}
+
+// Cubic ease-in/out function for non-linear motion
+
+static float ease_in_out_cubic(float t) {
+ t *= 2.0f;
+
+ if (t < 1.0f) {
+ return 0.5f * t * t * t;
+ }
+
+ t -= 2.0f;
+
+ return 0.5f * (t * t * t + 2.0f);
+}
+
+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), uniforms.time * 2.0f + i);
+
+ 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)(uniforms.time / 2.0f);
+ int camera_preset = pattern_num % 4; // Cycle through 4 different angles
+
+ vec3 cam_pos, cam_target;
+
+ switch (camera_preset) {
+ case 0: // High angle, orbiting
+ {
+ 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 = 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(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 = 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 = uniforms.aspect_ratio;
+
+ // Draw
+
+ renderer_.draw(pass, scene_, camera_, uniforms.time);
+}