summaryrefslogtreecommitdiff
path: root/tools/shadertoy/README.md
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-10 17:47:15 +0100
committerskal <pascal.massimino@gmail.com>2026-02-10 17:47:15 +0100
commitae810e1a9c68d05bee254ef570fbb0e783e25931 (patch)
tree407f3d7d8e03da07d8f7995df78d37be7d1f32c1 /tools/shadertoy/README.md
parentf3c7ef8cd612f5ac908f39310c4c11566879313f (diff)
feat: Add ShaderToy conversion tools
Add automated conversion pipeline for ShaderToy shaders to demo effects: - convert_shadertoy.py: Automated code generation script - Manual templates: Header, implementation, and WGSL boilerplate - Example shader: Test case for conversion workflow - README: Complete conversion guide with examples Handles basic GLSL→WGSL conversion (types, uniforms, mainImage extraction). Manual fixes needed for fragColor returns and complex type inference. Organized under tools/shadertoy/ for maintainability. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
Diffstat (limited to 'tools/shadertoy/README.md')
-rw-r--r--tools/shadertoy/README.md191
1 files changed, 191 insertions, 0 deletions
diff --git a/tools/shadertoy/README.md b/tools/shadertoy/README.md
new file mode 100644
index 0000000..e734684
--- /dev/null
+++ b/tools/shadertoy/README.md
@@ -0,0 +1,191 @@
+# ShaderToy Conversion Guide
+
+Quick guide to convert ShaderToy shaders to demo effects.
+
+## Quick Start (Automated)
+
+```bash
+# Save ShaderToy code to a file
+cat > tunnel.txt << 'EOF'
+void mainImage(out vec4 fragColor, in vec2 fragCoord) {
+ vec2 uv = fragCoord / iResolution.xy;
+ vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0,2,4));
+ fragColor = vec4(col, 1.0);
+}
+EOF
+
+# Generate effect files
+./tools/shadertoy/convert_shadertoy.py tunnel.txt Tunnel
+
+# Follow printed instructions to integrate
+```
+
+## Files
+
+**Automated Script:**
+- `convert_shadertoy.py` - Generates all files from ShaderToy code
+- `example.txt` - Example ShaderToy shader for testing
+
+**Manual Templates:**
+- `template.h` - Header boilerplate
+- `template.cc` - Implementation boilerplate
+- `template.wgsl` - Shader boilerplate with conversion notes
+
+## Manual Steps
+
+### 1. Copy Templates
+
+```bash
+# Choose effect name (e.g., "tunnel", "plasma", "warp")
+EFFECT_NAME="myeffect"
+
+cp tools/shadertoy/template.h src/gpu/effects/${EFFECT_NAME}_effect.h
+cp tools/shadertoy/template.cc src/gpu/effects/${EFFECT_NAME}_effect.cc
+cp tools/shadertoy/template.wgsl workspaces/main/shaders/${EFFECT_NAME}.wgsl
+```
+
+### 2. Rename Class
+
+In both `.h` and `.cc`:
+- `ShaderToyEffect` → `MyEffectEffect`
+- `SHADERTOY_EFFECT_H_` → `MYEFFECT_EFFECT_H_`
+- `shadertoy_effect.h` → `myeffect_effect.h`
+
+### 3. Convert Shader
+
+In `.wgsl`, paste ShaderToy `mainImage()` into `fs_main()`:
+
+**ShaderToy:**
+```glsl
+void mainImage(out vec4 fragColor, in vec2 fragCoord) {
+ vec2 uv = fragCoord / iResolution.xy;
+ fragColor = vec4(uv, 0.5, 1.0);
+}
+```
+
+**WGSL:**
+```wgsl
+@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
+ let uv = p.xy / uniforms.resolution;
+ return vec4<f32>(uv, 0.5, 1.0);
+}
+```
+
+### 4. Update Asset Name
+
+In `.cc`, update `AssetId::ASSET_SHADERTOY_SHADER` to match your shader filename:
+```cpp
+AssetId::ASSET_MYEFFECT_SHADER
+```
+
+### 5. Add to Assets
+
+In `workspaces/main/assets.txt`:
+```
+shaders/myeffect.wgsl
+```
+
+### 6. Register Effect
+
+In `src/gpu/demo_effects.h`:
+```cpp
+#include "gpu/effects/myeffect_effect.h"
+```
+
+In `workspaces/main/timeline.seq`:
+```
+SEQUENCE 0.0 0
+ EFFECT MyEffectEffect 0.0 10.0 0
+```
+
+### 7. Update Tests
+
+In `tests/test_demo_effects.cc`:
+- Add `"MyEffectEffect"` to test list
+- Increment `EXPECTED_*_COUNT`
+
+### 8. Build & Test
+
+```bash
+cmake --build build -j4
+./build/demo64k
+
+# Run tests
+cmake -S . -B build -DDEMO_BUILD_TESTS=ON
+cmake --build build -j4
+cd build && ctest
+```
+
+## Example Conversion
+
+**Input ShaderToy:**
+```glsl
+void mainImage(out vec4 fragColor, in vec2 fragCoord) {
+ vec2 uv = fragCoord / iResolution.xy;
+ vec3 col = 0.5 + 0.5 * cos(iTime + uv.xyx + vec3(0,2,4));
+ fragColor = vec4(col, 1.0);
+}
+```
+
+**Generated WGSL (after script + manual fixes):**
+```wgsl
+@fragment fn fs_main(@builtin(position) p: vec4<f32>) -> @location(0) vec4<f32> {
+ let uv = p.xy / uniforms.resolution;
+ let col = vec3<f32>(0.5) + 0.5 * cos(uniforms.time + uv.xyx + vec3<f32>(0.0, 2.0, 4.0));
+ return vec4<f32>(col, 1.0);
+}
+```
+
+## Common Conversions
+
+| ShaderToy | WGSL |
+|-----------|------|
+| `iResolution.xy` | `uniforms.resolution` |
+| `iTime` | `uniforms.time` |
+| `fragCoord` | `p.xy` |
+| `float` | `f32` |
+| `vec2` | `vec2<f32>` |
+| `mod(x, y)` | `x % y` |
+| `texture(iChannel0, uv)` | `textureSample(txt, smplr, uv)` |
+| `fragColor = ...` | `return ...` |
+| `vec2 p = ...` | `let p = vec2<f32>(...)` or `var p: vec2<f32> = ...` |
+
+## Custom Parameters
+
+For tunable values:
+
+**C++ (`.h`):**
+```cpp
+struct MyEffectParams {
+ float speed;
+ float scale;
+ float _pad[2];
+};
+static_assert(sizeof(MyEffectParams) == 16, "...");
+```
+
+**WGSL:**
+```wgsl
+struct MyEffectParams {
+ speed: f32,
+ scale: f32,
+ _pad0: f32,
+ _pad1: f32,
+}
+@group(0) @binding(3) var<uniform> params: MyEffectParams;
+```
+
+## Available Uniforms
+
+Always available in `uniforms: CommonUniforms`:
+- `resolution: vec2<f32>` - Screen resolution
+- `aspect_ratio: f32` - Width/height
+- `time: f32` - Demo time (seconds)
+- `beat: f32` - Music beat sync (0-1)
+- `audio_intensity: f32` - Audio reactivity
+
+## Next Steps
+
+- See `doc/CONTRIBUTING.md` for commit policy
+- See `doc/SEQUENCE.md` for timeline syntax
+- See existing effects in `src/gpu/effects/` for examples