feat(renderer): add motion blur compute shader

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-26 15:57:05 +09:00
parent 831365a622
commit 447473598a
5 changed files with 425 additions and 0 deletions

View File

@@ -0,0 +1,49 @@
struct MotionBlurParams {
inv_view_proj: mat4x4<f32>,
prev_view_proj: mat4x4<f32>,
num_samples: u32,
strength: f32,
_pad: vec2<f32>,
};
@group(0) @binding(0) var color_tex: texture_2d<f32>;
@group(0) @binding(1) var depth_tex: texture_depth_2d;
@group(0) @binding(2) var output_tex: texture_storage_2d<rgba16float, write>;
@group(0) @binding(3) var<uniform> params: MotionBlurParams;
@compute @workgroup_size(16, 16)
fn main(@builtin(global_invocation_id) gid: vec3<u32>) {
let dims = textureDimensions(color_tex);
if (gid.x >= dims.x || gid.y >= dims.y) { return; }
let pos = vec2<i32>(gid.xy);
let uv = (vec2<f32>(gid.xy) + 0.5) / vec2<f32>(dims);
// Reconstruct world position from depth
let depth = textureLoad(depth_tex, pos, 0);
let ndc = vec4<f32>(uv.x * 2.0 - 1.0, 1.0 - uv.y * 2.0, depth, 1.0);
let world = params.inv_view_proj * ndc;
let world_pos = world.xyz / world.w;
// Project to previous frame
let prev_clip = params.prev_view_proj * vec4<f32>(world_pos, 1.0);
let prev_ndc = prev_clip.xyz / prev_clip.w;
let prev_uv = vec2<f32>(prev_ndc.x * 0.5 + 0.5, 1.0 - (prev_ndc.y * 0.5 + 0.5));
// Velocity = current_uv - prev_uv
let velocity = (uv - prev_uv) * params.strength;
// Sample along velocity direction
var color = vec4<f32>(0.0);
let n = params.num_samples;
for (var i = 0u; i < n; i++) {
let t = f32(i) / f32(n - 1u) - 0.5; // -0.5 to 0.5
let sample_uv = uv + velocity * t;
let sample_pos = vec2<i32>(sample_uv * vec2<f32>(dims));
let clamped = clamp(sample_pos, vec2<i32>(0), vec2<i32>(dims) - 1);
color += textureLoad(color_tex, clamped, 0);
}
color /= f32(n);
textureStore(output_tex, pos, color);
}