diff --git a/src/client/render/voxel/pipeline.rs b/src/client/render/voxel/pipeline.rs index 8ca660b..23e234e 100644 --- a/src/client/render/voxel/pipeline.rs +++ b/src/client/render/voxel/pipeline.rs @@ -125,7 +125,7 @@ impl VoxelPipeline { r: (x as f32 / lx as f32 * 255.0) as u8, g: (y as f32 / ly as f32 * 255.0) as u8, b: 0, - a: 20, + a: 100, }; } } @@ -149,10 +149,11 @@ impl VoxelPipeline { data.len(), &[ArrBufUpdate { offset: 0, data }], ); + let thing = Translation3::new(0.0, 0.0, 20.0) + * Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5) + * Translation3::new(-(lx as f32 / 2.0), -(ly as f32 / 2.0), -(lz as f32 / 2.0)); let group = VoxelGroup { - transform: Transform3::identity() - * (Translation3::new(-5.0, -5.0, 20.0) - * Rotation3::from_axis_angle(&Vector3::y_axis(), 0.5)).inverse(), + transform: Transform3::identity() * thing.inverse(), dimensions: Vector3::new(lx as u32, ly as u32, lz as u32), }; self.voxel_groups.update( diff --git a/src/client/render/voxel/shader.wgsl b/src/client/render/voxel/shader.wgsl index 8ebbf97..9dccfa0 100644 --- a/src/client/render/voxel/shader.wgsl +++ b/src/client/render/voxel/shader.wgsl @@ -43,46 +43,154 @@ fn vs_main( // Fragment shader +const n0 = vec3(1.0, 0.0, 0.0); +const n1 = -n0; +const n2 = vec3(0.0, 1.0, 0.0); +const n3 = -n2; +const n4 = vec3(0.0, 0.0, 1.0); +const n5 = -n4; + +const ORIGIN = vec3(0.0, 0.0, 0.0); +const ORIGIN2 = vec2(0.0, 0.0); +const NO_COLOR = vec4(0.0, 0.0, 0.0, 0.0); + @fragment fn fs_main( in: VertexOutput, ) -> @location(0) vec4 { let aspect = f32(view.height) / f32(view.width); - var pixel_pos = vec3(in.clip_position.x / f32(view.width), 1.0 - in.clip_position.y / f32(view.height), 1.0); - pixel_pos.x -= 0.5; - pixel_pos.y -= 0.5; - pixel_pos.x *= 2.0; - pixel_pos.y *= 2.0; - pixel_pos.y *= aspect; + var pos = vec3(in.clip_position.x / f32(view.width), 1.0 - in.clip_position.y / f32(view.height), 1.0); + pos.x -= 0.5; + pos.y -= 0.5; + pos.x *= 2.0; + pos.y *= 2.0; + pos.y *= aspect; let group = voxel_groups[0]; let dim_f = vec3(group.dimensions); // this should definitely be done per pixel trust me guys let transform = group.transform * view.transform; - pixel_pos = (transform * vec4(pixel_pos, 1.0)).xyz; - let origin = (transform * vec4(0.0, 0.0, 0.0, 1.0)).xyz; - let dir = normalize(pixel_pos - origin); + pos = (transform * vec4(pos, 1.0)).xyz; + let origin = (transform * vec4(ORIGIN, 1.0)).xyz; + let dir = normalize(pos - origin); - var t = 0; - var color = vec4(0.0, 0.0, 0.0, 0.0); - for(t = 0; t < 1000; t += 1) { - let pos = pixel_pos + f32(t) * 0.1 * dir; - if pos.x < 0.0 || pos.y < 0.0 || pos.z < 0.0 || pos.x > dim_f.x || pos.y > dim_f.y || pos.z > dim_f.z { - continue; + var p = ORIGIN; + + var na: vec3; + var nb: vec3; + var nc: vec3; + if dot(dir, n0) < 0.0 { + na = n0; + p.x = 1.0; + } else { + na = n1; + } + if dot(dir, n2) < 0.0 { + nb = n2; + p.y = 1.0; + } else { + nb = n3; + } + if dot(dir, n4) < 0.0 { + nc = n4; + p.z = 1.0; + } else { + nc = n5; + } + p *= dim_f; + + var vox_pos: vec3; + var offset = ORIGIN; + let dir_if = sign(dir) * ceil(abs(dir)); + if outside(pos, ORIGIN, dim_f) { + let ta = intersect(pos, dir, p, na); + let tb = intersect(pos, dir, p, nb); + let tc = intersect(pos, dir, p, nc); + let pa = pos + ta * dir; + let pb = pos + tb * dir; + let pc = pos + tc * dir; + + if inside2(pa.yz, ORIGIN2, dim_f.yz) && ta > 0.0 { + pos = pa; + } else if inside2(pb.xz, ORIGIN2, dim_f.xz) && tb > 0.0 { + pos = pb; + } else if inside2(pc.xy, ORIGIN2, dim_f.xy) && tc > 0.0 { + pos = pc; } else { - let rel_coords = vec3(pos.xyz); - let i = u32(rel_coords.x + rel_coords.y * group.dimensions.x + rel_coords.z * group.dimensions.x * group.dimensions.y); - let vcolor = unpack4x8unorm(voxels[i]); - // now I understand premultiplied alpha lmao - color += vec4(vcolor.xyz * vcolor.a * (1.0 - color.a), (1.0 - color.a) * vcolor.a); - if color.a == 1.0 { - break; - } + return NO_COLOR; } } + vox_pos = vec3(pos); + let dim_i = vec3(group.dimensions); + vox_pos = clamp(vox_pos, vec3(0, 0, 0), dim_i - vec3(1, 1, 1)); - return color; + + + let dir_i = vec3(dir_if); + let inc_t = abs(1.0 / dir); + let corner = vec3(vox_pos) + vec3(0.5, 0.5, 0.5) + dir_if / 2.0; + var next_t = inc_t * abs(pos - corner); + var color = NO_COLOR; + var t = 0; + loop { + let i = u32(vox_pos.x + vox_pos.y * dim_i.x + vox_pos.z * dim_i.x * dim_i.y); + let vcolor = unpack4x8unorm(voxels[i]); + color += vec4(vcolor.xyz * vcolor.a * (1.0 - color.a), (1.0 - color.a) * vcolor.a); + if color.a >= 1.0 { + return color; + } + + if next_t.x < next_t.y && next_t.x < next_t.z { + vox_pos.x += dir_i.x; + next_t.x += inc_t.x; + if vox_pos.x < 0 || vox_pos.x >= dim_i.x { + return color; + } + } else if next_t.y < next_t.z { + vox_pos.y += dir_i.y; + next_t.y += inc_t.y; + if vox_pos.y < 0 || vox_pos.y >= dim_i.y { + return color; + } + } else { + vox_pos.z += dir_i.z; + next_t.z += inc_t.z; + if vox_pos.z < 0 || vox_pos.z >= dim_i.z { + return color; + } + } + + t += 1; + if t > 1000 { + break; + } + } + return vec4(1.0, 0.0, 0.0, 1.0); +} + +fn intersect(lp: vec3, ld: vec3, pp: vec3, pn: vec3) -> f32 { + let v = pn * (lp - pp); + let a = v.x + v.y + v.z; + let u = pn * ld; + let b = u.x + u.y + u.z; + return -a / b; +} + +fn outside(v: vec3, low: vec3, high: vec3) -> bool { + return v.x < low.x || v.y < low.y || v.z < low.z || v.x > high.x || v.y > high.y || v.z > high.z; +} + +fn inside(v: vec3, low: vec3, high: vec3) -> bool { + return !outside(v, low, high); +} + +fn outside2(v: vec2, low: vec2, high: vec2) -> bool { + return v.x < low.x || v.y < low.y || v.x > high.x || v.y > high.y; +} + +fn inside2(v: vec2, low: vec2, high: vec2) -> bool { + return !outside2(v, low, high); }