Skip to content
master
Switch branches/tags
Code

Files

Permalink
Failed to load latest commit information.

README.md

% Embree: High Performance Ray Tracing Kernels 3.13.0-alpha.0 % Intel Corporation

Embree Overview

Intel® Embree is a collection of high-performance ray tracing kernels, developed at Intel. The target users of Intel® Embree are graphics application engineers who want to improve the performance of their photo-realistic rendering application by leveraging Embree's performance-optimized ray tracing kernels. The kernels are optimized for the latest Intel® processors with support for SSE, AVX, AVX2, and AVX-512 instructions. Intel® Embree supports runtime code selection to choose the traversal and build algorithms that best matches the instruction set of your CPU. We recommend using Intel® Embree through its API to get the highest benefit from future improvements. Intel® Embree is released as Open Source under the Apache 2.0 license.

Intel® Embree supports applications written with the Intel® SPMD Program Compiler (ISPC, https://ispc.github.io/) by also providing an ISPC interface to the core ray tracing algorithms. This makes it possible to write a renderer in ISPC that automatically vectorizes and leverages SSE, AVX, AVX2, and AVX-512 instructions. ISPC also supports runtime code selection, thus ISPC will select the best code path for your application.

Intel® Embree contains algorithms optimized for incoherent workloads (e.g. Monte Carlo ray tracing algorithms) and coherent workloads (e.g. primary visibility and hard shadow rays).

The single-ray traversal kernels of Intel® Embree provide high performance for incoherent workloads and are very easy to integrate into existing rendering applications. Using the stream kernels, even higher performance for incoherent rays is possible, but integration might require significant code changes to the application to use the stream paradigm. In general for coherent workloads, the stream mode with coherent flag set gives the best performance.

Intel® Embree also supports dynamic scenes by implementing high-performance two-level spatial index structure construction algorithms.

In addition to the ray tracing kernels, Intel® Embree provides some Embree Tutorials to demonstrate how to use the Embree API.

Supported Platforms

Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS (64-bit) both x86 and Apple M1 based. The code compiles with the Intel® Compiler, GCC, Clang, and the Microsoft Compiler.

Using the Intel® Compiler improves performance by approximately 10%. Performance also varies across different operating systems, with Linux typically performing best as it supports transparently transitioning to 2MB pages.

Embree is optimized for Intel CPUs supporting SSE, AVX, AVX2, and AVX-512 instructions. Embree requires at least an x86 CPU with support for SSE2 or an Apple M1 CPU. Embree Support and Contact

If you encounter bugs please report them via Embree's GitHub Issue Tracker.

For questions and feature requests please write us at embree_support@intel.com.

To receive notifications of updates and new features of Embree please subscribe to the Embree mailing list.

Installation of Embree

Windows MSI Installer

You can install the Embree library using the Windows MSI installer embree-3.13.0-alpha.0-x64.vc14.msi. This will install the 64-bit Embree version by default in Program Files\Intel\Embree3.

You have to set the path to the bin folders manually to your PATH environment variable for applications to find Embree.

To compile applications with Embree using CMake, please have a look at the find_embree tutorial. To compile this tutorial, you need to set the embree_DIR CMake variable of this tutorial to Program Files\Intel\Embree3.

To uninstall Embree, open Programs and Features by clicking the Start button, clicking Control Panel, clicking Programs, and then clicking Programs and Features. Select Embree 3.13.0-alpha.0 x64 and uninstall it.

Windows ZIP File

Embree linked against Visual Studio 2015 are provided as a ZIP file embree-3.13.0-alpha.0.x64.vc14.windows.zip. After unpacking this ZIP file, you should set the path to the lib folder manually to your PATH environment variable for applications to find Embree. To compile applications with Embree, you also have to set the Include Directories path in Visual Studio to the include folder of the Embree installation.

If you plan to ship Embree with your application, best use the Embree version from this ZIP file.

Linux tar.gz Files

The Linux version of Embree is also delivered as a tar.gz file: embree-3.13.0-alpha.0.x86_64.linux.tar.gz. Unpack this file using tar and source the provided embree-vars.sh (if you are using the bash shell) or embree-vars.csh (if you are using the C shell) to set up the environment properly:

tar xzf embree-3.13.0-alpha.0.x86_64.linux.tar.gz
source embree-3.13.0-alpha.0.x86_64.linux/embree-vars.sh

If you want to ship Embree with your application, best use the Embree version provided in the tar.gz file.

We recommend adding a relative RPATH to your application that points to the location where Embree (and TBB) can be found, e.g. $ORIGIN/../lib.

macOS PKG Installer

To install the Embree library on your macOS system use the provided package installer inside embree-3.13.0-alpha.0.x86_64.pkg. This will install Embree by default into /opt/local/lib and /opt/local/include directories. The Embree tutorials are installed into the /Applications/Embree3 directory.

You also have to install the Intel® Threading Building Blocks (TBB) using MacPorts:

sudo port install tbb

Alternatively you can download the latest TBB version from https://www.threadingbuildingblocks.org/download and set the DYLD_LIBRARY_PATH environment variable to point to the TBB library.

To uninstall Embree, execute the uninstaller script /Applications/Embree3/uninstall.command.

macOS ZIP file

The macOS version of Embree is also delivered as a ZIP file: embree-3.13.0-alpha.0.x86_64.macosx.zip. Unpack this file using tar and source the provided embree-vars.sh (if you are using the bash shell) or embree-vars.csh (if you are using the C shell) to set up the environment properly:

unzip embree-3.13.0-alpha.0.x64.macosx.zip
source embree-3.13.0-alpha.0.x64.macosx/embree-vars.sh

If you want to ship Embree with your application, please use the Embree library of the provided ZIP file. The library name of that Embree library is of the form @rpath/libembree.3.dylib (and similar also for the included TBB library). This ensures that you can add a relative RPATH to your application that points to the location where Embree (and TBB) can be found, e.g. @loader_path/../lib.

Compiling Embree

We recommend to use CMake to build Embree. Do not enable fast-math optimizations; these might break Embree.

Linux and macOS

To compile Embree you need a modern C++ compiler that supports C++11. Embree is tested with the following compilers:

Linux

  • Intel® Compiler 2020 Update 1
  • Intel® Compiler 2019 Update 4
  • Intel® Compiler 2017 Update 1
  • Intel® Compiler 2016 Update 3
  • Intel® Compiler 2015 Update 3
  • Clang 5.0.0
  • Clang 4.0.0
  • GCC 10.0.1 (Fedora 32) AVX512 support
  • GCC 8.3.1 (Fedora 28) AVX512 support
  • GCC 7.3.1 (Fedora 27) AVX2 support
  • GCC 7.3.1 (Fedora 26) AVX2 support
  • GCC 6.4.1 (Fedora 25) AVX2 support

macOS x86

  • Intel® Compiler 2020 Update 1
  • Intel® Compiler 2019 Update 4
  • Apple LLVM 10.0.1 (macOS 10.14.6)

macOS M1

  • Apple Clang 12.0.0

Embree supports using the Intel® Threading Building Blocks (TBB) as the tasking system. For performance and flexibility reasons we recommend to use Embree with the Intel® Threading Building Blocks (TBB) and best also use TBB inside your application. Optionally you can disable TBB in Embree through the EMBREE_TASKING_SYSTEM CMake variable.

Embree supports the Intel® SPMD Program Compiler (ISPC), which allows straightforward parallelization of an entire renderer. If you do not want to use ISPC then you can disable EMBREE_ISPC_SUPPORT in CMake. Otherwise, download and install the ISPC binaries (we have tested ISPC version 1.9.1) from ispc.github.io. After installation, put the path to ispc permanently into your PATH environment variable or you need to correctly set the ISPC_EXECUTABLE variable during CMake configuration.

You additionally have to install CMake 3.1.0 or higher and the developer version of GLUT.

Under macOS, all these dependencies can be installed using MacPorts:

sudo port install cmake tbb-devel glfw-devel

Depending on your Linux distribution you can install these dependencies using yum or apt-get. Some of these packages might already be installed or might have slightly different names.

Type the following to install the dependencies using yum:

sudo yum install cmake
sudo yum install tbb-devel
sudo yum install glfw-devel

Type the following to install the dependencies using apt-get:

sudo apt-get install cmake-curses-gui
sudo apt-get install libtbb-dev
sudo apt-get install libglfw3-dev

Finally you can compile Embree using CMake. Create a build directory inside the Embree root directory and execute ccmake .. inside this build directory.

mkdir build
cd build
ccmake ..

Per default CMake will use the compilers specified with the CC and CXX environment variables. Should you want to use a different compiler, run cmake first and set the CMAKE_CXX_COMPILER and CMAKE_C_COMPILER variables to the desired compiler. For example, to use the Intel® Compiler instead of the default GCC on most Linux machines (g++ and gcc), execute

cmake -DCMAKE_CXX_COMPILER=icpc -DCMAKE_C_COMPILER=icc ..

Similarly, to use Clang set the variables to clang++ and clang, respectively. Note that the compiler variables cannot be changed anymore after the first run of cmake or ccmake.

Running ccmake will open a dialog where you can perform various configurations as described below in [CMake Configuration]. After having configured Embree, press c (for configure) and g (for generate) to generate a Makefile and leave the configuration. The code can be compiled by executing make.

make

The executables will be generated inside the build folder. We recommend to finally install the Embree library and header files on your system. Therefore set the CMAKE_INSTALL_PREFIX to /usr in cmake and type:

sudo make install

If you keep the default CMAKE_INSTALL_PREFIX of /usr/local then you have to make sure the path /usr/local/lib is in your LD_LIBRARY_PATH.

You can also uninstall Embree again by executing:

sudo make uninstall

If you cannot install Embree on your system (e.g. when you don't have administrator rights) you need to add embree_root_directory/build to your LD_LIBRARY_PATH.

Windows

Embree is tested using the following compilers under Windows:

  • Visual Studio 2019
  • Visual Studio 2017
  • Visual Studio 2015 (Update 1)
  • Intel® Compiler 2019 Update 6
  • Intel® Compiler 2017 Update 8
  • LLVM Clang 9.0.0

To compile Embree for AVX-512 you have to use the Intel® Compiler.

Embree supports using the Intel® Threading Building Blocks (TBB) as the tasking system. For performance and flexibility reasons we recommend to use Embree with the Intel® Threading Building Blocks (TBB) and best also use TBB inside your application. Optionally you can disable TBB in Embree through the EMBREE_TASKING_SYSTEM CMake variable.

Embree will either find the Intel® Threading Building Blocks (TBB) installation that comes with the Intel® Compiler, or you can install the binary distribution of TBB directly from www.threadingbuildingblocks.org into a folder named tbb into your Embree root directory. You also have to make sure that the libraries tbb.dll and tbb_malloc.dll can be found when executing your Embree applications, e.g. by putting the path to these libraries into your PATH environment variable.

Embree supports the Intel® SPMD Program Compiler (ISPC), which allows straightforward parallelization of an entire renderer. When installing ISPC, make sure to download an ISPC version from ispc.github.io that is compatible with your Visual Studio version. After installation, put the path to ispc.exe permanently into your PATH environment variable or you need to correctly set the ISPC_EXECUTABLE variable during CMake configuration. If you do not want to use ISPC then you can disable EMBREE_ISPC_SUPPORT in CMake.

We have tested Embree with the following ISPC versions:

  • ISPC 1.14.1
  • ISPC 1.13.0
  • ISPC 1.12.0
  • ISPC 1.9.2

You additionally have to install CMake (version 2.8.11 or higher). Note that you need a native Windows CMake installation, because CMake under Cygwin cannot generate solution files for Visual Studio.

Using the IDE

Run cmake-gui, browse to the Embree sources, set the build directory and click Configure. Now you can select the Generator, e.g. "Visual Studio 12 2013" for a 32-bit build or "Visual Studio 12 2013 Win64" for a 64-bit build.

To use a different compiler than the Microsoft Visual C++ compiler, you additionally need to specify the proper compiler toolset through the option "Optional toolset to use (-T parameter)". E.g. to use Clang for compilation set the toolset to "LLVM_v142", to use the Intel® Compiler 2017 for compilation set the toolset to "Intel C++ Compiler 17.0".

Do not change the toolset manually in a solution file (neither through the project properties dialog, nor through the "Use Intel Compiler" project context menu), because then some compiler specific command line options cannot be set by CMake.

Most configuration parameters described in the [CMake Configuration] can be set under Windows as well. Finally, click "Generate" to create the Visual Studio solution files.

The following CMake options are only available under Windows:

  • CMAKE_CONFIGURATION_TYPE: List of generated configurations. Default value is Debug;Release;RelWithDebInfo.

  • USE_STATIC_RUNTIME: Use the static version of the C/C++ runtime library. This option is turned OFF by default.

Use the generated Visual Studio solution file embree2.sln to compile the project. To build Embree with support for the AVX2 instruction set you need at least Visual Studio 2013 (Update 4).

We recommend enabling syntax highlighting for the .ispc source and .isph header files. To do so open Visual Studio, go to Tools ⇒ Options ⇒ Text Editor ⇒ File Extension and add the isph and ispc extensions for the "Microsoft Visual C++" editor.

Using the Command Line

Embree can also be configured and built without the IDE using the Visual Studio command prompt:

cd path\to\embree
mkdir build
cd build
cmake -G "Visual Studio 12 2013 Win64" ..
cmake --build . --config Release

To use the Intel® Compiler, set the proper toolset, e.g. for Intel Compiler 17.0:

cmake -G "Visual Studio 12 2013 Win64" -T "Intel C++ Compiler 17.0" ..
cmake --build . --config Release

You can also build only some projects with the --target switch. Additional parameters after "--" will be passed to msbuild. For example, to build the Embree library in parallel use

cmake --build . --config Release --target embree -- /m

CMake Configuration

The default CMake configuration in the configuration dialog should be appropriate for most usages. The following list describes all parameters that can be configured in CMake:

  • CMAKE_BUILD_TYPE: Can be used to switch between Debug mode (Debug), Release mode (Release) (default), and Release mode with enabled assertions and debug symbols (RelWithDebInfo).

  • EMBREE_STACK_PROTECTOR: Enables protection of return address from buffer overwrites. This option is OFF by default.

  • EMBREE_ISPC_SUPPORT: Enables ISPC support of Embree. This option is ON by default.

  • EMBREE_STATIC_LIB: Builds Embree as a static library (OFF by default). Further multiple static libraries are generated for the different ISAs selected (e.g. embree3.a, embree3_sse42.a, embree3_avx.a, embree3_avx2.a, embree3_avx512.a). You have to link these libraries in exactly this order of increasing ISA.

  • EMBREE_API_NAMESPACE: Specifies a namespace name to put all Embree API symbols inside. By default no namespace is used and plain C symbols exported.

  • EMBREE_LIBRARY_NAME: Specifies the name of the Embree library file created. By default the name embree3 is used.

  • EMBREE_IGNORE_CMAKE_CXX_FLAGS: When enabled, Embree ignores default CMAKE_CXX_FLAGS. This option is turned ON by default.

  • EMBREE_TUTORIALS: Enables build of Embree tutorials (default ON).

  • EMBREE_BACKFACE_CULLING: Enables backface culling, i.e. only surfaces facing a ray can be hit. This option is turned OFF by default.

  • EMBREE_COMPACT_POLYS: Enables compact tris/quads, i.e. only geomIDs and primIDs are stored inside the leaf nodes.

  • EMBREE_FILTER_FUNCTION: Enables the intersection filter function feature (ON by default).

  • EMBREE_RAY_MASK: Enables the ray masking feature (OFF by default).

  • EMBREE_RAY_PACKETS: Enables ray packet traversal kernels. This feature is turned ON by default. When turned on packet traversal is used internally and packets passed to rtcIntersect4/8/16 are kept intact in callbacks (when the ISA of appropiate width is enabled).

  • EMBREE_IGNORE_INVALID_RAYS: Makes code robust against the risk of full-tree traversals caused by invalid rays (e.g. rays containing INF/NaN as origins). This option is turned OFF by default.

  • EMBREE_TASKING_SYSTEM: Chooses between Intel® Threading TBB Building Blocks (TBB), Parallel Patterns Library (PPL) (Windows only), or an internal tasking system (INTERNAL). By default TBB is used.

  • EMBREE_TBB_ROOT: If Intel® Threading TBB Building Blocks (TBB) is used as a tasking system, search the library in this directory tree.

  • EMBREE_TBB_POSTFIX: If Intel® Threading TBB Building Blocks (TBB) is used as a tasking system, link to tbb<EMBREE_TBB_POSTFIX>.(so,dll,lib). Defaults to the empty string.

  • EMBREE_TBB_DEBUG_ROOT: If Intel® Threading TBB Building Blocks (TBB) is used as a tasking system, search the library in this directory tree in Debug mode. Defaults to EMBREE_TBB_ROOT.

  • EMBREE_TBB_DEBUG_POSTFIX: If Intel® Threading TBB Building Blocks (TBB) is used as a tasking system, link to tbb<EMBREE_TBB_DEBUG_POSTFIX>.(so,dll,lib) in Debug mode. Defaults to "_debug".

  • EMBREE_MAX_ISA: Select highest supported ISA (SSE2, SSE4.2, AVX, AVX2, AVX512, or NONE). When set to NONE the EMBREE_ISA_* variables can be used to enable ISAs individually. By default the option is set to AVX2.

  • EMBREE_ISA_SSE2: Enables SSE2 when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF.

  • EMBREE_ISA_SSE42: Enables SSE4.2 when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF.

  • EMBREE_ISA_AVX: Enables AVX when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF.

  • EMBREE_ISA_AVX2: Enables AVX2 when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF.

  • EMBREE_ISA_AVX512: Enables AVX-512 for Skylake when EMBREE_MAX_ISA is set to NONE. By default this option is turned OFF.

  • EMBREE_GEOMETRY_TRIANGLE: Enables support for trianglegeometries (ON by default).

  • EMBREE_GEOMETRY_QUAD: Enables support for quad geometries (ON by default).

  • EMBREE_GEOMETRY_CURVE: Enables support for curve geometries (ON by default).

  • EMBREE_GEOMETRY_SUBDIVISION: Enables support for subdivision geometries (ON by default).

  • EMBREE_GEOMETRY_INSTANCE: Enables support for instances (ON by default).

  • EMBREE_GEOMETRY_USER: Enables support for user defined geometries (ON by default).

  • EMBREE_GEOMETRY_POINT: Enables support for point geometries (ON by default).

  • EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR: Specifies a factor that controls the self intersection avoidance feature for flat curves. Flat curve intersections which are closer than curve_radius*EMBREE_CURVE_SELF_INTERSECTION_AVOIDANCE_FACTOR to the ray origin are ignored. A value of 0.0f disables self intersection avoidance while 2.0f is the default value.

  • EMBREE_MIN_WIDTH: Enabled the min-width feature, which allows increasing the radius of curves and points to match some amount of pixels. See [rtcSetGeometryMaxRadiusScale] for more details.

  • EMBREE_MAX_INSTANCE_LEVEL_COUNT: Specifies the maximum number of nested instance levels. Should be greater than 0; the default value is 1. Instances nested any deeper than this value will silently disappear in release mode, and cause assertions in debug mode.

Using Embree

The most convenient way of using Embree is through CMake. Just let CMake find Embree using the FIND_PACKAGE function inside your CMakeLists.txt file:

 FIND_PACKAGE(embree 3.0 REQUIRED)

If you installed Embree using the Linux RPM or macOS PKG installer, this will automatically find Embree. If you used the zip or tar.gz files to extract Embree, you need to set the embree_DIR variable to the folder you extracted Embree to. If you used the Windows MSI installer, you need to set embree_DIR to point to the Embree install location (e.g. C:\Program Files\Intel\Embree3).

The FIND_PACKAGE function will create an embree target that you can add to your target link libraries:

TARGET_LINK_LIBRARIES(application embree)

Now please have a look at the Embree Tutorials source code and the Embree API section to get started.

Embree API

The Embree API is a low-level C99 ray tracing API which can be used to construct 3D scenes and perform ray queries of different types inside these scenes. All API calls carry the prefix rtc (or RTC for types) which stands for ray tracing core.

The API also exists in an ISPC version, which is almost identical but contains additional functions that operate on ray packets with a size of the native SIMD width used by ISPC. For simplicity this document refers to the C99 version of the API functions. For changes when upgrading from the Embree 2 to the current Embree 3 API see Section [Upgrading from Embree 2 to Embree 3].

The API supports scenes consisting of different geometry types such as triangle meshes, quad meshes (triangle pairs), grid meshes, flat curves, round curves, oriented curves, subdivision meshes, instances, and user-defined geometries. See Section Scene Object for more information.

Finding the closest hit of a ray segment with the scene (rtcIntersect-type functions), and determining whether any hit between a ray segment and the scene exists (rtcOccluded-type functions) are both supported. The API supports queries for single rays, ray packets, and ray streams. See Section Ray Queries for more information.

The API is designed in an object-oriented manner, e.g. it contains device objects (RTCDevice type), scene objects (RTCScene type), geometry objects (RTCGeometry type), buffer objects (RTCBuffer type), and BVH objects (RTCBVH type). All objects are reference counted, and handles can be released by calling the appropriate release function (e.g. rtcReleaseDevice) or retained by incrementing the reference count (e.g. rtcRetainDevice). In general, API calls that access the same object are not thread-safe, unless specified differently. However, attaching geometries to the same scene and performing ray queries in a scene is thread-safe.

Device Object

Embree supports a device concept, which allows different components of the application to use the Embree API without interfering with each other. An application typically first creates a device using the [rtcNewDevice] function. This device can then be used to construct further objects, such as scenes and geometries. Before the application exits, it should release all devices by invoking [rtcReleaseDevice]. An application typically creates only a single device. If required differently, it should only use a small number of devices at any given time.

Each user thread has its own error flag per device. If an error occurs when invoking an API function, this flag is set to an error code (if it isn't already set by a previous error). See Section [rtcGetDeviceError] for information on how to read the error code and Section [rtcSetDeviceErrorFunction] on how to register a callback that is invoked for each error encountered. It is recommended to always set a error callback function, to detect all errors.

Scene Object

A scene is a container for a set of geometries, and contains a spatial acceleration structure which can be used to perform different types of ray queries.

A scene is created using the rtcNewScene function call, and released using the rtcReleaseScene function call. To populate a scene with geometries use the rtcAttachGeometry call, and to detach them use the rtcDetachGeometry call. Once all scene geometries are attached, an rtcCommitScene call (or rtcJoinCommitScene call) will finish the scene description and trigger building of internal data structures. After the scene got committed, it is safe to perform ray queries (see Section Ray Queries) or to query the scene bounding box (see [rtcGetSceneBounds] and [rtcGetSceneLinearBounds]).

If scene geometries get modified or attached or detached, the rtcCommitScene call must be invoked before performing any further ray queries for the scene; otherwise the effect of the ray query is undefined. The modification of a geometry, committing the scene, and tracing of rays must always happen sequentially, and never at the same time. Any API call that sets a property of the scene or geometries contained in the scene count as scene modification, e.g. including setting of intersection filter functions.

Scene flags can be used to configure a scene to use less memory (RTC_SCENE_FLAG_COMPACT), use more robust traversal algorithms (RTC_SCENE_FLAG_ROBUST), and to optimize for dynamic content. See Section [rtcSetSceneFlags] for more details.

A build quality can be specified for a scene to balance between acceleration structure build performance and ray query performance. See Section [rtcSetSceneBuildQuality] for more details on build quality.

Geometry Object

A new geometry is created using the rtcNewGeometry function. Depending on the geometry type, different buffers must be bound (e.g. using rtcSetSharedGeometryBuffer) to set up the geometry data. In most cases, binding of a vertex and index buffer is required. The number of primitives and vertices of that geometry is typically inferred from the size of these bound buffers.

Changes to the geometry always must be committed using the rtcCommitGeometry call before using the geometry. After committing, a geometry is not included in any scene. A geometry can be added to a scene by using the rtcAttachGeometry function (to automatically assign a geometry ID) or using the rtcAttachGeometryById function (to specify the geometry ID manually). A geometry can get attached to multiple scenes.

All geometry types support multi-segment motion blur with an arbitrary number of equidistant time steps (in the range of 2 to 129) inside a user specified time range. Each geometry can have a different number of time steps and a different time range. The motion blur geometry is defined by linearly interpolating the geometries of neighboring time steps. To construct a motion blur geometry, first the number of time steps of the geometry must be specified using the rtcSetGeometryTimeStepCount function, and then a vertex buffer for each time step must be bound, e.g. using the rtcSetSharedGeometryBuffer function. Optionally, a time range defining the start (and end time) of the first (and last) time step can be set using the rtcSetGeometryTimeRange function. This feature will also allow geometries to appear and disappear during the camera shutter time if the time range is a sub range of [0,1].

The API supports per-geometry filter callback functions (see rtcSetGeometryIntersectFilterFunction and rtcSetGeometryOccludedFilterFunction) that are invoked for each intersection found during the rtcIntersect-type or rtcOccluded-type calls. The former ones are called geometry intersection filter functions, the latter ones geometry occlusion filter functions. These filter functions are designed to be used to ignore intersections outside of a user-defined silhouette of a primitive, e.g. to model tree leaves using transparency textures.

Ray Queries

The API supports finding the closest hit of a ray segment with the scene (rtcIntersect-type functions), and determining whether any hit between a ray segment and the scene exists (rtcOccluded-type functions).

Supported are single ray queries (rtcIntersect1 and rtcOccluded1) as well as ray packet queries for ray packets of size 4 (rtcIntersect4 and rtcOccluded4), ray packets of size 8 (rtcIntersect8 and rtcOccluded8), and ray packets of size 16 (rtcIntersect16 and rtcOccluded16).

Ray streams in a variety of layouts are supported as well, such as streams of single rays (rtcIntersect1M and rtcOccluded1M), streams of pointers to single rays (rtcIntersect1p and rtcOccluded1p), streams of ray packets (rtcIntersectNM and rtcOccludedNM), and large packet-like streams in structure of pointer layout (rtcIntersectNp and rtcOccludedNp).

See Sections [rtcIntersect1] and [rtcOccluded1] for a detailed description of how to set up and trace a ray.

See tutorial Triangle Geometry for a complete example of how to trace single rays and ray packets. Also have a look at the tutorial Stream Viewer for an example of how to trace ray streams.

Point Queries

The API supports traversal of the BVH using a point query object that specifies a location and a query radius. For all primitives intersecting the according domain, a user defined callback function is called which allows queries such as finding the closest point on the surface geometries of the scene (see Tutorial Closest Point) or nearest neighbour queries (see Tutorial Voronoi).

See Section [rtcPointQuery] for a detailed description of how to set up point queries.

Collision Detection

The Embree API also supports collision detection queries between two scenes consisting only of user geometries. Embree only performs broadphase collision detection, the narrow phase detection can be performed through a callback function.

See Section [rtcCollide] for a detailed description of how to set up collision detection.

Seen tutorial Collision Detection for a complete example of collsion detection being used on a simple cloth solver.

Miscellaneous

A context filter function, which can be set per ray query is supported (see rtcInitIntersectContext). This filter function is designed to change the semantics of the ray query, e.g. to accumulate opacity for transparent shadows, count the number of surfaces along a ray, collect all hits along a ray, etc.

The internal algorithms to build a BVH are exposed through the RTCBVH object and rtcBuildBVH call. This call makes it possible to build a BVH in a user-specified format over user-specified primitives. See the documentation of the rtcBuildBVH call for more details.

For getting the most performance out of Embree, see the Section [Performance Recommendations].

Upgrading from Embree 2 to Embree 3

We decided to introduce an improved API in Embree 3 that is not backward compatible with the Embree 2 API. This step was required to remove various deprecated API functions that accumulated over time, improve extensibility of the API, fix suboptimal design decisions, fix design mistakes (such as incompatible single ray and ray packet layouts), clean up inconsistent naming, and increase flexibility.

To make porting to the new API easy, we provide a conversion script that can do most of the work, and will annotate the code with remaining changes required. The script can be invoked the following way for CPP files:

./scripts/cpp-patch.py --patch embree2_to_embree3.patch
  --in infile.cpp --out outfile.cpp

When invoked for ISPC files, add the --ispc option:

./scripts/cpp-patch.py --ispc --patch embree2_to_embree3.patch
  --in infile.ispc --out outfile.ispc

Apply the script to each source file of your project that contains Embree API calls or types. The input file and output file can also be identical to perform the patch in-place. Please always backup your original code before running the script, and inspect the code changes done by the script using diff (e.g. git diff), to make sure no undesired code locations got changed. Grep the code for comments containing EMBREE_FIXME and perform the action described in the comment.

The following changes need to be performed when switching from Embree 2 to Embree 3. Most of these changes are automatically done by the script if not described differently.

We strongly recommend to set an error callback function (see rtcSetDeviceErrorFunction) when porting to Embree 3 to detect all runtime errors early.

Device

  • rtcInit and rtcExit got removed. Please use the device concept using the rtcNewDevice and rtcReleaseDevice functions instead.

  • Functions that conceptually should operate on a device but did not get a device argument got removed. The upgrade script replaces these functions by the proper functions that operate on a device, however, manually propagating the device handle to these function calls might still be required.

Scene

  • The API no longer distinguishes between a static and a dynamic scene. Some users had issues as they wanted to do minor modifications to static scenes, but maintain high traversal performance.

    The new approach gives more flexibility, as each scene is changeable, and build quality settings can be changed on a commit basis to balance between build performance and render performance.

  • The rtcCommitThread function got removed; use rtcJoinCommitScene instead.

  • The scene now supports different build quality settings. Please use those instead of the previous way of RTC_SCENE_STATIC, RTC_SCENE_DYNAMIC, and RTC_SCENE_HIGH_QUALITY flags.

Geometry

  • There is now only one rtcNewGeometry function to create geometries which gets passed an enum to specify the type of geometry to create. The number of vertices and primitives of the geometries is inferred from the size of data buffers.

  • We introduced an object type RTCGeometry for all geometries. Previously a geometry was not a standalone object and could only exist inside a scene. The new approach comes with more flexibility and more readable code.

    Operations like rtcInterpolate can now be performed on the geometry object directly without the need of a scene. Further, an application can choose to create its geometries independent of a scene, e.g. each time a geometry node is added to its scene graph.

    This modification changed many API functions to get passed one RTCGeometry object instead of a RTCScene and geomID. The script does all required changed automatically. However, in some cases the script may introduce rtcGetGeometry(scene, geomID) calls to retrieve the geometry handle. Best store the geometry handle inside your scene representation (and release it in the destructor) and access the handle directly instead of calling rtcGetGeometry.

  • Geometries are not included inside a scene anymore but can be attached to a multiple scenes using the rtcAttachGeomety or rtcAttachGeometryByID functions.

  • As geometries are separate objects, commit semantics got introduced for them too. Thus geometries must be committed through the rtcCommitGeometry call before getting used. This allows for earlier error checking and pre-calculating internal data per geometry object.

    Such commit points were previously not required in the Embree 2 API. The upgrade script attempts to insert the commits automatically, but cannot do so properly under all circumstances. Thus please check if every rtcCommitGeometry call inserted by the script is properly placed, and if a rtcCommitGeometry call is placed after a sequence of changes to a geometry.

  • Only the latest version of the previous displacement function call (RTCDisplacementFunc2) is now supported, and the callback is passed as a structure containing all arguments.

  • The deprecated RTCBoundaryMode type and rtcSetBoundaryMode function got removed and replaced by RTCSubdivisionMode enum and the rtcSetGeometrySubdivisionMode function. The script does this replacement automatically.

  • Ribbon curves and lines now avoid self-intersections automatically The application can be simplified by removing special code paths that previously did the self-intersection handling.

  • The previous Embree 2 way of instancing was suboptimal as it required user geometries to update the instID field of the ray differently when used inside an instanced scene or inside a top-level scene. The user geometry intersection code now just has to copy the context.instID field into the ray.instID field to function properly under all circumstances.

  • The internal instancing code will update the context.instID field properly when entering or leaving an instance. When instancing is implemented manually through user geometries, the code must be modified to set the context.instID field properly and no longer pass instID through the ray. This change must done manually and cannot be performed by the script.

  • We flipped the direction of the geometry normal to the widely used convention that a shape with counter-clockwise layout of vertices has the normal pointing upwards (right-hand rule). Most modeling tools follow that convention.

    The conversion script does not perform this change, thus if required adjust your code to flip Ng for triangle, quad, and subdivision surfaces.

Buffers

  • With Embree 3 we are introducing explicit RTCBuffer objects. However, you can still use the short way of sharing buffers with Embree through the rtcSetSharedGeometryBuffer call.

  • The rtcMapBuffer and rtcUnmapBuffer API calls were removed, and we added the rtcGetBufferData call instead.

    Previously the rtcMapBuffer call had the semantics of creating an internal buffer when no buffer was shared for the corresponding buffer slot. These invocations of rtcMapBuffer must be replaced by an explicit creation of an internally managed buffer using the rtcNewGeometryBuffer function.

    The upgrade script cannot always detect if the rtcMapBuffer call would create an internal buffer or just map the buffer pointer. Thus check whether the rtcNewGeometryBuffer and rtcGetBufferData calls are correct after the conversion.

  • The rtcUpdateGeometryBuffer function now must be called for every buffer that got modified by the application. Note that the conversion script cannot automatically detect each location where a buffer update is now required.

  • The buffer type no longer encodes the time step or user vertex buffer index. Now RTC_VERTEX_BUFFER_TYPE and additional slot specifies the vertex buffer for a specific time step, and RTC_USER_VERTEX_BUFFER_TYPE and additional slot specifies a vertex attribute.

Miscellaneous {#miscellaneous}

  • The header files for Embree 3 are now inside the embree3 folder (instead of embree2 folder) and libembree.so is now called libembree3.so to be able to install multiple Embree versions side by side. We made the headers C99 compliant.

  • All API objects are now reference counted with release functions to decrement and retain functions to increment the reference count (if required).

  • Most callback functions no longer get different arguments as input, but a pointer to a structure containing all arguments. This results in more readable code, faster callback invocation (as some arguments do not change between invocations) and is extensible, as new members to the structure can be later added in a backward compatible way (if required).

    The conversion script can convert the definition and declaration of the old callback functions in most cases. Before running the script, make sure that you never type-cast a callback function when assigning it (as this has the danger of assigning a callback function with a wrong type if the conversion did not detect some callbacks as such). If the script does not detect a callback function, make sure the argument types match exactly the types in the header (e.g. write const int instead of int const or convert the callback manually).

  • An intersection context is now required for each ray query invocation. The context should be initialized using the rtcInitIntersectContext function.

  • The rtcIntersect-type functions get as input an RTCRayHit type, which is similar to before, but has the ray and hit parts split into two sub-structures.

    The rtcOccluded-type functions get as input an RTCRay type, which does not contain hit data anymore. When an occlusion is found, the tfar element of the ray is set to -inf.

    Required code changes cannot be done by the upgrade script and need to be done manually.

  • The ray layout for single rays and packets of rays had certain incompatibilities (alignment of org and dir for single rays caused gaps in the single ray layout that were not in the ray packet layout). This issue never showed up because single rays and ray packets were separate in the system initially. This layout issue is now fixed, and a single ray has the same layout as a ray packet of size 1.

  • Previously Embree supported placing additional data at the end of the ray structure, and accessing that data inside user geometry callbacks and filter callback functions.

    With Embree 3 this is no longer supported, and the ray passed to a callback function may be copied to a different memory location. To attach additional data to your ray, simply extend the intersection context with a pointer to that data.

    This change cannot be done by the script. Further, code will still work if you extend the ray as the implementation did not change yet.

  • The ray structure now contains an additional id and flags field. The id can be used to store the index of the ray with respect to a ray packet or ray stream. The flags is reserved for future use, and currently must be set to 0.

  • All previous intersection filter callback variants have been removed, except for the RTCFilterFuncN which gets a varying size ray packet as input. The semantics of this filter function type have changed from copying the hit on acceptance to clearing the ray's valid argument in case of non-acceptance. This way, chaining multiple filters is more efficient.

    We kept the guarantee that for rtcIntersect1/4/8/16 and rtcOccluded1/4/8/16 calls the packet size and ray order will not change from the initial size and ordering when entering a filter callback.

  • We no longer export ISPC-specific symbols. This has the advantage that certain linking issues went away, e.g. it is now possible to link an ISPC application compiled for any combination of ISAs, and link this to an Embree library compiled with a different set of ISAs. Previously the ISAs of the application had to be a subset of the ISAs of Embree, and when the user enabled exactly one ISA, they had to do this in Embree and the application.

  • We no longer export the ISPC tasking system, which means that the application has the responsibility to implement the ISPC tasking system itself. ISPC comes with example code on how to do this. This change is not performed by the script and must be done manually.

  • Fixed many naming inconsistencies, and changed names of further API functions. All these renamings are properly done by the script and need no further attention.

Embree API Reference

rtcNewDevice

NAME

rtcNewDevice - creates a new device

SYNOPSIS

#include <embree3/rtcore.h>

RTCDevice rtcNewDevice(const char* config);

DESCRIPTION

This function creates a new device and returns a handle to this device. The device object is reference counted with an initial reference count of 1. The handle can be released using the rtcReleaseDevice API call.

The device object acts as a class factory for all other object types. All objects created from the device (like scenes, geometries, etc.) hold a reference to the device, thus the device will not be destroyed unless these objects are destroyed first.

Objects are only compatible if they belong to the same device, e.g it is not allowed to create a geometry in one device and attach it to a scene created with a different device.

A configuration string (config argument) can be passed to the device construction. This configuration string can be NULL to use the default configuration.

The following configuration is supported:

  • threads=[int]: Specifies a number of build threads to use. A value of 0 enables all detected hardware threads. By default all hardware threads are used.

  • user_threads=[int]: Sets the number of user threads that can be used to join and participate in a scene commit using rtcJoinCommitScene. The tasking system will only use threads-user_threads many worker threads, thus if the app wants to solely use its threads to commit scenes, just set threads equal to user_threads. This option only has effect with the Intel(R) Threading Building Blocks (TBB) tasking system.

  • set_affinity=[0/1]: When enabled, build threads are affinitized to hardware threads. This option is disabled by default on standard CPUs, and enabled by default on Xeon Phi Processors.

  • start_threads=[0/1]: When enabled, the build threads are started upfront. This can be useful for benchmarking to exclude thread creation time. This option is disabled by default.

  • isa=[sse2,sse4.2,avx,avx2,avx512]: Use specified ISA. By default the ISA is selected automatically.

  • max_isa=[sse2,sse4.2,avx,avx2,avx512]: Configures the automated ISA selection to use maximally the specified ISA.

  • hugepages=[0/1]: Enables or disables usage of huge pages. Under Linux huge pages are used by default but under Windows and macOS they are disabled by default.

  • enable_selockmemoryprivilege=[0/1]: When set to 1, this enables the SeLockMemoryPrivilege privilege with is required to use huge pages on Windows. This option has an effect only under Windows and is ignored on other platforms. See Section [Huge Page Support] for more details.

  • verbose=[0,1,2,3]: Sets the verbosity of the output. When set to 0, no output is printed by Embree, when set to a higher level more output is printed. By default Embree does not print anything on the console.

  • frequency_level=[simd128,simd256,simd512]: Specifies the frequency level the application want to run on, which can be either: a) simd128 to run at highest frequency b) simd256 to run at AVX2-heavy frequency level c) simd512 to run at heavy AVX512 frequency level. When some frequency level is specified, Embree will avoid doing optimizations that may reduce the frequency level below the level specified. E.g. if your app does not use AVX instructions setting "frequency_level=simd128" will cause some CPUs to run at highest frequency, which may result in higher application performance if you do much shading. If you application heavily uses AVX code, you should best set the frequency level to simd256. Per default Embree tries to avoid reducing the frequency of the CPU by setting the simd256 level only when the CPU has no significant down clocking.

Different configuration options should be separated by commas, e.g.:

rtcNewDevice("threads=1,isa=avx");

EXIT STATUS

On success returns a handle of the created device. On failure returns NULL as device and sets a per-thread error code that can be queried using rtcGetDeviceError(NULL).

SEE ALSO

[rtcRetainDevice], [rtcReleaseDevice]

rtcRetainDevice

NAME {#name}

rtcRetainDevice - increments the device reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcRetainDevice(RTCDevice device);

DESCRIPTION {#description}

Device objects are reference counted. The rtcRetainDevice function increments the reference count of the passed device object (device argument). This function together with rtcReleaseDevice allows to use the internal reference counting in a C++ wrapper class to manage the ownership of the object.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewDevice], [rtcReleaseDevice]

rtcReleaseDevice

NAME {#name}

rtcReleaseDevice - decrements the device reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcReleaseDevice(RTCDevice device);

DESCRIPTION {#description}

Device objects are reference counted. The rtcReleaseDevice function decrements the reference count of the passed device object (device argument). When the reference count falls to 0, the device gets destroyed.

All objects created from the device (like scenes, geometries, etc.) hold a reference to the device, thus the device will not get destroyed unless these objects are destroyed first.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewDevice], [rtcRetainDevice]

rtcGetDeviceProperty

NAME {#name}

rtcGetDeviceProperty - queries properties of the device

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

ssize_t rtcGetDeviceProperty(
  RTCDevice device,
  enum RTCDeviceProperty prop
);

DESCRIPTION {#description}

The rtcGetDeviceProperty function can be used to query properties (prop argument) of a device object (device argument). The returned property is an integer of type ssize_t.

Possible properties to query are:

  • RTC_DEVICE_PROPERTY_VERSION: Queries the combined version number (MAJOR.MINOR.PATCH) with two decimal digits per component. E.g. for Embree 2.8.3 the integer 208003 is returned.

  • RTC_DEVICE_PROPERTY_VERSION_MAJOR: Queries the major version number of Embree.

  • RTC_DEVICE_PROPERTY_VERSION_MINOR: Queries the minor version number of Embree.

  • RTC_DEVICE_PROPERTY_VERSION_PATCH: Queries the patch version number of Embree.

  • RTC_DEVICE_PROPERTY_NATIVE_RAY4_SUPPORTED: Queries whether the rtcIntersect4 and rtcOccluded4 functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with EMBREE_RAY_PACKETS and SSE2 (or SSE4.2) enabled, and if the machine it is running on supports SSE2 (or SSE4.2).

  • RTC_DEVICE_PROPERTY_NATIVE_RAY8_SUPPORTED: Queries whether the rtcIntersect8 and rtcOccluded8 functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with EMBREE_RAY_PACKETS and AVX (or AVX2) enabled, and if the machine it is running on supports AVX (or AVX2).

  • RTC_DEVICE_PROPERTY_NATIVE_RAY16_SUPPORTED: Queries whether the rtcIntersect16 and rtcOccluded16 functions preserve packet size and ray order when invoking callback functions. This is only the case if Embree is compiled with EMBREE_RAY_PACKETS and AVX512 enabled, and if the machine it is running on supports AVX512.

  • RTC_DEVICE_PROPERTY_RAY_STREAM_SUPPORTED: Queries whether rtcIntersect1M, rtcIntersect1Mp, rtcIntersectNM, rtcIntersectNp, rtcOccluded1M, rtcOccluded1Mp, rtcOccludedNM, and rtcOccludedNp are supported. This is only the case if Embree is compiled with EMBREE_RAY_PACKETS enabled.

  • RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED: Queries whether ray masks are supported. This is only the case if Embree is compiled with EMBREE_RAY_MASK enabled.

  • RTC_DEVICE_PROPERTY_BACKFACE_CULLING_ENABLED: Queries whether back face culling is enabled. This is only the case if Embree is compiled with EMBREE_BACKFACE_CULLING enabled.

  • RTC_DEVICE_PROPERTY_COMPACT_POLYS_ENABLED: Queries whether compact polys is enabled. This is only the case if Embree is compiled with EMBREE_COMPACT_POLYS enabled.

  • RTC_DEVICE_PROPERTY_FILTER_FUNCTION_SUPPORTED: Queries whether filter functions are supported, which is the case if Embree is compiled with EMBREE_FILTER_FUNCTION enabled.

  • RTC_DEVICE_PROPERTY_IGNORE_INVALID_RAYS_ENABLED: Queries whether invalid rays are ignored, which is the case if Embree is compiled with EMBREE_IGNORE_INVALID_RAYS enabled.

  • RTC_DEVICE_PROPERTY_TRIANGLE_GEOMETRY_SUPPORTED: Queries whether triangles are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_TRIANGLE enabled.

  • RTC_DEVICE_PROPERTY_QUAD_GEOMETRY_SUPPORTED: Queries whether quads are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_QUAD enabled.

  • RTC_DEVICE_PROPERTY_SUBDIVISION_GEOMETRY_SUPPORTED: Queries whether subdivision meshes are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_SUBDIVISION enabled.

  • RTC_DEVICE_PROPERTY_CURVE_GEOMETRY_SUPPORTED: Queries whether curves are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_CURVE enabled.

  • RTC_DEVICE_PROPERTY_POINT_GEOMETRY_SUPPORTED: Queries whether points are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_POINT enabled.

  • RTC_DEVICE_PROPERTY_USER_GEOMETRY_SUPPORTED: Queries whether user geometries are supported, which is the case if Embree is compiled with EMBREE_GEOMETRY_USER enabled.

  • RTC_DEVICE_PROPERTY_TASKING_SYSTEM: Queries the tasking system Embree is compiled with. Possible return values are:

    1. internal tasking system
    2. Intel Threading Building Blocks (TBB)
    3. Parallel Patterns Library (PPL)
  • RTC_DEVICE_PROPERTY_JOIN_COMMIT_SUPPORTED: Queries whether rtcJoinCommitScene is supported. This is not the case when Embree is compiled with PPL or older versions of TBB.

  • RTC_DEVICE_PROPERTY_PARALLEL_COMMIT_SUPPORTED: Queries whether rtcCommitScene can get invoked from multiple TBB worker threads concurrently. This feature is only supported starting with TBB 2019 Update 9.

EXIT STATUS {#exit-status}

On success returns the value of the queried property. For properties returning a boolean value, the return value 0 denotes false and 1 denotes true.

On failure zero is returned and an error code is set that can be queried using rtcGetDeviceError.

rtcGetDeviceError

NAME {#name}

rtcGetDeviceError - returns the error code of the device

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCError rtcGetDeviceError(RTCDevice device);

DESCRIPTION {#description}

Each thread has its own error code per device. If an error occurs when calling an API function, this error code is set to the occurred error if it stores no previous error. The rtcGetDeviceError function reads and returns the currently stored error and clears the error code. This assures that the returned error code is always the first error occurred since the last invocation of rtcGetDeviceError.

Possible error codes returned by rtcGetDeviceError are:

  • RTC_ERROR_NONE: No error occurred.

  • RTC_ERROR_UNKNOWN: An unknown error has occurred.

  • RTC_ERROR_INVALID_ARGUMENT: An invalid argument was specified.

  • RTC_ERROR_INVALID_OPERATION: The operation is not allowed for the specified object.

  • RTC_ERROR_OUT_OF_MEMORY: There is not enough memory left to complete the operation.

  • RTC_ERROR_UNSUPPORTED_CPU: The CPU is not supported as it does not support the lowest ISA Embree is compiled for.

  • RTC_ERROR_CANCELLED: The operation got canceled by a memory monitor callback or progress monitor callback function.

When the device construction fails, rtcNewDevice returns NULL as device. To detect the error code of a such a failed device construction, pass NULL as device to the rtcGetDeviceError function. For all other invocations of rtcGetDeviceError, a proper device pointer must be specified.

EXIT STATUS {#exit-status}

Returns the error code for the device.

SEE ALSO {#see-also}

[rtcSetDeviceErrorFunction]

rtcSetDeviceErrorFunction

NAME {#name}

rtcSetDeviceErrorFunction - sets an error callback function for the device

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

typedef void (*RTCErrorFunction)(
  void* userPtr,
  RTCError code,
  const char* str
);

void rtcSetDeviceErrorFunction(
  RTCDevice device,
  RTCErrorFunction error,
  void* userPtr
);

DESCRIPTION {#description}

Using the rtcSetDeviceErrorFunction call, it is possible to set a callback function (error argument) with payload (userPtr argument), which is called whenever an error occurs for the specified device (device argument).

Only a single callback function can be registered per device, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

When the registered callback function is invoked, it gets passed the user-defined payload (userPtr argument as specified at registration time), the error code (code argument) of the occurred error, as well as a string (str argument) that further describes the error.

The error code is also set if an error callback function is registered.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcGetDeviceError]

rtcSetDeviceMemoryMonitorFunction

NAME {#name}

rtcSetDeviceMemoryMonitorFunction - registers a callback function
  to track memory consumption

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

typedef bool (*RTCMemoryMonitorFunction)(
  void* userPtr,
  ssize_t bytes,
  bool post
);

void rtcSetDeviceMemoryMonitorFunction(
  RTCDevice device,
  RTCMemoryMonitorFunction memoryMonitor,
  void* userPtr
);

DESCRIPTION {#description}

Using the rtcSetDeviceMemoryMonitorFunction call, it is possible to register a callback function (memoryMonitor argument) with payload (userPtr argument) for a device (device argument), which is called whenever internal memory is allocated or deallocated by objects of that device. Using this memory monitor callback mechanism, the application can track the memory consumption of an Embree device, and optionally terminate API calls that consume too much memory.

Only a single callback function can be registered per device, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

Once registered, the Embree device will invoke the memory monitor callback function before or after it allocates or frees important memory blocks. The callback function gets passed the payload as specified at registration time (userPtr argument), the number of bytes allocated or deallocated (bytes argument), and whether the callback is invoked after the allocation or deallocation took place (post argument). The callback function might get called from multiple threads concurrently.

The application can track the current memory usage of the Embree device by atomically accumulating the bytes input parameter provided to the callback function. This parameter will be >0 for allocations and <0 for deallocations.

Embree will continue its operation normally when returning true from the callback function. If false is returned, Embree will cancel the current operation with the RTC_ERROR_OUT_OF_MEMORY error code. Issuing multiple cancel requests from different threads is allowed. Canceling will only happen when the callback was called for allocations (bytes > 0), otherwise the cancel request will be ignored.

If a callback to cancel was invoked before the allocation happens (post == false), then the bytes parameter should not be accumulated, as the allocation will never happen. If the callback to cancel was invoked after the allocation happened (post == true), then the bytes parameter should be accumulated, as the allocation properly happened and a deallocation will later free that data block.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewDevice]

rtcNewScene

NAME {#name}

rtcNewScene - creates a new scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCScene rtcNewScene(RTCDevice device);

DESCRIPTION {#description}

This function creates a new scene bound to the specified device (device argument), and returns a handle to this scene. The scene object is reference counted with an initial reference count of 1. The scene handle can be released using the rtcReleaseScene API call.

EXIT STATUS {#exit-status}

On success a scene handle is returned. On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcRetainScene], [rtcReleaseScene]

rtcGetSceneDevice

NAME {#name}

rtcGetSceneDevice - returns the device the scene got created in

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCDevice rtcGetSceneDevice(RTCScene scene);

DESCRIPTION {#description}

This function returns the device object the scene got created in. The returned handle own one additional reference to the device object, thus you should need to call rtcReleaseDevice when the returned handle is no longer required.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcReleaseDevice]

rtcRetainScene

NAME {#name}

rtcRetainScene - increments the scene reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcRetainScene(RTCScene scene);

DESCRIPTION {#description}

Scene objects are reference counted. The rtcRetainScene function increments the reference count of the passed scene object (scene argument). This function together with rtcReleaseScene allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewScene], [rtcReleaseScene]

rtcReleaseScene

NAME {#name}

rtcReleaseScene - decrements the scene reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcReleaseScene(RTCScene scene);

DESCRIPTION {#description}

Scene objects are reference counted. The rtcReleaseScene function decrements the reference count of the passed scene object (scene argument). When the reference count falls to 0, the scene gets destroyed.

The scene holds a reference to all attached geometries, thus if the scene gets destroyed, all geometries get detached and their reference count decremented.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewScene], [rtcRetainScene]

rtcAttachGeometry

NAME {#name}

rtcAttachGeometry - attaches a geometry to the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

unsigned int rtcAttachGeometry(
  RTCScene scene,
  RTCGeometry geometry
);

DESCRIPTION {#description}

The rtcAttachGeometry function attaches a geometry (geometry argument) to a scene (scene argument) and assigns a geometry ID to that geometry. All geometries attached to a scene are defined to be included inside the scene. A geometry can get attached to multiplee scene. The geometry ID is unique for the scene, and is used to identify the geometry when hit by a ray during ray queries.

This function is thread-safe, thus multiple threads can attach geometries to a scene in parallel.

The geometry IDs are assigned sequentially, starting from 0, as long as no geometry got detached. If geometries got detached, the implementation will reuse IDs in an implementation dependent way. Consequently sequential assignment is no longer guaranteed, but a compact range of IDs.

These rules allow the application to manage a dynamic array to efficiently map from geometry IDs to its own geometry representation. Alternatively, the application can also use per-geometry user data to map to its geometry representation. See rtcSetGeometryUserData and rtcGetGeometryUserData for more information.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryUserData], [rtcGetGeometryUserData]

rtcAttachGeometryByID

NAME {#name}

rtcAttachGeometryByID - attaches a geometry to the scene
  using a specified geometry ID

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcAttachGeometryByID(
  RTCScene scene,
  RTCGeometry geometry,
  unsigned int geomID
);

DESCRIPTION {#description}

The rtcAttachGeometryByID function attaches a geometry (geometry argument) to a scene (scene argument) and assigns a user provided geometry ID (geomID argument) to that geometry. All geometries attached to a scene are defined to be included inside the scene. A geometry can get attached to multiple scenes. The passed user-defined geometry ID is used to identify the geometry when hit by a ray during ray queries. Using this function, it is possible to share the same IDs to refer to geometries inside the application and Embree.

This function is thread-safe, thus multiple threads can attach geometries to a scene in parallel.

The user-provided geometry ID must be unused in the scene, otherwise the creation of the geometry will fail. Further, the user-provided geometry IDs should be compact, as Embree internally creates a vector which size is equal to the largest geometry ID used. Creating very large geometry IDs for small scenes would thus cause a memory consumption and performance overhead.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcAttachGeometry]

rtcDetachGeometry

NAME {#name}

rtcDetachGeometry - detaches a geometry from the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcDetachGeometry(RTCScene scene, unsigned int geomID);

DESCRIPTION {#description}

This function detaches a geometry identified by its geometry ID (geomID argument) from a scene (scene argument). When detached, the geometry is no longer contained in the scene.

This function is thread-safe, thus multiple threads can detach geometries from a scene at the same time.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcAttachGeometry], [rtcAttachGeometryByID]

rtcGetGeometry

NAME {#name}

rtcGetGeometry - returns the geometry bound to
  the specified geometry ID

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);

DESCRIPTION {#description}

The rtcGetGeometry function returns the geometry that is bound to the specified geometry ID (geomID argument) for the specified scene (scene argument). This function just looks up the handle and does not increment the reference count. If you want to get ownership of the handle, you need to additionally call rtcRetainGeometry. For this reason, this function is fast and can be used during rendering. However, it is generally recommended to store the geometry handle inside the application's geometry representation and look up the geometry handle from that representation directly.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcAttachGeometry], [rtcAttachGeometryByID]

rtcCommitScene

NAME {#name}

rtcCommitScene - commits scene changes

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcCommitScene(RTCScene scene);

DESCRIPTION {#description}

The rtcCommitScene function commits all changes for the specified scene (scene argument). This internally triggers building of a spatial acceleration structure for the scene using all available worker threads. Ray queries can be performed only after committing all scene changes.

If the application uses TBB 2019 Update 9 or later for parallelization of rendering, lazy scene construction during rendering is supported by rtcCommitScene. Therefore rtcCommitScene can get called from multiple TBB worker threads concurrently for the same scene. The rtcCommitScene function will then internally isolate the scene construction using a tbb::isolated_task_group. The alternative approach of using rtcJoinCommitScene which uses an tbb:task_arena internally, is not recommended due to it's high runtime overhead.

If scene geometries get modified or attached or detached, the rtcCommitScene call must be invoked before performing any further ray queries for the scene; otherwise the effect of the ray query is undefined. The modification of a geometry, committing the scene, and tracing of rays must always happen sequentially, and never at the same time. Any API call that sets a property of the scene or geometries contained in the scene count as scene modification, e.g. including setting of intersection filter functions.

The kind of acceleration structure built can be influenced using scene flags (see rtcSetSceneFlags), and the quality can be specified using the rtcSetSceneBuildQuality function.

Embree silently ignores primitives during spatial acceleration structure construction that would cause numerical issues, e.g. primitives containing NaNs, INFs, or values greater than 1.844E18f (as no reasonable calculations can be performed with such values without causing overflows).

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcJoinCommitScene]

rtcJoinCommitScene

NAME {#name}

rtcJoinCommitScene - commits the scene from multiple threads

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcJoinCommitScene(RTCScene scene);

DESCRIPTION {#description}

The rtcJoinCommitScene function commits all changes for the specified scene (scene argument). The scene commit internally triggers building of a spatial acceleration structure for the scene. Ray queries can be performed after scene changes got properly committed.

The rtcJoinCommitScene function can get called from multiple user threads which will all cooperate in the build operation. All threads calling into this function will return from rtcJoinCommitScene after the scene commit is finished. All threads must consistently call rtcJoinCommitScene and not rtcCommitScene.

In contrast to the rtcCommitScene function, the rtcJoinCommitScene function can be called from multiple user threads, while the rtcCommitScene can only get called from multiple TBB worker threads when used concurrently. For optimal performance we strongly recommend using TBB inside the application together with the rtcCommitScene function and to avoid using the rtcJoinCommitScene function.

The rtcJoinCommitScene feature allows a flexible way to lazily create hierarchies during rendering. A thread reaching a not-yet-constructed sub-scene of a two-level scene can generate the sub-scene geometry and call rtcJoinCommitScene on that just generated scene. During construction, further threads reaching the not-yet-built scene can join the build operation by also invoking rtcJoinCommitScene. A thread that calls rtcJoinCommitScene after the build finishes will directly return from the rtcJoinCommitScene call.

Multiple scene commit operations on different scenes can be running at the same time, hence it is possible to commit many small scenes in parallel, distributing the commits to many threads.

When using Embree with the Intel® Threading Building Blocks (which is the default), threads that call rtcJoinCommitScene will join the build operation, but other TBB worker threads might also participate in the build. To avoid thread oversubscription, we recommend using TBB also inside the application. Further, the join mode only works properly starting with TBB v4.4 Update 1. For earlier TBB versions, threads that call rtcJoinCommitScene to join a running build will just trigger the build and wait for the build to finish. Further, old TBB versions with TBB_INTERFACE_VERSION_MAJOR < 8 do not support rtcJoinCommitScene, and invoking this function will result in an error.

When using Embree with the internal tasking system, only threads that call rtcJoinCommitScene will perform the build operation, and no additional worker threads will be scheduled.

When using Embree with the Parallel Patterns Library (PPL), rtcJoinCommitScene is not supported and calling that function will result in an error.

To detect whether rtcJoinCommitScene is supported, use the rtcGetDeviceProperty function.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcCommitScene], [rtcGetDeviceProperty]

rtcSetSceneProgressMonitorFunction

NAME {#name}

rtcSetSceneProgressMonitorFunction - registers a callback
  to track build progress

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

typedef bool (*RTCProgressMonitorFunction)(
  void* ptr,
  double n
);

void rtcSetSceneProgressMonitorFunction(
  RTCScene scene,
  RTCProgressMonitorFunction progress,
  void* userPtr
);

DESCRIPTION {#description}

Embree supports a progress monitor callback mechanism that can be used to report progress of hierarchy build operations and to cancel build operations.

The rtcSetSceneProgressMonitorFunction registers a progress monitor callback function (progress argument) with payload (userPtr argument) for the specified scene (scene argument).

Only a single callback function can be registered per scene, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

Once registered, Embree will invoke the callback function multiple times during hierarchy build operations of the scene, by passing the payload as set at registration time (userPtr argument), and a double in the range $[0, 1]$ which estimates the progress of the operation (n argument). The callback function might be called from multiple threads concurrently.

When returning true from the callback function, Embree will continue the build operation normally. When returning false, Embree will cancel the build operation with the RTC_ERROR_CANCELLED error code. Issuing multiple cancel requests for the same build operation is allowed.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewScene]

rtcSetSceneBuildQuality

NAME {#name}

rtcSetSceneBuildQuality - sets the build quality for
  the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetSceneBuildQuality(
  RTCScene scene,
  enum RTCBuildQuality quality
);

DESCRIPTION {#description}

The rtcSetSceneBuildQuality function sets the build quality (quality argument) for the specified scene (scene argument). Possible values for the build quality are:

  • RTC_BUILD_QUALITY_LOW: Create lower quality data structures, e.g. for dynamic scenes. A two-level spatial index structure is built when enabling this mode, which supports fast partial scene updates, and allows for setting a per-geometry build quality through the rtcSetGeometryBuildQuality function.

  • RTC_BUILD_QUALITY_MEDIUM: Default build quality for most usages. Gives a good compromise between build and render performance.

  • RTC_BUILD_QUALITY_HIGH: Create higher quality data structures for final-frame rendering. For certain geometry types this enables a spatial split BVH.

Selecting a higher build quality results in better rendering performance but slower scene commit times. The default build quality for a scene is RTC_BUILD_QUALITY_MEDIUM.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryBuildQuality]

rtcSetSceneFlags

NAME {#name}

rtcSetSceneFlags - sets the flags for the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags);

DESCRIPTION {#description}

The rtcSetSceneFlags function sets the scene flags (flags argument) for the specified scene (scene argument). Possible scene flags are:

  • RTC_SCENE_FLAG_NONE: No flags set.

  • RTC_SCENE_FLAG_DYNAMIC: Provides better build performance for dynamic scenes (but also higher memory consumption).

  • RTC_SCENE_FLAG_COMPACT: Uses compact acceleration structures and avoids algorithms that consume much memory.

  • RTC_SCENE_FLAG_ROBUST: Uses acceleration structures that allow for robust traversal, and avoids optimizations that reduce arithmetic accuracy. This mode is typically used for avoiding artifacts caused by rays shooting through edges of neighboring primitives.

  • RTC_SCENE_FLAG_CONTEXT_FILTER_FUNCTION: Enables support for a filter function inside the intersection context for this scene. See Section [rtcInitIntersectContext] for more details.

Multiple flags can be enabled using an or operation, e.g. RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcGetSceneFlags]

rtcGetSceneFlags

NAME {#name}

rtcGetSceneFlags - returns the flags of the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene);

DESCRIPTION {#description}

Queries the flags of a scene. This function can be useful when setting individual flags, e.g. to just set the robust mode without changing other flags the following way:

RTCSceneFlags flags = rtcGetSceneFlags(scene);
rtcSetSceneFlags(scene, RTC_SCENE_FLAG_ROBUST | flags);

EXIT STATUS {#exit-status}

On failure RTC_SCENE_FLAG_NONE is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetSceneFlags]

rtcGetSceneBounds

NAME {#name}

rtcGetSceneBounds - returns the axis-aligned bounding box of the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCORE_ALIGN(16) RTCBounds
{
  float lower_x, lower_y, lower_z, align0;
  float upper_x, upper_y, upper_z, align1;
};

void rtcGetSceneBounds(
  RTCScene scene,
  struct RTCBounds* bounds_o
);

DESCRIPTION {#description}

The rtcGetSceneBounds function queries the axis-aligned bounding box of the specified scene (scene argument) and stores that bounding box to the provided destination pointer (bounds_o argument). The stored bounding box consists of lower and upper bounds for the x, y, and z dimensions as specified by the RTCBounds structure.

The provided destination pointer must be aligned to 16 bytes. The function may be invoked only after committing the scene; otherwise the result is undefined.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcGetSceneLinearBounds], [rtcCommitScene], [rtcJoinCommitScene]

rtcGetSceneLinearBounds

NAME {#name}

rtcGetSceneLinearBounds - returns the linear bounds of the scene

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCORE_ALIGN(16) RTCLinearBounds
{
  RTCBounds bounds0;
  RTCBounds bounds1;
};

void rtcGetSceneLinearBounds(
  RTCScene scene,
  struct RTCLinearBounds* bounds_o
);

DESCRIPTION {#description}

The rtcGetSceneLinearBounds function queries the linear bounds of the specified scene (scene argument) and stores them to the provided destination pointer (bounds_o argument). The stored linear bounds consist of bounding boxes for time 0 (bounds0 member) and time 1 (bounds1 member) as specified by the RTCLinearBounds structure. Linearly interpolating these bounds to a specific time t yields bounds for the geometry at that time.

The provided destination pointer must be aligned to 16 bytes. The function may be called only after committing the scene, otherwise the result is undefined.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcGetSceneBounds], [rtcCommitScene], [rtcJoinCommitScene]

rtcNewGeometry

NAME {#name}

rtcNewGeometry - creates a new geometry object

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

enum RTCGeometryType
{
 RTC_GEOMETRY_TYPE_TRIANGLE,
 RTC_GEOMETRY_TYPE_QUAD,
 RTC_GEOMETRY_TYPE_SUBDIVISION,
 RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE,
 RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,
 RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE,
 RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE,
 RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE,
 RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE,
 RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE,
 RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE,
 RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE,
 RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE,
 RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE,
 RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE,
 RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE,
 RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE,
 RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE,
 RTC_GEOMETRY_TYPE_GRID,
 RTC_GEOMETRY_TYPE_SPHERE_POINT,
 RTC_GEOMETRY_TYPE_DISC_POINT,
 RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT,
 RTC_GEOMETRY_TYPE_USER,
 RTC_GEOMETRY_TYPE_INSTANCE
};

RTCGeometry rtcNewGeometry(
  RTCDevice device,
  enum RTCGeometryType type
);

DESCRIPTION {#description}

Geometries are objects that represent an array of primitives of the same type. The rtcNewGeometry function creates a new geometry of specified type (type argument) bound to the specified device (device argument) and returns a handle to this geometry. The geometry object is reference counted with an initial reference count of 1. The geometry handle can be released using the rtcReleaseGeometry API call.

Supported geometry types are triangle meshes (RTC_GEOMETRY_TYPE_TRIANGLE type), quad meshes (triangle pairs) (RTC_GEOMETRY_TYPE_QUAD type), Catmull-Clark subdivision surfaces (RTC_GEOMETRY_TYPE_SUBDIVISION type), curve geometries with different bases (RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE,
RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE,
RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE, RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE types) grid meshes (RTC_GEOMETRY_TYPE_GRID), point geometries (RTC_GEOMETRY_TYPE_SPHERE_POINT, RTC_GEOMETRY_TYPE_DISC_POINT, RTC_TYPE_ORIENTED_DISC_POINT), user-defined geometries (RTC_GEOMETRY_TYPE_USER), and instances (RTC_GEOMETRY_TYPE_INSTANCE).

The types RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, and RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE will treat the curve as a sweep surface of a varying-radius circle swept tangentially along the curve. The types RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, and RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE use ray-facing ribbons as a faster-to-intersect approximation.

After construction, geometries are enabled by default and not attached to any scene. Geometries can be disabled (rtcDisableGeometry call), and enabled again (rtcEnableGeometry call). A geometry can be attached to multiple scenes using the rtcAttachGeometry call (or rtcAttachGeometryByID call), and detached using the rtcDetachGeometry call. During attachment, a geometry ID is assigned to the geometry (or assigned by the user when using the rtcAttachGeometryByID call), which uniquely identifies the geometry inside that scene. This identifier is returned when primitives of the geometry are hit in later ray queries for the scene.

Geometries can also be modified, including their vertex and index buffers. After modifying a buffer, rtcUpdateGeometryBuffer must be called to notify that the buffer got modified.

The application can use the rtcSetGeometryUserData function to set a user data pointer to its own geometry representation, and later read out this pointer using the rtcGetGeometryUserData function.

After setting up the geometry or modifying it, rtcCommitGeometry must be called to finish the geometry setup. After committing the geometry, vertex data interpolation can be performed using the rtcInterpolate and rtcInterpolateN functions.

A build quality can be specified for a geometry using the rtcSetGeometryBuildQuality function, to balance between acceleration structure build performance and ray query performance. The build quality per geometry will be used if a two-level acceleration structure is built internally, which is the case if the RTC_BUILD_QUALITY_LOW is set as the scene build quality. See Section [rtcSetSceneBuildQuality] for more details.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcEnableGeometry], [rtcDisableGeometry], [rtcAttachGeometry], [rtcAttachGeometryByID], [rtcUpdateGeometryBuffer], [rtcSetGeometryUserData], [rtcGetGeometryUserData], [rtcCommitGeometry], [rtcInterpolate], [rtcInterpolateN], [rtcSetGeometryBuildQuality], [rtcSetSceneBuildQuality], [RTC_GEOMETRY_TYPE_TRIANGLE], [RTC_GEOMETRY_TYPE_QUAD], [RTC_GEOMETRY_TYPE_SUBDIVISION], [RTC_GEOMETRY_TYPE_CURVE], [RTC_GEOMETRY_TYPE_GRID], [RTC_GEOMETRY_TYPE_POINT], [RTC_GEOMETRY_TYPE_USER], [RTC_GEOMETRY_TYPE_INSTANCE]

RTC_GEOMETRY_TYPE_TRIANGLE

NAME {#name}

RTC_GEOMETRY_TYPE_TRIANGLE - triangle geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);

DESCRIPTION {#description}

Triangle meshes are created by passing RTC_GEOMETRY_TYPE_TRIANGLE to the rtcNewGeometry function call. The triangle indices can be specified by setting an index buffer (RTC_BUFFER_TYPE_INDEX type) and the triangle vertices by setting a vertex buffer (RTC_BUFFER_TYPE_VERTEX type). See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers. The index buffer must contain an array of three 32-bit indices per triangle (RTC_FORMAT_UINT3 format) and the number of primitives is inferred from the size of that buffer. The vertex buffer must contain an array of single precision x, y, z floating point coordinates (RTC_FORMAT_FLOAT3 format), and the number of vertices are inferred from the size of that buffer. The vertex buffer can be at most 16 GB large.

The parametrization of a triangle uses the first vertex p0 as base point, the vector p1 - p0 as u-direction and the vector p2 - p0 as v-direction. Thus vertex attributes t0,t1,t2 can be linearly interpolated over the triangle the following way:

t_uv = (1-u-v)*t0 + u*t1 + v*t2
     = t0 + u*(t1-t0) + v*(t2-t0)

A triangle whose vertices are laid out counter-clockwise has its geometry normal pointing upwards outside the front face, like illustrated in the following picture:

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers have to have the same stride and size.

Also see tutorial Triangle Geometry for an example of how to create triangle meshes.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that be get queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry]

RTC_GEOMETRY_TYPE_QUAD

NAME {#name}

RTC_GEOMETRY_TYPE_QUAD - quad geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_QUAD);

DESCRIPTION {#description}

Quad meshes are created by passing RTC_GEOMETRY_TYPE_QUAD to the rtcNewGeometry function call. The quad indices can be specified by setting an index buffer (RTC_BUFFER_TYPE_INDEX type) and the quad vertices by setting a vertex buffer (RTC_BUFFER_TYPE_VERTEX type). See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers. The index buffer contains an array of four 32-bit indices per quad (RTC_FORMAT_UINT4 format), and the number of primitives is inferred from the size of that buffer. The vertex buffer contains an array of single precision x, y, z floating point coordinates (RTC_FORMAT_FLOAT3 format), and the number of vertices is inferred from the size of that buffer. The vertex buffer can be at most 16 GB large.

A quad is internally handled as a pair of two triangles v0,v1,v3 and v2,v3,v1, with the u'/v' coordinates of the second triangle corrected by u = 1-u' and v = 1-v' to produce a quad parametrization where u and v are in the range 0 to 1. Thus the parametrization of a quad uses the first vertex p0 as base point, and the vector p1 - p0 as u-direction, and p3 - p0 as v-direction. Thus vertex attributes t0,t1,t2,t3 can be bilinearly interpolated over the quadrilateral the following way:

t_uv = (1-v)((1-u)*t0 + u*t1) + v*((1-u)*t3 + u*t2)

Mixed triangle/quad meshes are supported by encoding a triangle as a quad, which can be achieved by replicating the last triangle vertex (v0,v1,v2 -> v0,v1,v2,v2). This way the second triangle is a line (which can never get hit), and the parametrization of the first triangle is compatible with the standard triangle parametrization.

A quad whose vertices are laid out counter-clockwise has its geometry normal pointing upwards outside the front face, like illustrated in the following picture.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers must have the same stride and size.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry]

RTC_GEOMETRY_TYPE_GRID

NAME {#name}

RTC_GEOMETRY_TYPE_GRID - grid geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID);

DESCRIPTION {#description}

Grid meshes are created by passing RTC_GEOMETRY_TYPE_GRID to the rtcNewGeometry function call, and contain an array of grid primitives. This array of grids can be specified by setting up a grid buffer (with RTC_BUFFER_TYPE_GRID type and RTC_FORMAT_GRID format) and the grid mesh vertices by setting a vertex buffer (RTC_BUFFER_TYPE_VERTEX type). See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers. The number of grid primitives in the grid mesh is inferred from the size of the grid buffer.

The vertex buffer contains an array of single precision x, y, z floating point coordinates (RTC_FORMAT_FLOAT3 format), and the number of vertices is inferred from the size of that buffer.

Each grid in the grid buffer is of the type RTCGrid:

struct RTCGrid
{
  unsigned int startVertexID;
  unsigned int stride;
  unsigned short width,height; 
};

The RTCGrid structure describes a 2D grid of vertices (with respect to the vertex buffer of the grid mesh). The width and height members specify the number of vertices in u and v direction, e.g. setting both width and height to 3 sets up a 3×3 vertex grid. The maximum allowed width and height is 32767. The startVertexID specifies the ID of the top-left vertex in the vertex grid, while the stride parameter specifies a stride (in number of vertices) used to step to the next row.

A vertex grid of dimensions width and height is treated as a (width-1) x (height-1) grid of quads (triangle-pairs), with the same shared edge handling as for regular quad meshes. However, the u/v coordinates have the uniform range [0..1] for an entire vertex grid. The u direction follows the width of the grid while the v direction the height.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers must have the same stride and size.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry]

RTC_GEOMETRY_TYPE_SUBDIVISION

NAME {#name}

RTC_GEOMETRY_TYPE_SUBDIVISION - subdivision geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION);

DESCRIPTION {#description}

Catmull-Clark subdivision meshes are supported, including support for edge creases, vertex creases, holes, non-manifold geometry, and face-varying interpolation. The number of vertices per face can be in the range of 3 to 15 vertices (triangles, quadrilateral, pentagons, etc).

Subdivision meshes are created by passing RTC_GEOMETRY_TYPE_SUBDIVISION to the rtcNewGeometry function. Various buffers need to be set by the application to set up the subdivision mesh. See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers. The face buffer (RTC_BUFFER_TYPE_FACE type and RTC_FORMAT_UINT format) contains the number of edges/indices of each face (3 to 15), and the number of faces is inferred from the size of this buffer. The index buffer (RTC_BUFFER_TYPE_INDEX type) contains multiple (3 to 15) 32-bit vertex indices (RTC_FORMAT_UINT format) for each face, and the number of edges is inferred from the size of this buffer. The vertex buffer (RTC_BUFFER_TYPE_VERTEX type) stores an array of single precision x, y, z floating point coordinates (RTC_FORMAT_FLOAT3 format), and the number of vertices is inferred from the size of this buffer.

Optionally, the application may set additional index buffers using different buffer slots if multiple topologies are required for face-varying interpolation. The standard vertex buffers (RTC_BUFFER_TYPE_VERTEX) are always bound to the geometry topology (topology 0) thus use RTC_BUFFER_TYPE_INDEX with buffer slot 0. User vertex data interpolation may use different topologies as described later.

Optionally, the application can set up the hole buffer (RTC_BUFFER_TYPE_HOLE) which contains an array of 32-bit indices (RTC_FORMAT_UINT format) of faces that should be considered non-existing in all topologies. The number of holes is inferred from the size of this buffer.

Optionally, the application can fill the level buffer (RTC_BUFFER_TYPE_LEVEL) with a tessellation rate for each of the edges of each face. This buffer must have the same size as the index buffer. The tessellation level is a positive floating point value (RTC_FORMAT_FLOAT format) that specifies how many quads along the edge should be generated during tessellation. If no level buffer is specified, a level of 1 is used. The maximally supported edge level is 4096, and larger levels are clamped to that value. Note that edges may be shared between (typically 2) faces. To guarantee a watertight tessellation, the level of these shared edges should be identical. A uniform tessellation rate for an entire subdivision mesh can be set by using the rtcSetGeometryTessellationRate function. The existence of a level buffer has precedence over the uniform tessellation rate.

Optionally, the application can fill the sparse edge crease buffers to make edges appear sharper. The edge crease index buffer (RTC_BUFFER_TYPE_EDGE_CREASE_INDEX) contains an array of pairs of 32-bit vertex indices (RTC_FORMAT_UINT2 format) that specify unoriented edges in the geometry topology. The edge crease weight buffer (RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT) stores for each of these crease edges a positive floating point weight (RTC_FORMAT_FLOAT format). The number of edge creases is inferred from the size of these buffers, which has to be identical. The larger a weight, the sharper the edge. Specifying a weight of infinity is supported and marks an edge as infinitely sharp. Storing an edge multiple times with the same crease weight is allowed, but has lower performance. Storing an edge multiple times with different crease weights results in undefined behavior. For a stored edge (i,j), the reverse direction edges (j,i) do not have to be stored, as both are considered the same unoriented edge. Edge crease features are shared between all topologies.

Optionally, the application can fill the sparse vertex crease buffers to make vertices appear sharper. The vertex crease index buffer (RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX), contains an array of 32-bit vertex indices (RTC_FORMAT_UINT format) to specify a set of vertices from the geometry topology. The vertex crease weight buffer (RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT) specifies for each of these vertices a positive floating point weight (RTC_FORMAT_FLOAT format). The number of vertex creases is inferred from the size of these buffers, and has to be identical. The larger a weight, the sharper the vertex. Specifying a weight of infinity is supported and makes the vertex infinitely sharp. Storing a vertex multiple times with the same crease weight is allowed, but has lower performance. Storing a vertex multiple times with different crease weights results in undefined behavior. Vertex crease features are shared between all topologies.

Subdivision modes can be used to force linear interpolation for parts of the subdivision mesh; see rtcSetGeometrySubdivisionMode for more details.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers have to have the same stride and size.

Also see tutorial Subdivision Geometry for an example of how to create subdivision surfaces.

Parametrization

The parametrization for subdivision faces is different for quadrilaterals and non-quadrilateral faces.

The parametrization of a quadrilateral face uses the first vertex p0 as base point, and the vector p1 - p0 as u-direction and p3 - p0 as v-direction.

The parametrization for all other face types (with number of vertices not equal 4), have a special parametrization where the subpatch ID n (of the n-th quadrilateral that would be obtained by a single subdivision step) and the local hit location inside this quadrilateral are encoded in the UV coordinates. The following code extracts the sub-patch ID i and local UVs of this subpatch:

unsigned int l = floorf(0.5f*U);
unsigned int h = floorf(0.5f*V);
unsigned int i = 4*h+l;
float u = 2.0f*fracf(0.5f*U)-0.5f;
float v = 2.0f*fracf(0.5f*V)-0.5f;

This encoding allows local subpatch UVs to be in the range [-0.5,1.5[ thus negative subpatch UVs can be passed to rtcInterpolate to sample subpatches slightly out of bounds. This can be useful to calculate derivatives using finite differences if required. The encoding further has the property that one can just move the value u (or v) on a subpatch by adding du (or dv) to the special UV encoding as long as it does not fall out of the [-0.5,1.5[ range.

To smoothly interpolate vertex attributes over the subdivision surface we recommend using the rtcInterpolate function, which will apply the standard subdivision rules for interpolation and automatically takes care of the special UV encoding for non-quadrilaterals.

Face-Varying Data

Face-varying interpolation is supported through multiple topologies per subdivision mesh and binding such topologies to vertex attribute buffers to interpolate. This way, texture coordinates may use a different topology with additional boundaries to construct separate UV regions inside one subdivision mesh.

Each such topology i has a separate index buffer (specified using RTC_BUFFER_TYPE_INDEX with buffer slot i) and separate subdivision mode that can be set using rtcSetGeometrySubdivisionMode. A vertex attribute buffer RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE bound to a buffer slot j can be assigned to use a topology for interpolation using the rtcSetGeometryVertexAttributeTopology call.

The face buffer (RTC_BUFFER_TYPE_FACE type) is shared between all topologies, which means that the n-th primitive always has the same number of vertices (e.g. being a triangle or a quad) for each topology. However, the indices of the topologies themselves may be different.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry]

RTC_GEOMETRY_TYPE_CURVE

NAME {#name}

RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE -
  flat curve geometry with linear basis

RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE -
  flat curve geometry with cubic Bézier basis

RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE - 
  flat curve geometry with cubic B-spline basis

RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE - 
  flat curve geometry with cubic Hermite basis

RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE - 
  flat curve geometry with Catmull-Rom basis

RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE -
  flat normal oriented curve geometry with cubic Bézier basis

RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE - 
  flat normal oriented curve geometry with cubic B-spline basis

RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE - 
  flat normal oriented curve geometry with cubic Hermite basis

RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE - 
  flat normal oriented curve geometry with Catmull-Rom basis

RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE -
  capped cone curve geometry with linear basis - discontinous at edge boundaries

RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE -
  capped cone curve geometry with linear basis and spherical ending

RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE -
  swept surface curve geometry with cubic Bézier basis

RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE -
  swept surface curve geometry with cubic B-spline basis

RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE -
  swept surface curve geometry with cubic Hermite basis

RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE -
  swept surface curve geometry with Catmull-Rom basis

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BEZIER_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_BSPLINE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_HERMITE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_CATMULL_ROM_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE);

DESCRIPTION {#description}

Curves with per vertex radii are supported with linear, cubic Bézier, cubic B-spline, and cubic Hermite bases. Such curve geometries are created by passing RTC_GEOMETRY_TYPE_FLAT_LINEAR_CURVE, RTC_GEOMETRY_TYPE_FLAT_BEZIER_CURVE, RTC_GEOMETRY_TYPE_FLAT_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_FLAT_HERMITE_CURVE, RTC_GEOMETRY_TYPE_FLAT_CATMULL_ROM_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BEZIER_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_HERMITE_CURVE, RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_FLAT_CATMULL_ROM_CURVE, RTC_GEOMETRY_TYPE_CONE_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_LINEAR_CURVE, RTC_GEOMETRY_TYPE_ROUND_BEZIER_CURVE, RTC_GEOMETRY_TYPE_ROUND_BSPLINE_CURVE, RTC_GEOMETRY_TYPE_ROUND_HERMITE_CURVE, or RTC_GEOMETRY_TYPE_ROUND_CATMULL_ROM_CURVE to the rtcNewGeometry function. The curve indices can be specified through an index buffer (RTC_BUFFER_TYPE_INDEX) and the curve vertices through a vertex buffer (RTC_BUFFER_TYPE_VERTEX). For the Hermite basis a tangent buffer (RTC_BUFFER_TYPE_TANGENT), normal oriented curves a normal buffer (RTC_BUFFER_TYPE_NORMAL), and for normal oriented Hermite curves a normal derivative buffer (RTC_BUFFER_TYPE_NORMAL_DERIVATIVE) has to get specified additionally. See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers.

The index buffer contains an array of 32-bit indices (RTC_FORMAT_UINT format), each pointing to the first control vertex in the vertex buffer, but also to the first tangent in the tangent buffer, and first normal in the normal buffer if these buffers are present.

The vertex buffer stores each control vertex in the form of a single precision position and radius stored in (x, y, z, r) order in memory (RTC_FORMAT_FLOAT4 format). The number of vertices is inferred from the size of this buffer. The radii may be smaller than zero but the interpolated radii should always be greater or equal to zero. Similarly, the tangent buffer stores the derivative of each control vertex (x, y, z, r order and RTC_FORMAT_FLOAT4 format) and the normal buffer stores a single precision normal per control vertex (x, y, z order and RTC_FORMAT_FLOAT3 format).

Linear Basis

For the linear basis the indices point to the first of 2 consecutive control points in the vertex buffer. The first control point is the start and the second control point the end of the line segment. When constructing hair strands in this basis, the end-point can be shared with the start of the next line segment.

For the linear basis the user optionally can provide a flags buffer of type RTC_BUFFER_TYPE_FLAGS which contains bytes that encode if the left neighbor segment (RTC_CURVE_FLAG_NEIGHBOR_LEFT flag) and/or right neighbor segment (RTC_CURVE_FLAG_NEIGHBOR_RIGHT flags) exist (see [RTCCurveFlags]). If this buffer is not set, than the left/right neighbor bits are automatically calculated base on the index buffer (left segment exists if segment(id-1)+1 == segment(id) and right segment exists if segment(id+1)-1 == segment(id)).

A left neighbor segment is assumed to end at the start vertex of the current segement, and to start at the previous vertex in the vertex buffer. Similarly, the right neighbor segment is assumed to start at the end vertex of the current segment, and to end at the next vertex in the vertex buffer.

Only when the left and right bits are properly specified the current segment can properly attach to the left and/or right neighbor, otherwise the touching area may not get rendererd properly.

Bézier Basis

For the cubic Bézier basis the indices point to the first of 4 consecutive control points in the vertex buffer. These control points use the cubic Bézier basis, where the first control point represents the start point of the curve, and the 4th control point the end point of the curve. The Bézier basis is interpolating, thus the curve does go exactly through the first and fourth control vertex.

B-spline Basis

For the cubic B-spline basis the indices point to the first of 4 consecutive control points in the vertex buffer. These control points make up a cardinal cubic B-spline (implicit equidistant knot vector). This basis is not interpolating, thus the curve does in general not go through any of the control points directly. A big advantage of this basis is that 3 control points can be shared for two continuous neighboring curve segments, e.g. the curves (p0,p1,p2,p3) and (p1,p2,p3,p4) are C1 continuous. This feature make this basis a good choise to construct continuous multi-segment curves, as memory consumption can be kept minimal.

Hermite Basis

For the cubic Hermite basis the indices point to the first of 2 consecutive points in the vertex buffer, and the first of 2 consecutive tangents in the tangent buffer. These two points and two tangents make up a cubic Hermite curve. This basis is interpolating, thus does exactly go through the first and second control point, and the first order derivative at the begin and end matches exactly the value specified in the tangent buffer. When connecting two segments continuously, the end point and tangent of the previous segment can be shared. Different versions of Catmull-Rom splines can be easily constructed usig the Hermite basis, by calculating a proper tangent buffer from the control points.

Catmull-Rom Basis

For the Catmull-Rom basis the indices point to the first of 4 consecutive control points in the vertex buffer. This basis goes through p1 and p2, with tangents (p2-p0)/2 and (p3-p1)/2.

Flat Curves

The RTC_GEOMETRY_TYPE_FLAT_* flat mode is a fast mode designed to render distant hair. In this mode the curve is rendered as a connected sequence of ray facing quads. Individual quads are considered to have subpixel size, and zooming onto the curve might show geometric artifacts. The number of quads to subdivide into can be specified through the rtcSetGeometryTessellationRate function. By default the tessellation rate is 4.

Normal Oriented Curves

The RTC_GEOMETRY_TYPE_NORMAL_ORIENTED_* mode is a mode designed to render blades of grass. In this mode a vertex spline has to get specified as for the previous modes, but additionally a normal spline is required. If the Hermite basis is used, the RTC_BUFFER_TYPE_NORMAL and RTC_BUFFER_TYPE_NORMAL_DERIVATIVE buffers have both to be set.

The curve is rendered as a flat band whose center approximately follows the provided vertex spline, whose half width approximately follows the provided radius spline, and whose normal orientation approximately follows the provided normal spline.

To intersect the normal oriented curve, we perform a newton-raphson style intersection of a ray with a tensor product surface of a linear basis (perpendicular to the curve) and cubic Bézier basis (along the curve). We use a guide curve and its derivatives to construct the control points of that surface. The guide curve is defined by a sweep surface defined by sweeping a line centered at the vertex spline location along the curve. At each parameter value the half width of the line matches the radius spline, and the direction matches the cross product of the normal from the normal spline and tangent of the vertex spline. Note that this construction does not work when the provided normals are parallel to the curve direction. For this reason the provided normals should best be kept as perpendicular to the curve direction as possible.

Round Curves

In the RTC_GEOMETRY_TYPE_ROUND_* round mode, a real geometric surface is rendered for the curve, which is more expensive but allows closeup views.

For the linear basis the round mode renders a cone that tangentially touches a start-sphere and end-sphere. The start sphere is rendered when no previous segments is indicated by the neighbor bits. The end sphere is always rendered but parts that lie inside the next segment are clipped away (if that next segment exists). This way a curve is closed on both ends and the interiour will render properly as long as only neighboring segments penetrate into a segment. For this to work properly it is important that the flags buffer is properly populated with neighbor information.

For the cubic polynomial bases, the round mode renders a sweep surface by sweeping a varying radius circle tangential along the curve. As a limitation, the radius of the curve has to be smaller than the curvature radius of the curve at each location on the curve.

The intersection with the curve segment stores the parametric hit location along the curve segment as u-coordinate (range 0 to +1).

For flat curves, the v-coordinate is set to the normalized distance in the range -1 to +1. For normal oriented curves the v-coordinate is in the range 0 to 1. For the linear basis and in round mode the v-coordinate is set to zero.

In flat mode, the geometry normal Ng is set to the tangent of the curve at the hit location. In round mode and for normal oriented curves, the geometry normal Ng is set to the non-normalized geometric normal of the surface.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers must have the same stride and size. For the Hermite basis also a tangent buffer has to be set for each time step and for normal oriented curves a normal buffer has to get specified for each time step.

Also see tutorials Hair and Curves for examples of how to create and use curve geometries.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [RTCCurveFlags]

RTC_GEOMETRY_TYPE_POINT

NAME {#name}

RTC_GEOMETRY_TYPE_SPHERE_POINT -
  point geometry spheres

RTC_GEOMETRY_TYPE_DISC_POINT -
  point geometry with ray-oriented discs

RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT -
  point geometry with normal-oriented discs

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SPHERE_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_DISC_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT);

DESCRIPTION {#description}

Points with per vertex radii are supported with sphere, ray-oriented discs, and normal-oriented discs geometric representations. Such point geometries are created by passing RTC_GEOMETRY_TYPE_SPHERE_POINT, RTC_GEOMETRY_TYPE_DISC_POINT, or RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT to the rtcNewGeometry function. The point vertices can be specified t through a vertex buffer (RTC_BUFFER_TYPE_VERTEX). For the normal oriented discs a normal buffer (RTC_BUFFER_TYPE_NORMAL) has to get specified additionally. See rtcSetGeometryBuffer and rtcSetSharedGeometryBuffer for more details on how to set buffers.

The vertex buffer stores each control vertex in the form of a single precision position and radius stored in (x, y, z, r) order in memory (RTC_FORMAT_FLOAT4 format). The number of vertices is inferred from the size of this buffer. Similarly, the normal buffer stores a single precision normal per control vertex (x, y, z order and RTC_FORMAT_FLOAT3 format).

In the RTC_GEOMETRY_TYPE_SPHERE_POINT mode, a real geometric surface is rendered for the curve, which is more expensive but allows closeup views.

The RTC_GEOMETRY_TYPE_DISC_POINT flat mode is a fast mode designed to render distant points. In this mode the point is rendered as a ray facing disc.

The RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT mode is a mode designed as a midpoint geometrically between ray facing discs and spheres. In this mode the point is rendered as a normal oriented disc.

For all point types, only the hit distance and geometry normal is returned as hit information, u and v are set to zero.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount call. Then a vertex buffer for each time step can be set using different buffer slots, and all these buffers must have the same stride and size.

Also see tutorial [Points] for an example of how to create and use point geometries.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry]

RTC_GEOMETRY_TYPE_USER

NAME {#name}

RTC_GEOMETRY_TYPE_USER - user geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
  rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER);

DESCRIPTION {#description}

User-defined geometries contain a number of user-defined primitives, just like triangle meshes contain multiple triangles. The shape of the user-defined primitives is specified through registered callback functions, which enable extending Embree with arbitrary types of primitives.

User-defined geometries are created by passing RTC_GEOMETRY_TYPE_USER to the rtcNewGeometry function call. One has to set the number of primitives (see rtcSetGeometryUserPrimitiveCount), a user data pointer (see rtcSetGeometryUserData), a bounding function closure (see rtcSetGeometryBoundsFunction), as well as user-defined intersect (see rtcSetGeometryIntersectFunction) and occluded (see rtcSetGeometryOccludedFunction) callback functions. The bounding function is used to query the bounds of all time steps of a user primitive, while the intersect and occluded callback functions are called to intersect the primitive with a ray. The user data pointer is passed to each callback invocation and can be used to point to the application's representation of the user geometry.

The creation of a user geometry typically looks the following:

RTCGeometry geometry = rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER);
rtcSetGeometryUserPrimitiveCount(geometry, numPrimitives);
rtcSetGeometryUserData(geometry, userGeometryRepresentation);
rtcSetGeometryBoundsFunction(geometry, boundsFunction);
rtcSetGeometryIntersectFunction(geometry, intersectFunction);
rtcSetGeometryOccludedFunction(geometry, occludedFunction);

Please have a look at the rtcSetGeometryBoundsFunction, rtcSetGeometryIntersectFunction, and rtcSetGeometryOccludedFunction functions on the implementation of the callback functions.

Primitives of a user geometry are ignored during rendering when their bounds are empty, thus bounds have lower>upper in at least one dimension.

See tutorial User Geometry for an example of how to use the user-defined geometries.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcSetGeometryUserPrimitiveCount], [rtcSetGeometryUserData], [rtcSetGeometryBoundsFunction], [rtcSetGeometryIntersectFunction], [rtcSetGeometryOccludedFunction]

RTC_GEOMETRY_TYPE_INSTANCE

NAME {#name}

RTC_GEOMETRY_TYPE_INSTANCE - instance geometry type

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

RTCGeometry geometry =
   rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE);

DESCRIPTION {#description}

Embree supports instancing of scenes using affine transformations (3×3 matrix plus translation). As the instanced scene is stored only a single time, even if instanced to multiple locations, this feature can be used to create very complex scenes with small memory footprint.

Embree supports both single-level instancing and multi-level instancing. The maximum instance nesting depth is RTC_MAX_INSTANCE_LEVEL_COUNT; it can be configured at compile-time using the constant EMBREE_MAX_INSTANCE_LEVEL_COUNT. Users should adapt this constant to their needs: instances nested any deeper are silently ignored in release mode, and cause assertions in debug mode.

Instances are created by passing RTC_GEOMETRY_TYPE_INSTANCE to the rtcNewGeometry function call. The instanced scene can be set using the rtcSetGeometryInstancedScene call, and the affine transformation can be set using the rtcSetGeometryTransform function.

Please note that rtcCommitScene on the instanced scene should be called first, followed by rtcCommitGeometry on the instance, followed by rtcCommitScene for the top-level scene containing the instance.

If a ray hits the instance, the geomID and primID members of the hit are set to the geometry ID and primitive ID of the hit primitive in the instanced scene, and the instID member of the hit is set to the geometry ID of the instance in the top-level scene.

The instancing scheme can also be implemented using user geometries. To achieve this, the user geometry code should set the instID member of the intersection context to the geometry ID of the instance, then trace the transformed ray, and finally set the instID field of the intersection context again to -1. The instID field is copied automatically by each primitive intersector into the instID field of the hit structure when the primitive is hit. See the User Geometry tutorial for an example.

For multi-segment motion blur, the number of time steps must be first specified using the rtcSetGeometryTimeStepCount function. Then a transformation for each time step can be specified using the rtcSetGeometryTransform function.

See tutorials Instanced Geometry and Multi Level Instancing for examples of how to use instances.

EXIT STATUS {#exit-status}

On failure NULL is returned and an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcSetGeometryInstancedScene], [rtcSetGeometryTransform]

RTCCurveFlags

NAME {#name}

RTCCurveFlags - per segment flags for curve geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

enum RTCCurveFlags { RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0), RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1) };

DESCRIPTION {#description}

The RTCCurveFlags type is used for linear curves to determine if the left and/or right neighbor segment exist. Therefore one attaches a buffer of type RTC_BUFFER_TYPE_FLAGS to the curve geometry which stores an individual byte per curve segment.

If the RTC_CURVE_FLAG_NEIGHBOR_LEFT flag in that byte is enabled for a curve segment, then the left segment exists (which starts one vertex before the start vertex of the current curve) and the current segment is rendered to properly attach to that segment.

If the RTC_CURVE_FLAG_NEIGHBOR_RIGHT flag in that byte is enabled for a curve segment, then the right segment exists (which ends one vertex after the end vertex of the current curve) and the current segment is rendered to properly attach to that segment.

When not properly specifying left and right flags for linear curves, the rendering at the ending of these curves may not look correct, in particular when round linear curves are viewed from the inside.

EXIT STATUS {#exit-status}

SEE ALSO {#see-also}

[RTC_GEOMETRY_TYPE_CURVE]

rtcRetainGeometry

NAME {#name}

rtcRetainGeometry - increments the geometry reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcRetainGeometry(RTCGeometry geometry);

DESCRIPTION {#description}

Geometry objects are reference counted. The rtcRetainGeometry function increments the reference count of the passed geometry object (geometry argument). This function together with rtcReleaseGeometry allows to use the internal reference counting in a C++ wrapper class to handle the ownership of the object.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcReleaseGeometry]

rtcReleaseGeometry

NAME {#name}

rtcReleaseGeometry - decrements the geometry reference count

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcReleaseGeometry(RTCGeometry geometry);

DESCRIPTION {#description}

Geometry objects are reference counted. The rtcReleaseGeometry function decrements the reference count of the passed geometry object (geometry argument). When the reference count falls to 0, the geometry gets destroyed.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcRetainGeometry]

rtcCommitGeometry

NAME {#name}

rtcCommitGeometry - commits geometry changes

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcCommitGeometry(RTCGeometry geometry);

DESCRIPTION {#description}

The rtcCommitGeometry function is used to commit all geometry changes performed to a geometry (geometry parameter). After a geometry gets modified, this function must be called to properly update the internal state of the geometry to perform interpolations using rtcInterpolate or to commit a scene containing the geometry using rtcCommitScene.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcInterpolate], [rtcCommitScene]

rtcEnableGeometry

NAME {#name}

rtcEnableGeometry - enables the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcEnableGeometry(RTCGeometry geometry);

DESCRIPTION {#description}

The rtcEnableGeometry function enables the specified geometry (geometry argument). Only enabled geometries are rendered. Each geometry is enabled by default at construction time.

After enabling a geometry, the scene containing that geometry must be committed using rtcCommitScene for the change to have effect.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcDisableGeometry], [rtcCommitScene]

rtcDisableGeometry

NAME {#name}

rtcDisableGeometry - disables the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcDisableGeometry(RTCGeometry geometry);

DESCRIPTION {#description}

The rtcDisableGeometry function disables the specified geometry (geometry argument). A disabled geometry is not rendered. Each geometry is enabled by default at construction time.

After disabling a geometry, the scene containing that geometry must be committed using rtcCommitScene for the change to have effect.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcEnableGeometry], [rtcCommitScene]

rtcSetGeometryTimeStepCount

NAME {#name}

rtcSetGeometryTimeStepCount - sets the number of time steps of the
  geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryTimeStepCount(
  RTCGeometry geometry,
  unsigned int timeStepCount
);

DESCRIPTION {#description}

The rtcSetGeometryTimeStepCount function sets the number of time steps for multi-segment motion blur (timeStepCount parameter) of the specified geometry (geometry parameter).

For triangle meshes (RTC_GEOMETRY_TYPE_TRIANGLE), quad meshes (RTC_GEOMETRY_TYPE_QUAD), curves (RTC_GEOMETRY_TYPE_CURVE), points (RTC_GEOMETRY_TYPE_POINT), and subdivision geometries (RTC_GEOMETRY_TYPE_SUBDIVISION), the number of time steps directly corresponds to the number of vertex buffer slots available (RTC_BUFFER_TYPE_VERTEX buffer type). For these geometries, one vertex buffer per time step must be specified when creating multi-segment motion blur geometries.

For instance geometries (RTC_GEOMETRY_TYPE_INSTANCE), a transformation must be specified for each time step (see rtcSetGeometryTransform).

For user geometries, the registered bounding callback function must provide a bounding box per primitive and time step, and the intersection and occlusion callback functions should properly intersect the motion-blurred geometry at the ray time.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcSetGeometryTimeRange]

rtcSetGeometryTimeRange

NAME {#name}

rtcSetGeometryTimeRange - sets the time range for a motion blur geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryTimeRange(
  RTCGeometry geometry,
  float startTime,
  float endTime
);

DESCRIPTION {#description}

The rtcSetGeometryTimeRange function sets a time range which defines the start (and end time) of the first (and last) time step of a motion blur geometry. The time range is defined relative to the camera shutter interval [0,1] but it can be arbitrary. Thus the startTime can be smaller, equal, or larger 0, indicating a geometry whose animation definition start before, at, or after the camera shutter opens. Similar the endTime can be smaller, equal, or larger than 1, indicating a geometry whose animation definition ends after, at, or before the camera shutter closes. The startTime has to be smaller or equal to the endTime.

The default time range when this function is not called is the entire camera shutter [0,1]. For best performance at most one time segment of the piece wise linear definition of the motion should fall outside the shutter window to the left and to the right. Thus do not set the startTime or endTime too far outside the [0,1] interval for best performance.

This time range feature will also allow geometries to appear and disappear during the camera shutter time if the specified time range is a sub range of [0,1].

Please also have a look at the rtcSetGeometryTimeStepCount function to see how to define the time steps for the specified time range.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryTimeStepCount]

rtcSetGeometryVertexAttributeCount

NAME {#name}

rtcSetGeometryVertexAttributeCount - sets the number of vertex
  attributes of the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryVertexAttributeCount(
  RTCGeometry geometry,
  unsigned int vertexAttributeCount
);

DESCRIPTION {#description}

The rtcSetGeometryVertexAttributeCount function sets the number of slots (vertexAttributeCount parameter) for vertex attribute buffers (RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) that can be used for the specified geometry (geometry parameter).

This function is supported only for triangle meshes (RTC_GEOMETRY_TYPE_TRIANGLE), quad meshes (RTC_GEOMETRY_TYPE_QUAD), curves (RTC_GEOMETRY_TYPE_CURVE), points (RTC_GEOMETRY_TYPE_POINT), and subdivision geometries (RTC_GEOMETRY_TYPE_SUBDIVISION).

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [RTCBufferType]

rtcSetGeometryMask

NAME {#name}

rtcSetGeometryMask - sets the geometry mask

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryMask(
  RTCGeometry geometry,
  unsigned int mask
);

DESCRIPTION {#description}

The rtcSetGeometryMask function sets a 32-bit geometry mask (mask argument) for the specified geometry (geometry argument).

This geometry mask is used together with the ray mask stored inside the mask field of the ray. The primitives of the geometry are hit by the ray only if the bitwise and operation of the geometry mask with the ray mask is not 0. This feature can be used to disable selected geometries for specifically tagged rays, e.g. to disable shadow casting for certain geometries.

Ray masks are disabled in Embree by default at compile time, and can be enabled through the EMBREE_RAY_MASK parameter in CMake. One can query whether ray masks are enabled by querying the RTC_DEVICE_PROPERTY_RAY_MASK_SUPPORTED device property using rtcGetDeviceProperty.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[RTCRay], [rtcGetDeviceProperty]

rtcSetGeometryBuildQuality

NAME {#name}

rtcSetGeometryBuildQuality - sets the build quality for the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryBuildQuality(
  RTCGeometry geometry,
  enum RTCBuildQuality quality
);

DESCRIPTION {#description}

The rtcSetGeometryBuildQuality function sets the build quality (quality argument) for the specified geometry (geometry argument). The per-geometry build quality is only a hint and may be ignored. Embree currently uses the per-geometry build quality when the scene build quality is set to RTC_BUILD_QUALITY_LOW. In this mode a two-level acceleration structure is build, and geometries build a separate acceleration structure using the geometry build quality. The per-geometry build quality can be one of:

  • RTC_BUILD_QUALITY_LOW: Creates lower quality data structures, e.g. for dynamic scenes.

  • RTC_BUILD_QUALITY_MEDIUM: Default build quality for most usages. Gives a good compromise between build and render performance.

  • RTC_BUILD_QUALITY_HIGH: Creates higher quality data structures for final-frame rendering. Enables a spatial split builder for certain primitive types.

  • RTC_BUILD_QUALITY_REFIT: Uses a BVH refitting approach when changing only the vertex buffer.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetSceneBuildQuality]

rtcSetGeometryBuffer

NAME {#name}

rtcSetGeometryBuffer - assigns a view of a buffer to the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryBuffer(
  RTCGeometry geometry,
  enum RTCBufferType type,
  unsigned int slot,
  enum RTCFormat format,
  RTCBuffer buffer,
  size_t byteOffset,
  size_t byteStride,
  size_t itemCount
);

DESCRIPTION {#description}

The rtcSetGeometryBuffer function binds a view of a buffer object (buffer argument) to a geometry buffer type and slot (type and slot argument) of the specified geometry (geometry argument).

One can specify the start of the first buffer element in bytes (byteOffset argument), the byte stride between individual buffer elements (byteStride argument), the format of the buffer elements (format argument), and the number of elements to bind (itemCount).

The start address (byteOffset argument) and stride (byteStride argument) must be both aligned to 4 bytes, otherwise the rtcSetGeometryBuffer function will fail.

After successful completion of this function, the geometry will hold a reference to the buffer object.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]

rtcSetSharedGeometryBuffer

NAME {#name}

rtcSetSharedGeometryBuffer - assigns a view of a shared data buffer
  to a geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetSharedGeometryBuffer(
  RTCGeometry geometry,
  enum RTCBufferType type,
  unsigned int slot,
  enum RTCFormat format,
  const void* ptr,
  size_t byteOffset,
  size_t byteStride,
  size_t itemCount
);

DESCRIPTION {#description}

The rtcSetSharedGeometryBuffer function binds a view of a shared user-managed data buffer (ptr argument) to a geometry buffer type and slot (type and slot argument) of the specified geometry (geometry argument).

One can specify the start of the first buffer element in bytes (byteOffset argument), the byte stride between individual buffer elements (byteStride argument), the format of the buffer elements (format argument), and the number of elements to bind (itemCount).

The start address (byteOffset argument) and stride (byteStride argument) must be both aligned to 4 bytes; otherwise the rtcSetGeometryBuffer function will fail.

When the buffer will be used as a vertex buffer (RTC_BUFFER_TYPE_VERTEX and RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE), the last buffer element must be readable using 16-byte SSE load instructions, thus padding the last element is required for certain layouts. E.g. a standard float3 vertex buffer layout should add storage for at least one more float to the end of the buffer.

The buffer data must remain valid for as long as the buffer may be used, and the user is responsible for freeing the buffer data when no longer required.

Sharing buffers can significantly reduce the memory required by the application, thus we recommend using this feature. When enabling the RTC_SCENE_FLAG_COMPACT scene flag, the spatial index structures index into the vertex buffer, resulting in even higher memory savings.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer]

rtcSetNewGeometryBuffer

NAME {#name}

rtcSetNewGeometryBuffer - creates and assigns a new data buffer to
  the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void* rtcSetNewGeometryBuffer(
  RTCGeometry geometry,
  enum RTCBufferType type,
  unsigned int slot,
  enum RTCFormat format,
  size_t byteStride,
  size_t itemCount
);

DESCRIPTION {#description}

The rtcSetNewGeometryBuffer function creates a new data buffer of specified format (format argument), byte stride (byteStride argument), and number of items (itemCount argument), and assigns it to a geometry buffer slot (type and slot argument) of the specified geometry (geometry argument). The buffer data is managed internally and automatically freed when the geometry is destroyed.

The byte stride (byteStride argument) must be aligned to 4 bytes; otherwise the rtcSetNewGeometryBuffer function will fail.

The allocated buffer will be automatically over-allocated slightly when used as a vertex buffer, where a requirement is that each buffer element should be readable using 16-byte SSE load instructions.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer]

RTCFormat

NAME {#name}

RTCFormat - specifies format of data in buffers

SYNOPSIS {#synopsis}

#include <embree3/rtcore_ray.h>

enum RTCFormat
{
  RTC_FORMAT_UINT,
  RTC_FORMAT_UINT2,
  RTC_FORMAT_UINT3,
  RTC_FORMAT_UINT4,

  RTC_FORMAT_FLOAT,
  RTC_FORMAT_FLOAT2,
  RTC_FORMAT_FLOAT3,
  RTC_FORMAT_FLOAT4,
  RTC_FORMAT_FLOAT5,
  RTC_FORMAT_FLOAT6,
  RTC_FORMAT_FLOAT7,
  RTC_FORMAT_FLOAT8,
  RTC_FORMAT_FLOAT9,
  RTC_FORMAT_FLOAT10,
  RTC_FORMAT_FLOAT11,
  RTC_FORMAT_FLOAT12,
  RTC_FORMAT_FLOAT13,
  RTC_FORMAT_FLOAT14,
  RTC_FORMAT_FLOAT15,
  RTC_FORMAT_FLOAT16,

  RTC_FORMAT_FLOAT3X4_ROW_MAJOR,
  RTC_FORMAT_FLOAT4X4_ROW_MAJOR,

  RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,
  RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR,

  RTC_FORMAT_GRID,

};

DESCRIPTION {#description}

The RTFormat structure defines the data format stored in data buffers provided to Embree using the [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], and [rtcSetNewGeometryBuffer] API calls.

The RTC_FORMAT_UINT/2/3/4 format are used to specify that data buffers store unsigned integers, or unsigned integer vectors of size 2,3 or 4. This format has typically to get used when specifying index buffers, e.g. RTC_FORMAT_UINT3 for triangle meshes.

The RTC_FORMAT_FLOAT/2/3/4... format are used to specify that data buffers store single precision floating point values, or vectors there of (size 2,3,4, etc.). This format is typcally used to specify to format of vertex buffers, e.g. the RTC_FORMAT_FLOAT3 type for vertex buffers of triangle meshes.

The RTC_FORMAT_FLOAT3X4_ROW_MAJOR and RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR formats, specify a 3x4 floating point matrix layed out either row major or column major. The RTC_FORMAT_FLOAT4X4_ROW_MAJOR and RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR formats, specify a 4x4 floating point matrix layed out either row major or column major. These matrix formats are used in the [rtcSetGeometryTransform] function in order to set a transformation matrix for geometries.

The RTC_FORMAT_GRID is a special data format used to specify grid primitives of layout RTCGrid when creating grid geometries (see [RTC_GEOMETRY_TYPE_GRID]).

EXIT STATUS {#exit-status}

SEE ALSO {#see-also}

[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer], [rtcSetGeometryTransform]

RTCBufferType

NAME {#name}

RTCFormat - specifies format of data in buffers

SYNOPSIS {#synopsis}

#include <embree3/rtcore_ray.h>

enum RTCBufferType
{
  RTC_BUFFER_TYPE_INDEX            = 0,
  RTC_BUFFER_TYPE_VERTEX           = 1,
  RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE = 2,
  RTC_BUFFER_TYPE_NORMAL           = 3,
  RTC_BUFFER_TYPE_TANGENT          = 4,
  RTC_BUFFER_TYPE_NORMAL_DERIVATIVE = 5,

  RTC_BUFFER_TYPE_GRID                 = 8,

  RTC_BUFFER_TYPE_FACE                 = 16,
  RTC_BUFFER_TYPE_LEVEL                = 17,
  RTC_BUFFER_TYPE_EDGE_CREASE_INDEX    = 18,
  RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT   = 19,
  RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX  = 20,
  RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT = 21,
  RTC_BUFFER_TYPE_HOLE                 = 22,

  RTC_BUFFER_TYPE_FLAGS = 32
};

DESCRIPTION {#description}

The RTBufferType structure defines slots to assign data buffers to using the [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], and [rtcSetNewGeometryBuffer] API calls.

For most geometry types the RTC_BUFFER_TYPE_INDEX slot is used to assign an index buffer, while the RTC_BUFFER_TYPE_VERTEX is used to assign the corresponding vertex buffer.

The RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE slot can get used to assign arbitrary additional vertex data which can get interpolated using the [rtcInterpolate] API call.

The RTC_BUFFER_TYPE_NORMAL, RTC_BUFFER_TYPE_TANGENT, and RTC_BUFFER_TYPE_NORMAL_DERIVATIVE are special buffers required to assign per vertex normals, tangents, and normal derivatives for some curve types.

The RTC_BUFFER_TYPE_GRID buffer is used to assign the grid primitive buffer for grid geometries (see [RTC_GEOMETRY_TYPE_GRID]).

The RTC_BUFFER_TYPE_FACE, RTC_BUFFER_TYPE_LEVEL, RTC_BUFFER_TYPE_EDGE_CREASE_INDEX, RTC_BUFFER_TYPE_EDGE_CREASE_WEIGHT, RTC_BUFFER_TYPE_VERTEX_CREASE_INDEX, RTC_BUFFER_TYPE_VERTEX_CREASE_WEIGHT, and RTC_BUFFER_TYPE_HOLE are special buffers required to create subdivision meshes (see [RTC_GEOMETRY_TYPE_SUBDIVISION]).

The RTC_BUFFER_TYPE_FLAGS can get used to add additional flag per primitive of a geometry, and is currently only used for linear curves.

EXIT STATUS {#exit-status}

SEE ALSO {#see-also}

[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]

rtcGetGeometryBufferData

NAME {#name}

rtcGetGeometryBufferData - gets pointer to
  the first buffer view element

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void* rtcGetGeometryBufferData(
  RTCGeometry geometry,
  enum RTCBufferType type,
  unsigned int slot
);

DESCRIPTION {#description}

The rtcGetGeometryBufferData function returns a pointer to the first element of the buffer view attached to the specified buffer type and slot (type and slot argument) of the geometry (geometry argument).

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]

rtcUpdateGeometryBuffer

NAME {#name}

rtcUpdateGeometryBuffer - marks a buffer view bound to the geometry
  as modified

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcUpdateGeometryBuffer(
  RTCGeometry geometry,
  enum RTCBufferType type,
  unsigned int slot
);

DESCRIPTION {#description}

The rtcUpdateGeometryBuffer function marks the buffer view bound to the specified buffer type and slot (type and slot argument) of a geometry (geometry argument) as modified.

If a data buffer is changed by the application, the rtcUpdateGeometryBuffer call must be invoked for that buffer. Each buffer view assigned to a buffer slot is initially marked as modified, thus this function needs to be called only when doing buffer modifications after the first rtcCommitScene.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcNewGeometry], [rtcCommitScene]

rtcSetGeometryIntersectFilterFunction

NAME {#name}

rtcSetGeometryIntersectFilterFunction - sets the intersection filter
  for the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCFilterFunctionNArguments
{
  int* valid;
  void* geometryUserPtr;
  const struct RTCIntersectContext* context;
  struct RTCRayN* ray;
  struct RTCHitN* hit;
  unsigned int N;
};

typedef void (*RTCFilterFunctionN)(
  const struct RTCFilterFunctionNArguments* args
);

void rtcSetGeometryIntersectFilterFunction(
  RTCGeometry geometry,
  RTCFilterFunctionN filter
);

DESCRIPTION {#description}

The rtcSetGeometryIntersectFilterFunction function registers an intersection filter callback function (filter argument) for the specified geometry (geometry argument).

Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

The registered intersection filter function is invoked for every hit encountered during the rtcIntersect-type ray queries and can accept or reject that hit. The feature can be used to define a silhouette for a primitive and reject hits that are outside the silhouette. E.g. a tree leaf could be modeled with an alpha texture that decides whether hit points lie inside or outside the leaf.

If the RTC_BUILD_QUALITY_HIGH mode is set, the filter functions may be called multiple times for the same primitive hit. Further, rays hitting exactly the edge might also report two hits for the same surface. For certain use cases, the application may have to work around this limitation by collecting already reported hits (geomID/primID pairs) and ignoring duplicates.

The filter function callback of type RTCFilterFunctionN gets passed a number of arguments through the RTCFilterFunctionNArguments structure. The valid parameter of that structure points to an integer valid mask (0 means invalid and -1 means valid). The geometryUserPtr member is a user pointer optionally set per geometry through the rtcSetGeometryUserData function. The context member points to the intersection context passed to the ray query function. The ray parameter points to N rays in SOA layout. The hit parameter points to N hits in SOA layout to test. The N parameter is the number of rays and hits in ray and hit. The hit distance is provided as the tfar value of the ray. If the hit geometry is instanced, the instID member of the ray is valid, and the ray and the potential hit are in object space.

The filter callback function has the task to check for each valid ray whether it wants to accept or reject the corresponding hit. To reject a hit, the filter callback function just has to write 0 to the integer valid mask of the corresponding ray. To accept the hit, it just has to leave the valid mask set to -1. The filter function is further allowed to change the hit and decrease the tfar value of the ray but it should not modify other ray data nor any inactive components of the ray or hit.

When performing ray queries using rtcIntersect1, it is guaranteed that the packet size is 1 when the callback is invoked. When performing ray queries using the rtcIntersect4/8/16 functions, it is not generally guaranteed that the ray packet size (and order of rays inside the packet) passed to the callback matches the initial ray packet. However, under some circumstances these properties are guaranteed, and whether this is the case can be queried using rtcGetDeviceProperty. When performing ray queries using the stream API such as rtcIntersect1M, rtcIntersect1Mp, rtcIntersectNM, or rtcIntersectNp the order of rays and ray packet size of the callback function might change to either 1, 4, 8, or 16.

For many usage scenarios, repacking and re-ordering of rays does not cause difficulties in implementing the callback function. However, algorithms that need to extend the ray with additional data must use the rayID component of the ray to identify the original ray to access the per-ray data.

The implementation of the filter function can choose to implement a single code path that uses the ray access helper functions RTCRay_XXX and hit access helper functions RTCHit_XXX to access ray and hit data. Alternatively the code can branch to optimized implementations for specific sizes of N and cast the ray and hit inputs to the proper packet types.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryOccludedFilterFunction]

rtcSetGeometryOccludedFilterFunction

NAME {#name}

rtcSetGeometryOccludedFilterFunction - sets the occlusion filter
  for the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryOccludedFilterFunction(
  RTCGeometry geometry,
  RTCFilterFunctionN filter
);

DESCRIPTION {#description}

The rtcSetGeometryOccludedFilterFunction function registers an occlusion filter callback function (filter argument) for the specified geometry (geometry argument).

Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

The registered intersection filter function is invoked for every hit encountered during the rtcOccluded-type ray queries and can accept or reject that hit. The feature can be used to define a silhouette for a primitive and reject hits that are outside the silhouette. E.g. a tree leaf could be modeled with an alpha texture that decides whether hit points lie inside or outside the leaf.

Please see the description of the rtcSetGeometryIntersectFilterFunction for a description of the filter callback function.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryIntersectFilterFunction]

rtcFilterIntersection

NAME {#name}

rtcFilterIntersection - invokes the intersection filter function

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcFilterIntersection(
  const struct RTCIntersectFunctionNArguments* args,
  const struct RTCFilterFunctionNArguments* filterArgs
);

DESCRIPTION {#description}

The rtcFilterIntersection function can be called inside an RTCIntersectFunctionN callback function to invoke the intersection filter registered to the geometry and stored inside the context. For this an RTCFilterFunctionNArguments structure must be created (see rtcSetGeometryIntersectFilterFunction) which basically consists of a valid mask, a hit packet to filter, the corresponding ray packet, and the packet size. After the invocation of rtcFilterIntersection, only rays that are still valid (valid mask set to -1) should update a hit.

EXIT STATUS {#exit-status}

For performance reasons this function does not do any error checks, thus will not set any error flags on failure.

SEE ALSO {#see-also}

[rtcFilterOcclusion], [rtcSetGeometryIntersectFunction]

rtcFilterOcclusion

NAME {#name}

rtcFilterOcclusion - invokes the occlusion filter function

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcFilterOcclusion(
  const struct RTCOccludedFunctionNArguments* args,
  const struct RTCFilterFunctionNArguments* filterArgs
);

DESCRIPTION {#description}

The rtcFilterOcclusion function can be called inside an RTCOccludedFunctionN callback function to invoke the occlusion filter registered to the geometry and stored inside the context. For this an RTCFilterFunctionNArguments structure must be created (see rtcSetGeometryIntersectFilterFunction) which basically consists of a valid mask, a hit packet to filter, the corresponding ray packet, and the packet size. After the invocation of rtcFilterOcclusion only rays that are still valid (valid mask set to -1) should signal an occlusion.

EXIT STATUS {#exit-status}

For performance reasons this function does not do any error checks, thus will not set any error flags on failure.

SEE ALSO {#see-also}

[rtcFilterIntersection], [rtcSetGeometryOccludedFunction]

rtcSetGeometryUserData

NAME {#name}

rtcSetGeometryUserData - sets the user-defined data pointer of the
  geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryUserData(RTCGeometry geometry, void* userPtr);

DESCRIPTION {#description}

The rtcSetGeometryUserData function sets the user-defined data pointer (userPtr argument) for a geometry (geometry argument). This user data pointer is intended to be pointing to the application's representation of the geometry, and is passed to various callback functions. The application can use this pointer inside the callback functions to access its geometry representation.

The rtcGetGeometryUserData function can be used to query an already set user data pointer of a geometry.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcGetGeometryUserData]

rtcGetGeometryUserData

NAME {#name}

rtcGetGeometryUserData - returns the user data pointer
  of the geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void* rtcGetGeometryUserData(RTCGeometry geometry);

DESCRIPTION {#description}

The rtcGetGeometryUserData function queries the user data pointer previously set with rtcSetGeometryUserData. When rtcSetGeometryUserData was not called yet, NULL is returned.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryUserData]

rtcSetGeometryUserPrimitiveCount

NAME {#name}

rtcSetGeometryUserPrimitiveCount - sets the number of primitives
  of a user-defined geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

void rtcSetGeometryUserPrimitiveCount(
  RTCGeometry geometry,
  unsigned int userPrimitiveCount
);

DESCRIPTION {#description}

The rtcSetGeometryUserPrimitiveCount function sets the number of user-defined primitives (userPrimitiveCount parameter) of the specified user-defined geometry (geometry parameter).

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[RTC_GEOMETRY_TYPE_USER]

rtcSetGeometryBoundsFunction

NAME {#name}

rtcSetGeometryBoundsFunction - sets a callback to query the
  bounding box of user-defined primitives

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCBoundsFunctionArguments
{
  void* geometryUserPtr;
  unsigned int primID;
  unsigned int timeStep;
  struct RTCBounds* bounds_o;
};

typedef void (*RTCBoundsFunction)(
  const struct RTCBoundsFunctionArguments* args
);

void rtcSetGeometryBoundsFunction(
  RTCGeometry geometry,
  RTCBoundsFunction bounds,
  void* userPtr
);

DESCRIPTION {#description}

The rtcSetGeometryBoundsFunction function registers a bounding box callback function (bounds argument) with payload (userPtr argument) for the specified user geometry (geometry argument).

Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

The registered bounding box callback function is invoked to calculate axis-aligned bounding boxes of the primitives of the user-defined geometry during spatial acceleration structure construction. The bounding box callback of RTCBoundsFunction type is invoked with a pointer to a structure of type RTCBoundsFunctionArguments which contains various arguments, such as: the user data of the geometry (geometryUserPtr member), the ID of the primitive to calculate the bounds for (primID member), the time step at which to calculate the bounds (timeStep member), and a memory location to write the calculated bound to (bounds_o member).

In a typical usage scenario one would store a pointer to the internal representation of the user geometry object using rtcSetGeometryUserData. The callback function can then read that pointer from the geometryUserPtr field and calculate the proper bounding box for the requested primitive and time, and store that bounding box to the destination structure (bounds_o member).

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[RTC_GEOMETRY_TYPE_USER]

rtcSetGeometryIntersectFunction

NAME {#name}

rtcSetGeometryIntersectFunction - sets the callback function to
  intersect a user geometry

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCIntersectFunctionNArguments
{
  int* valid;
  void* geometryUserPtr;
  unsigned int primID;
  struct RTCIntersectContext* context;
  struct RTCRayHitN* rayhit;
  unsigned int N;
  unsigned int geomID;
};

typedef void (*RTCIntersectFunctionN)(
  const struct RTCIntersectFunctionNArguments* args
);

void rtcSetGeometryIntersectFunction(
  RTCGeometry geometry,
  RTCIntersectFunctionN intersect
);

DESCRIPTION {#description}

The rtcSetGeometryIntersectFunction function registers a ray/primitive intersection callback function (intersect argument) for the specified user geometry (geometry argument).

Only a single callback function can be registered per geometry and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

The registered callback function is invoked by rtcIntersect-type ray queries to calculate the intersection of a ray packet of variable size with one user-defined primitive. The callback function of type RTCIntersectFunctionN gets passed a number of arguments through the RTCIntersectFunctionNArguments structure. The value N specifies the ray packet size, valid points to an array of integers that specify whether the corresponding ray is valid (-1) or invalid (0), the geometryUserPtr member points to the geometry user data previously set through rtcSetGeometryUserData, the context member points to the intersection context passed to the ray query, the rayhit member points to a ray and hit packet of variable size N, and the geomID and primID member identifies the geometry ID and primitive ID of the primitive to intersect.

The ray component of the rayhit structure contains valid data, in particular the tfar value is the current closest hit distance found. All data inside the hit component of the rayhit structure are undefined and should not be read by the function.

The task of the callback function is to intersect each active ray from the ray packet with the specified user primitive. If the user-defined primitive is missed by a ray of the ray packet, the function should return without modifying the ray or hit. If an intersection of the user-defined primitive with the ray was found in the valid range (from tnear to tfar), it should update the hit distance of the ray (tfar member) and the hit (u, v, Ng, instID, geomID, primID members). In particular, the currently intersected instance is stored in the instID field of the intersection context, which must be deep copied into the instID member of the hit.

As a primitive might have multiple intersections with a ray, the intersection filter function needs to be invoked by the user geometry intersection callback for each encountered intersection, if filtering of intersections is desired. This can be achieved through the rtcFilterIntersection call.

Within the user geometry intersect function, it is safe to trace new rays and create new scenes and geometries.

When performing ray queries using rtcIntersect1, it is guaranteed that the packet size is 1 when the callback is invoked. When performing ray queries using the rtcIntersect4/8/16 functions, it is not generally guaranteed that the ray packet size (and order of rays inside the packet) passed to the callback matches the initial ray packet. However, under some circumstances these properties are guaranteed, and whether this is the case can be queried using rtcGetDeviceProperty. When performing ray queries using the stream API such as rtcIntersect1M, rtcIntersect1Mp, rtcIntersectNM, or rtcIntersectNp the order of rays and ray packet size of the callback function might change to either 1, 4, 8, or 16.

For many usage scenarios, repacking and re-ordering of rays does not cause difficulties in implementing the callback function. However, algorithms that need to extend the ray with additional data must use the rayID component of the ray to identify the original ray to access the per-ray data.

EXIT STATUS {#exit-status}

On failure an error code is set that can be queried using rtcGetDeviceError.

SEE ALSO {#see-also}

[rtcSetGeometryOccludedFunction], [rtcSetGeometryUserData], [rtcFilterIntersection]

rtcSetGeometryOccludedFunction

NAME {#name}

rtcSetGeometryOccludedFunction - sets the callback function to
  test a user geometry for occlusion

SYNOPSIS {#synopsis}

#include <embree3/rtcore.h>

struct RTCOccludedFunctionNArguments
{
  int* valid;
  void* geometryUserPtr;
  unsigned int primID;
  struct RTCIntersectContext* context;
  struct RTCRayN* ray;
  unsigned int N;
  unsigned int geomID;
};

typedef void (*RTCOccludedFunctionN)(
  const struct RTCOccludedFunctionNArguments* args
);

void rtcSetGeometryOccludedFunction(
  RTCGeometry geometry,
  RTCOccludedFunctionN filter
);

DESCRIPTION {#description}

The rtcSetGeometryOccludedFunction function registers a ray/primitive occlusion callback function (filter argument) for the specified user geometry (geometry argument).

Only a single callback function can be registered per geometry, and further invocations overwrite the previously set callback function. Passing NULL as function pointer disables the registered callback function.

The registered callback function is invoked by rtcOccluded-type ray queries to test whether the rays of a packet of variable size are occluded by a user-defined primitive. The callback function of type RTCOccludedFunctionN gets passed a number of arguments through the RTCOccludedFunctionNArguments structure. The value N specifies the ray packet size, valid points to an array of integers which specify whether the corresponding ray is valid (-1) or invalid (0), the geometryUserPtr member points to the geometry user data previously set through rtcSetGeometryUserData, the context member points to the intersection context passed to the ray query, the ray member points to a ray packet of variable size N, and the geomID and primID member identifies the geometry ID and primitive ID of the primitive to intersect.

The task of the callback function is to intersect each active ray from the ray packet with the specified user primitive. If the user-defined primitive is missed by a ray of the ray packet, the function should return without modifying the ray. I