cyborg/src/shaders/raymarch.wgsl

56 lines
1.3 KiB
WebGPU Shading Language

struct MarchResult {
position: vec3<f32>;
normal: vec3<f32>;
mask: f32;
};
fn sdf_sphere(pos: vec3<f32>, origin: vec3<f32>, radius: f32) -> f32 {
return length(pos - origin) - radius;
}
fn sdf(pos: vec3<f32>) -> f32 {
let a = sdf_sphere(pos, vec3<f32>(-5.0, -5.0, 2.0), 3.5);
let b = sdf_sphere(pos, vec3<f32>(8.0, 0.0, -1.0), 3.5);
let c = sdf_sphere(pos, vec3<f32>(1.0, 5.0, -3.0), 3.5);
return min(min(a, b), c);
}
fn sdf_normal(pos: vec3<f32>) -> vec3<f32> {
let h = 0.0001;
let k = vec2<f32>(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<f32>, ray_dir: vec3<f32>) -> MarchResult {
let max_steps = 100;
let max_dist = 10000.0;
let epsilon = 0.0001;
var depth = 0.0;
var pos = vec3<f32>(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;
}