summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--assets/demo.seq4
-rw-r--r--assets/final/demo_assets.txt3
-rw-r--r--src/gpu/demo_effects.h33
-rw-r--r--src/gpu/effects/distort_effect.cc28
-rw-r--r--src/gpu/effects/shaders.cc4
-rw-r--r--src/gpu/effects/shaders.h1
-rw-r--r--src/tests/test_demo_effects.cc9
-rw-r--r--tools/seq_compiler.cc18
9 files changed, 89 insertions, 12 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 66dba79..e4c1417 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -107,6 +107,7 @@ set(GPU_SOURCES
src/gpu/effects/solarize_effect.cc
src/gpu/effects/distort_effect.cc
src/gpu/effects/chroma_aberration_effect.cc
+ src/gpu/effects/vignette_effect.cc
src/gpu/effects/post_process_helper.cc
src/gpu/effects/shaders.cc
src/gpu/effects/hybrid_3d_effect.cc
diff --git a/assets/demo.seq b/assets/demo.seq
index cada95e..9c55fe5 100644
--- a/assets/demo.seq
+++ b/assets/demo.seq
@@ -27,6 +27,7 @@ SEQUENCE 0b 0
EFFECT + FlashEffect 0.0 1. color=1.0,0.5,0.5 decay=0.95 # Red-tinted flash
EFFECT + FadeEffect 0.1 1. # Priority 1
EFFECT + SolarizeEffect 0 4b # Priority 2 (was 3, now contiguous)
+ EFFECT + VignetteEffect 0 6 radius=0.6 softness=0.1
SEQUENCE 4b 0
EFFECT - FlashCubeEffect 0.1 3. # Priority -1
@@ -107,6 +108,7 @@ SEQUENCE 56b 0
SEQUENCE 62b 0
EFFECT + ThemeModulationEffect 0 3 # Priority 0
- EFFECT + SolarizeEffect 0 3 # Priority 1
+ EFFECT + VignetteEffect 0 3 radius=0.6 softness=0.3 # New effect
+ EFFECT + SolarizeEffect 0 3 # Priority 2
# Demo automatically exits at this time (supports beat notation)
END_DEMO 65b
diff --git a/assets/final/demo_assets.txt b/assets/final/demo_assets.txt
index 14e7cdb..bf39c5d 100644
--- a/assets/final/demo_assets.txt
+++ b/assets/final/demo_assets.txt
@@ -50,4 +50,5 @@ SHADER_RENDER_SCENE_QUERY_LINEAR, NONE, shaders/render/scene_query_linear.wgsl,
SHADER_RENDER_LIGHTING_UTILS, NONE, shaders/render/lighting_utils.wgsl, "Lighting Utils Snippet"
SHADER_MESH, NONE, shaders/mesh_render.wgsl, "Mesh Rasterization Shader"
MESH_CUBE, NONE, test_mesh.obj, "A simple cube mesh"
-DODECAHEDRON, NONE, dodecahedron.obj, "A dodecahedron mesh" \ No newline at end of file
+DODECAHEDRON, NONE, dodecahedron.obj, "A dodecahedron mesh"
+SHADER_VIGNETTE, NONE, shaders/vignette.wgsl, "Vignette Shader"
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index 6c8729d..ad95cfe 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -127,6 +127,39 @@ class DistortEffect : public PostProcessEffect {
void update_bind_group(WGPUTextureView input_view) override;
};
+// Parameters for VignetteEffect
+struct VignetteParams {
+ float radius = 0.5f; // Radius of the clear center
+ float softness = 0.5f; // Softness of the vignette edge
+};
+
+// Uniform data for VignetteEffect
+struct VignetteUniforms {
+ float time; // offset 0
+ float beat; // offset 4
+ float intensity; // offset 8
+ float aspect_ratio; // offset 12
+ float width; // offset 16
+ float height; // offset 20
+ float radius; // offset 24
+ float softness; // offset 28
+};
+static_assert(sizeof(VignetteUniforms) == 32,
+ "VignetteUniforms must be 32 bytes for WGSL alignment");
+
+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 update_bind_group(WGPUTextureView input_view) override;
+
+ private:
+ VignetteParams params_;
+ UniformBuffer<VignetteUniforms> uniforms_;
+};
+
// Parameters for ChromaAberrationEffect (set at construction time)
struct ChromaAberrationParams {
float offset_scale = 0.02f; // Default: 2% screen offset
diff --git a/src/gpu/effects/distort_effect.cc b/src/gpu/effects/distort_effect.cc
index b7e27a7..589cdff 100644
--- a/src/gpu/effects/distort_effect.cc
+++ b/src/gpu/effects/distort_effect.cc
@@ -5,21 +5,33 @@
#include "gpu/gpu.h"
// --- DistortEffect ---
-DistortEffect::DistortEffect(const GpuContext& ctx) : PostProcessEffect(ctx) {
- uniforms_ =
- gpu_create_buffer(ctx_.device, sizeof(float) * 6,
- WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
+DistortEffect::DistortEffect(const GpuContext& ctx)
+ : DistortEffect(ctx, DistortParams()) {}
+
+DistortEffect::DistEffect(const GpuContext& ctx, const DistortParams& params)
+ : PostProcessEffect(ctx), params_(params) {
+ uniforms_ = gpu_create_buffer(ctx_.device, sizeof(DistortUniforms),
+ WGPUBufferUsage_Uniform | WGPUBufferUsage_CopyDst);
pipeline_ = create_post_process_pipeline(ctx_.device, ctx_.format,
distort_shader_wgsl);
}
+
void DistortEffect::render(WGPURenderPassEncoder pass, float t, float b,
float i, float a) {
- struct {
- float t, b, i, a, w, h;
- } u = {t, b, i, a, (float)width_, (float)height_};
+ DistortUniforms u = {
+ .time = t,
+ .beat = b,
+ .intensity = i,
+ .aspect_ratio = a,
+ .width = (float)width_,
+ .height = (float)height_,
+ .strength = params_.strength,
+ .speed = params_.speed,
+ };
wgpuQueueWriteBuffer(ctx_.queue, uniforms_.buffer, 0, &u, sizeof(u));
PostProcessEffect::render(pass, t, b, i, a);
}
+
void DistortEffect::update_bind_group(WGPUTextureView v) {
pp_update_bind_group(ctx_.device, pipeline_, &bind_group_, v, uniforms_);
-}
+} \ No newline at end of file
diff --git a/src/gpu/effects/shaders.cc b/src/gpu/effects/shaders.cc
index ce60a74..2e1cfe5 100644
--- a/src/gpu/effects/shaders.cc
+++ b/src/gpu/effects/shaders.cc
@@ -98,3 +98,7 @@ const char* distort_shader_wgsl =
const char* chroma_aberration_shader_wgsl =
SafeGetAsset(AssetId::ASSET_SHADER_CHROMA_ABERRATION);
+
+const char* vignette_shader_wgsl =
+
+ SafeGetAsset(AssetId::ASSET_SHADER_VIGNETTE);
diff --git a/src/gpu/effects/shaders.h b/src/gpu/effects/shaders.h
index f8e45ba..50b4f32 100644
--- a/src/gpu/effects/shaders.h
+++ b/src/gpu/effects/shaders.h
@@ -17,3 +17,4 @@ extern const char* gaussian_blur_shader_wgsl;
extern const char* solarize_shader_wgsl;
extern const char* distort_shader_wgsl;
extern const char* chroma_aberration_shader_wgsl;
+extern const char* vignette_shader_wgsl;
diff --git a/src/tests/test_demo_effects.cc b/src/tests/test_demo_effects.cc
index a5500a8..03d22e3 100644
--- a/src/tests/test_demo_effects.cc
+++ b/src/tests/test_demo_effects.cc
@@ -13,9 +13,9 @@
// Expected effect counts - UPDATE THESE when adding new effects!
static constexpr int EXPECTED_POST_PROCESS_COUNT =
- 8; // FlashEffect, PassthroughEffect, GaussianBlurEffect,
+ 9; // FlashEffect, PassthroughEffect, GaussianBlurEffect,
// ChromaAberrationEffect, DistortEffect, SolarizeEffect, FadeEffect,
- // ThemeModulationEffect
+ // ThemeModulationEffect, VignetteEffect
static constexpr int EXPECTED_SCENE_COUNT =
6; // HeptagonEffect, ParticlesEffect, ParticleSprayEffect,
// MovingEllipseEffect, FlashCubeEffect, Hybrid3DEffect
@@ -98,6 +98,7 @@ static void test_post_process_effects() {
{"FadeEffect", std::make_shared<FadeEffect>(fixture.ctx())},
{"ThemeModulationEffect",
std::make_shared<ThemeModulationEffect>(fixture.ctx())},
+ {"VignetteEffect", std::make_shared<VignetteEffect>(fixture.ctx())},
};
int passed = 0;
@@ -211,6 +212,10 @@ static void test_effect_type_classification() {
assert(blur->is_post_process() &&
"GaussianBlurEffect should be post-process");
+ auto vignette = std::make_shared<VignetteEffect>(fixture.ctx());
+ assert(vignette->is_post_process() &&
+ "VignetteEffect should be post-process");
+
// Scene effects should return false
auto heptagon = std::make_shared<HeptagonEffect>(fixture.ctx());
assert(!heptagon->is_post_process() &&
diff --git a/tools/seq_compiler.cc b/tools/seq_compiler.cc
index 218ef93..0a17005 100644
--- a/tools/seq_compiler.cc
+++ b/tools/seq_compiler.cc
@@ -978,6 +978,24 @@ int main(int argc, char* argv[]) {
<< eff.class_name << ">(ctx, p), " << eff.start << "f, "
<< eff.end << "f, " << eff.priority << ");\n";
out_file << " }\n";
+ } else if (!eff.params.empty() &&
+ eff.class_name == "VignetteEffect") {
+ // Generate parameter struct initialization for VignetteEffect
+ out_file << " {\n";
+ out_file << " VignetteParams p;\n";
+
+ for (const auto& [key, value] : eff.params) {
+ if (key == "radius") {
+ out_file << " p.radius = " << value << "f;\n";
+ } else if (key == "softness") {
+ out_file << " p.softness = " << value << "f;\n";
+ }
+ }
+
+ out_file << " seq->add_effect(std::make_shared<"
+ << eff.class_name << ">(ctx, p), " << eff.start << "f, "
+ << eff.end << "f, " << eff.priority << ");\n";
+ out_file << " }\n";
} else {
// No parameters or unsupported effect - use default constructor
out_file << " seq->add_effect(std::make_shared<" << eff.class_name