Intersection

Ray-mesh intersection queries in RayD

Overview#

scene.intersect() traces rays against the scene BVH and returns an Intersection (or IntersectionAD for AD inputs) with hit geometry data.

its = scene.intersect(rays)
 
if its.is_valid():
    print("hit at t =", its.t)
    print("hit point =", its.p)
    print("normal =", its.n)

scene.intersect()#

scene.intersect(ray, active=True, flags=RayFlags.All)
ParameterTypeDescription
rayRay or RayADBatch of rays to trace
activeMask or MaskADPer-ray active mask
flagsRayFlagsControls which intersection data is computed

Returns Intersection for Ray inputs, IntersectionAD for RayAD inputs.

Intersection fields#

FieldDescription
tHit distance along the ray
pHit point in world space
nShading normal
geo_nGeometric normal
uvUV coordinates at the hit point
barycentricBarycentric coordinates
shape_idIndex of the hit mesh
prim_idLocal primitive index within the hit mesh
local_prim_idLocal primitive index
global_prim_idGlobal primitive index across all meshes

its.is_valid() — Boolean mask indicating which rays hit something.

Ray#

rd.Ray(origin, direction)
FieldDescription
ray.oRay origin (Array3f)
ray.dRay direction (Array3f)
ray.tmaxMaximum hit distance. Default is infinity
ray = rd.Ray(
    dr.cuda.Array3f([0.0], [0.0], [-1.0]),
    dr.cuda.Array3f([0.0], [0.0], [1.0]),
)
ray.tmax = dr.cuda.Float(10.0)

ray.reversed() — Returns a new ray with the direction negated.

Shadow test#

scene.shadow_test() is an any-hit occlusion test. It returns a boolean mask and is faster than intersect() when you only need to know if something was hit.

scene.shadow_test(ray, active=True)

Returns Mask for Ray inputs, MaskAD for RayAD inputs.

Note

shadow_test() is not differentiable — it returns a boolean and discrete hit decisions are always detached.

AD Convention#

Pass RayAD to get differentiable outputs:

ray = rd.RayAD(
    dr.cuda.ad.Array3f([0.25], [0.25], [-1.0]),
    dr.cuda.ad.Array3f([0.0], [0.0], [1.0]),
)
its = scene.intersect(ray)  # returns IntersectionAD
loss = dr.sum(its.t)
dr.backward(loss)

Geometric outputs (t, p, n, geo_n) carry Dr.Jit gradients with respect to mesh vertices and transforms. Discrete selection (which triangle was hit) runs detached.

Next Steps#