summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-28 09:48:08 +0100
committerskal <pascal.massimino@gmail.com>2026-02-28 09:48:08 +0100
commitf9ac4caf2f36c283c2d90bcb985e3298c417d564 (patch)
tree70960c6115442c6f342ee5c0e50726e9c8f9f226
parentbc1beb58ba259263eb98d43d2aa742307764591c (diff)
fix(tools/shadertoy): fix Next Steps instructions and update EFFECT_WORKFLOW.md
- Fix assets.txt path: shaders/xxx.wgsl (not ../../src/shaders/) - Fix shader output path to workspaces/main/shaders/ - Step 5: reference cmake/DemoSourceLists.cmake COMMON_GPU_EFFECTS (not CMakeLists.txt GPU_SOURCES) - Add step for test_demo_effects.cc Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--cmake/DemoSourceLists.cmake1
-rw-r--r--doc/EFFECT_WORKFLOW.md27
-rw-r--r--src/effects/scene2_effect.cc47
-rw-r--r--src/effects/scene2_effect.h24
-rw-r--r--src/effects/shaders.cc1
-rw-r--r--src/effects/shaders.h1
-rw-r--r--src/gpu/demo_effects.h2
-rwxr-xr-xtools/shadertoy/convert_shadertoy.py16
-rw-r--r--workspaces/main/assets.txt1
-rw-r--r--workspaces/main/shaders/scene2.wgsl43
-rw-r--r--workspaces/main/timeline.seq7
11 files changed, 151 insertions, 19 deletions
diff --git a/cmake/DemoSourceLists.cmake b/cmake/DemoSourceLists.cmake
index f4574c7..3439cd5 100644
--- a/cmake/DemoSourceLists.cmake
+++ b/cmake/DemoSourceLists.cmake
@@ -40,6 +40,7 @@ set(COMMON_GPU_EFFECTS
src/effects/flash_effect.cc
src/effects/peak_meter_effect.cc
src/effects/scene1_effect.cc
+ src/effects/scene2_effect.cc
# TODO: Port CNN effects to v2 (complex v1 dependencies)
# cnn_v1/src/cnn_v1_effect.cc
# cnn_v2/src/cnn_v2_effect.cc
diff --git a/doc/EFFECT_WORKFLOW.md b/doc/EFFECT_WORKFLOW.md
index 46aebd2..3e574f6 100644
--- a/doc/EFFECT_WORKFLOW.md
+++ b/doc/EFFECT_WORKFLOW.md
@@ -68,13 +68,11 @@ SHADER_<UPPER_NAME>, NONE, shaders/<name>.wgsl, "Description"
Asset ID: `AssetId::ASSET_SHADER_<UPPER_NAME>`
-### 3. Add to CMakeLists.txt
+### 3. Add to DemoSourceLists.cmake
-**File**: `CMakeLists.txt`
+**File**: `cmake/DemoSourceLists.cmake`
-Add `src/effects/<name>_effect.cc` to **BOTH** GPU_SOURCES sections:
-- Headless mode (around line 141-167)
-- Normal mode (around line 171-197)
+Add `src/effects/<name>_effect.cc` to the `COMMON_GPU_EFFECTS` list.
### 4. Include in demo_effects.h
@@ -84,7 +82,19 @@ Add `src/effects/<name>_effect.cc` to **BOTH** GPU_SOURCES sections:
#include "effects/<name>_effect.h"
```
-### 5. Add to Timeline
+### 5. Add to test_demo_effects.cc
+
+**File**: `src/tests/gpu/test_demo_effects.cc`
+
+Add entry to the effects vector:
+```cpp
+{"MyEffect", std::make_shared<MyEffect>(
+ fixture.ctx(), inputs, outputs, 0.0f, 1000.0f)},
+```
+
+Run with: `./build/test_demo_effects`
+
+### 6. Add to Timeline
**File**: `workspaces/main/timeline.seq`
@@ -95,7 +105,7 @@ SEQUENCE <start> <priority> "name"
**Priority modifiers** (REQUIRED): `+` (increment), `=` (same), `-` (decrement)
-### 6. Regenerate and Build
+### 7. Regenerate and Build
```bash
# Regenerate timeline.cc
@@ -241,8 +251,7 @@ class My3DEffect : public Effect {
- Asset ID is `ASSET_` + uppercase entry name
**Build Error: "undefined symbol"**
-- Effect not in CMakeLists.txt GPU_SOURCES
-- Must add to BOTH sections (headless + normal)
+- Effect not in `cmake/DemoSourceLists.cmake` COMMON_GPU_EFFECTS
**Runtime Error: "Node not found"**
- Forgot `declare_nodes()` for temp nodes
diff --git a/src/effects/scene2_effect.cc b/src/effects/scene2_effect.cc
new file mode 100644
index 0000000..b1b9975
--- /dev/null
+++ b/src/effects/scene2_effect.cc
@@ -0,0 +1,47 @@
+// This file is part of the 64k demo project.
+// Scene2 effect - ShaderToy conversion (scene)
+// Generated by convert_shadertoy.py
+
+#include "effects/scene2_effect.h"
+#include "effects/shaders.h"
+#include "gpu/gpu.h"
+#include "gpu/post_process_helper.h"
+#include "util/fatal_error.h"
+
+Scene2Effect::Scene2Effect(const GpuContext& ctx,
+ const std::vector<std::string>& inputs,
+ const std::vector<std::string>& outputs,
+ float start_time, float end_time)
+ : Effect(ctx, inputs, outputs, start_time, end_time) {
+ HEADLESS_RETURN_IF_NULL(ctx_.device);
+ create_nearest_sampler();
+ create_dummy_scene_texture();
+ pipeline_.set(create_post_process_pipeline(
+ ctx_.device, WGPUTextureFormat_RGBA8Unorm, scene2_shader_wgsl));
+}
+
+void Scene2Effect::render(WGPUCommandEncoder encoder,
+ const UniformsSequenceParams& params,
+ NodeRegistry& nodes) {
+ WGPUTextureView output_view = nodes.get_view(output_nodes_[0]);
+
+ // uniforms_buffer_ auto-updated by base class dispatch_render()
+ pp_update_bind_group(ctx_.device, pipeline_.get(), bind_group_.get_address(),
+ dummy_texture_view_.get(), uniforms_buffer_.get(),
+ {nullptr, 0});
+
+ WGPURenderPassColorAttachment color_attachment = {};
+ gpu_init_color_attachment(color_attachment, output_view);
+
+ WGPURenderPassDescriptor pass_desc = {};
+ pass_desc.colorAttachmentCount = 1;
+ pass_desc.colorAttachments = &color_attachment;
+
+ WGPURenderPassEncoder pass =
+ wgpuCommandEncoderBeginRenderPass(encoder, &pass_desc);
+ wgpuRenderPassEncoderSetPipeline(pass, pipeline_.get());
+ wgpuRenderPassEncoderSetBindGroup(pass, 0, bind_group_.get(), 0, nullptr);
+ wgpuRenderPassEncoderDraw(pass, 3, 1, 0, 0);
+ wgpuRenderPassEncoderEnd(pass);
+ wgpuRenderPassEncoderRelease(pass);
+}
diff --git a/src/effects/scene2_effect.h b/src/effects/scene2_effect.h
new file mode 100644
index 0000000..effc19f
--- /dev/null
+++ b/src/effects/scene2_effect.h
@@ -0,0 +1,24 @@
+// This file is part of the 64k demo project.
+// Scene2 effect - ShaderToy conversion (scene)
+// Generated by convert_shadertoy.py
+
+#pragma once
+
+#include "gpu/effect.h"
+#include "gpu/wgpu_resource.h"
+
+class Scene2Effect : public Effect {
+ public:
+ Scene2Effect(const GpuContext& ctx,
+ const std::vector<std::string>& inputs,
+ const std::vector<std::string>& outputs,
+ float start_time, float end_time);
+
+ void render(WGPUCommandEncoder encoder,
+ const UniformsSequenceParams& params,
+ NodeRegistry& nodes) override;
+
+ private:
+ RenderPipeline pipeline_;
+ BindGroup bind_group_;
+};
diff --git a/src/effects/shaders.cc b/src/effects/shaders.cc
index 7e32aa6..c6a81d0 100644
--- a/src/effects/shaders.cc
+++ b/src/effects/shaders.cc
@@ -96,6 +96,7 @@ const char* rotating_cube_wgsl =
SafeGetAsset(AssetId::ASSET_SHADER_ROTATING_CUBE_V2);
const char* flash_shader_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_FLASH);
const char* scene1_shader_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_SCENE1);
+const char* scene2_shader_wgsl = SafeGetAsset(AssetId::ASSET_SHADER_SCENE2);
// Compute shaders
const char* gen_noise_compute_wgsl =
diff --git a/src/effects/shaders.h b/src/effects/shaders.h
index ee6c65e..5fc442a 100644
--- a/src/effects/shaders.h
+++ b/src/effects/shaders.h
@@ -15,6 +15,7 @@ extern const char* particle_render_wgsl;
extern const char* rotating_cube_wgsl;
extern const char* flash_shader_wgsl;
extern const char* scene1_shader_wgsl;
+extern const char* scene2_shader_wgsl;
// Compute shaders
extern const char* gen_noise_compute_wgsl;
diff --git a/src/gpu/demo_effects.h b/src/gpu/demo_effects.h
index f746326..e1a9c17 100644
--- a/src/gpu/demo_effects.h
+++ b/src/gpu/demo_effects.h
@@ -27,6 +27,8 @@
#include "effects/placeholder_effect.h"
#include "effects/rotating_cube_effect.h"
#include "effects/scene1_effect.h"
+#include "effects/scene2_effect.h"
+
// TODO: Port CNN effects
// #include "../../cnn_v1/src/cnn_v1_effect.h"
// #include "../../cnn_v2/src/cnn_v2_effect.h"
diff --git a/tools/shadertoy/convert_shadertoy.py b/tools/shadertoy/convert_shadertoy.py
index 22b3276..9df42bb 100755
--- a/tools/shadertoy/convert_shadertoy.py
+++ b/tools/shadertoy/convert_shadertoy.py
@@ -12,7 +12,7 @@
# Generates:
# - src/effects/<effect>_effect.h
# - src/effects/<effect>_effect.cc
-# - src/shaders/<effect>.wgsl
+# - workspaces/main/shaders/<effect>.wgsl
#
# The script performs basic ShaderToy→WGSL conversion:
# - Converts types (float→f32, vec2→vec2f, etc.)
@@ -333,7 +333,7 @@ def main():
print("This will generate:")
print(" src/effects/<effect>_effect.h")
print(" src/effects/<effect>_effect.cc")
- print(" src/shaders/<effect>.wgsl")
+ print(" workspaces/main/shaders/<effect>.wgsl")
sys.exit(1)
shader_file = sys.argv[1]
@@ -361,7 +361,7 @@ def main():
repo_root = Path(__file__).parent.parent.parent
header_path = repo_root / "src" / "effects" / f"{snake_name}_effect.h"
impl_path = repo_root / "src" / "effects" / f"{snake_name}_effect.cc"
- shader_path = repo_root / "src" / "shaders" / f"{snake_name}.wgsl"
+ shader_path = repo_root / "workspaces" / "main" / "shaders" / f"{snake_name}.wgsl"
# Generate files
if shader_only:
@@ -389,7 +389,7 @@ def main():
print("Next steps (see doc/EFFECT_WORKFLOW.md for details):")
print()
print("1. Add shader to workspaces/main/assets.txt:")
- print(f" SHADER_{upper_name}, NONE, ../../src/shaders/{snake_name}.wgsl, \"{effect_name} effect\"")
+ print(f" SHADER_{upper_name}, NONE, shaders/{snake_name}.wgsl, \"{effect_name} effect\"")
print()
print("2. Add shader declaration to src/effects/shaders.h:")
print(f" extern const char* {snake_name}_shader_wgsl;")
@@ -400,7 +400,7 @@ def main():
print("4. Include header in src/gpu/demo_effects.h:")
print(f' #include "effects/{snake_name}_effect.h"')
print()
- print("5. Add to CMakeLists.txt GPU_SOURCES (both headless and normal mode sections):")
+ print("5. Add to cmake/DemoSourceLists.cmake COMMON_GPU_EFFECTS list:")
print(f" src/effects/{snake_name}_effect.cc")
print()
print("6. Add to timeline in workspaces/main/timeline.seq:")
@@ -410,7 +410,11 @@ def main():
print(" python3 tools/seq_compiler.py workspaces/main/timeline.seq \\")
print(" --output src/generated/timeline.cc")
print()
- print("8. Build and test:")
+ print("8. Add to src/tests/gpu/test_demo_effects.cc:")
+ print(f' {{"{effect_name}", std::make_shared<{effect_name}Effect>(')
+ print(f' fixture.ctx(), inputs, outputs, 0.0f, 1000.0f)}}')
+ print()
+ print("9. Build and test:")
print(" cmake --build build -j4")
print(" ./build/demo64k")
print()
diff --git a/workspaces/main/assets.txt b/workspaces/main/assets.txt
index 85ae1fc..56d0942 100644
--- a/workspaces/main/assets.txt
+++ b/workspaces/main/assets.txt
@@ -82,6 +82,7 @@ CIRCLE_MASK_COMPUTE_SHADER, NONE, shaders/circle_mask_compute.wgsl, "Circle mask
CIRCLE_MASK_RENDER_SHADER, NONE, shaders/circle_mask_render.wgsl, "Circle mask render shader"
MASKED_CUBE_SHADER, NONE, shaders/masked_cube.wgsl, "Masked cube shader"
SHADER_SCENE1, NONE, shaders/scene1.wgsl, "Scene1 effect shader"
+SHADER_SCENE2, NONE, shaders/scene2.wgsl, "Scene2 effect shader"
# --- Sequence Shaders ---
SHADER_SEQUENCE_V2_UNIFORMS, NONE, ../../src/shaders/sequence_uniforms.wgsl, "Sequence Uniforms Snippet"
diff --git a/workspaces/main/shaders/scene2.wgsl b/workspaces/main/shaders/scene2.wgsl
new file mode 100644
index 0000000..486f41e
--- /dev/null
+++ b/workspaces/main/shaders/scene2.wgsl
@@ -0,0 +1,43 @@
+// Scene2 effect shader - ShaderToy conversion
+// Generated by convert_shadertoy.py
+// NOTE: Manual review recommended - conversion is basic
+
+#include "sequence_uniforms"
+#include "render/fullscreen_uv_vs"
+
+@group(0) @binding(2) var<uniform> uniforms: UniformsSequenceParams;
+
+
+fn N(vec3f a, vec3f p) { return abs(dot(sin(uniforms.time+.1*p.z+.3*p / a), vec3f(a+a))); }
+const NUM_LAYERS: f32 = 12.;
+
+
+
+@fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f {
+ // Flip Y to match ShaderToy convention (origin at bottom-left)
+ let flipped = vec2f(in.position.x, uniforms.resolution.y - in.position.y);
+ let q = flipped / uniforms.resolution;
+ var coord = -1.0 + 2.0 * q;
+ coord.x *= uniforms.resolution.x / uniforms.resolution.y;
+
+ f32 i,s;
+ vec3f p = vec3f[0),r = uniforms.resolution;
+
+ vec2f uv = (u-.5*uniforms.resolution.xy)/uniforms.resolution.y;
+
+ f32 t = uniforms.time*.0;
+ vec3f col = vec3f(0);
+
+ u = (u+u-r.xy)/r.y;
+ for(o*=i; i++<1e2; ) {
+ p += vec3f(u * s, s);
+ s = 6.+(p.y);
+ s -= N(.08);
+ s -= N(.2);
+ s -= N(.6);
+ s = .1 + abs(s)*.2;
+ o += vec4f(4,2,1,0)/s;
+ }
+ o *= smoothstep(0.8, 0.75, abs(u.y));
+ o = tanh(o / 2e3 / length(u));
+}
diff --git a/workspaces/main/timeline.seq b/workspaces/main/timeline.seq
index 2b843a7..6399bdf 100644
--- a/workspaces/main/timeline.seq
+++ b/workspaces/main/timeline.seq
@@ -9,10 +9,9 @@ SEQUENCE 4.00 0 "rotating_cube"
EFFECT + RotatingCube source -> temp1 0.00 4.00
EFFECT + Placeholder temp1 -> sink 1.00 4.00
-SEQUENCE 8.00 0 "flash_cube"
- # FlashCube (placeholder) -> Flash (placeholder) -> sink
- EFFECT - Placeholder source -> temp1 0.00 4.02
- EFFECT + Placeholder temp1 -> sink 0.00 0.40
+SEQUENCE 8.00 0 "scene 2"
+ # Scene2 test
+ EFFECT + Scene2Effect source -> sink 0.0 4.0
SEQUENCE 12.00 1 "particles"
# Particles -> Blur -> sink