Skip to main content

RayD: Dr.Jit-native GPU primitives for differentiable ray geometry and multipath simulation.

Project description

RayD

PyPI Downloads Code Size Total Lines License

RayD is a Dr.Jit-native GPU library for differentiable ray geometry and multipath simulation primitives built on OptiX.

pip install rayd

RayD is not a full renderer. It exposes low-level scene, ray, edge, visibility, and reflection-path queries for building custom renderers, RF simulators, acoustic tools, and inverse-design systems without adopting a material-light-integrator framework.

Scope

RayD focuses on geometry and wave-propagation primitives:

  • differentiable ray-mesh intersection
  • scene-level GPU acceleration through OptiX
  • nearest-edge queries through a scene-global edge BVH
  • primary-edge sampling support for edge-based gradient terms
  • segment visibility and multipath reflection primitives
  • Dr.Jit arrays and Dr.Jit autodiff as the public Python API

RayD intentionally does not provide:

  • a material or BSDF system
  • emitters
  • integrators
  • scene loading
  • image I/O
  • a complete path-tracing runtime
  • alternate Python frontend wrappers

Why RayD?

RayD is for users who need fast differentiable geometry queries, but do not want a full rendering framework.

Mitsuba is excellent for physically based rendering, but it can be too high-level when the main workload is RF propagation, acoustics, sonar, visibility analysis, or custom wave simulation. In those settings, direct control over ray-scene queries, edge queries, reflection paths, and geometry gradients is often more useful than a complete renderer.

RayD keeps the API surface small: meshes, scenes, rays, intersections, edges, and multipath query results.

Core API

  • Mesh: triangle geometry, transforms, UVs, and edge topology
  • Scene: a container of meshes plus OptiX acceleration structures
  • scene.intersect(ray): differentiable ray-mesh intersection
  • scene.shadow_test(ray): occlusion testing
  • scene.nearest_edge(query): nearest-edge queries for points and rays
  • scene.set_edge_mask(mask) / scene.edge_mask(): scene-global filtering for secondary-edge queries
  • scene.trace_reflections(...): specular reflection-path tracing
  • scene.visible(...): batched segment visibility queries
  • scene.trace_refl_epc(...): equivalent-path correction primitives for reflection paths
  • scene.accum_dfr_direct(...) / scene.accum_dfr(...): native diffraction grid accumulation
  • scene.trace_dfr_paths(...): compact native first-order diffraction path export

Feature Overview

Each core query, what it computes, its input/output, and how it behaves under Dr.Jit autodiff (AD):

API What it computes Input -> Output AD
scene.intersect(ray) Closest-hit ray-mesh intersection rays -> Intersection (t, point, normal, uv, ids) AD
scene.shadow_test(ray) Any-hit occlusion test rays -> boolean mask Boolean
scene.nearest_edge(point) Nearest scene edge to each point points -> NearestPointEdge (distance, points, edge id) AD
scene.nearest_edge(ray) Nearest scene edge to each ray (segment on [0, tmax] when tmax is finite) rays -> NearestRayEdge AD
scene.nearest_edges(point, k) k nearest scene edges per point (k <= 16) points -> NearestEdgesTopK AD
scene.visible(start, end) Mutual visibility between two segment endpoints endpoints -> SegmentVisibility Boolean
scene.visible_pair / visible_chain / visible_edge Shared-origin pair, polyline-chain, and edge-sample visibility segments -> segment/chain/edge visibility Boolean
scene.trace_reflections(ray, max_bounces) Specular reflection paths with image sources rays -> ReflectionChain (hit points, normals, image sources, ids) AD
scene.trace_refl_epc(ray, receiver, ...) Equivalent-path-correction reflection toward a receiver rays + receiver -> ReflEpc Detached
scene.trace_refl_epc_field(tx, receiver, ...) EPC trace returning the complex reflected field tx position + receiver + ReflEpcFieldOptions(AD) -> ReflEpcField (complex E-field) Native AD
scene.accumulate_reflections(...) Accumulate reflected field/power onto a grid rays + grid + material -> AccumResult Native AD
scene.accum_dfr_direct(...) Native direct/Keller/suffix diffraction accumulation onto a grid DfrStates + DfrGrid + DfrMaterial -> DfrAccum Native AD for direct, Keller, and suffix-reflection order-1, including suffix reflector mesh-vertex gradients; detached for unsupported AD strategies
scene.accum_dfr(...) Native order-2/3 diffraction-chain accumulation onto a grid initial/recursive DfrStates + grid + material -> DfrAccum Native AD for direct, Keller, and suffix-reflection order-2/3 chains, including suffix reflector mesh-vertex gradients
scene.trace_dfr_paths(...) Compact first-order diffraction path export tx/rx + DfrStates + DfrMaterial -> DfrPaths AD

AD legend:

  • AD - differentiable geometry: geometric outputs carry Dr.Jit gradients with respect to mesh vertices and transforms; the discrete hit/edge/path selection runs detached.
  • Native AD - the native RayD multipath implementation preserves Dr.Jit gradients for continuous inputs passed as AD arrays and supplies RayD-side derivative code. Diffraction grid accumulation uses CUDA custom-op JVP/VJP over a fixed OptiX forward tape for direct, Keller, and suffix-reflection order-1 and order-2/3 chain accumulation. Discrete visibility/path-selection decisions remain detached.
  • Boolean - returns occlusion/visibility booleans and is not differentiable.
  • Detached - native fast path: runs detached only and rejects AD inputs.

Trace vs. accum:

  • trace_* APIs enumerate geometric or field paths and return per-ray/per-path records. They do not reduce contributions into receiver grids.
  • accum_* APIs launch native accumulation kernels that reduce contributions into aggregate outputs, usually grid cells, with atomic or tiled writes. They are the high-throughput path for radiomap-style workloads when individual path records are not needed.

Minimal Example

The example below traces one ray against one triangle and backpropagates the hit distance to the vertex positions.

import drjit as dr
import rayd as rd


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]),
)

verts = dr.cuda.ad.Array3f(
    [0.0, 1.0, 0.0],
    [0.0, 0.0, 1.0],
    [0.0, 0.0, 0.0],
)
dr.enable_grad(verts)
mesh.vertex_positions = verts

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

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)
loss = dr.sum(its.t)
dr.backward(loss)

print("t =", its.t)
print("grad z =", dr.grad(verts)[2])

Edge Queries

RayD provides a scene-level edge acceleration structure for nearest-edge and edge-sampling workloads.

This is useful for:

  • edge sampling
  • nearest-edge queries
  • visibility-boundary terms
  • geometric diffraction models

Scene.set_edge_mask(mask) filters the secondary-edge BVH in scene-global edge index space. It does not modify scene.edge_info(), scene.edge_topology(), or scene.mesh_edge_offsets().

Multipath Queries

RayD includes low-level reflection and visibility primitives for custom wave simulators:

  • trace_reflections(...) for specular reflection chains
  • visible(...), visible_pair(...), visible_chain(...), and visible_edge(...) for segment and polyline-chain visibility
  • trace_refl_epc(...) and trace_refl_epc_field(...) for equivalent-path correction workflows
  • accumulate_reflections(...) for reflection grid accumulation workloads
  • accum_dfr_direct(...), accum_dfr(...), trace_dfr_paths(...) for native diffraction kernels

These APIs expose primitives, not a complete propagation simulator. Callers own the source model, receiver model, material policy, objective, and optimization loop.

Naming rule: use Dfr for diffraction (DfrStates, DfrAccum, accum_dfr_direct), Refl for reflection-specific short names, keep Epc in equivalent-path-correction APIs, and reserve AD for automatic differentiation. See API_NAMING_STANDARD.md.

Examples

Performance

The chart below was generated on March 25, 2026 on an NVIDIA GeForce RTX 5080 and AMD Ryzen 7 9800X3D, comparing RayD (0.1.2) against Mitsuba 3.8.0 with the cuda_ad_rgb variant.

Raw benchmark data is stored in docs/performance_benchmark.json.

  • RayD is consistently faster on static forward and static gradient workloads across all three scene sizes.
  • Dynamic reduced forward reaches parity or better from the medium scene onward, and dynamic full is effectively tied on the largest case.
  • On the largest 192x192 mesh / 384x384 ray benchmark, RayD vs Mitsuba average latency in milliseconds is: static full 0.162 vs 0.190, static reduced 0.124 vs 0.224, dynamic full 0.741 vs 0.740, dynamic reduced 0.689 vs 0.714, gradient static 0.411 vs 0.757, gradient dynamic 1.324 vs 1.413.
  • Correctness stayed aligned throughout the sweep: forward mismatch counts remained 0, and the largest static gradient discrepancy was 9.54e-7.

RayD vs Mitsuba performance benchmark

Device Selection

RayD follows Dr.Jit's current-thread CUDA device selection. Choose a GPU before constructing RayD resources:

import rayd as rd

rd.set_device(0)

Existing RayD scenes, OptiX pipelines, and BVHs should not be reused across device switches in the same process.

Building Locally

RayD is a Python package with a C++/CUDA extension.

You need Python >=3.10, CUDA Toolkit >=11.0, CMake, a C++17 compiler, drjit==1.3.1, nanobind==2.9.2, and scikit-build-core.

On Windows, use Visual Studio 2022 with Desktop C++ tools. On Linux, use GCC or Clang with C++17 support.

Recommended environment:

conda create -n myenv python=3.10 -y
conda activate myenv
python -m pip install -U pip setuptools wheel
python -m pip install cmake scikit-build-core nanobind==2.9.2
python -m pip install drjit==1.3.1

Install from the repository root:

python -m pip install .

For editable development builds:

python -m pip install --no-build-isolation -ve .

Repository Layout

Testing

python -m unittest tests.drjit.test_geometry -v
python -m unittest tests.drjit.test_visibility_topk -v
python -m unittest tests.drjit.test_reflection_epc -v
python -m unittest tests.drjit.test_reflection_accumulation -v
python -m unittest tests.test_project_metadata -v

The default development environment used by this repository is:

conda activate witwin3

Credits

RayD is developed with reference to:

Citation

@inproceedings{chen2026rfdt,
  title     = {Physically Accurate Differentiable Inverse Rendering
               for Radio Frequency Digital Twin},
  author    = {Chen, Xingyu and Zhang, Xinyu and Zheng, Kai and
               Fang, Xinmin and Li, Tzu-Mao and Lu, Chris Xiaoxuan
               and Li, Zhengxiong},
  booktitle = {Proceedings of the 32nd Annual International Conference
               on Mobile Computing and Networking (MobiCom)},
  year      = {2026},
  doi       = {10.1145/3795866.3796686},
  publisher = {ACM},
  address   = {Austin, TX, USA},
}

License

BSD 3-Clause. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

rayd-0.5.0.tar.gz (2.5 MB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

rayd-0.5.0-cp313-cp313-win_amd64.whl (7.5 MB view details)

Uploaded CPython 3.13Windows x86-64

rayd-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

rayd-0.5.0-cp312-cp312-win_amd64.whl (7.5 MB view details)

Uploaded CPython 3.12Windows x86-64

rayd-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.0 MB view details)

Uploaded CPython 3.12manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

rayd-0.5.0-cp311-cp311-win_amd64.whl (7.5 MB view details)

Uploaded CPython 3.11Windows x86-64

rayd-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.0 MB view details)

Uploaded CPython 3.11manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

rayd-0.5.0-cp310-cp310-win_amd64.whl (7.5 MB view details)

Uploaded CPython 3.10Windows x86-64

rayd-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl (6.0 MB view details)

Uploaded CPython 3.10manylinux: glibc 2.27+ x86-64manylinux: glibc 2.28+ x86-64

File details

Details for the file rayd-0.5.0.tar.gz.

File metadata

  • Download URL: rayd-0.5.0.tar.gz
  • Upload date:
  • Size: 2.5 MB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rayd-0.5.0.tar.gz
Algorithm Hash digest
SHA256 e3578fbfb3a6fe861046829b99a34f0e9157c65acf5eca19b675b39a123aac43
MD5 c812f887751fd7782c72ee563964d102
BLAKE2b-256 799f26476cb30efd22f4a4d6723e9c25d9903548415f41891b76c59974af50ce

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0.tar.gz:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: rayd-0.5.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 7.5 MB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rayd-0.5.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 01e2830e78b96a4a9b86e42d51178ee3a084e9a4beee6044bc275518f783a0cb
MD5 f8a8be2a184993457a7af4eb903e87cb
BLAKE2b-256 09567f40047fa1ef20d987365884507b18d59ecf337b6de69585d08230d4de73

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp313-cp313-win_amd64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rayd-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 f74b331f7563baa9b9f875a2427d4965f46a410b78e9714274afef0dfe7219ee
MD5 9d430626169dac5e015996d491dbd46f
BLAKE2b-256 f841850402b25aa18acc2ebc07b9065d42cea8043b3b1bd5c45efcfbc2cd36fa

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: rayd-0.5.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 7.5 MB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rayd-0.5.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 522b3a6807030f04634c8b2d975cd31c2dc65e2d10c3cbfc7d8707fd930da70e
MD5 5ac16ff642c2efd95391ada3a8d8d93f
BLAKE2b-256 9ca4218bfa10fdc8c7d31b5fdb8cea71c8191b7a5650f82aecc1538048d74d38

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp312-cp312-win_amd64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rayd-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1b7cc1860c55ed3c08e15139af3a1582c035eaefeb2588e44e27e51dfd21e076
MD5 a650000dd81ad48dab615c2c4626e9d9
BLAKE2b-256 42a624b06470b5108f7ed3bf2e2710447cd133954b087428d926bd81805c5c4d

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: rayd-0.5.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 7.5 MB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rayd-0.5.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 1e31f37ade987d728ac542d2ee164f6bb549907b2ff6372428406529194950d1
MD5 33875e4f0d25fee6215b8126e85588bd
BLAKE2b-256 3d4dba6990e60644af76e06d2d3423471f06e79a4893d85bc01ac8b58c3dbbc7

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp311-cp311-win_amd64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rayd-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 ee350e7f71884f6c5c92d352d1a0cd43b63f2cb8d10bf2995a9de012d1ef8419
MD5 98cf1834736dbb9fb29e5bd02ff663e7
BLAKE2b-256 f979428a6973d0ccd8f28ae2a046b53af5fa690ddfde9f794be2b98338b85342

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: rayd-0.5.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 7.5 MB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for rayd-0.5.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 891a67f1d259bd0cf04369ddaeb4e3fe8b0677c7447f20c26cef8b789e9b5aae
MD5 6bf794012241bc4ccdca4d0b75d8b0dd
BLAKE2b-256 a0d758975b55c8528b14f579042f548fd512984f11f8224afdbf52d9b4e1228f

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp310-cp310-win_amd64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file rayd-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for rayd-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 1ac4e5d9c466a6d8ed3316b0ba77d229f02c127776f5776f7d1f54144b4b7473
MD5 6a68c53090fb4c4c2259f867d88d2156
BLAKE2b-256 30cc6e8a63d2605a4b1e8b85baa9c8316ca5cb3db2813969c731f0fe5164e700

See more details on using hashes here.

Provenance

The following attestation bundles were made for rayd-0.5.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl:

Publisher: pypi.yml on Asixa/RayD

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page