Skip to content

Latest commit

 

History

History
424 lines (305 loc) · 8.62 KB

File metadata and controls

424 lines (305 loc) · 8.62 KB

API Reference

This document describes the current public Python API exposed by rayd.

RayD also ships an optional parallel API under rayd.torch. It mirrors the same object model while using CUDA torch.Tensor inputs and outputs instead of Dr.Jit arrays.

Module Overview

RayD is a geometry-only differentiable ray-intersection package built on Dr.Jit and OptiX.

Public top-level exports:

  • Mesh
  • Scene
  • SceneSyncProfile
  • Camera
  • Ray
  • Intersection
  • NearestPointEdge
  • NearestRayEdge
  • PrimaryEdgeSample
  • SecondaryEdgeInfo

All array-valued inputs and outputs use Dr.Jit CUDA arrays or tensors.

For the optional rayd.torch module:

  • install with pip install "rayd[torch]"
  • all array inputs and outputs must be CUDA torch.Tensor
  • vectors use (N, 3) / (N, 2) layout
  • index tensors use (F, 3)
  • images use (H, W)
  • transforms use (4, 4)
  • CPU tensors are rejected instead of being moved implicitly

Type Conventions

AD mode is inferred automatically from the inputs:

  • if any input tensor carries gradient (requires_grad in torch, or dr.grad_enabled in Dr.Jit), the operation runs in AD mode
  • otherwise, the operation runs detached

Typical input types:

  • detached scalar/array types:
    • drjit.cuda.Float
    • drjit.cuda.Array2f
    • drjit.cuda.Array3f
    • drjit.cuda.Array3i
    • drjit.cuda.Matrix4f
  • differentiable types:
    • drjit.cuda.ad.Float
    • drjit.cuda.ad.Array2f
    • drjit.cuda.ad.Array3f
    • drjit.cuda.ad.Matrix4f
  • differentiable tensor output:
    • drjit.cuda.ad.TensorXf

Batched queries are represented by dynamic Dr.Jit arrays.

Mesh

Mesh stores triangle geometry, optional UVs, transforms, and precomputed edge data.

Construction:

mesh = rd.Mesh(v, f)
mesh = rd.Mesh(v, f, uv)
mesh = rd.Mesh(v, f, uv, f_uv)
mesh = rd.Mesh(v, f, uv, f_uv, verbose=True)

Parameters:

  • v: vertex positions, usually Array3f or ad.Array3f
  • f: triangle vertex indices, Array3i
  • uv: optional vertex UVs, Array2f
  • f_uv: optional UV indices, Array3i
  • verbose: print basic mesh loading statistics

Methods:

  • build()
    • builds derived geometry caches and GPU buffers
  • set_transform(mat, set_left=True)
  • append_transform(mat, append_left=True)
  • edge_indices()
    • returns a 5-tuple of integer arrays describing mesh edges
  • secondary_edges()
    • returns SecondaryEdgeInfo

Properties:

  • num_vertices
  • num_faces
  • to_world
  • to_world_left
  • to_world_right
  • vertex_positions
  • vertex_positions_world
  • vertex_normals
  • vertex_uv
  • face_indices
  • face_uv_indices
  • use_face_normals
  • edges_enabled

Notes:

  • call build() before adding the mesh to a scene if you want mesh-local caches immediately
  • Scene.build() will also build meshes added to that scene
  • updating geometry or transforms marks derived data dirty until rebuilt or synced through Scene

Scene

Scene owns meshes plus the OptiX and edge acceleration data used by queries.

Construction:

scene = rd.Scene()

Methods:

  • add_mesh(mesh, dynamic=False) -> int
    • adds a mesh and returns its scene-local mesh id
  • build()
    • builds scene-wide triangle and edge acceleration data
  • update_mesh_vertices(mesh_id, positions)
    • only valid for meshes added with dynamic=True
  • set_mesh_transform(mesh_id, mat, set_left=True)
  • append_mesh_transform(mesh_id, mat, append_left=True)
  • sync()
    • pushes pending dynamic mesh updates into scene acceleration structures
  • is_ready() -> bool
  • has_pending_updates() -> bool
  • intersect(ray, active=True) -> Intersection
  • nearest_edge(point, active=True) -> NearestPointEdge
  • nearest_edge(ray, active=True) -> NearestRayEdge

Properties:

  • num_meshes
  • last_sync_profile

Notes:

  • a scene must be built before queries
  • if has_pending_updates() is true, queries will raise until sync() is called
  • camera primary-edge caches are invalidated when the scene is rebuilt or synced

SceneSyncProfile

Timing and update counters from the last Scene.sync() call.

Fields:

  • mesh_update_ms
  • triangle_scatter_ms
  • triangle_eval_ms
  • optix_sync_ms
  • total_ms
  • optix_gas_update_ms
  • optix_ias_update_ms
  • updated_meshes
  • updated_vertex_meshes
  • updated_transform_meshes

Camera

Camera provides primary-ray sampling, primary-edge preparation, point-sampled depth rendering, and primary-edge gradient rendering.

Construction with horizontal FOV:

camera = rd.Camera.perspective(fov_x=45.0)
camera = rd.Camera(45.0, 1e-4, 1e4)          # positional form also accepted

Construction with calibrated intrinsics:

camera = rd.Camera.from_intrinsics(fx=100, fy=100, cx=64, cy=64)
camera = rd.Camera(fx, fy, cx, cy, 1e-4, 1e4)  # positional form also accepted

Methods:

  • build(cache=True)
    • rebuilds projection and world/sample transform caches
  • prepare_edges(scene)
    • preprocesses primary image-space edges for the current scene
  • sample_ray(sample) -> Ray
  • sample_edge(sample1) -> PrimaryEdgeSample
  • render(scene, background=0.0) -> TensorXf
    • point-sampled depth image
  • render_grad(scene, spp=4, background=0.0) -> TensorXf
    • primary-edge visibility gradient image
  • set_transform(mat, set_left=True)
  • append_transform(mat, append_left=True)

Properties:

  • width
  • height
  • to_world
  • to_world_left
  • to_world_right
  • camera_to_sample
  • sample_to_camera
  • world_to_sample
  • sample_to_world

Notes:

  • call build() after changing camera parameters or transforms
  • render_grad() depends on the camera鈥檚 primary-edge pipeline and is connected directly to the Dr.Jit AD graph
  • prepare_edges(scene) must be rerun after scene updates that affect visibility

Ray Types

Ray

Ray container. AD mode is inferred from whether any field carries gradient.

Fields:

  • o
  • d
  • tmax

Methods:

  • reversed()

Intersection Types

Intersection

Result of Scene.intersect(ray, ...).

Fields:

  • t
  • p
  • n
  • geo_n
  • uv
  • barycentric
  • shape_id
  • prim_id

Methods:

  • is_valid()

Nearest-Edge Types

NearestPointEdge

Result of Scene.nearest_edge(point, ...).

Fields:

  • distance
  • point
  • edge_t
  • edge_point
  • shape_id
  • edge_id
  • is_boundary

Methods:

  • is_valid()

Notes:

  • point is the original query point
  • edge_t is the closest-point parameter along the edge segment

NearestRayEdge

Result of Scene.nearest_edge(ray, ...).

Fields:

  • distance
  • ray_t
  • point
  • edge_t
  • edge_point
  • shape_id
  • edge_id
  • is_boundary

Methods:

  • is_valid()

Notes:

  • ray_t is the closest-point parameter along the query ray or finite ray segment
  • point is the closest point on the query ray

Edge Sampling Types

PrimaryEdgeSample

Result of Camera.sample_edge(sample1).

Fields:

  • x_dot_n
  • idx
  • ray_n
  • ray_p
  • pdf

Interpretation:

  • idx: flattened pixel index
  • ray_n and ray_p: primary rays on opposite sides of the sampled image-space edge
  • x_dot_n: signed boundary term
  • pdf: sampling density at the sampled edge point

SecondaryEdgeInfo

Per-edge geometric information precomputed on a mesh.

Fields:

  • start
  • edge
  • normal0
  • normal1
  • opposite
  • is_boundary

Methods:

  • size()

Interpretation:

  • start: first endpoint in world space
  • edge: edge vector, so the second endpoint is start + edge
  • normal0: face normal on one side
  • normal1: face normal on the opposite side
  • opposite: third vertex of the normal0 face

Minimal Examples

Ray Intersection

import rayd as rd
import drjit as dr

mesh = rd.Mesh(
    dr.cuda.Array3f([0.0, 1.0, 0.0],
                    [0.0, 0.0, 1.0],
                    [0.0, 0.0, 0.0]),
    dr.cuda.Array3i([0], [1], [2]),
)

scene = rd.Scene()
scene.add_mesh(mesh)
scene.build()

ray = rd.Ray(
    dr.cuda.Array3f([0.25], [0.25], [-1.0]),
    dr.cuda.Array3f([0.0], [0.0], [1.0]),
)

its = scene.intersect(ray)

Point Nearest-Edge Query

import rayd as rd
import drjit as dr

points = dr.cuda.Array3f([0.25], [0.1], [0.0])
edge = scene.nearest_edge(points)

Ray Nearest-Edge Query

import rayd as rd
import drjit as dr

ray = rd.Ray(
    dr.cuda.Array3f([0.2], [0.4], [1.0]),
    dr.cuda.Array3f([0.0], [0.0], [-1.0]),
)
ray.tmax = dr.cuda.Float([2.0])
edge = scene.nearest_edge(ray)

Depth Rendering

import rayd as rd

camera = rd.Camera.perspective(fov_x=45.0)
camera.width = 128
camera.height = 128
camera.build()

depth = camera.render(scene)

Primary-Edge Gradient Rendering

image = camera.render_grad(scene, spp=8)

This returns a TensorXf directly from the C++ extension.