// 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, aabbMax: vec3, 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(0.0); r.hitKind = 0u; return r; }