Scene (Dr.Jit)
rayd.drjit.Scene - building and updating a triangle scene, ray intersection, shadow tests, edge queries, visibility, and topology inspection.
rayd.drjit.Scene holds meshes and the acceleration structures that answer queries over them. This page lists its construction, lifecycle, inspection, ray, edge, and visibility methods. The reflection and diffraction methods are on Reflection and Diffraction.
Every query method has a detached overload (taking Ray, drjit.cuda arrays) and a differentiable one (taking RayAD, drjit.cuda.ad arrays). The result type follows: Intersection or IntersectionAD, and so on. active is a per-lane mask, or True for all lanes.
Scene#
Scene(edge_bvh_backend: str = "auto", trace_backend: str = "auto")'auto'Edge query backend: "auto", "optix", "drjit", or "optix_drjit" (point and top-k queries on the Dr.Jit BVH, ray queries on OptiX). "auto" picks OptiX when available.
'auto'Triangle trace backend: "auto", "optix", "cuda", or "none" (no triangle structure, edge queries only). "auto" picks OptiX when the driver accepts an OptiX context, else CUDA.
Raises RuntimeError at build() when an explicitly requested backend is unavailable.
See Scene build and sync.
Building and updating#
add_mesh#
add_mesh(mesh: Mesh, dynamic: bool = False) -> intAdds a copy of mesh and returns its mesh id (0, 1, 2, ... in call order). A mesh added to a built scene invalidates it until the next build().
The mesh to add.
FalseAllow update_mesh_vertices and the transform setters after build(). Static meshes get a faster acceleration structure.
add_instance#
add_instance(geometry_id: int, transform: drjit.cuda.ad.Matrix4f, dynamic: bool = True) -> intAdds a transformed copy of an existing static mesh that shares its geometry, and returns the new shape id.
Id of a static mesh added with add_mesh. Dynamic meshes and other instances cannot be instanced.
Instance-to-world transform, column vectors.
TrueAllow transform updates with set_mesh_transform after build(). Vertices of an instance cannot change.
build#
build() -> NoneBuilds the triangle acceleration structure and the edge BVH. Required before any query and after adding geometry.
update_mesh_vertices#
update_mesh_vertices(mesh_id: int, positions: drjit.cuda.ad.Array3f) -> NoneQueues new object-space positions for a dynamic mesh. The vertex count must stay the same. AD positions make the following queries differentiable with respect to them.
Raises RuntimeError ("target mesh is not dynamic") for a static mesh.
set_mesh_transform#
set_mesh_transform(mesh_id: int, mat: drjit.cuda.ad.Matrix4f, set_left: bool = True) -> NoneQueues a replacement of the left (or right) transform factor of a dynamic mesh or instance.
append_mesh_transform#
append_mesh_transform(mesh_id: int, mat: drjit.cuda.ad.Matrix4f, append_left: bool = True) -> NoneQueues a multiplication of mat onto the left (or right) transform factor.
set_edge_mask#
set_edge_mask(mask: drjit.cuda.Bool | drjit.cuda.ad.Bool) -> NoneQueues an edge mask: one entry per scene-global edge, False hides the edge from edge queries. Ids and offsets do not change. edge_mask() returns the current mask.
sync#
sync() -> NoneApplies all queued updates by refitting the affected structures in place. Edge queries raise "scene has pending updates. Call Scene::sync() first." until you call it.
is_ready, has_pending_updates#
is_ready() -> bool
has_pending_updates() -> boolis_ready() is True after a successful build(). has_pending_updates() is True between a queued update and sync().
Properties#
| Property | Meaning |
|---|---|
num_meshes | number of meshes and instances |
version | increases with every build or geometry sync |
edge_version | increases when the edge set or mask changes |
edge_bvh_backend | resolved edge backend name |
last_sync_profile | SceneSyncProfile of the last sync(): stage timings in milliseconds and counts of updated meshes and edges |
Inspection#
| Method | Returns |
|---|---|
trace_backend_name() -> str | resolved trace backend: "optix", "cuda", or "none" |
capabilities() -> dict | resolved backends, integration modes, and per-operation availability |
mesh_face_offsets() -> Int | prefix sums of face counts per mesh |
mesh_edge_offsets() -> Int | prefix sums of edge counts per mesh |
mesh_vertex_offsets() -> Int | prefix sums of vertex counts per mesh |
global_geometry() -> SceneGeometry | all world-space vertices, faces, face normals, and ids |
edge_info() -> SceneEdgeInfo | geometry of every global edge |
edge_topology() -> SceneEdgeTopology | vertex, face, and opposite-vertex ids of every global edge |
edge_bvh_stats() -> SceneEdgeBVHStats | edge BVH size, height, leaf sizes, and overlap (meaningful for the "drjit" edge backend) |
edge_mask() -> Bool | the current edge mask |
triangle_edge_indices#
triangle_edge_indices(prim_id: drjit.cuda.Int, global_: bool = True) -> tupleReturns the three edge ids of each triangle as a 3-tuple of Int. With global_=True, both prim_id and the returned ids are scene-global.
edge_adjacent_faces#
edge_adjacent_faces(edge_id: drjit.cuda.Int, global_: bool = True) -> tupleReturns the two adjacent face ids of each edge as a 2-tuple of Int; -1 marks a missing face.
print(scene.capabilities()["trace_backend"]) # 'optix'
print(scene.mesh_face_offsets()) # [0, 2, 4] for two quadsRay queries#
intersect#
intersect(ray: Ray, active: Bool = True, flags: RayFlags = RayFlags.All) -> Intersection
intersect(ray: RayAD, active: ad.Bool = True, flags: RayFlags = RayFlags.All) -> IntersectionADFinds the closest hit of each ray within [0, ray.tmax].
The rays. A RayAD returns a differentiable result.
TrueLane mask. Inactive lanes return a miss.
RayFlags.AllWhich fields to compute. See RayFlags.
Returns an Intersection. A miss has t = inf and ids of -1.
hit = scene.intersect(rd.Ray(origins, directions))
mask = hit.is_valid()shadow_test#
shadow_test(ray: Ray | RayAD, active: Bool = True) -> BoolReturns True for each ray that hits any triangle within [0, ray.tmax]. Cheaper than intersect; it has no gradient.
Edge queries#
nearest_edge#
nearest_edge(point: Array3f, active: Bool = True) -> NearestPointEdge
nearest_edge(ray: Ray, active: Bool = True) -> NearestRayEdgeFinds the closest enabled edge to each point, or to each ray (a segment when tmax is finite). AD inputs return the ...AD record.
Query points. Use the ray overload to query by ray instead.
TrueLane mask.
Returns a NearestPointEdge or NearestRayEdge.
Raises RuntimeError when the scene has pending updates.
nearest_edges#
nearest_edges(point: Array3f, k: int, active: Bool = True) -> NearestEdgesTopKFinds up to k nearest edges per point, nearest first.
Query points.
Edges per point, from 1 to 16.
TrueLane mask.
Returns a NearestEdgesTopK with query_count * k flat entries; entry q * k + j is the j-th edge of query q.
Visibility#
All visibility queries return masks without gradients. Hits at segment endpoints are not counted.
visible#
visible(start: Array3f, end: Array3f, ignore_prim_ids: Int = [], active: Bool = True) -> SegmentVisibilityTests whether each segment from start to end is unobstructed.
Segment starts.
Segment ends.
[]Global primitive ids to ignore, K per segment, so the width is a multiple of the segment count. Pad with -1.
TrueLane mask.
Returns SegmentVisibility with visible and ray_count.
visible_pair#
visible_pair(start: Array3f, end_a: Array3f, end_b: Array3f, ignore_prim_ids: Int = [], active: Bool = True) -> SegmentPairVisibilityTests two segments that share a start point in one pass. Returns visible_a, visible_b, and ray_count.
visible_edge#
visible_edge(
src: Array3f,
edge_pos: Array3f,
edge_dir: Array3f,
edge_t_min: Float,
edge_t_max: Float,
sample_fractions: Sequence[float] = [0.0, 0.25, 0.5, 0.75, 1.0],
active: Bool = True,
) -> AxialEdgeVisibilityTests whether src sees any sample point on the edge segment edge_pos + t * edge_dir, sampled at sample_fractions of [edge_t_min, edge_t_max]. Returns any_visible and state_count.
visible_chain#
visible_chain(points: Array3f, chain_length: Int, ignore_prim_per_segment: Int = [], active: Bool = True) -> SegmentChainVisibilityTests polylines. Each chain stores up to P points flat, padded to the longest chain.
Chain points, chain_count * P entries.
Number of points in each chain. A chain of n points has n - 1 segments.
[]Primitive ids to ignore per segment; the width is a multiple of chain_count * max_segments.
TrueChain mask.
Returns SegmentChainVisibility with all_visible, first_blocked_segment, first_blocked_prim (-1 when clear), chain_count, and max_segments.