Crafter.Graphics/examples/RTVolume/intersection.wgsl

33 lines
1.3 KiB
WebGPU Shading Language
Raw Permalink Normal View History

// RTVolume intersection shader (runs in TRACE, per AABB the ray enters).
// Analytic ray-sphere test: the unit box [-1,1]^3 is treated as the
// bounding volume of a sphere of radius 1 centred at the box centre. The
// ray is in object space and is NOT normalised (it is worldToObject *
// worldRay), so the returned t is directly comparable to the world-space
// ray parameter the tracer commits — solve the quadratic with the general
// a = dot(d,d) form rather than assuming |d| == 1.
fn intersection_main(ray: RayDesc, aabbMin: vec3<f32>, aabbMax: vec3<f32>,
primitiveId: u32) -> IntersectionResult {
var r: IntersectionResult;
r.hit = false;
let center = (aabbMin + aabbMax) * 0.5;
let radius = (aabbMax.x - aabbMin.x) * 0.5;
let oc = ray.origin - center;
let a = dot(ray.direction, ray.direction);
let b = 2.0 * dot(oc, ray.direction);
let c = dot(oc, oc) - radius * radius;
let disc = b * b - 4.0 * a * c;
if (disc < 0.0) { return r; }
let sq = sqrt(disc);
var t = (-b - sq) / (2.0 * a); // near root
if (t < ray.tMin) { t = (-b + sq) / (2.0 * a); } // fall back to far root
if (t < ray.tMin || t > ray.tMax) { return r; }
r.hit = true;
r.t = t;
r.attribs = vec2<f32>(0.0);
r.hitKind = 0u;
return r;
}