# 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) -> @location(0) vec4 { let uv = p.xy / uniforms.resolution; return vec4(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) -> @location(0) vec4 { let uv = p.xy / uniforms.resolution; let col = vec3(0.5) + 0.5 * cos(uniforms.time + uv.xyx + vec3(0.0, 2.0, 4.0)); return vec4(col, 1.0); } ``` ## Common Conversions | ShaderToy | WGSL | |-----------|------| | `iResolution.xy` | `uniforms.resolution` | | `iTime` | `uniforms.time` | | `fragCoord` | `p.xy` | | `float` | `f32` | | `vec2` | `vec2` | | `mod(x, y)` | `x % y` | | `texture(iChannel0, uv)` | `textureSample(txt, smplr, uv)` | | `fragColor = ...` | `return ...` | | `vec2 p = ...` | `let p = vec2(...)` or `var p: vec2 = ...` | ## 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 params: MyEffectParams; ``` ## Available Uniforms Always available in `uniforms: CommonUniforms`: - `resolution: vec2` - 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