From a954a77c91b60f958126f099543443c2b711c755 Mon Sep 17 00:00:00 2001 From: skal Date: Tue, 10 Feb 2026 00:27:52 +0100 Subject: feat: Add HTML WGSL shader editor tool ShaderToy-like web tool for live WGSL shader editing with WebGPU preview. Features: - Live WebGPU preview with real-time shader updates - Shader composition: #include directive support - Animation controls: time, loop_time (0..1), audio_peak - File I/O: Load/save .wgsl files - CommonUniforms binding (resolution, time, beat, audio_intensity) - Keyboard shortcuts: Ctrl+S (save), Ctrl+O (load), Space (play/pause) Single-file HTML (no build step, no CORS issues). handoff(Claude): Implemented HTML WGSL shader editor per plan Co-Authored-By: Claude Sonnet 4.5 --- tools/shader_editor/README.md | 121 +++++++ tools/shader_editor/index.html | 767 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 888 insertions(+) create mode 100644 tools/shader_editor/README.md create mode 100644 tools/shader_editor/index.html diff --git a/tools/shader_editor/README.md b/tools/shader_editor/README.md new file mode 100644 index 0000000..d22fe5e --- /dev/null +++ b/tools/shader_editor/README.md @@ -0,0 +1,121 @@ +# WGSL Shader Editor + +ShaderToy-like web tool for live WGSL shader editing with WebGPU preview. + +## Features + +- **Live Preview**: WebGPU rendering with real-time shader updates +- **Shader Composition**: `#include` directive support for modular shaders +- **Animation Controls**: Configurable time, loop, and audio parameters +- **File I/O**: Load/save `.wgsl` files directly from browser +- **Snippet Library**: Pre-loaded math, SDF, and rendering utilities + +## Usage + +1. **Open**: `file:///path/to/tools/shader_editor/index.html` in Chrome/Edge +2. **Edit**: Type WGSL code in right pane (auto-composes on change) +3. **Preview**: View live output in left canvas +4. **Save**: Click "Save .wgsl" to download + +## Keyboard Shortcuts + +- `Ctrl/Cmd+S` - Save shader +- `Ctrl/Cmd+O` - Load shader +- `Space` - Play/Pause animation + +## Available Uniforms + +All shaders have access to `CommonUniforms` at `@binding(2)`: + +```wgsl +struct CommonUniforms { + resolution: vec2, // Canvas width/height + aspect_ratio: f32, // width / height + time: f32, // Seconds since start (resetable) + beat: f32, // Loop time 0.0→1.0 (configurable period) + audio_intensity: f32, // Manual slider or auto-pulse +}; +@group(0) @binding(2) var uniforms: CommonUniforms; +``` + +Standard bindings: +- `@binding(0)` - Sampler +- `@binding(1)` - Texture (1x1 black placeholder) +- `@binding(2)` - CommonUniforms + +## Available Snippets + +Use `#include "name"` to import: + +- `common_uniforms` - CommonUniforms struct definition +- `math/sdf_shapes` - Sphere, box, torus primitives +- `math/sdf_utils` - SDF operations (union, smooth blend) +- `math/common_utils` - Rotation matrices, utilities +- `math/noise` - Noise functions +- `render/scene_query_linear` - Linear scene traversal +- `render/scene_query_bvh` - BVH scene traversal +- `render/lighting_utils` - Lighting helpers +- `render/shadows` - Shadow calculation +- `sdf_primitives` - Additional SDF shapes +- `lighting` - Phong/lighting models +- `ray_box` - Ray-AABB intersection +- `ray_triangle` - Ray-triangle intersection + +Click "📚 Snippets" to browse and insert. + +## Animation Controls + +- **Play/Pause**: Start/stop animation +- **Loop Time**: Progress bar showing 0.0→1.0 cycle +- **Loop Period**: Adjust cycle duration (1-10s) +- **Time**: Ever-increasing clock (reset button) +- **Audio Peak**: Manual slider (0-1) or auto-pulse mode +- **Resolution**: Preset canvas sizes + +## Example Shaders + +### Minimal (No Composition) +```wgsl +@group(0) @binding(2) var uniforms: CommonUniforms; + +@fragment fn fs_main(@builtin(position) p: vec4) -> @location(0) vec4 { + let uv = p.xy / uniforms.resolution; + return vec4(uv, 0.5 + 0.5 * sin(uniforms.time), 1.0); +} +``` + +### With Includes +```wgsl +#include "common_uniforms" +@group(0) @binding(2) var uniforms: CommonUniforms; + +#include "math/sdf_shapes" + +@fragment fn fs_main(@builtin(position) p: vec4) -> @location(0) vec4 { + let uv = (p.xy / uniforms.resolution) * 2.0 - 1.0; + let d = sdSphere(vec3(uv, 0.0), 0.5); + return vec4(vec3(step(d, 0.0)), 1.0); +} +``` + +## Limitations + +- **Fragment shaders only** (no compute/vertex customization) +- **Single texture input** (1x1 black placeholder) +- **No custom uniforms** (CommonUniforms only) +- **Read-only snippet library** (hardcoded from workspace) +- **No syntax highlighting** (plain textarea) + +## Testing + +Load existing shaders from workspace: +- `../../workspaces/main/shaders/passthrough.wgsl` - Basic +- `../../workspaces/main/shaders/distort.wgsl` - With includes + +## Future Enhancements + +- Monaco editor (syntax highlighting, autocomplete) +- Custom uniform parameter UI +- Texture upload support +- Compute shader support +- Export C++ Effect class skeleton diff --git a/tools/shader_editor/index.html b/tools/shader_editor/index.html new file mode 100644 index 0000000..d74b9ff --- /dev/null +++ b/tools/shader_editor/index.html @@ -0,0 +1,767 @@ + + + + + + WGSL Shader Editor + + + +
+
+ + +
FPS: 0
+ +
+
+ + +
+ +
+ +
+
+
+
+ +
+ +
+ +
+ +
+ +
+ + 0.50 + +
+ +
+ +
+
+
+ +
+
+ + + + +
+ + + + +
+
+ + + + -- cgit v1.2.3