• Stars
    star
    1,019
  • Rank 45,159 (Top 0.9 %)
  • Language
    C++
  • License
    MIT License
  • Created about 9 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

NanoRT, single header only modern ray tracing kernel.

NanoRT, single header only modern ray tracing kernel.

Travis Build Status AppVeyor Build status

Path tracing example contributed by https://github.com/daseyb

NanoRT is simple single header only ray tracing kernel.

Features

  • Portable C++
  • BVH spatial data structure for efficient ray intersection finding.
    • Should be able to handle ~10M triangles scene efficiently with moderate memory consumption
  • Custom geometry & intersection
    • Built-in triangle mesh gemetry & intersector is provided.
  • Cross platform
    • MacOSX, Linux, Windows, iOS, Android, ARM, x86, SPARC, (maybe) MIPS, (will be) RISC-V, etc.
    • For example, NanoRT works finely on Raspberry Pi 2 (arm 32bit) and Raspberrry Pi 3!(AARCH64 kernel)
  • GPU efficient data structure
    • Built BVH tree from NanoRT is a linear array and does not have pointers, thus it is suited for GPU raytracing (GPU ray traversal).
  • OpenMP multithreaded BVH build.
  • Robust intersection calculation.
  • Double precision support
    • Beneficial for HPC and scientific visualization.

Applications

Projects using NanoRT

Projects similar/related to NanoRT

API

nanort::Ray represents ray. The origin org, the direction dir (not necessarily normalized), the minimum hit distance min_t(usually 0.0) and the maximum hit distance max_t (usually too far, e.g. 1.0e+30) must be filled before shooting ray.

nanort::BVHAccel builds BVH data structure from geometry, and provides the function to find intersection point for a given ray.

nanort::BVHBuildOptions specifies parameters for BVH build. Usually default parameters should work well.

nanort::BVHTraceOptions specifies ray traverse/intersection options.

template<typename T>
class {
  T org[3];        // [in] must set
  T dir[3];        // [in] must set
  T min_t;         // [in] must set
  T max_t;         // [in] must set
  unsigned int type;  // optional. ray type.
} Ray;

class BVHTraceOptions {
  // Trace rays only in face ids range. faceIdsRange[0] < faceIdsRange[1]
  // default: 0 to 0x3FFFFFFF(2G faces)
  unsigned int prim_ids_range[2];
  bool cull_back_face; // default: false
};

nanort::BVHBuildOptions<float> build_options; // BVH build option(optional)

const float *vertices = ...;
const unsigned int *faces = ...;

// Need to specify stride bytes for `vertices`.
// When vertex is stored XYZXYZXYZ... in float type, stride become 12(= sizeof(float) * 3).
nanort::TriangleMesh<float> triangle_mesh(vertices, faces, /* stride */sizeof(float) * 3);
nanort::TriangleSAHPred<float> triangle_pred(vertices, faces, /* stride */sizeof(float) * 3);

nanort::BVHAccel<float> accel;
ret = accel.Build(mesh.num_faces, triangle_mesh, triangle_pred, build_options);

nanort::TriangleIntersector<> triangle_intersecter(vertices, faces, /* stride */sizeof(float) * 3);

nanort::Ray<float> ray;
// fill ray org and ray dir.
...
// fill minimum and maximum hit distance.
ray.min_t = 0.0f;
ray.max_t = 1.0e+30f;

nanort::TriangleIntersection<float> isect;

// Store nearest hit point to `isect` and returns true if the hit point found.
BVHTraceOptions trace_options; // optional
bool hit = accel.Traverse(ray, triangle_intersecter, &isect, trace_options);

Application must prepare geometric information and store it in linear array.

For a builtin Triangle intersector,

  • vertices : The array of triangle vertices (e.g. xyz * numVertices)
  • faces : The array of triangle face indices (3 * numFaces)
  • stride : Byte stride of each vertex data

are required attributes.

Usage

// NanoRT defines template based class, so no NANORT_IMPLEMENTATION anymore.
#include "nanort.h"
Mesh mesh;
// load mesh data...
nanort::BVHBuildOptions<float> options; // Use default option
nanort::TriangleMesh<float> triangle_mesh(mesh.vertices, mesh.faces, /* stride */sizeof(float) * 3);
nanort::TriangleSAHPred<float> triangle_pred(mesh.vertices, mesh.faces, /* stride */sizeof(float) * 3);
nanort::BVHAccel<float> accel;
ret = accel.Build(mesh.vertices, mesh.faces, mesh.num_faces, options);
assert(ret);
nanort::BVHBuildStatistics stats = accel.GetStatistics();
printf("  BVH statistics:\n");
printf("    # of leaf   nodes: %d\n", stats.num_leaf_nodes);
printf("    # of branch nodes: %d\n", stats.num_branch_nodes);
printf("  Max tree depth   : %d\n", stats.max_tree_depth);

std::vector<float> rgb(width * height * 3, 0.0f);
const float tFar = 1.0e+30f;
// Shoot rays.
#ifdef _OPENMP
#pragma omp parallel for
#endif
for (int y = 0; y < height; y++) {
  for (int x = 0; x < width; x++) {
    BVHTraceOptions trace_options;
    // Simple camera. change eye pos and direction fit to .obj model.
    nanort::Ray<float> ray;
    ray.min_t = 0.0f;
    ray.max_t = tFar;
    ray.org[0] = 0.0f;
    ray.org[1] = 5.0f;
    ray.org[2] = 20.0f;
    float3 dir;
    dir[0] = (x / (float)width) - 0.5f;
    dir[1] = (y / (float)height) - 0.5f;
    dir[2] = -1.0f;
    dir.normalize();
    ray.dir[0] = dir[0];
    ray.dir[1] = dir[1];
    ray.dir[2] = dir[2];

    nanort::TriangleIntersector<> triangle_intersecter(mesh.vertices, mesh.faces, /* stride */sizeof(float) * 3);
    nanort::TriangleIntersection<> isect,
    bool hit = accel.Traverse(ray, triangle_intersector, &isect, trace_options);
    if (hit) {
      // Write your shader here.
      float3 normal;
      unsigned int fid = triangle_intersector.intersect.prim_id;
      normal[0] = mesh.facevarying_normals[3*3*fid+0]; // @todo { interpolate normal }
      normal[1] = mesh.facevarying_normals[3*3*fid+1];
      normal[2] = mesh.facevarying_normals[3*3*fid+2];
      // Flip Y
      rgb[3 * ((height - y - 1) * width + x) + 0] = fabsf(normal[0]);
      rgb[3 * ((height - y - 1) * width + x) + 1] = fabsf(normal[1]);
      rgb[3 * ((height - y - 1) * width + x) + 2] = fabsf(normal[2]);
    }
  }
}

Defines

NANORT_USE_CPP11_FEATURE : Enable C++11 feature
NANORT_ENABLE_PARALLEL_BUILD : Enable parallel BVH build(OpenMP version is not yet fully tested).

More example

See examples directory for example renderer using NanoRT.

Screenshots

Raytracing allows to implement different camera models quite easily. See examples/gui for different camera models which can be set via the config.json or the GUI itself:

  • perspective
  • orthographic
  • spherical FoV 120 & 180:
  • spherical-panorama FoV 120 & 180:
  • cylindrical: FoV 90 & 120:
  • fish-eye: FoV 120 & 180:
  • fish-eye MKX22: nonlinear fish-eye lens "iZugar MKX22 Fisheye Lens" with fixed FoV 220:

Custom geometry

Here is an example of custom geometry.

  • Spheres(particles) examples/particle_primitive/
  • Cubic Bezier Curves
    • Approximate as lines examples/curves_primitive/
    • Recursive Ray-Bezier intersection.
  • Cylinders examples/cylinder_primitive/

And plesae see API at wiki: https://github.com/lighttransport/nanort/wiki/API

License

nanort.h is licensed under MIT license.

NanoRT uses stack_container.h which is licensed under:

// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

NanoRT examples use some external third party libraries. Licenses for such third party libraries obey their own license.

Lucy statue model is from The Stanford 3D Scanning Repository http://graphics.stanford.edu/data/3Dscanrep/

TODO

PR are always welcome!

  • Optimize ray tracing kernel
  • Better cmake build.
  • Implement more Embree compatible API.
  • Scene graph support.
  • Fix multi-hit ray traversal.
  • Optimize Multi-hit ray traversal for BVH.
  • Ray traversal option.
    • FaceID range.
    • Double sided on/off.
    • Ray offset.
    • Avoid self-intersection(BVHTraceOptions.skip_prim_id).
    • Custom intersection filter through C++ template.
  • Fast BVH build
  • Efficient BVH build
    • Spatial split BVH
  • Motion blur
  • Fast, Accurate ray curve intersection
    • Phantom Ray-Hair Intersector
  • Example bi-directional path tracing renderer by @tatsy.

More Repositories

1

nanogi

A small, reference GI renderer
C++
153
star
2

nanostl

NanoSTL, a small subset of C++ STL and libm
C++
111
star
3

nnview

A neural network visualizer
C
90
star
4

colorcorrectionmatrix

Compute color correction matrix in python and C++
C++
86
star
5

prnet-infer

C++11 port of YadiraF's PRNet(inference only)
C
68
star
6

mallie

Mallie, bootstrap for your own ray tracer.
C
57
star
7

embree-aarch64

AARCH64 port of Embree ray tracing library
C++
47
star
8

softcompute

SoftCompute, CPU JIT execution of SPIR-V compute shader
C++
42
star
9

lighttransportequation-orb

Light Transport Equation Orb
40
star
10

pbrlab

`pbrlab` is well-verified(through brute force human verification and debugging) path tracing + PBR shading/rendering implementation.
C++
35
star
11

japanese-llama-experiment

Japanese LLaMa experiment
C
33
star
12

nanocsv

Multithreaded header only C++11 CSV parser
C
29
star
13

gltf-insight

C++11 based glTF 2.0 data insight tool
C
25
star
14

nanosnap

Nanoscale Signal, Noise and Audio Processing library in C++11
C
22
star
15

c-libtorch

Experimental C binding for libtorch
C++
15
star
16

lighttransportequation-glass

Light Transport Equation Glass
15
star
17

nanolog

Nanoscale logging library in C++11
C++
13
star
18

simple_vulkan

simple vulkan framework
C++
13
star
19

oclc

Simple OpenCL offline compiler
C++
13
star
20

VisemeNet-infer

CPU inference version of VisemeNet-tensorflow
Jupyter Notebook
11
star
21

vermeer-box

Vermeer box scene
11
star
22

tf-frozen2cc

TensorFlow frozen forward model to plain C++ converter
Python
10
star
23

francine

Highly scalable renderer backend
C++
10
star
24

procedural-eyeball-shader

Fully procedural GLSL eyeball shader
JavaScript
10
star
25

sss-model

Test model for subsurface scattering
9
star
26

mlspv

Machine Learning with SPIR-V(Experimental)
C
8
star
27

cpp-guidelines

Light Transport Entertainment's C/C++ coding guidelines
8
star
28

nanolibc

Nanoscale libc
C
7
star
29

kuroga

Kuroga, simple & single python file meta-build system for ninja
Python
7
star
30

obj2eson

Wavefront obj to ESON converter.
C++
7
star
31

tubular-cpp

Curves to tube mesh conversion in cpp
C++
6
star
32

rainbowmist

RainbowMist 🌈🌫️ is a simple C++ macro and template based unified compute kernel utility.
C++
5
star
33

ZoCap

C++
4
star
34

objlab

Simple wavefront .obj viewer
C
4
star
35

tinyvtkxml

Tiny VTK XML parser in C++.
C++
4
star
36

brdfview

C++
3
star
37

francine-ui

francine viewer
JavaScript
3
star
38

usd-fuzz

USD(USDA, USDC, USDZ) poc and regression files for fuzzing test
3
star
39

chainer2tflite

Chainer model to TensorFlow-Lite converter
3
star
40

rcopy-win

Windows port of rcopy from librdmacm
C
3
star
41

tinyplotlib

Tiny plotting library in C++11
3
star
42

jagger-python

Python binding for Jagger(C++ implementation of Pattern-based Japanese Morphological Analyzer)
C++
3
star
43

japanese-normalizer-cpp

Header-only Japanese Normalizer in C++11
C++
2
star
44

is

Interstellar: file sync utility for multiple remote servers with terabytes of files
Go
2
star
45

USD-android

Building USD(Universal Scene Description) on Android
C++
2
star
46

nanodenoise-example

GUI and other example codes for nanodenoise
2
star
47

nanozlib

Nanoscale secure zlib library
C
1
star
48

imagediffview

Image diff view in HTML.
JavaScript
1
star
49

simpleVK

C++
1
star
50

english-text-to-sequence

English text to sequence conversion in Python
Python
1
star