diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/shaders/camera_common.wgsl | 7 | ||||
| -rw-r--r-- | src/shaders/combined_postprocess.wgsl | 2 | ||||
| -rw-r--r-- | src/shaders/gaussian_blur.wgsl | 2 | ||||
| -rw-r--r-- | src/shaders/passthrough.wgsl | 2 | ||||
| -rw-r--r-- | src/shaders/render/fullscreen_uv_vs.wgsl | 24 | ||||
| -rw-r--r-- | src/shaders/skybox.wgsl | 2 |
6 files changed, 29 insertions, 10 deletions
diff --git a/src/shaders/camera_common.wgsl b/src/shaders/camera_common.wgsl index 846d052..67544f1 100644 --- a/src/shaders/camera_common.wgsl +++ b/src/shaders/camera_common.wgsl @@ -1,4 +1,9 @@ -// Camera parameters and helpers for SDF raymarching effects +// Camera parameters and helpers for SDF raymarching effects. +// +// Coordinate conventions: +// World space: Z-up, Y-forward, X-right +// View space: X-right, Y-up, -Z-forward (camera looks down -Z) +// getCameraRay: expects uv in [-1,1] y-up (pass in.st from fullscreen_uv_vs) struct CameraParams { inv_view: mat4x4f, diff --git a/src/shaders/combined_postprocess.wgsl b/src/shaders/combined_postprocess.wgsl index c0acfe7..7402284 100644 --- a/src/shaders/combined_postprocess.wgsl +++ b/src/shaders/combined_postprocess.wgsl @@ -11,7 +11,7 @@ @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { // Sample base color - var color = textureSample(input_texture, input_sampler, in.uv); + var color = textureSampleYUp(input_texture, input_sampler, in.uv); // Apply effects in sequence (customize as needed) // color = apply_solarize(color, 0.4, 0.4, uniforms.time); diff --git a/src/shaders/gaussian_blur.wgsl b/src/shaders/gaussian_blur.wgsl index 7f85719..75f8c39 100644 --- a/src/shaders/gaussian_blur.wgsl +++ b/src/shaders/gaussian_blur.wgsl @@ -24,7 +24,7 @@ struct GaussianBlurParams { for (var i = -kernel_size; i <= kernel_size; i++) { let sample_offset = f32(i) * offset; let weight = exp(-f32(i * i) / (2.0 * params.radius * params.radius)); - color += textureSample(input_texture, input_sampler, in.uv + sample_offset) * weight; + color += textureSampleYUp(input_texture, input_sampler, in.uv + sample_offset) * weight; weight_sum += weight; } diff --git a/src/shaders/passthrough.wgsl b/src/shaders/passthrough.wgsl index bce377c..90ba08b 100644 --- a/src/shaders/passthrough.wgsl +++ b/src/shaders/passthrough.wgsl @@ -7,5 +7,5 @@ @group(0) @binding(2) var<uniform> uniforms: UniformsSequenceParams; @fragment fn fs_main(in: VertexOutput) -> @location(0) vec4f { - return textureSample(input_texture, input_sampler, in.uv); + return textureSampleYUp(input_texture, input_sampler, in.uv); } diff --git a/src/shaders/render/fullscreen_uv_vs.wgsl b/src/shaders/render/fullscreen_uv_vs.wgsl index f9ae427..5f76160 100644 --- a/src/shaders/render/fullscreen_uv_vs.wgsl +++ b/src/shaders/render/fullscreen_uv_vs.wgsl @@ -1,15 +1,29 @@ // Common vertex shader for fullscreen post-processing effects. -// Draws a single triangle that covers the entire screen, with uv -// coordinates in [0..1] +// Draws a single triangle that covers the entire screen. +// +// Screen-space convention: Y-UP, origin at BOTTOM-LEFT +// uv in [0,1]: (0,0) = bottom-left, (1,1) = top-right +// st in [-1,1]: NDC directly, y-up +// +// WebGPU textures are Y-DOWN ((0,0) at top-left). +// Use textureSampleYUp() instead of textureSample() when sampling with uv. struct VertexOutput { - @builtin(position) position: vec4f, - @location(0) uv: vec2f, + @builtin(position) position: vec4f, // in pixel screen units + @location(0) uv: vec2f, // in [0, 1] + @location(1) st: vec2f, // in [-1, 1] }; @vertex fn vs_main(@builtin(vertex_index) i: u32) -> VertexOutput { - let pos = array<vec4f, 3>(vec4f(-1, -1, 0, 1.), vec4f(3, -1, 2., 1.), vec4f(-1, 3, 0, -1)); + let pos = array<vec4f, 3>(vec4f(-1, -1, 0, 0.), vec4f(3, -1, 2., 0.), vec4f(-1, 3, 0, 2.)); var out: VertexOutput; out.position = vec4f(pos[i].xy, 0.0, 1.0); out.uv = pos[i].zw; + out.st = pos[i].xy; return out; } + +// Sample a texture using y-up UV coordinates (uv.y=0 at bottom). +// Flips Y to match WebGPU texture convention (texel (0,0) at top-left). +fn textureSampleYUp(tex: texture_2d<f32>, s: sampler, uv: vec2f) -> vec4f { + return textureSample(tex, s, vec2f(uv.x, 1.0 - uv.y)); +} diff --git a/src/shaders/skybox.wgsl b/src/shaders/skybox.wgsl index 075eeb6..652743f 100644 --- a/src/shaders/skybox.wgsl +++ b/src/shaders/skybox.wgsl @@ -10,7 +10,7 @@ fn fs_main(in: VertexOutput) -> @location(0) vec4f { // Convert UV to NDC let ndc_x = in.uv.x * 2.0 - 1.0; - let ndc_y = (1.0 - in.uv.y) * 2.0 - 1.0; // Un-flip Y for NDC (Y-up) + let ndc_y = in.uv.y * 2.0 - 1.0; // uv is y-up, matches NDC directly // Unproject to find world direction // We want the direction from camera to the far plane at this pixel |
