diff --git a/src/assets/coast_sand_rocks_02_diff_1k.jpg b/src/assets/coast_sand_rocks_02_diff_1k.jpg new file mode 100644 index 0000000..1555f85 Binary files /dev/null and b/src/assets/coast_sand_rocks_02_diff_1k.jpg differ diff --git a/src/assets/coast_sand_rocks_02_metalrough_1k.png b/src/assets/coast_sand_rocks_02_metalrough_1k.png new file mode 100644 index 0000000..8b9d5cb Binary files /dev/null and b/src/assets/coast_sand_rocks_02_metalrough_1k.png differ diff --git a/src/main.rs b/src/main.rs index 2f1d246..cfa3528 100644 --- a/src/main.rs +++ b/src/main.rs @@ -71,12 +71,12 @@ impl Metaballs { let field = |x: i32, y: i32, z: i32| { let c = glam::Vec3A::new(x as f32, y as f32, z as f32); - let mut sum = 0.0; + let mut sum = metaballs[0].distance(c) - 3.75; for ball in metaballs.iter() { - sum += 1.0 / ball.distance(c); + sum = sum.min(ball.distance(c) - 3.75); } - sum - 0.4 + sum }; let r = 20; @@ -107,7 +107,7 @@ impl Metaballs { data: vec![0x00; 256], }; - let albedo_raw = include_bytes!("assets/brick_moss_001_diff_1k.jpg"); + let albedo_raw = include_bytes!("assets/coast_sand_rocks_02_diff_1k.jpg"); let albedo_data = load_texture_data(albedo_raw); let metalrough_raw = include_bytes!("assets/brick_moss_001_metalrough_1k.jpg"); @@ -245,15 +245,15 @@ fn main() { }, PointLight { center: glam::Vec3A::new(-7.0, 5.0, 7.0), - intensity: glam::Vec3A::new(100.0, 0.0, 0.0), + intensity: glam::Vec3A::new(100.0, 100.0, 0.0), }, PointLight { center: glam::Vec3A::new(7.0, 5.0, 7.0), - intensity: glam::Vec3A::new(0.0, 100.0, 0.0), + intensity: glam::Vec3A::new(100.0, 100.0, 100.0), }, PointLight { center: glam::Vec3A::new(0.0, 5.0, -7.0), - intensity: glam::Vec3A::new(0.0, 0.0, 100.0), + intensity: glam::Vec3A::new(100.0, 100.0, 100.0), }, PointLight { center: glam::Vec3A::new(0.0, 50.0, 0.0), diff --git a/src/procgen/marching_cubes.rs b/src/procgen/marching_cubes.rs index 13be750..44e9fab 100644 --- a/src/procgen/marching_cubes.rs +++ b/src/procgen/marching_cubes.rs @@ -66,7 +66,7 @@ pub fn marching_cubes( ) -> Vec { let samples = sample_corners(scalar_field, domain); - let test = |corner| samples[&corner] > 0.0; + let test = |corner| samples[&corner] < 0.0; // TODO this could be optimized using single-edge interpolation // TODO improve with glam vector math diff --git a/src/shader.wgsl b/src/shader.wgsl index ec9669b..6130e9e 100644 --- a/src/shader.wgsl +++ b/src/shader.wgsl @@ -1,6 +1,7 @@ #include src/shaders/basic_structs.wgsl #include src/shaders/basic_pbr.wgsl #include src/shaders/tri_sampler.wgsl +#include src/shaders/raymarch.wgsl [[group(0), binding(0)]] var camera: CameraUniform; @@ -39,11 +40,13 @@ fn fs_main( let normal = normalize(frag.normal); let view = normalize(camera.eye.xyz - frag.position); + let march_result = Raymarch(camera.eye.xyz, -1.0 * view); + //let albedo = textureSample(m_albedo, m_sampler, frag.tex_coords).xyz; - let albedo = TriSampler(m_albedo, m_sampler, frag.position / 5.0, normal, 10.0); + let albedo = TriSampler(m_albedo, m_sampler, march_result.position / 5.0, march_result.normal, 10.0); //let metallic_roughness = textureSample(m_metallic_roughness, m_sampler, frag.tex_coords).bg; - let metallic_roughness = TriSampler(m_metallic_roughness, m_sampler, frag.position / 5.0, normal, 10.0); + let metallic_roughness = TriSampler(m_metallic_roughness, m_sampler, march_result.position / 5.0, march_result.normal, 10.0); let metallic = metallic_roughness.x; let roughness = metallic_roughness.y; @@ -57,12 +60,12 @@ fn fs_main( let radiance = light_intensity / dot(light_position, light_position); let reflected = BRDF( - light_direction, normal, view, + light_direction, march_result.normal, view, albedo, metallic, roughness ); lum = lum + (radiance * reflected); } - return vec4(lum, 1.0); + return vec4(lum * march_result.mask, 1.0); } diff --git a/src/shaders/raymarch.wgsl b/src/shaders/raymarch.wgsl new file mode 100644 index 0000000..ee60c3b --- /dev/null +++ b/src/shaders/raymarch.wgsl @@ -0,0 +1,56 @@ +struct MarchResult { + position: vec3; + normal: vec3; + mask: f32; +}; + +fn sdf_sphere(pos: vec3, origin: vec3, radius: f32) -> f32 { + return length(pos - origin) - radius; +} + +fn sdf(pos: vec3) -> f32 { + let a = sdf_sphere(pos, vec3(-5.0, -5.0, 2.0), 3.5); + let b = sdf_sphere(pos, vec3(8.0, 0.0, -1.0), 3.5); + let c = sdf_sphere(pos, vec3(1.0, 5.0, -3.0), 3.5); + return min(min(a, b), c); +} + +fn sdf_normal(pos: vec3) -> vec3 { + let h = 0.0001; + let k = vec2(1.0, -1.0); + return normalize(k.xyy * sdf(pos + (k.xyy * h)) + k.yyx * sdf(pos + (k.yyx * h)) + k.yxy * sdf(pos + (k.yxy * h)) + k.xxx * sdf(pos + (k.xxx * h))); +} + +fn Raymarch(cam_pos: vec3, ray_dir: vec3) -> MarchResult { + let max_steps = 100; + let max_dist = 10000.0; + let epsilon = 0.0001; + + var depth = 0.0; + var pos = vec3(0.0, 0.0, 0.0); + var mask = 1.0; + + var i = 0; + loop { + pos = cam_pos + (ray_dir * depth); + let dist = sdf(pos); + depth = depth + dist; + + if (dist <= epsilon) { + break; + } + + if (depth > max_dist) { + mask = 0.0; + break; + } + + i = i + 1; + } + + var out: MarchResult; + out.position = pos; + out.normal = sdf_normal(pos); + out.mask = mask; + return out; +} \ No newline at end of file