From 8296fe5180b979b9d1f32f6375b41f0e0a8a399d Mon Sep 17 00:00:00 2001 From: skal Date: Sun, 8 Feb 2026 17:39:33 +0100 Subject: feat(gpu): Add parameter-driven ChromaAberrationEffect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implements Task #73 - Extends shader parametrization system to ChromaAberrationEffect following the FlashEffect pattern. Changes: - Added ChromaAberrationParams struct (offset_scale, angle) - Added ChromaUniforms with proper WGSL alignment (32 bytes) - Updated shader to compute offset direction from angle parameter - Extended seq_compiler to parse offset/angle parameters - Updated demo.seq with 2 parameterized instances: * Line 50: offset=0.03 angle=0.785 (45° diagonal, stronger) * Line 76: offset=0.01 angle=1.57 (90° vertical, subtle) Technical details: - Backward-compatible default constructor maintained - Migrated from raw buffer to UniformBuffer - Shader computes direction: vec2(cos(angle), sin(angle)) - Generated code creates ChromaAberrationParams initialization Testing: - All 32/32 tests pass - Demo runs without errors - Binary size: 5.6M stripped (~200-300 bytes impact) Co-Authored-By: Claude Sonnet 4.5 --- src/3d/object.h | 3 ++- src/3d/renderer.h | 6 +++--- src/3d/scene_loader.cc | 36 ++++++++++++++++++++++-------------- 3 files changed, 27 insertions(+), 18 deletions(-) (limited to 'src/3d') diff --git a/src/3d/object.h b/src/3d/object.h index dfd31ce..a8eb98c 100644 --- a/src/3d/object.h +++ b/src/3d/object.h @@ -43,7 +43,8 @@ class Object3D { AssetId mesh_asset_id; vec3 local_extent; // Half-extents for AABB (used by meshes for shadows) void* user_data; // For tool-specific data, not for general use - std::shared_ptr shared_user_data; // For tool-specific data managed with shared ownership + std::shared_ptr + shared_user_data; // For tool-specific data managed with shared ownership Object3D(ObjectType t = ObjectType::CUBE) : position(0, 0, 0), rotation(0, 0, 0, 1), scale(1, 1, 1), type(t), diff --git a/src/3d/renderer.h b/src/3d/renderer.h index 94a194d..bf3b497 100644 --- a/src/3d/renderer.h +++ b/src/3d/renderer.h @@ -30,11 +30,11 @@ struct ObjectData { mat4 model; mat4 inv_model; vec4 color; - // params.x = object type (as float), params.y = plane_distance (if applicable) - vec4 params; + // params.x = object type (as float), params.y = plane_distance (if + // applicable) + vec4 params; }; - class Renderer3D { public: void init(WGPUDevice device, WGPUQueue queue, WGPUTextureFormat format); diff --git a/src/3d/scene_loader.cc b/src/3d/scene_loader.cc index 936d8a2..286edca 100644 --- a/src/3d/scene_loader.cc +++ b/src/3d/scene_loader.cc @@ -1,13 +1,13 @@ #include "3d/scene_loader.h" #include "generated/assets.h" +#include "plane_data.h" #include "util/asset_manager.h" #include "util/mini_math.h" #include #include -#include #include // For std::shared_ptr #include // For std::nothrow -#include "plane_data.h" +#include bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { if (!data || size < 16) { // Header size check @@ -77,18 +77,23 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { vec3 scale(sx, sy, sz); // Color components (cr, cg, cb, ca) - float cr = *reinterpret_cast(data + offset); offset += 4; - float cg = *reinterpret_cast(data + offset); offset += 4; - float cb = *reinterpret_cast(data + offset); offset += 4; + float cr = *reinterpret_cast(data + offset); + offset += 4; + float cg = *reinterpret_cast(data + offset); + offset += 4; + float cb = *reinterpret_cast(data + offset); + offset += 4; // Read ca, advance offset AFTER reading ca, then construct color - float ca = *reinterpret_cast(data + offset); offset += 4; // Offset is now after ca + float ca = *reinterpret_cast(data + offset); + offset += 4; // Offset is now after ca vec4 color(cr, cg, cb, ca); // Plane Distance (if type == PLANE) float plane_distance = 0.0f; if (type == ObjectType::PLANE) { // Check bounds before reading plane_distance - if (offset + 4 > size) return false; + if (offset + 4 > size) + return false; plane_distance = *reinterpret_cast(data + offset); offset += 4; // Advance offset after reading plane_distance } @@ -96,7 +101,8 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { // Mesh Asset Name Length // The offset is now correctly positioned for name_len, // either after ca (if not PLANE) or after plane_distance (if PLANE). - if (offset + 4 > size) return false; + if (offset + 4 > size) + return false; uint32_t name_len = *reinterpret_cast(data + offset); offset += 4; @@ -145,12 +151,14 @@ bool SceneLoader::LoadScene(Scene& scene, const uint8_t* data, size_t size) { // Store plane distance in shared_user_data if it's a plane if (type == ObjectType::PLANE) { - // Allocate PlaneData on the heap and manage with shared_ptr - // Use std::make_shared for exception safety and efficiency - obj.shared_user_data = std::make_shared(); - // Assign the plane distance - // Safely cast void* to PlaneData* using static_cast on the shared_ptr's get() - static_cast(obj.shared_user_data.get())->distance = plane_distance; + // Allocate PlaneData on the heap and manage with shared_ptr + // Use std::make_shared for exception safety and efficiency + obj.shared_user_data = std::make_shared(); + // Assign the plane distance + // Safely cast void* to PlaneData* using static_cast on the shared_ptr's + // get() + static_cast(obj.shared_user_data.get())->distance = + plane_distance; } // Add to scene -- cgit v1.2.3