summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CLAUDE.md1
-rw-r--r--CMakeLists.txt2
-rw-r--r--README.md1
-rw-r--r--doc/AI_RULES.md19
-rw-r--r--doc/CONTRIBUTING.md15
-rw-r--r--doc/EFFECT_WORKFLOW.md228
-rw-r--r--doc/HOWTO.md2
-rw-r--r--doc/RECIPE.md4
-rw-r--r--tools/shadertoy/README.md22
-rwxr-xr-xtools/shadertoy/convert_shadertoy.py16
-rw-r--r--workspaces/main/timeline.seq3
11 files changed, 291 insertions, 22 deletions
diff --git a/CLAUDE.md b/CLAUDE.md
index a52dfce..714339b 100644
--- a/CLAUDE.md
+++ b/CLAUDE.md
@@ -11,6 +11,7 @@
@doc/HOWTO.md
@doc/CONTRIBUTING.md
@doc/AI_RULES.md
+@doc/EFFECT_WORKFLOW.md
# ============================================
# TIER 3: DESIGN DOCS (Load On-Demand)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 97b371a..753a9b1 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -149,6 +149,7 @@ if (DEMO_HEADLESS)
src/gpu/effects/particle_spray_effect.cc
src/gpu/effects/gaussian_blur_effect.cc
src/gpu/effects/solarize_effect.cc
+# Disabled: src/gpu/effects/cube_sphere_effect.cc (incomplete conversion)
src/gpu/effects/chroma_aberration_effect.cc
src/gpu/effects/vignette_effect.cc
src/gpu/effects/cnn_effect.cc
@@ -179,6 +180,7 @@ else()
src/gpu/effects/particle_spray_effect.cc
src/gpu/effects/gaussian_blur_effect.cc
src/gpu/effects/solarize_effect.cc
+# Disabled: src/gpu/effects/cube_sphere_effect.cc (incomplete conversion)
src/gpu/effects/chroma_aberration_effect.cc
src/gpu/effects/vignette_effect.cc
src/gpu/effects/cnn_effect.cc
diff --git a/README.md b/README.md
index f7d78de..ac723db 100644
--- a/README.md
+++ b/README.md
@@ -16,5 +16,6 @@ cmake --build build -j4
- **TODO.md** - Active tasks and priorities
- **doc/HOWTO.md** - Common operations (building, testing, assets)
- **doc/CONTRIBUTING.md** - Development guidelines and protocols
+- **doc/EFFECT_WORKFLOW.md** - Step-by-step guide for adding visual effects
See `doc/` for detailed technical documentation.
diff --git a/doc/AI_RULES.md b/doc/AI_RULES.md
index d18a0cc..1a4ee78 100644
--- a/doc/AI_RULES.md
+++ b/doc/AI_RULES.md
@@ -5,3 +5,22 @@
- Prefer small, reviewable commits
- All `cmake --build` commands must use the `-j4` option for parallel building.
- after a task, a 'big' final commit should contain a short handoff tag like "handoff(Gemini):..." if you're gemini-cli, or "handoff(Claude): ..." if you're claude-code.
+
+## Adding Visual Effects
+
+**IMPORTANT:** When adding new visual effects, follow the complete workflow in `doc/EFFECT_WORKFLOW.md`.
+
+**Required steps (must complete ALL):**
+1. Create effect files (.h, .cc, .wgsl)
+2. Add shader to `workspaces/main/assets.txt`
+3. Add `.cc` to CMakeLists.txt GPU_SOURCES (BOTH sections: headless and normal)
+4. Include header in `src/gpu/demo_effects.h`
+5. Add to timeline with `EFFECT +` (priority modifier is REQUIRED)
+6. Add to test list in `src/tests/gpu/test_demo_effects.cc`
+7. Build and verify: `cmake --build build -j4 && cd build && ./test_demo_effects`
+
+**Common mistakes to avoid:**
+- Missing priority modifier in timeline (`EFFECT` must be `EFFECT +`, `EFFECT =`, or `EFFECT -`)
+- Adding `.cc` to only one CMakeLists.txt section (need BOTH headless and normal)
+- Wrong asset ID (check assets.txt entry name → `ASSET_SHADER_<NAME>`)
+- Forgetting to add to test file
diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md
index 9cd785b..98df873 100644
--- a/doc/CONTRIBUTING.md
+++ b/doc/CONTRIBUTING.md
@@ -65,12 +65,15 @@ See `doc/CODING_STYLE.md` for detailed examples.
## Development Protocols
### Adding Visual Effect
-1. Implement `Effect` subclass in `src/gpu/demo_effects.cc`
-2. Add to workspace `timeline.seq` (e.g., `workspaces/main/timeline.seq`)
-3. **Update `test_demo_effects.cc`**:
- - Add to test list
- - Increment `EXPECTED_*_COUNT`
-4. Verify:
+1. Create effect class files (use `tools/shadertoy/convert_shadertoy.py` or templates)
+2. Add shader to `workspaces/main/assets.txt`
+3. Add effect `.cc` file to `CMakeLists.txt` GPU_SOURCES (both sections)
+4. Include header in `src/gpu/demo_effects.h`
+5. Add to workspace `timeline.seq` (e.g., `workspaces/main/timeline.seq`)
+6. **Update `src/tests/gpu/test_demo_effects.cc`**:
+ - Add to `post_process_effects` list (lines 80-93) or `scene_effects` list (lines 125-137)
+ - Example: `{"MyEffect", std::make_shared<MyEffect>(fixture.ctx())},`
+7. Verify:
```bash
cmake -S . -B build -DDEMO_BUILD_TESTS=ON
cmake --build build -j4 --target test_demo_effects
diff --git a/doc/EFFECT_WORKFLOW.md b/doc/EFFECT_WORKFLOW.md
new file mode 100644
index 0000000..45c47b7
--- /dev/null
+++ b/doc/EFFECT_WORKFLOW.md
@@ -0,0 +1,228 @@
+# Effect Creation Workflow
+
+**Target Audience:** AI coding agents and developers
+
+Automated checklist for adding new visual effects to the demo.
+
+---
+
+## Quick Reference
+
+**For ShaderToy conversions:** Use `tools/shadertoy/convert_shadertoy.py` then follow steps 3-8 below.
+
+**For custom effects:** Follow all steps 1-8.
+
+---
+
+## Step-by-Step Workflow
+
+### 1. Create Effect Files
+
+**Location:**
+- Header: `src/gpu/effects/<effect_name>_effect.h`
+- Implementation: `src/gpu/effects/<effect_name>_effect.cc`
+- Shader: `workspaces/main/shaders/<effect_name>.wgsl`
+
+**Naming Convention:**
+- Class name: `<EffectName>Effect` (e.g., `TunnelEffect`, `PlasmaEffect`)
+- Files: `<effect_name>_effect.*` (snake_case)
+
+**Base Class:**
+- Post-process effects: inherit from `PostProcessEffect`
+- Scene effects: inherit from `Effect`
+
+**Template:** See `tools/shadertoy/template.*` or use `convert_shadertoy.py`
+
+### 2. Add Shader to Assets
+
+**File:** `workspaces/main/assets.txt`
+
+**Format:**
+```
+SHADER_<UPPER_SNAKE_NAME>, NONE, shaders/<effect_name>.wgsl, "Effect description"
+```
+
+**Example:**
+```
+SHADER_TUNNEL, NONE, shaders/tunnel.wgsl, "Tunnel effect shader"
+```
+
+**Asset ID:** Will be `AssetId::ASSET_SHADER_<UPPER_SNAKE_NAME>` in C++
+
+### 3. Add to CMakeLists.txt
+
+**File:** `CMakeLists.txt`
+
+**Action:** Add `src/gpu/effects/<effect_name>_effect.cc` to **BOTH** GPU_SOURCES sections:
+- Headless mode section (around line 141-167)
+- Normal mode section (around line 171-197)
+
+**Location:** After similar effects (post-process with post-process, scene with scene)
+
+**Example:**
+```cmake
+# In headless section (line ~152):
+ src/gpu/effects/solarize_effect.cc
+ src/gpu/effects/tunnel_effect.cc # <-- Add here
+ src/gpu/effects/chroma_aberration_effect.cc
+
+# In normal section (line ~183):
+ src/gpu/effects/solarize_effect.cc
+ src/gpu/effects/tunnel_effect.cc # <-- Add here
+ src/gpu/effects/chroma_aberration_effect.cc
+```
+
+### 4. Include in demo_effects.h
+
+**File:** `src/gpu/demo_effects.h`
+
+**Action:** Add include directive:
+```cpp
+#include "gpu/effects/<effect_name>_effect.h"
+```
+
+**Location:** Alphabetically with other effect includes
+
+### 5. Add to Timeline
+
+**File:** `workspaces/main/timeline.seq`
+
+**Format:**
+```
+SEQUENCE <start_time> <priority>
+ EFFECT <+|=|-> <EffectName>Effect <local_start> <local_end> [params...]
+```
+
+**Priority Modifiers (REQUIRED):**
+- `+` : Increment priority
+- `=` : Same priority as previous effect
+- `-` : Decrement priority (for backgrounds)
+
+**Example:**
+```
+SEQUENCE 0.0 0
+ EFFECT + TunnelEffect 0.0 10.0
+```
+
+**Common Mistake:** Missing priority modifier (`+`, `=`, `-`) after EFFECT keyword
+
+### 6. Update Tests
+
+**File:** `src/tests/gpu/test_demo_effects.cc`
+
+**Action:** Add effect to appropriate list:
+
+**Post-Process Effects (lines 80-93):**
+```cpp
+{"TunnelEffect", std::make_shared<TunnelEffect>(fixture.ctx())},
+```
+
+**Scene Effects (lines 125-137):**
+```cpp
+{"TunnelEffect", std::make_shared<TunnelEffect>(fixture.ctx())},
+```
+
+**3D Effects:** If requires Renderer3D, add to `requires_3d` check (line 148-151)
+
+### 7. Build and Test
+
+```bash
+# Full build
+cmake --build build -j4
+
+# Run effect tests
+cmake -S . -B build -DDEMO_BUILD_TESTS=ON
+cmake --build build -j4 --target test_demo_effects
+cd build && ./test_demo_effects
+
+# Run all tests
+cd build && ctest
+```
+
+### 8. Verify
+
+**Checklist:**
+- [ ] Effect compiles without errors
+- [ ] Effect appears in timeline
+- [ ] test_demo_effects passes
+- [ ] Effect renders correctly: `./build/demo64k`
+- [ ] No shader compilation errors
+- [ ] Follows naming conventions
+
+---
+
+## Common Issues
+
+### Build Error: "no member named 'ASSET_..._SHADER'"
+
+**Cause:** Shader not in assets.txt or wrong asset ID name
+
+**Fix:**
+1. Check `workspaces/main/assets.txt` has shader entry
+2. Asset ID is `ASSET_` + uppercase entry name (e.g., `SHADER_TUNNEL` → `ASSET_SHADER_TUNNEL`)
+
+### Build Error: "undefined symbol for architecture"
+
+**Cause:** Effect not in CMakeLists.txt GPU_SOURCES
+
+**Fix:** Add `.cc` file to BOTH sections (headless and normal mode)
+
+### Timeline Parse Error: "Expected '+', '=', or '-'"
+
+**Cause:** Missing priority modifier after EFFECT keyword
+
+**Fix:** Use `EFFECT +`, `EFFECT =`, or `EFFECT -` (never just `EFFECT`)
+
+### Test Failure: Effect not in test list
+
+**Cause:** Effect not added to test_demo_effects.cc
+
+**Fix:** Add to `post_process_effects` or `scene_effects` list
+
+---
+
+## Automation Script Example
+
+```bash
+#!/bin/bash
+# Example automation for AI agents
+
+EFFECT_NAME="$1" # CamelCase (e.g., "Tunnel")
+SNAKE_NAME=$(echo "$EFFECT_NAME" | sed 's/\([A-Z]\)/_\L\1/g' | sed 's/^_//')
+UPPER_NAME=$(echo "$SNAKE_NAME" | tr '[:lower:]' '[:upper:]')
+
+echo "Creating effect: $EFFECT_NAME"
+echo " Snake case: $SNAKE_NAME"
+echo " Upper case: $UPPER_NAME"
+
+# 1. Generate files (if using ShaderToy)
+# ./tools/shadertoy/convert_shadertoy.py shader.txt "$EFFECT_NAME"
+
+# 2. Add to assets.txt
+echo "SHADER_${UPPER_NAME}, NONE, shaders/${SNAKE_NAME}.wgsl, \"${EFFECT_NAME} effect\"" \
+ >> workspaces/main/assets.txt
+
+# 3. Add to CMakeLists.txt (both sections)
+# Use Edit tool to add to both GPU_SOURCES sections
+
+# 4. Add include to demo_effects.h
+# Use Edit tool to add #include line
+
+# 5. Add to timeline.seq
+# Use Edit tool to add EFFECT line with priority modifier
+
+# 6. Add to test file
+# Use Edit tool to add to appropriate test list
+
+# 7. Build
+cmake --build build -j4
+```
+
+---
+
+## See Also
+
+- `tools/shadertoy/README.md` - ShaderToy conversion guide
+- `doc/SEQUENCE.md` - Timeline format documentation
+- `doc/CONTRIBUTING.md` - General contribution guidelines
+- `src/gpu/effects/` - Existing effect examples
diff --git a/doc/HOWTO.md b/doc/HOWTO.md
index 07d480b..a57a161 100644
--- a/doc/HOWTO.md
+++ b/doc/HOWTO.md
@@ -108,7 +108,7 @@ Generate shaders from checkpoint:
Edit `workspaces/main/timeline.seq`:
```text
SEQUENCE 0.0 0
- EFFECT HeptagonEffect 0.0 60.0 0
+ EFFECT + HeptagonEffect 0.0 60.0 0
```
Rebuild to apply. See `doc/SEQUENCE.md`.
diff --git a/doc/RECIPE.md b/doc/RECIPE.md
index 6404391..d563027 100644
--- a/doc/RECIPE.md
+++ b/doc/RECIPE.md
@@ -157,8 +157,8 @@ void MyEffect::render(WGPUTextureView prev, WGPUTextureView target,
**.seq syntax:**
```
-EFFECT MyEffect 0.0 10.0 strength=0.5 speed=3.0
-EFFECT MyEffect 10.0 20.0 strength=2.0 # speed keeps previous value
+EFFECT + MyEffect 0.0 10.0 strength=0.5 speed=3.0
+EFFECT = MyEffect 10.0 20.0 strength=2.0 # speed keeps previous value
```
**Example:** `src/gpu/effects/flash_effect.cc`, `src/gpu/effects/chroma_aberration_effect.cc`
diff --git a/tools/shadertoy/README.md b/tools/shadertoy/README.md
index e734684..d12865f 100644
--- a/tools/shadertoy/README.md
+++ b/tools/shadertoy/README.md
@@ -2,6 +2,8 @@
Quick guide to convert ShaderToy shaders to demo effects.
+**For complete workflow:** See `doc/EFFECT_WORKFLOW.md` for full integration checklist.
+
## Quick Start (Automated)
```bash
@@ -95,16 +97,24 @@ In `src/gpu/demo_effects.h`:
In `workspaces/main/timeline.seq`:
```
SEQUENCE 0.0 0
- EFFECT MyEffectEffect 0.0 10.0 0
+ EFFECT + MyEffectEffect 0.0 10.0
+```
+
+### 7. Update CMakeLists.txt
+
+Add effect source to `CMakeLists.txt` GPU_SOURCES (both headless and normal mode sections):
+```cmake
+src/gpu/effects/myeffect_effect.cc
```
-### 7. Update Tests
+### 8. Update Tests
-In `tests/test_demo_effects.cc`:
-- Add `"MyEffectEffect"` to test list
-- Increment `EXPECTED_*_COUNT`
+In `src/tests/gpu/test_demo_effects.cc`:
+- Add to `post_process_effects` list (lines 80-93) if it's a post-process effect
+- OR add to `scene_effects` list (lines 125-137) if it's a scene effect
+- Example: `{"MyEffectEffect", std::make_shared<MyEffectEffect>(fixture.ctx())},`
-### 8. Build & Test
+### 9. Build & Test
```bash
cmake --build build -j4
diff --git a/tools/shadertoy/convert_shadertoy.py b/tools/shadertoy/convert_shadertoy.py
index 4956cfd..29eca1d 100755
--- a/tools/shadertoy/convert_shadertoy.py
+++ b/tools/shadertoy/convert_shadertoy.py
@@ -383,7 +383,7 @@ def main():
print("✓ Files generated")
print()
- print("Next steps:")
+ print("Next steps (see doc/EFFECT_WORKFLOW.md for details):")
print()
print("1. Add shader to workspaces/main/assets.txt:")
print(f" shaders/{snake_name}.wgsl")
@@ -392,13 +392,17 @@ def main():
print(f' #include "gpu/effects/{snake_name}_effect.h"')
print()
print("3. Add to timeline in workspaces/main/timeline.seq:")
- print(f" EFFECT {effect_name}Effect 0.0 10.0 0")
+ print(f" EFFECT + {effect_name}Effect 0.0 10.0")
print()
- print("4. Update tests/test_demo_effects.cc:")
- print(f' - Add "{effect_name}Effect" to test list')
- print(" - Increment EXPECTED_*_COUNT")
+ print("4. Add to CMakeLists.txt GPU_SOURCES (both headless and normal mode):")
+ print(f" src/gpu/effects/{snake_name}_effect.cc")
print()
- print("5. Build and test:")
+ print("5. Update src/tests/gpu/test_demo_effects.cc:")
+ print(f' - Add "{{{effect_name}Effect", std::make_shared<{effect_name}Effect>(fixture.ctx())}}" to appropriate list')
+ print(" - Use post_process_effects (lines 80-93) for post-process effects")
+ print(" - Use scene_effects (lines 125-137) for scene effects")
+ print()
+ print("6. Build and test:")
print(" cmake --build build -j4")
print(" ./build/demo64k")
print()
diff --git a/workspaces/main/timeline.seq b/workspaces/main/timeline.seq
index 8f7eea6..5e9a84f 100644
--- a/workspaces/main/timeline.seq
+++ b/workspaces/main/timeline.seq
@@ -36,7 +36,8 @@ SEQUENCE 8.50 2 "Hybrid3D"
SEQUENCE 10.50 0 "CNN effect"
EFFECT + HeptagonEffect 0.0 12.00
# EFFECT + RotatingCubeEffect 0.00 12.0
- EFFECT + Hybrid3DEffect 0.00 12.00
+# EFFECT + Hybrid3DEffect 0.00 12.00
+# EFFECT + CubeSphereEffect 0.0 10.0
EFFECT + CNNEffect 1.0 12.0 layers=3 blend=1.5
SEQUENCE 22.0 0 "buggy"