summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-28 09:15:23 +0100
committerskal <pascal.massimino@gmail.com>2026-02-28 09:15:23 +0100
commit34bee8b09566a52cedced99b7bd13d29907512ce (patch)
tree3adda379abfd0787b24543a32f98a060f1999f00
parent9ee410594a52cbc699b13de2bde4860d70c959a3 (diff)
fix(shader_editor): sync CommonUniforms to current struct, fix layout
- Update CommonUniforms: remove _pad0/_pad1, add beat_time/beat_phase, move _pad to end (matches src/shaders/common_uniforms.wgsl) - Fix JS uniform write order to match new layout - Fix flex-direction: row override (common.css forced column, hiding editor) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
-rw-r--r--tools/shader_editor/SHADER_EDITOR_DETAILS.md20
-rw-r--r--tools/shader_editor/index.html35
2 files changed, 31 insertions, 24 deletions
diff --git a/tools/shader_editor/SHADER_EDITOR_DETAILS.md b/tools/shader_editor/SHADER_EDITOR_DETAILS.md
index b8bbb25..f6fdf2e 100644
--- a/tools/shader_editor/SHADER_EDITOR_DETAILS.md
+++ b/tools/shader_editor/SHADER_EDITOR_DETAILS.md
@@ -18,17 +18,17 @@ All shaders receive `CommonUniforms` at `@group(0) @binding(2)`:
```wgsl
struct CommonUniforms {
- resolution: vec2<f32>, // Canvas width/height (1280, 720)
- _pad0: f32, // Alignment padding
- _pad1: f32,
+ resolution: vec2f, // Canvas width/height (1280, 720)
aspect_ratio: f32, // resolution.x / resolution.y
time: f32, // Seconds since start (resetable)
- beat: f32, // Loop time 0.0→1.0 (period: 0.1-10s)
+ beat_time: f32, // Absolute beat counter (currentTime / loopPeriod)
+ beat_phase: f32, // Fractional beat 0.0→1.0 within current period
audio_intensity: f32, // Manual slider 0-1 or auto-pulse
+ _pad: f32, // Alignment padding
};
```
-**Size:** 32 bytes (matches C++ `CommonPostProcessUniforms`)
+**Size:** 32 bytes (matches `src/shaders/common_uniforms.wgsl`)
## Bind Group Specification
@@ -85,12 +85,13 @@ Standard bindings for all shaders:
@group(0) @binding(1) var txt: texture_2d<f32>;
struct CommonUniforms {
- resolution: vec2<f32>,
- _pad0: f32, _pad1: f32,
+ resolution: vec2f,
aspect_ratio: f32,
time: f32,
- beat: f32,
+ beat_time: f32,
+ beat_phase: f32,
audio_intensity: f32,
+ _pad: f32,
};
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
@@ -115,6 +116,7 @@ struct CommonUniforms {
#include "common_uniforms"
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
+// uniforms.beat_phase → fractional beat, uniforms.beat_time → absolute beats
@vertex fn vs_main(@builtin(vertex_index) i: u32) -> @builtin(position) vec4<f32> {
var pos = array<vec2<f32>, 3>(
@@ -154,7 +156,7 @@ Animated gradient background with pulsing circle synced to `beat`:
);
// Pulsing circle
- let d = length(uv) - 0.3 - 0.1 * sin(uniforms.beat * 6.28);
+ let d = length(uv) - 0.3 - 0.1 * sin(uniforms.beat_phase * 6.28);
let circle = smoothstep(0.02, 0.0, d);
let glow = 0.02 / (abs(d) + 0.02);
diff --git a/tools/shader_editor/index.html b/tools/shader_editor/index.html
index d93a595..d318304 100644
--- a/tools/shader_editor/index.html
+++ b/tools/shader_editor/index.html
@@ -6,6 +6,10 @@
<title>WGSL Shader Editor</title>
<link rel="stylesheet" href="../common/style.css">
<style>
+.container {
+ flex-direction: row;
+}
+
.preview-pane {
flex: 0 0 57%;
background: #252526;
@@ -428,13 +432,13 @@ class WebGPUPreview {
@group(0) @binding(1) var txt: texture_2d<f32>;
struct CommonUniforms {
- resolution: vec2<f32>,
- _pad0: f32,
- _pad1: f32,
+ resolution: vec2f,
aspect_ratio: f32,
time: f32,
- beat: f32,
+ beat_time: f32,
+ beat_phase: f32,
audio_intensity: f32,
+ _pad: f32,
};
@group(0) @binding(2) var<uniform> uniforms: CommonUniforms;
@@ -460,7 +464,7 @@ struct CommonUniforms {
);
// Pulsing circle
- let d = length(uv) - 0.3 - 0.1 * sin(uniforms.beat * 6.28);
+ let d = length(uv) - 0.3 - 0.1 * sin(uniforms.beat_phase * 6.28);
let circle = smoothstep(0.02, 0.0, d);
let glow = 0.02 / (abs(d) + 0.02);
@@ -528,13 +532,14 @@ struct CommonUniforms {
this.currentTime = (now - this.startTime) / 1000;
}
- const loopTime = (this.currentTime % this.loopPeriod) / this.loopPeriod;
+ const beatPhase = (this.currentTime % this.loopPeriod) / this.loopPeriod;
+ const beatTime = this.currentTime / this.loopPeriod;
const audioPeak = this.autoPulse ? 0.5 + 0.5 * Math.sin(this.currentTime * Math.PI) : this.audioPeak;
const uniformData = new Float32Array([
- this.canvas.width, this.canvas.height, 0, 0,
+ this.canvas.width, this.canvas.height,
this.canvas.width / this.canvas.height,
- this.currentTime, loopTime, audioPeak,
+ this.currentTime, beatTime, beatPhase, audioPeak, 0,
]);
this.device.queue.writeBuffer(this.uniformBuffer, 0, uniformData);
@@ -546,7 +551,7 @@ struct CommonUniforms {
this.lastFrameTime = now;
}
- return { time: this.currentTime, loopTime, audioPeak };
+ return { time: this.currentTime, beatPhase, beatTime, audioPeak };
}
render() {
@@ -608,13 +613,13 @@ struct CommonUniforms {
// Main App
const composer = new ShaderComposer();
composer.registerSnippet('common_uniforms', `struct CommonUniforms {
- resolution: vec2<f32>,
- _pad0: f32,
- _pad1: f32,
+ resolution: vec2f,
aspect_ratio: f32,
time: f32,
- beat: f32,
+ beat_time: f32,
+ beat_phase: f32,
audio_intensity: f32,
+ _pad: f32,
};`);
const canvas = document.getElementById('preview-canvas');
@@ -718,8 +723,8 @@ function renderLoop() {
if (stats) {
fpsCounter.textContent = `FPS: ${preview.getFPS()}`;
timeValue.textContent = stats.time.toFixed(2);
- loopTimeValue.textContent = stats.loopTime.toFixed(2);
- loopTimeBar.style.width = `${stats.loopTime * 100}%`;
+ loopTimeValue.textContent = stats.beatPhase.toFixed(2);
+ loopTimeBar.style.width = `${stats.beatPhase * 100}%`;
audioPeakValue.textContent = stats.audioPeak.toFixed(2);
}
requestAnimationFrame(renderLoop);