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)| Parameter | Type | Description |
|---|---|---|
ray | Ray or RayAD | Batch of rays to trace |
active | Mask or MaskAD | Per-ray active mask |
flags | RayFlags | Controls which intersection data is computed |
Returns Intersection for Ray inputs, IntersectionAD for RayAD inputs.
Intersection fields#
| Field | Description |
|---|---|
t | Hit distance along the ray |
p | Hit point in world space |
n | Shading normal |
geo_n | Geometric normal |
uv | UV coordinates at the hit point |
barycentric | Barycentric coordinates |
shape_id | Index of the hit mesh |
prim_id | Local primitive index within the hit mesh |
local_prim_id | Local primitive index |
global_prim_id | Global primitive index across all meshes |
its.is_valid() — Boolean mask indicating which rays hit something.
Ray#
rd.Ray(origin, direction)| Field | Description |
|---|---|
ray.o | Ray origin (Array3f) |
ray.d | Ray direction (Array3f) |
ray.tmax | Maximum 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#
- Edge queries — nearest-edge and visibility queries
- Multipath — reflection path tracing