From 33f3aae3494970b92c47f00094b8e96eda786b2d Mon Sep 17 00:00:00 2001 From: Jarrod Doyle Date: Sat, 8 Apr 2023 21:52:22 +0100 Subject: [PATCH] Add a simple voxel raycast compute shader --- assets/shaders/branchless_dda.wgsl | 87 ++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 assets/shaders/branchless_dda.wgsl diff --git a/assets/shaders/branchless_dda.wgsl b/assets/shaders/branchless_dda.wgsl new file mode 100644 index 0000000..211a918 --- /dev/null +++ b/assets/shaders/branchless_dda.wgsl @@ -0,0 +1,87 @@ +// Based on: https://www.shadertoy.com/view/4dX3zl + +@group(0) @binding(0) var output: texture_storage_2d; + +fn sdSphere(p: vec3, d: f32) -> f32 { + return length(p) - d; +} + +fn sdBox(p: vec3, b: vec3) -> f32 { + let d: vec3 = abs(p) - b; + return min(max(d.x, max(d.y, d.z)), 0.0) + length(max(d, vec3(0.0))); +} + +fn getVoxel(c: vec3) -> bool { + let p = vec3(c) + vec3(0.5); + let d = min(max(-sdSphere(p, 7.5), sdBox(p, vec3(6.0))), -sdSphere(p, 25.0)); + return d < 0.0; +} + +@compute @workgroup_size(8, 8, 1) +fn compute(@builtin(global_invocation_id) global_id: vec3) { + let img_coord = vec2(global_id.xy); + let img_dims = textureDimensions(output); + let img_coord_frac = vec2( + f32(img_coord.x) / f32(img_dims.x), + f32(img_coord.y) / f32(img_dims.y) + ); + + // Camera setup + let screen_pos = img_coord_frac * 2.0 - vec2(1.0); + let camera_dir = vec3(0.0, 0.0, 0.8); + let camera_plane_u = vec3(1.0, 0.0, 0.0); + let camera_plane_v = vec3(0.0, 1.0, 0.0) * f32(img_dims.y) / f32(img_dims.x); + let ray_dir = camera_dir + screen_pos.x * camera_plane_u + screen_pos.y * camera_plane_v; + let ray_pos = vec3(0.01, 2.0, -12.0); + + // DDA setup + var map_pos: vec3 = vec3(floor(ray_pos + 0.0)); + var delta_dist: vec3 = abs(vec3(length(ray_dir)) / ray_dir); + var ray_step: vec3 = vec3(sign(ray_dir)); + var side_dist: vec3 = (sign(ray_dir) * (vec3(map_pos) - ray_pos) + (sign(ray_dir) * 0.5) + 0.5) * delta_dist; + var mask: vec3 = vec3(false, false, false); + + // DDA loop + for (var i: i32 = 0; i < 64; i++){ + if (getVoxel(map_pos)) { + break; + } + if (side_dist.x < side_dist.y) { + if (side_dist.x < side_dist.z) { + side_dist += vec3(delta_dist.x, 0.0, 0.0); + map_pos += vec3(ray_step.x, 0, 0); + mask = vec3(true, false, false); + } + else { + side_dist += vec3(0.0, 0.0, delta_dist.z); + map_pos += vec3(0, 0, ray_step.z); + mask = vec3(false, false, true); + } + } + else { + if (side_dist.y < side_dist.z) { + side_dist += vec3(0.0, delta_dist.y, 0.0); + map_pos += vec3(0, ray_step.y, 0); + mask = vec3(false, true, false); + } + else { + side_dist += vec3(0.0, 0.0, delta_dist.z); + map_pos += vec3(0, 0, ray_step.z); + mask = vec3(false, false, true); + } + } + } + + var color = vec4(0.0, 0.0, 0.0, 1.0); + if (mask.x) { + color.x = 1.0; + } + if (mask.y) { + color.y = 1.0; + } + if (mask.z) { + color.z = 1.0; + } + + textureStore(output, img_coord, color); +} \ No newline at end of file