% Embree: High Performance Ray Tracing Kernels 4.4.1 % Intel Corporation
Intel® Embree is a high-performance ray tracing library developed at Intel, which is released as open source under the Apache 2.0 license. Intel® Embree supports x86 CPUs under Linux, macOS, and Windows; ARM CPUs on Linux and macOS; as well as Intel® GPUs under Linux and Windows.
Intel® Embree targets graphics application developers to improve the performance of photo-realistic rendering applications. Embree is optimized towards production rendering, by putting focus on incoherent ray performance, high quality acceleration structure construction, a rich feature set, accurate primitive intersection, and low memory consumption.
Embree's feature set includes various primitive types such as triangles (as well quad and grids for lower memory consumption); Catmull-Clark subdivision surfaces; various types of curve primitives, such as flat curves (for distant views), round curves (for closeup views), and normal oriented curves, all supported with different basis functions (linear, Bézier, B-spline, Hermite, and Catmull Rom); point-like primitives, such as ray oriented discs, normal oriented discs, and spheres; user defined geometries with a procedural intersection function; multi-level instancing; filter callbacks invoked for any hit encountered; motion blur including multi-segment motion blur, deformation blur, and quaternion motion blur; and ray masking.
Intel® Embree contains ray tracing kernels optimized for the latest x86 processors with support for SSE, AVX, AVX2, and AVX-512 instructions, and uses runtime code selection to choose between these kernels. 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) as well as supports for dynamic scenes by implementing high-performance two-level spatial index structure construction algorithms.
Intel® Embree supports applications written with the Intel® Implicit SPMD Program Compiler (Intel® ISPC, https://ispc.github.io/) by providing an ISPC interface to the core ray tracing algorithms. This makes it possible to write a renderer that automatically vectorizes and leverages SSE, AVX, AVX2, and AVX-512 instructions.
Intel® Embree supports Intel GPUs through the SYCL open standard programming language. SYCL allows to write C++ code that can be run on various devices, such as CPUs and GPUs. Using Intel® Embree application developers can write a single source renderer that executes efficiently on CPUs and GPUs. Maintaining just one code base this way can significantly improve productivity and eliminate inconsistencies between a CPU and GPU version of the renderer. Embree supports GPUs based on the Xe HPG and Xe HPC microarchitecture, which support hardware accelerated ray tracing do deliver excellent levels of ray tracing performance.
Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS (64-bit). Under Windows, Linux and macOS x86 based CPUs are supported, while ARM CPUs are currently only supported under Linux and macOS (e.g. Apple M1). ARM support for Windows experimental.
Embree supports Intel GPUs based on the Xe HPG microarchitecture (Intel® Arc™ GPU) under Linux and Windows and Xe HPC microarchitecture (Intel® Data Center GPU Flex Series and Intel® Data Center GPU Max Series) under Linux.
The code compiles with the Intel® Compiler, Intel® oneAPI DPC++ Compiler, GCC, Clang, and the Microsoft Compiler. To use Embree on the GPU the Intel® oneAPI DPC++ Compiler must be used. Please see section [Compiling Embree] for details on tested compiler versions.
Embree requires at least an x86 CPU with support for SSE2 or an Apple M1 CPU.
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.
A pre-built version of Embree for Windows is provided as a ZIP archive
embree-4.4.1.x64.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.
A pre-built version of Embree for Linux is provided as a tar.gz archive:
embree-4.4.1.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-4.4.1.x86_64.linux.tar.gz
source embree-4.4.1.x86_64.linux/embree-vars.sh
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.
The macOS version of Embree is also delivered as a ZIP file:
embree-4.4.1.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-4.4.1.x64.macosx.zip source embree-4.4.1.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.4.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.
The most convenient way to build an Embree application is through
CMake. Just let CMake find your unpacked Embree package using the
FIND_PACKAGE function inside your CMakeLists.txt file:
FIND_PACKAGE(embree 4 REQUIRED)
For CMake to properly find Embree you need to set the embree_DIR variable to
the folder containing the embree_config.cmake file. You might also have to
set the TBB_DIR variable to the path containing TBB-config.cmake of a local
TBB install, in case you do not have TBB installed globally on your system,
e.g:
cmake -D embree_DIR=path_to_embree_package/lib/cmake/embree-4.4.1/ \
-D TBB_DIR=path_to_tbb_package/lib/cmake/tbb/ \
..
The FIND_PACKAGE function will create an embree target that
you can add to your target link libraries:
TARGET_LINK_LIBRARIES(application embree)
For a full example on how to build an Embree application please have a
look at the minimal tutorial provided in the src folder of the
Embree package and also the contained README.txt file.
Building Embree SYCL applications is also best done using CMake. Please first get some compatible SYCL compiler and setup the environment as decribed in sections [Linux SYCL Compilation] and [Windows SYCL Compilation].
Also perform the setup steps from the previous [Building Embree Applications] section.
Please also have a look at the [Minimal] tutorial that is provided with the Embree release, for an example how to build a simple SYCL application using CMake and Embree.
To properly compile your SYCL application you have to add additional SYCL compile flags for each C++ file that contains SYCL device side code or kernels as described next.
We recommend using just in time compilation (JIT compilation) together with [SYCL JIT caching] to compile Embree SYCL applications. For JIT compilation add these options to the compilation phase of all C++ files that contain SYCL code:
-fsycl -Xclang -fsycl-allow-func-ptr -fsycl-targets=spir64
These options enable SYCL two phase compilation (-fsycl option),
enable function pointer support (-Xclang -fsycl-allow-func-ptr
option), and just in time (JIT) compilation only
(-fsycl-targets=spir64 option).
The following link options have to get added to the linking stage of your application when using just in time compilation:
-fsycl -fsycl-targets=spir64
For a full example on how to build an Embree SYCL application please
have a look at the SYCL version of the minimal tutorial provided in
the src folder of the Embree package and also the contained
README.txt file.
Please have a look at the [Compiling Embree] section on how to create an Embree package from sources if required.
Ahead of time compilation (AOT compilation) allows to speed up first application start up time as device binaries are precompiled. We do not recommend using AOT compilation as it does not allow the usage of specialization constants to reduce code complexity.
For ahead of time compilation add these compile options to the compilation phase of all C++ files that contain SYCL code:
-fsycl -Xclang -fsycl-allow-func-ptr -fsycl-targets=spir64_gen
These options enable SYCL two phase compilation (-fsycl option),
enable function pointer support (-Xclang -fsycl-allow-func-ptr
option), and ahead of time (AOT) compilation
(-fsycl-targets=spir64_gen option).
The following link options have to get added to the linking stage of your application when compiling ahead of time for Xe HPG devices:
-fsycl -fsycl-targets=spir64_gen
-Xsycl-target-backend=spir64_gen "-device XE_HPG_CORE"
This in particular configures the devices for AOT compilation to
XE_HPG_CORE.
To get a list of all device supported by AOT compilation look at the help of the device option in ocloc tool:
ocloc compile --help
Embree is released with a bundle of tests in an optional testing package. To run these tests extract the testing package in the same folder as your embree installation. e.g.:
tar -xzf embree-4.4.1-testing.zip -C /path/to/installed/embree
The tests are extracted into a new folder inside you embree installation and can be run with:
cd /path/to/installed/embree/testing
cmake -B build
cmake --build build target=tests
We recommend using the prebuild Embree packages from https://github.com/embree/embree/releases. If you need to compile Embree yourself you need to use CMake as described in the following.
Do not enable fast-math optimizations in your compiler as this mode is not supported by Embree.
To compile Embree you need a modern C++ compiler that supports C++11. Embree is tested with the following compilers:
Linux
macOS x86_64
macOS Arm64
Embree supports using the Intel® Threading Building Blocks (TBB) as the
tasking system. For performance and flexibility reasons we recommend
using 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® Implicit SPMD Program Compiler (Intel® ISPC), which allows
straightforward parallelization of an entire renderer. If you
want to use Intel® ISPC then you can enable EMBREE_ISPC_SUPPORT in
CMake. Download and install the Intel® ISPC binaries from
ispc.github.io. After
installation, put the path to ispc permanently into your PATH environment
variable or you set the EMBREE_ISPC_EXECUTABLE variable to point at the ISPC
executable during CMake configuration.
You additionally have to install CMake 3.10 or higher and the developer version of GLFW version 3.
Under macOS, all these dependencies can be installed using MacPorts:
sudo port install cmake tbb 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 Clang compiler instead of the default GCC on most Linux machines
(g++ and gcc), execute
cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
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 -j 8
The executables will be generated inside the build folder. We recommend
installing 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
You can also create an Embree package using the following command:
make package
Please see the [Building Embree Applications] section on how to build your application with such an Embree package.
There are two options to compile Embree with SYCL support: The open source "oneAPI DPC++ Compiler" or the "Intel(R) oneAPI DPC++/C++ Compiler". Other SYCL compilers are not supported.
The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI DPC++/C++ Compiler" but less stable. The current tested version of the "oneAPI DPC++ compiler is
The compiler can be downloaded and simply extracted. The oneAPI DPC++ compiler can be set up executing the following commands in a Linux (bash) shell:
export SYCL_BUNDLE_ROOT=path_to_dpcpp_compiler
export PATH=$SYCL_BUNDLE_ROOT/bin:$PATH
export CPATH=$SYCL_BUNDLE_ROOT/include:$CPATH
export LIBRARY_PATH=$SYCL_BUNDLE_ROOT/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=$SYCL_BUNDLE_ROOT/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$SYCL_BUNDLE_ROOT/linux/lib/x64:$LD_LIBRARY_PATH
where the path_to_dpcpp_compiler should point to the unpacked oneAPI DPC++
compiler. This will put clang++ and clang from the oneAPI DPC++ Compiler
into your path.
Please also install all Linux packages described in the previous section.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER=clang \
-DEMBREE_SYCL_SUPPORT=ON
This will create a directory build to use as the CMake build directory,
configure the usage of the oneAPI DPC++ Compiler, and turn on SYCL support
through EMBREE_SYCL_SUPPORT=ON.
Alternatively, you can download and run the installer of the
After installation, you can set up the compiler by sourcing the
vars.sh script in the env directory of the compiler install directory, for example,
source /opt/intel/oneAPI/compiler/latest/env/vars.sh
This script will put the icpx and icx compiler executables from the
Intel(R) oneAPI DPC++/C++ Compiler in your path.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build \
-DCMAKE_CXX_COMPILER=icpx \
-DCMAKE_C_COMPILER=icx \
-DEMBREE_SYCL_SUPPORT=ON
More information about setting up the Intel(R) oneAPI DPC++/C++ compiler can be found in the Development Reference Guide. Please note, that the Intel(R) oneAPI DPC++/C++ compiler requires at least CMake version 3.20.5 on Linux.
Independent of the DPC++ compiler choice, you can now build Embree using
cmake --build build -j 8
The executables will be generated inside the build folder. The
executable names of the SYCL versions of the tutorials end with
_sycl.
To run the SYCL code you need to install the latest GPGPU drivers for your Intel Xe HPG/HPC GPUs from here https://dgpu-docs.intel.com/. Follow the driver installation instructions for your graphics card and operating system.
After installing the drivers you have to install an additional package manually using
sudo apt install intel-level-zero-gpu-raytracing
Embree is tested using the following compilers under Windows:
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
using 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
https://github.com/oneapi-src/oneTBB/releases
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® Implicit SPMD Program Compiler (Intel® ISPC), which
allows straightforward parallelization of an entire renderer. When installing
Intel® ISPC, make sure to download an Intel® 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 EMBREE_ISPC_EXECUTABLE variable during CMake configuration to point to
the ISPC executable. If you want to use Intel® ISPC, you have to enable
EMBREE_ISPC_SUPPORT in CMake.
You additionally have to install CMake (version 3.1 or higher). Note that you need a native Windows CMake installation because CMake under Cygwin cannot generate solution files for Visual Studio.
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".
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. The 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 embree4.sln to compile
the project.
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.
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 16 2019" ..
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
You can download and install Embree using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install embree3
The Embree port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.
There are two options to compile Embree with SYCL support: The open source "oneAPI DPC++ Compiler" or the "Intel(R) oneAPI DPC++/C++ Compiler". Other SYCL compilers are not supported. You will also need an installed version of Visual Studio that supports the C++17 standard, e.g. Visual Studio 2019.
The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI DPC++/C++ Compiler" but less stable. The current tested version of the oneAPI DPC++ compiler is
Download and unpack the archive and open the "x64 Native Tools Command Prompt" of Visual Studio and execute the following lines to properly configure the environment to use the oneAPI DPC++ compiler:
set "DPCPP_DIR=path_to_dpcpp_compiler"
set "PATH=%DPCPP_DIR%\bin;%PATH%"
set "PATH=%DPCPP_DIR%\lib;%PATH%"
set "CPATH=%DPCPP_DIR%\include;%CPATH%"
set "INCLUDE=%DPCPP_DIR%\include;%INCLUDE%"
set "LIB=%DPCPP_DIR%\lib;%LIB%"
The path_to_dpcpp_compiler should point to the unpacked oneAPI DPC++
compiler.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build
-G Ninja
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_CXX_COMPILER=clang++
-D CMAKE_C_COMPILER=clang
-D EMBREE_SYCL_SUPPORT=ON
-D TBB_ROOT=path_to_tbb\lib\cmake\tbb
This will create a directory build to use as the CMake build directory, and
configure a release build that uses clang++ and clang from the oneAPI DPC++
compiler.
The Ninja generator is currently the easiest way to use the oneAPI DPC++ compiler.
We also enable SYCL support in Embree using the EMBREE_SYCL_SUPPORT CMake
option.
Alternatively, you can download and run the installer of the
After installation, you can either open a regular Command Prompt and execute
the vars.bat script in the env directory of the compiler install directory,
for example
C:\Program Files (x86)\Intel\oneAPI\compiler\latest\env\vars.bat
or simply open the installed "Intel oneAPI command prompt for Intel 64 for Visual Studio".
Both ways will put the icx compiler executable from the
Intel(R) oneAPI DPC++/C++ compiler in your path.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build
-G Ninja
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_CXX_COMPILER=icx
-D CMAKE_C_COMPILER=icx
-D EMBREE_SYCL_SUPPORT=ON
-D TBB_ROOT=path_to_tbb\lib\cmake\tbb
More information about setting up the Intel(R) oneAPI DPC++/C++ compiler can be found in the Development Reference Guide. Please note, that the Intel(R) oneAPI DPC++/C++ compiler requires at least CMake version 3.23 on Windows.
Independent of the DPC++ compiler choice, you can now build Embree using
cmake --build build
If you have problems with Ninja re-running CMake in an infinite loop,
then first remove the "Re-run CMake if any of its inputs changed."
section from the build.ninja file and run the above command again.
You can also create an Embree package using the following command:
cmake --build build --target package
Please see the [Building Embree SYCL Applications] section on how to build your application with such an Embree package.
In order to run the SYCL tutorials on HPG hardware, you first need to install the graphics drivers for your graphics card from https://www.intel.com. Please make sure to have installed version 31.0.101.4644 or newer.
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 Intel® ISPC support of Embree. This option
is OFF by default.
EMBREE_SYCL_SUPPORT: Enables GPU support using SYCL. When this
option is enabled you have to use some DPC++ compiler. Please see
the sections [Linux SYCL Compilation] and [Windows SYCL Compilation]
on supported DPC++ compilers. This option is OFF by default.
EMBREE_SYCL_AOT_DEVICES: Selects a list of GPU devices for
ahead-of-time (AOT) compilation of device code. Possible values are
either, "none" which enables only just in time (JIT) compilation, or
a list of the Embree-supported Xe GPUs for AOT compilation:
One can also specify multiple devices separated by comma to compile ahead of time for multiple devices, e.g. "XE_HPG_CORE,XE_HP_CORE". When enabling AOT compilation for one or multiple devices, JIT compilation will always additionally be enabled in case the code is executed on a device no code is precompiled for.
Execute "ocloc compile --help" for more details of possible devices to pass. Embree is only supported on Xe HPG/HPC and newer devices.
Per default, this option is set to "none" to enable JIT compilation. We recommend using JIT compilation as this enables the use of specialization constants to reduce code complexity.
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. embree4.a, embree4_sse42.a,
embree4_avx.a, embree4_avx2.a, embree4_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
are exported.
EMBREE_LIBRARY_NAME: Specifies the name of the Embree library file
created. By default, the name embree4 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_BACKFACE_CULLING_CURVES: Enables backface culling for curves,
i.e. only surfaces facing a ray can be hit. This option is turned OFF
by default.
EMBREE_BACKFACE_CULLING_SPHERES: Enables backface culling for spheres,
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 appropriate 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 Building Blocks (TBB)
is used as a tasking system, search the library in this directory
tree.
EMBREE_TBB_COMPONENT: The component/library name of Intel® Threading
Building Blocks (TBB). Embree searches for this library name (default: tbb)
when TBB is used as the tasking system.
EMBREE_TBB_POSTFIX: If Intel® Threading 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 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 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 triangle geometries
(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_INSTANCE_ARRAY: Enables support for instance arrays (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_DISC_POINT_SELF_INTERSECTION_AVOIDANCE: Enables self-intersection
avoidance for RTC_GEOMETRY_TYPE_DISC_POINT geometry type (ON by default).
When enabled intersections are skipped if the ray origin lies inside the
sphere defined by the point primitive.
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.
The Embree API is a low-level C99 ray tracing API which can be used to build spatial index structures for 3D scenes and perform ray queries of different types.
The API can get used on the CPU using standard C, C++, and ISPC code and Intel GPUs by using SYCL code.
The Intel® Implicit SPMD Program Compiler (Intel® ISPC) version of the API, is almost identical to the standard C99 version, but contains additional functions that operate on ray packets with a size of the native SIMD width used by Intel® ISPC.
The SYCL version of the API is also mostly identical to the C99 version of the API, with some exceptions listed in section [Embree SYCL API].
For simplicity this document refers to the C99 version of the API functions. For changes when upgrading from the Embree 3 to the current Embree 4 API see Section [Upgrading from Embree 3 to Embree 4].
All API calls carry the prefix rtc (or RTC for types) which stands
for ray tracing core. 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
and ray packets. 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 otherwise.
However, attaching geometries to the same scene and performing ray
queries in a scene is thread-safe.
Starting with Embree 4.4 intersection and occlusion queries on a SYCL
device require the use of the rtcTraversableIntersect-type functions
or the rtcTraversableOccluded-type function respectively. These
functions take a traversable object (RTCTraversable type) which
corresponds to a RTCScene. Traversable objects are not reference
counted and therefore they do not have to be released like the other
handles. Traversable objects grant read-only access to a scene object
on a SYCL device and are valid as long as the corresponding scene
object is valid.
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 (or [rtcNewSYCLDevice] when using SYCL for the GPU). 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.
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.
When using SYCL, calls to rtcCommitScene trigger memory transfers
from the host (CPU) to the device (GPU). Calling rtcCommitScene will
be blocking and return only after the memory transfers are completed.
Embree also provides the function rtcCommitSceneWithQueue which takes
a SYCL queue as argument to which the memory transfer operations are
submitted. Calling rtcCommitSceneWithQueue will trigger the memory
transfers asynchronously and the application is responsible for
sychronizing command on the queue properly to ensure the scene data is
available on a SYCL device when a SYCL kernels performs intersection
queries that rely on the scene data.
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.
Starting with Embree 4.4 scene objects (RTCScene types) are not valid
handles on SYCL devices anymore and therefore can not be used for
Embree API calls in a SYCL kernel. Instead, Embree API calls on a SYCL
kernel have a variation which use traversable objects (RTCTraversable
type).
Traversable objects grant read-only access to a scene object on a SYCL
device and are valid as long as the corresponding scene object is
valid. They can be queried from a scene object using the
rtcGetSceneTraversable function and used in
rtcTraversableIntersect-type functions or the
rtcTraversableOccluded-type function. They can also be used in CPU
code and Embree provides other API calls such as the
rtcTraversablePointQuery (which are not currently implemented for
SYCL) to help write portable code compatible with CPU and SYCL device
execution.
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 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).
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.
On SYCL devices the API functions rtcTraversableIntersect and
rtcTraversableOccluded have to be used.
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]).
Point Queries can currently not be used on SYCL devices.
See Section [rtcPointQuery] for a detailed description of how to set up point queries.
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.
Collision detection can currently not be used on SYCL devices.
See Section [rtcCollide] for a detailed description of how to set up collision detection.
Seen tutorial Collision Detection for a complete example of collision detection being used on a simple cloth solver.
The API supports filter functions that are invoked for each
intersection found during the rtcIntersect-type or rtcOccluded-type
calls.
The filter functions can be set per-geometry using the
rtcSetGeometryIntersectFilterFunction and
rtcSetGeometryOccludedFilterFunction 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.
The filter function can also get passed as arguments directly to the
traversal functions, see section [rtcInitIntersectArguments] and
[rtcInitOccludedArguments] for more details. These argument filter
functions are 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 argument
filter function must be enabled to be used for a scene using the
RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS scene flag. The callback
is only invoked for geometries that enable the callback using the
rtcSetGeometryEnableFilterFunctionFromArguments call, or enabled for
all geometries when the RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER ray
query flag is set.
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.
Embree supports ray tracing on Intel GPUs by using the SYCL programming language. SYCL is a Khronos standardized C++ based language for single source heterogenous programming for acceleration offload, see the SYCL webpage for details.
The Embree SYCL API is designed for photorealistic rendering use cases, where scene setup is performed on the host, and rendering on the device. The Embree SYCL API is very similar to the standard Embree C99 API, and supports most of its features, such as all triangle-type geometries, all curve types and basis functions, point geometry types, user geometries, filter callbacks, multi-level instancing, and motion blur.
To enable SYCL support you have to include the sycl.hpp file before
the Embree API headers:
#include <sycl/sycl.hpp>
#include <embree4/rtcore.h>
Next you need to initializes an Embree SYCL device using the
rtcNewSYCLDevice API function by providing a SYCL context.
Embree provides the rtcIsSYCLDeviceSupported API function to check if
some SYCL device is supported by Embree. You can also use the
rtcSYCLDeviceSelector to conveniently select the first SYCL device
that is supported by Embree, e.g.:
sycl::device device(rtcSYCLDeviceSelector);
sycl::queue queue(device, exception_handler);
sycl::context context(device);
RTCDevice device = rtcNewSYCLDevice(context,"");
Scenes created with an Embree SYCL device can only get used to trace rays using SYCL on the GPU, it is not possible to trace rays on the CPU with such a device. To render on the CPU and GPU in parallel, the user has to create a second Embree device and create a second scene to be used on the CPU.
Starting with Embree 4.4 scene objects (RTCScene types) are not valid
handles on SYCL devices anymore and therefore can not be used for
Embree API calls in a SYCL kernel. Instead, Embree API calls on a SYCL
kernel have a variation which use traversable objects (RTCTraversable
type). To get a traversable object for a scene object the application
can call rtcGetSceneTraversable.
Files containing SYCL code, have to get compiled with the Intel® oneAPI DPC++ compiler. Please see section [Linux SYCL Compilation] and [Windows SYCL Compilation] for supported compilers. The DPC++ compiler performs a two-phase compilation, where host code is compiled in a first phase, and device code compiled in a second compilation phase.
Standard Embree API functions for scene construction can get used on the host but not the device.
Before version 4.4, Embree made heavy use of unified shared memory
(USM) shared memory which simplifies memory management with SYCL
devices by letting the SYCL runtime transfer data from host to device
implicitly. However, some applications require more control over when
and how data is migrated from CPU to GPU. Embree 4.4 allows to use
explicit host and device memory allocations. See for example
rtcSetNewGeometryBufferHostDevice,
rtcSetSharedGeometryBufferHostDevice, rtcNewBufferHostDevice, and
rtcNewSharedBufferHostDevice. It is still possible to share data
buffers with Embree using SYCL USM shared memory by using the API calls
without the HostDevice suffix.
The easiest way to share data buffers with Embree (e.g. for vertex of
index buffers) is to allocate the data as USM shared memory, using the
sycl::malloc or sycl::aligned_alloc calls with
sycl::usm::alloc::shared property, or the sycl::aligned_alloc_shared
call, e.g:
void* ptr = sycl::aligned_alloc(16, bytes, queue, sycl::usm::alloc::shared);
These shared allocations have to be valid during rendering, as Embree may access contained data when tracing rays.
Device side rendering can get invoked by submitting a SYCL
parallel_for to the SYCL queue:
const sycl::specialization_id<RTCFeatureFlags> feature_mask;
RTCFeatureFlags required_features = RTC_FEATURE_FLAG_TRIANGLE;
RTCTraversable traversable = rtcGetSceneTraversable(scene);
queue.submit([=](sycl::handler& cgh)
{
cgh.set_specialization_constant<feature_mask>(required_features);
cgh.parallel_for(sycl::range<1>(1),[=](sycl::id<1> item, sycl::kernel_handler kh)
{
RTCIntersectArguments args;
rtcInitIntersectArguments(&args);
const RTCFeatureFlags features = kh.get_specialization_constant<feature_mask>();
args.feature_mask = features;
struct RTCRayHit rayhit;
rayhit.ray.org_x = ox;
rayhit.ray.org_y = oy;
rayhit.ray.org_z = oz;
rayhit.ray.dir_x = dx;
rayhit.ray.dir_y = dy;
rayhit.ray.dir_z = dz;
rayhit.ray.tnear = 0;
rayhit.ray.tfar = std::numeric_limits<float>::infinity();
rayhit.ray.mask = -1;
rayhit.ray.flags = 0;
rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
rtcTraversableIntersect1(traversable, &rayhit, &args);
result->geomID = rayhit.hit.geomID;
result->primID = rayhit.hit.primID;
result->tfar = rayhit.ray.tfar;
});
});
queue.wait_and_throw();
This example passes a feature mask using a specialization constant to
the rtcTraversableIntersect1 function, which is recommended for GPU
rendering. For best performance, this feature mask should get used to
enable only features required by the application to render the scene,
e.g. just triangles in this example.
Inside the SYCL parallel_for loop you can use rendering related
functions, such as the rtcTraversableIntersect1 and
rtcTraversableOccluded1 functions to trace rays,
rtcTraversableForwardIntersect1/Ex and
rtcTraversableForwardOccluded1/Ex to continue object traversal from
inside a user geometry callback, and
rtcGetGeometryUserDataFromTraversable to get the user data pointer of
some geometry.
Have a look at the [Minimal] tutorial for a minimal SYCL example and the [Host Device Memory] tutorial shows four different ways in which data buffers can be created by or shared with Embree using explicit host/device data buffers.
Compile times for just in time compilation (JIT compilation) can be
large. To resolve this issue we recommend enabling persistent JIT
compilation caching inside your application, by setting the
SYCL_CACHE_PERSISTENT environment variable to 1, and the
SYCL_CACHE_DIR environment variable to some proper directory where
the JIT cache should get stored. These environment variables have to
get set before the SYCL device is created, e.g:
setenv("SYCL_CACHE_PERSISTENT","1",1);
setenv("SYCL_CACHE_DIR","cache_dir",1);
sycl::device device(rtcSYCLDeviceSelector);
...
Memory Pooling is a mechanism where small USM memory allocations are packed into larger allocation blocks. This mode is required when your application performs many small USM allocations, as otherwise only a small fraction of GPU memory is usable and data transfer performance will be low.
Memory pooling is supported for USM allocations that are read-only by the device. The following example allocated device read-only memory with memory pooling support:
sycl::aligned_alloc_shared(align, bytes, queue,
sycl::ext::oneapi::property::usm::device_read_only());
Embree only supports Xe HPC and HPG GPUs as SYCL devices, thus in particular the CPU and other GPUs cannot get used as a SYCL device. To render on the CPU just use the standard C99 API without relying on SYCL.
The SYCL language spec puts some restrictions to device functions, such
as disallowing: global variable access, malloc, invocation of virtual
functions, function pointers, runtime type information, exceptions,
recursion, etc. See Section
5.4. Language Restrictions for device functions of the SYCL
specification
for more details.
Using Intel's oneAPI DPC++ compiler invoking an indirectly called function is allowed, but we do not recommend this for performance reasons.
Some features are not supported by the Embree SYCL API thus cannot get used on the GPU:
Since Embree 4.4, all the ray query functions that take an
RTCScene object as argument cannot get used in SYCL device side
code. Instead, the API functions taking a RTCTraversable object
(e.g. rtcTraversableIntersect1) have to be used.
The packet tracing functions rtcTraversableIntersect4/8/16 and
rtcTraversableOccluded4/8/16 are not supported in SYCL device
side code. Using these functions makes no sense for SYCL, as the
programming model is implicitly executed in SIMT mode on the GPU
anyway.
Filter and user geometry callbacks stored inside the geometry
objects are not supported on SYCL. Please use the alternative
approach of passing the function pointer through the
RTCIntersectArguments (or RTCOccludedArguments) structures to
the tracing function, which enables inlining on the GPU.
The rtcInterpolate function cannot get used on the the device.
For most primitive types the vertex data interpolation is anyway a
trivial operation, and an API call just introduces overheads. On
the CPU that overhead is acceptable, but on the GPU it is not. The
rtcInterpolate function does not know the geometry type it is
interpolating over, thus its implementation on the GPU would
contain a large switch statement for all potential geometry types.
Tracing rays using rtcTraversableIntersect1 and
rtcTraversableOccluded1 functions from user geometry callbacks is
not supported in SYCL. Please use the tail recursive
rtcTraversableForwardIntersect1 and
rtcTraversableForwardOccluded1 calls instead.
Subdivision surfaces are not supported for Embree SYCL devices.
Collision detection (rtcCollide API call) is not supported in
SYCL device side code.
Point queries (rtcPointQuery API call) are not supported in SYCL
device side code.
This section summarizes API changes between Embree 3 and Embree4. Most of these changes are motivated by GPU performance and having a consistent API that works properly for the CPU and GPU.
The API include folder got renamed from embree3 to embree4, to be able to install Embree 3 and Embree 4 side by side, without having conflicts in API folder.
The RTCIntersectContext is renamed to RTCRayQueryContext and
the RTCIntersectContextFlags got renamed to RTCRayQueryFlags.
There are some changes to the rtcIntersect and rtcOccluded
functions. Most members of the old intersect context have been
moved to some optional RTCIntersectArguments (and
RTCOccludedArguments) structures, which also contains a pointer
to the new ray query context. The argument structs fulfill the task
of providing additional advanced arguments to the traversal
functions. The ray query context can get used to pass additional
data to callbacks, and to maintain an instID stack in case
instancing is done manually inside user geometry callbacks. The
arguments struct is not available inside callbacks. This change was
in particular necessary for SYCL to allow inlining of function
pointers provided to the traversal functions, and to reduce the
amount of state passed to callbacks, which both improves GPU
performance. Most applications can just drop passing the ray query
context to port to Embree 4.
The rtcFilterIntersection and rtcFilterOcclusion API calls that
invoke both, the geometry and argument version of the filter
callback, from a user geometry callback are no longer supported.
Instead applications should use the
rtcInvokeIntersectFilterFromGeometry and
rtcInvokeOccludedFilterFromGeometry API calls that invoke just
the geometry version of the filter function, and invoke the
argument filter function manually if required.
The filter function passed as arguments to rtcIntersect and
rtcOccluded functions is only invoked for some geometry if
enabled through rtcSetGeometryEnableFilterFunctionFromArguments
for that geometry. Alternatively, argument filter functions can get
enabled for all geometries using the
RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER ray query flag.
User geometry callbacks get a valid vector as input to identify valid and invalid rays. In Embree 3 the user geometry callback just had to update the ray hit members when an intersection was found and perform no operation otherwise. In Embree 4 the callback additionally has to return valid=-1 when a hit was found, and valid=0 when no hit was found. This allows Embree to properly pass the new hit distance to the ray tracing hardware only in the case a hit was found.
Further ray masking is enabled by default now as required by most applications and the default ray mask for geometries got changed from 0xFFFFFFFF to 0x1.
The stream tracing functions rtcIntersect1M, rtcIntersect1Mp,
rtcIntersectNM, rtcIntersectNp, rtcOccluded1M,
rtcOccluded1Mp, rtcOccludedNM, and rtcOccludedNp got removed
as they were rarely used and did not provide relevant performance
benefits. As alternative the application can just iterate over
rtcIntersect1 and potentially rtcIntersect4/8/16 to get similar
performance.
To use Embree through SYCL on the CPU and GPU additional changes are required:
Embree 3 allows to use rtcIntersect recursively from a user
geometry or intersection filter callback to continue a ray inside
an instantiated object. In Embree 4 using rtcIntersect
recursively is disallowed on the GPU but still supported on the
CPU. To properly continue a ray inside an instantiated object use
the new rtc(Traversable)ForwardIntersect1 and
rtc(Traversable)ForwardOccluded1 functions.
The geometry object and scene object of Embree 4 are a host side
only objects, thus accessing it during rendering from the GPU is
not allowed. Thus all API functions that take an RTCGeometry object
or RTCScene object as argument cannot get used during rendering. In
particular the rtcGetGeometryUserData(RTCGeometry) call cannot
get used, but there is an alternative function
rtcGetGeometryUserDataFromTraversable(RTCTraversable traversable,uint geomID)
that should get used instead. To perform ray queries on the GPU
(e.g. rtcTraversableIntersect1) the application has to get a
RTCTraversable object first (using rtcGetSceneTraversable) and
pass it to the SYCL kernel.
The user geometry callback and filter callback functions should get
passed through the intersection and occlusion argument structures
to the rtcTraversableIntersect1 and rtcTraversableOccluded1
functions directly to allow inlining. The experimental geometry
version of the callbacks is disabled in SYCL and should not get
used.
The feature flags should get used in SYCL to minimal GPU code for optimal performance.
The rtcInterpolate function cannot get used on the device, and
vertex data interpolation should get implemented by the
application.
Indirectly called functions must be declared with
RTC_SYCL_INDIRECTLY_CALLABLE when used as filter or user geometry
callbacks.
rtcNewDevice - creates a new device
#include <embree4/rtcore.h>
RTCDevice rtcNewDevice(const char* config);
This function creates a new device to be used for CPU ray tracing 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");
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).
[rtcRetainDevice], [rtcReleaseDevice], [rtcNewSYCLDevice]
rtcNewSYCLDevice - creates a new device to be used with SYCL
#include <embree4/rtcore.h>
RTCDevice rtcNewSYCLDevice(sycl::context context, const char* config);
This function creates a new device to be used with SYCL for GPU
rendering and returns a handle to this device. The device object is
reference counted with an initial reference count of 1. The handle can
get released using the rtcReleaseDevice API call.
The passed SYCL context (context argument) is used to allocate GPU
data, thus only devices contained inside this context can be used for
rendering. By default the GPU data is allocated on the first GPU device
of the context, but this behavior can get changed with the
[rtcSetDeviceSYCLDevice] function.
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.
For an overview of configurations that can get passed (config
argument) please see the [rtcNewDevice] function description.
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).
[rtcRetainDevice], [rtcReleaseDevice], [rtcNewDevice]
rtcIsSYCLDeviceSupported - checks if some SYCL device is supported by Embree
#include <embree4/rtcore.h>
bool rtcIsSYCLDeviceSupported(const sycl::device sycl_device);
This function can be used to check if some SYCL device (sycl_device
argument) is supported by Embree.
The function returns true if the SYCL device is supported by Embree and
false otherwise. On failure an error code is set that can get queried
using rtcGetDeviceError.
[rtcSYCLDeviceSelector]
rtcSYCLDeviceSelector - SYCL device selector function to select
devices supported by Embree
#include <embree4/rtcore.h>
int rtcSYCLDeviceSelector(const sycl::device sycl_device);
This function checks if the passed SYCL device (sycl_device
arguments) is supported by Embree or not. This function can be used
directly to select some supported SYCL device by using it as SYCL
device selector function. For instance, the following code sequence
selects an Embree supported SYCL device and creates an Embree device
from it:
sycl::device sycl_device(rtcSYCLDeviceSelector);
sycl::queue sycl_queue(sycl_device);
sycl::context(sycl_device);
RTCDevice device = rtcNewSYCLDevice(sycl_context,nullptr);
The function returns -1 if the SYCL device is supported by Embree and 1
otherwise. On failure an error code is set that can get queried using
rtcGetDeviceError.
[rtcIsSYCLDeviceSupported]
rtcSetDeviceSYCLDevice - sets the SYCL device to be used for memory allocations
#include <embree4/rtcore.h>
void rtcSetDeviceSYCLDevice(RTCDevice device, const sycl::device sycl_device);
This function sets the SYCL device (sycl_device argument) to be used
to allocate GPU memory when using the specified Embree device (device
argument). This SYCL device must be one of the SYCL devices contained
inside the SYCL context used to create the Embree device.
On failure an error code is set that can get queried using
rtcGetDeviceError.
[rtcNewSYCLDevice]
rtcRetainDevice - increments the device reference count
#include <embree4/rtcore.h>
void rtcRetainDevice(RTCDevice device);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice], [rtcReleaseDevice]
rtcReleaseDevice - decrements the device reference count
#include <embree4/rtcore.h>
void rtcReleaseDevice(RTCDevice device);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice], [rtcRetainDevice]
rtcGetDeviceProperty - queries properties of the device
#include <embree4/rtcore.h>
ssize_t rtcGetDeviceProperty(
RTCDevice device,
enum RTCDeviceProperty prop
);
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_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_BACKFACE_CULLING_CURVES_ENABLED: Queries
whether back face culling for curves is enabled. This is only the
case if Embree is compiled with EMBREE_BACKFACE_CULLING_CURVES
enabled.
RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: Queries
whether back face culling for spheres is enabled. This is only the
case if Embree is compiled with EMBREE_BACKFACE_CULLING_SPHERES
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:
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.
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 - returns the error code of the device
#include <embree4/rtcore.h>
RTCError rtcGetDeviceError(RTCDevice device);
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.
RTC_ERROR_LEVEL_ZERO_RAYTRACING_SUPPORT_MISSING: This error can
occur when creating an Embree device with SYCL support using
rtcNewSYCLDevice fails. This error probably means that the GPU
driver is to old or not installed properly. Install a new GPU
driver and on Linux make sure that the package
intel-level-zero-gpu-raytracing is installed. For general driver
installation information for Linux refer to
https://dgpu-docs.intel.com.
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.
The API function rtcGetDeviceLastErrorMessage can be used to get more
details about the last RTCError a RTCDevice encountered.
For convenient reporting of a RTCError, the API function
rtcGetErrorString can be used, which returns a string representation
of a given RTCError.
Returns the error code for the device.
[rtcSetDeviceErrorFunction], [rtcGetDeviceLastErrorMessage], [rtcGetErrorString]
rtcGetDeviceLastErrorMessage - returns a message corresponding
to the last error code
#include <embree4/rtcore.h>
const char* rtcGetDeviceLastErrorMessage(RTCDevice device);
This function can be used to get a message corresponding to the last
error code (returned by rtcGetDeviceError) which often provides
details about the error that happened. The message is the same as the
message that will written to console when verbosity is > 0 or which is
passed as the str argument of the RTCErrorFunction (see
[rtcSetDeviceErrorFunction]). However, when device construction fails
this is the only way to get additional information about the error. In
this case, rtcNewDevice returns NULL as device. To query the error
message for such a failed device construction, pass NULL as device to
the rtcGetDeviceLastErrorMessage function. For all other invocations
of rtcGetDeviceLastErrorMessage, a proper device pointer must be
specified.
Returns a message corresponding to the last error code.
[rtcGetDeviceError], [rtcSetDeviceErrorFunction]
rtcGetErrorString - returns a string representation
of a given RTCError
#include <embree4/rtcore.h>
const char* rtcGetErrorString(RTCError code);
Returns a string representation for a RTCError error code. For
example, for the RTCError RTC_ERROR_UNKNOWN this function will return
the string "Unknown Error". This is purely a convenience function for
printing error information on the user side.
The returned strings should not be used for comparing different
RTCError error codes or make other decisions based on the type of
error that occurred. For such things only the RTCError enum values
should be used.
Returns a string representation of a given RTCError error code.
[rtcGetDeviceError]
rtcSetDeviceErrorFunction - sets an error callback function for the device
#include <embree4/rtcore.h>
typedef void (*RTCErrorFunction)(
void* userPtr,
RTCError code,
const char* str
);
void rtcSetDeviceErrorFunction(
RTCDevice device,
RTCErrorFunction error,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetDeviceError]
rtcSetDeviceMemoryMonitorFunction - registers a callback function
to track memory consumption
#include <embree4/rtcore.h>
typedef bool (*RTCMemoryMonitorFunction)(
void* userPtr,
ssize_t bytes,
bool post
);
void rtcSetDeviceMemoryMonitorFunction(
RTCDevice device,
RTCMemoryMonitorFunction memoryMonitor,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice]
rtcNewScene - creates a new scene
#include <embree4/rtcore.h>
RTCScene rtcNewScene(RTCDevice device);
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.
On success a scene handle is returned. On failure NULL is returned
and an error code is set that can be queried using rtcGetDeviceError.
[rtcRetainScene], [rtcReleaseScene]
rtcGetSceneDevice - returns the device the scene got created in
#include <embree4/rtcore.h>
RTCDevice rtcGetSceneDevice(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcReleaseDevice]
rtcRetainScene - increments the scene reference count
#include <embree4/rtcore.h>
void rtcRetainScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene], [rtcReleaseScene]
rtcReleaseScene - decrements the scene reference count
#include <embree4/rtcore.h>
void rtcReleaseScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene], [rtcRetainScene]
rtcAttachGeometry - attaches a geometry to the scene
#include <embree4/rtcore.h>
unsigned int rtcAttachGeometry(
RTCScene scene,
RTCGeometry geometry
);
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 multiple
scenes. 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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryUserData], [rtcGetGeometryUserData]
rtcAttachGeometryByID - attaches a geometry to the scene
using a specified geometry ID
#include <embree4/rtcore.h>
void rtcAttachGeometryByID(
RTCScene scene,
RTCGeometry geometry,
unsigned int geomID
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcAttachGeometry]
rtcDetachGeometry - detaches a geometry from the scene
#include <embree4/rtcore.h>
void rtcDetachGeometry(RTCScene scene, unsigned int geomID);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID]
rtcGetGeometry - returns the geometry bound to
the specified geometry ID
#include <embree4/rtcore.h>
RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);
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.
This function is not thread safe and thus 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.
If you need a thread safe version of this function please use [rtcGetGeometryThreadSafe].
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometryThreadSafe]
rtcGetGeometryThreadSafe - returns the geometry bound to
the specified geometry ID
#include <embree4/rtcore.h>
RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID);
The rtcGetGeometryThreadSafe 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.
This function is thread safe and should NOT get used during rendering. If you need a fast non-thread safe version during rendering please use the [rtcGetGeometry] function.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometry]
rtcCommitScene - commits scene changes
#include <embree4/rtcore.h>
void rtcCommitScene(RTCScene scene);
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).
In case the RTCDevice associated with the scene is a SYCL device,
rtcCommitScene will internally create a temporary SYCL queue to issue
memory transfers from host to device memory. In this case, the call to
rtcCommitScene will be blocking and return only after the memory
transfers are completed and SYCL kernels can traverse the scene savely
on the device. The function rtcCommitSceneWithQueue can be used to
commit all changes for the specified scene asynchronously. Handles to
traversal objects (RTCTraversable type) that have been aquired before
a call to rtcCommitScene will be invalidated. Use
rtcGetSceneTraversable to get a valid handle from the scene after
every scene commit.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitSceneWithQueue], [rtcJoinCommitScene]
rtcCommitSceneWithQueue - commits scene changes using a given
SYCL queue for host-to-device memory transfers
#include <embree4/rtcore.h>
void rtcCommitScene(RTCScene scene,
sycl::queue queue,
sycl::event* event);
The rtcCommitSceneWithQueue 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.
The rtcCommitSceneWithQueue function differs from rtcCommitScene
only in that the former uses a SYCL queue passed by the application for
asynchronous host-to-device memory transfers and the latter uses an
internal and temporary SYCL queue and is blocking, i.e. the function
returns after all memory transfers are completed.
The application is responsible for synchronization when using
rtcCommitSceneWithQueue by either calling wait() on the queue or
use the optional event argument to receive a copy of the sycl::event
associated with the last memcpy command that was submitted to the
queue. The argument event can also be a null pointer in which case
the argument will be ignored internally.
A SYCL kernel calling rtcTraversableIntersect or rtcTraversableOccluded
using a RTCTraversable associated with the RTCScene scene has a
dependency on the host-to-device memory transfers and therefore has to
be synchronized properly.
This function is only available when SYCL support is enabled. In case
the RTCDevice associated with the scene is not a SYCL device,
rtcCommitSceneWithQueue will behave the same as rtcCommitScene.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitScene]
rtcJoinCommitScene - commits the scene from multiple threads
#include <embree4/rtcore.h>
void rtcJoinCommitScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitScene], [rtcGetDeviceProperty]
rtcSetSceneProgressMonitorFunction - registers a callback
to track build progress
#include <embree4/rtcore.h>
typedef bool (*RTCProgressMonitorFunction)(
void* ptr,
double n
);
void rtcSetSceneProgressMonitorFunction(
RTCScene scene,
RTCProgressMonitorFunction progress,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene]
rtcSetSceneBuildQuality - sets the build quality for
the scene
#include <embree4/rtcore.h>
void rtcSetSceneBuildQuality(
RTCScene scene,
enum RTCBuildQuality quality
);
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. When high quality mode is enabled, filter
callbacks may be invoked multiple times for the same geometry.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryBuildQuality]
rtcSetSceneFlags - sets the flags for the scene
#include <embree4/rtcore.h>
enum RTCSceneFlags
{
RTC_SCENE_FLAG_NONE = 0,
RTC_SCENE_FLAG_DYNAMIC = (1 << 0),
RTC_SCENE_FLAG_COMPACT = (1 << 1),
RTC_SCENE_FLAG_ROBUST = (1 << 2),
RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS = (1 << 3)
};
void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags);
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_FILTER_FUNCTION_IN_ARGUMENTS: Enables scene
support for filter functions passed as argument to the traversal
functions. See Section [rtcInitIntersectArguments] and
[rtcInitOccludedArguments] for more details.
Multiple flags can be enabled using an or operation,
e.g. RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneFlags]
rtcGetSceneFlags - returns the flags of the scene
#include <embree4/rtcore.h>
enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene);
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);
On failure RTC_SCENE_FLAG_NONE is returned and an error code is set
that can be queried using rtcGetDeviceError.
[rtcSetSceneFlags]
rtcGetSceneBounds - returns the axis-aligned bounding box of the scene
#include <embree4/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
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneLinearBounds], [rtcCommitScene], [rtcJoinCommitScene]
rtcGetSceneLinearBounds - returns the linear bounds of the scene
#include <embree4/rtcore.h>
struct RTCORE_ALIGN(16) RTCLinearBounds
{
RTCBounds bounds0;
RTCBounds bounds1;
};
void rtcGetSceneLinearBounds(
RTCScene scene,
struct RTCLinearBounds* bounds_o
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneBounds], [rtcCommitScene], [rtcJoinCommitScene]
rtcGetSceneTraversable - gets a read-only hand to a RTCScene object
that is also valid on a SYCL device and can be used for ray queries.
#include <embree4/rtcore.h>
RTCTraversable rtcGetSceneTraversable(RTCScene scene);
The rtcGetSceneTraversable function returns a read-only handle to a
RTCScene object (scene argument). Traversable objects are used for
ray queries on a SYCL device.
Traversable objects can also be used in host/CPU code and Embree
provides other API calls such as the rtcTraversablePointQuery to help
write portable code compatible with CPU and SYCL device execution.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcTraversableIntersect1]
rtcNewGeometry - creates a new geometry object
#include <embree4/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,
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY,
};
RTCGeometry rtcNewGeometry(
RTCDevice device,
enum RTCGeometryType type
);
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), instances (RTC_GEOMETRY_TYPE_INSTANCE),
and instance arrays (RTC_GEOMETRY_TYPE_INSTANCE_ARRAY).
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[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_INSTANCE_ARRAY]
RTC_GEOMETRY_TYPE_TRIANGLE - triangle geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
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:
![][imgTriangleUV]
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.
On failure NULL is returned and an error code is set that be get
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_QUAD - quad geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_QUAD);
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.
![][imgQuadUV]
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_GRID - grid geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_SUBDIVISION - subdivision geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION);
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.
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 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
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 - discontinuous 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
#include <embree4/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);
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).
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 segment, 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 rendered properly.
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.
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 makes this basis a good choice to construct continuous multi-segment curves, as memory consumption can be kept minimal.
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 using the Hermite basis, by calculating a proper tangent buffer from the control points.
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.
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.
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. We further assume second order derivatives of the center curve to be zero for this construction, as otherwise very large curvatures occurring in corner cases, can thicken the constructed curve significantly.
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 interior 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [RTCCurveFlags]
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
#include <embree4/rtcore.h>
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SPHERE_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_DISC_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_USER - user geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryUserPrimitiveCount], [rtcSetGeometryUserData], [rtcSetGeometryBoundsFunction], [rtcSetGeometryIntersectFunction], [rtcSetGeometryOccludedFunction]
RTC_GEOMETRY_TYPE_INSTANCE - instance geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE);
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 ray query context to the geometry ID of the instance, then trace
the transformed ray, and finally set the instID field of the ray
query 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryInstancedScene], [rtcSetGeometryTransform]
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY - instance array geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE_ARRAY);
Embree supports instance arrays, which is a more memory efficient way to represent large amounts of instances of the same or a small set of (sub)scenes. The main difference to regular Embree instances is that Embree instance arrays have a buffer of transformations (either affine transformations or quaternion decompositions [RTCQuaternionDecomposition]) that can be allocated by Embree or a shared buffer, similar to vertex buffers for triangle meshes. Optionally, instead of instancing only one scene, an instance array can instance multiple scenes by passing an array of scenes and a corresponding index buffer that specifies which instance of the instance array instances which of the scenes in the scenes array.
Instance arrays are created by passing
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY to the rtcNewGeometry function
call. The instanced scene can be either be set using the
rtcSetGeometryInstancedScene call, or if multiple scenes should be
instanced by passing an array of scenes using
rtcSetGeometryInstancedScenes. The latter also requires to specify an
index buffer using rtcSetNewGeometryBuffer or
rtcSetSharedGeometryBuffer with RTC_BUFFER_TYPE_INDEX as the buffer
type.
Because the transformation information can become large for a large
amount of instances, the instance array allows to share the
transformation buffer between the user application and Embree. It can
be either stored in a buffer created by Embree with
rtcSetNewGeometryBuffer or an already existing buffer can be shared
using rtcSetSharedGeometryBuffer. In either case, the buffer type has
to be RTC_BUFFER_TYPE_TRANSFORM and the allowed formats are
RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,
RTC_FORMAT_FLOAT3X4_ROW_MAJOR, and
RTC_FORMAT_QUATERNION_DECOMPOSITION. Embree will not modify the data
in the transformation buffer.
Embree instance arrays support 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.
Please note that rtcCommitScene on the instanced scene(s) should be
called first, followed by rtcCommitGeometry on the instance array,
followed by rtcCommitScene for the top-level scene containing the
instance array.
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. The instID member of the hit is set to the
geometry ID of the instance array in the top-level scene and the
instPrimID member is set to the index of the hit instance of the
instance array.
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
rtcSetNewGeometryBuffer or rtcSetSharedGeometryBuffer function and
passing the time step as the slot parameter of these calls.
See the [Instance Array Geometry] tutorial for an example of how to use instance arrays.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryInstancedScene], [rtcSetGeometryInstancedScenes], [rtcSetNewGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcGetGeometryTransformEx]
RTCCurveFlags - per segment flags for curve geometry
#include <embree4/rtcore.h>
enum RTCCurveFlags
{
RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0),
RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1)
};
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.
[RTC_GEOMETRY_TYPE_CURVE]
rtcRetainGeometry - increments the geometry reference count
#include <embree4/rtcore.h>
void rtcRetainGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcReleaseGeometry]
rtcReleaseGeometry - decrements the geometry reference count
#include <embree4/rtcore.h>
void rtcReleaseGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcRetainGeometry]
rtcCommitGeometry - commits geometry changes
#include <embree4/rtcore.h>
void rtcCommitGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcInterpolate], [rtcCommitScene]
rtcEnableGeometry - enables the geometry
#include <embree4/rtcore.h>
void rtcEnableGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcDisableGeometry], [rtcCommitScene]
rtcDisableGeometry - disables the geometry
#include <embree4/rtcore.h>
void rtcDisableGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcEnableGeometry], [rtcCommitScene]
rtcSetGeometryTimeStepCount - sets the number of time steps of the
geometry
#include <embree4/rtcore.h>
void rtcSetGeometryTimeStepCount(
RTCGeometry geometry,
unsigned int timeStepCount
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryTimeRange]
rtcSetGeometryTimeRange - sets the time range for a motion blur geometry
#include <embree4/rtcore.h>
void rtcSetGeometryTimeRange(
RTCGeometry geometry,
float startTime,
float endTime
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryTimeStepCount]
rtcSetGeometryVertexAttributeCount - sets the number of vertex
attributes of the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryVertexAttributeCount(
RTCGeometry geometry,
unsigned int vertexAttributeCount
);
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).
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [RTCBufferType]
rtcSetGeometryMask - sets the geometry mask
#include <embree4/rtcore.h>
void rtcSetGeometryMask(
RTCGeometry geometry,
unsigned int mask
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[RTCRay], [rtcGetDeviceProperty]
rtcSetGeometryBuildQuality - sets the build quality for the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryBuildQuality(
RTCGeometry geometry,
enum RTCBuildQuality quality
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSceneBuildQuality]
rtcSetGeometryMaxRadiusScale - assigns a maximal curve radius scale factor for min-width feature
#include <embree4/rtcore.h>
void rtcSetGeometryMaxRadiusScale(RTCGeometry geometry, float maxRadiusScale);
The rtcSetMaxGeometryScale function specifies a maximal scaling
factor for curve radii used by the min-width feature.
The min-width feature can increase the radius of curves and points, in order to reduce aliasing and improve render times. The feature is disabled by default and has to get enabled using the EMBREE_MIN_WIDTH cmake option.
To use the feature, one has to specify a maximal curve radius scaling factor using the [rtcSetGeometryMaxRadiusScale] function. This factor should be a small number (e.g. 4) as the constructed BVH bounds get increased in order to bound the curve in the worst case of maximal radii.
One also has to set the minWidthDistanceFactor in the RTCRayQueryContext when tracing a ray. This factor controls the target radius size of a curve or point at some distance away of the ray origin.
For each control point p with radius r of a curve or point primitive, the primitive intersectors first calculate a target radius r' as:
r' = length(p-ray_org) * minWidthDistanceFactor
Typically the minWidthDistanceFactor is set by the application such that the target radius projects to the width of half a pixel (thus primitive diameter is pixel sized).
The target radius r' is then clamped against the minimal bound r and maximal bound maxRadiusScale*r to obtain the final radius r'':
r'' = max(r, min(r', maxRadiusScale*r))
Thus curves or points close to the camera are rendered with a normal radii r, and curves or points far from the camera are not enlarged too much, as this would be very expensive to render.
When rtcSetGeometryMaxRadiusScale function is not invoked for a curve
or point geometry (or if the maximal scaling factor is set to 1.0),
then the curve or point geometry renders normally, with radii not
modified by the min-width feature.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcInitRayQueryContext]
rtcSetGeometryBuffer - assigns a view of a buffer to the geometry
#include <embree4/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
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetSharedGeometryBuffer - assigns a view of a shared data buffer
to a geometry
#include <embree4/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
);
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
rtcSetSharedGeometryBuffer 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.
If using a SYCL Embree device, ptr must be allocated using SYCL USM
shared memory to be accessible on the device. Alternatively the
function rtcSetSharedGeometryBufferHostDevice can be used to pass an
explicitly managed host/device buffer pair.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBufferHostDevice], [rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetSharedGeometryBufferHostDevice - assigns views of shared data buffers
to a geometry using explicit host and device memory
#include <embree4/rtcore.h>
void rtcSetSharedGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
const void* ptr,
const void* dptr,
size_t byteOffset,
size_t byteStride,
size_t itemCount
);
The rtcSetSharedGeometryBufferHostDevice function binds views of a
shared user-managed data buffers to a geometry buffer type and slot
(type and slot argument) of the specified geometry (geometry
argument). The user-managed data buffers are passed using the ptr
argument for the host side allocated memory and the dptr parameter
for the memory allocated on the device.
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
rtcSetSharedGeometryBufferHostDevice 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.
The application is responsible of keeping the host and device memory in
sync. The host memory has to be updated before calls of
rtcCommitScene involving the associated geometry.
If Embree has no SYCL support or the associated Embree device is no
SYCL device the dptr argument must be a null pointer. In this case
the function rtcSetSharedGeometryBufferHostDevice will behave like
rtcSetSharedGeometryBuffer.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBuffer], [rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetNewGeometryBuffer - creates and assigns a new data buffer to
the geometry
#include <embree4/rtcore.h>
void* rtcSetNewGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
size_t byteStride,
size_t itemCount
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer]
rtcSetNewGeometryBufferHostDevice - creates and assigns a new host/device
data buffer pair to the geometry
#include <embree4/rtcore.h>
void rtcSetNewGeometryBufferHostDevice(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
size_t byteStride,
size_t itemCount,
void** ptr,
void** dptr
);
The rtcSetNewGeometryBufferHostDevice function creates a new
host/device data buffer pair 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 rtcSetNewGeometryBufferHostDevice 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.
If ptr is not null, it will be used to return the address of the host
data buffer. If dptr is not null, it will be used to return the
address of the device data buffer. Either ptr or dptr or both can
be null. In this case rtcGetGeometryBufferData and
rtcGetGeometryBufferDataDevice can be used to get the addresses of
the host and device data buffers.
The application is responsible of keeping the host and device memory in
sync. The host memory has to be updated before calls of
rtcCommitScene involving the associated geometry.
If Embree has no SYCL support or the associated Embree device is no
SYCL device the dptr argument will return the same address as ptr
if on null. In this case the function
rtcSetNewGeometryBufferHostDevice will behave like
rtcSetSharedGeometryBuffer.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetNewGeometryBuffer], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcGetGeometryBufferData], [rtcGetGeometryBufferDataDevice]
RTCFormat - specifies format of data in buffers
#include <embree4/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,
RTC_FORMAT_QUATERNION_DECOMPOSITION
};
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. The RTC_FORMAT_QUATERNION_DECOMPOSITION format
specifies a structure that represents a quaternion decomposition (see
[RTCQuaternionDecomposition]) of an affine transformation. These
formats are used in the [rtcSetGeometryTransform] function or in
geometry buffers with type RTC_BUFFER_TYPE_TRANSFORM in order to set
a transformation matrix for instance and instance array 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]).
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer], [rtcSetGeometryTransform] [RTCQuaternionDecomposition]
RTCFormat - specifies format of data in buffers
#include <embree4/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_TRANSFORM = 23,
RTC_BUFFER_TYPE_FLAGS = 32
};
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_TRANSFORM buffer is used to provide instance
transformation information for instance array geometries (see
[RTC_GEOMETRY_TYPE_INSTANCE_ARRAY]).
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.
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcGetGeometryBufferData - gets pointer to
the first buffer view element
#include <embree4/rtcore.h>
void* rtcGetGeometryBufferData(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
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).
If the device associated with geometry is a SYCL device, the returned
pointer only accessible on the host. The function
rtcGetGeometryBufferDataDevice can be used to get a pointer
accessible on the SYCL device. #### EXIT STATUS
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetGeometryBufferDataDevice], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcGetGeometryBufferDataDevice - gets pointer to
the first buffer view element on the device.
#include <embree4/rtcore.h>
void* rtcGetGeometryBufferDataDevice(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
The rtcGetGeometryBufferDataDevice 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) on the device.
If the device associated with geometry is no SYCL device, or if
Embree is executed on a system with host unified memory (e.g., on an
iGPU), the returned pointer is the same as the one returned by
rtcGetGeometryBufferData.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetGeometryBufferData], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcUpdateGeometryBuffer - marks a buffer view bound to the geometry
as modified
#include <embree4/rtcore.h>
void rtcUpdateGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcCommitScene]
rtcSetGeometryIntersectFilterFunction - sets the intersection filter
for the geometry
#include <embree4/rtcore.h>
struct RTCFilterFunctionNArguments
{
int* valid;
void* geometryUserPtr;
const struct RTCRayQueryContext* context;
struct RTCRayN* ray;
struct RTCHitN* hit;
unsigned int N;
};
typedef void (*RTCFilterFunctionN)(
const struct RTCFilterFunctionNArguments* args
);
void rtcSetGeometryIntersectFilterFunction(
RTCGeometry geometry,
RTCFilterFunctionN filter
);
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
ray query 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. When accepting a hit, 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.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryOccludedFilterFunction]
rtcSetGeometryOccludedFilterFunction - sets the occlusion filter
for the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryOccludedFilterFunction(
RTCGeometry geometry,
RTCFilterFunctionN filter
);
Truncated — view the full README on GitHub.
(top 24 of 30)
365 followers · starred Jan 2015
5,731 followers · starred Mar 2026
2,035 followers · starred May 2017
138 followers · starred Apr 2019
% Embree: High Performance Ray Tracing Kernels 4.4.1 % Intel Corporation
Intel® Embree is a high-performance ray tracing library developed at Intel, which is released as open source under the Apache 2.0 license. Intel® Embree supports x86 CPUs under Linux, macOS, and Windows; ARM CPUs on Linux and macOS; as well as Intel® GPUs under Linux and Windows.
Intel® Embree targets graphics application developers to improve the performance of photo-realistic rendering applications. Embree is optimized towards production rendering, by putting focus on incoherent ray performance, high quality acceleration structure construction, a rich feature set, accurate primitive intersection, and low memory consumption.
Embree's feature set includes various primitive types such as triangles (as well quad and grids for lower memory consumption); Catmull-Clark subdivision surfaces; various types of curve primitives, such as flat curves (for distant views), round curves (for closeup views), and normal oriented curves, all supported with different basis functions (linear, Bézier, B-spline, Hermite, and Catmull Rom); point-like primitives, such as ray oriented discs, normal oriented discs, and spheres; user defined geometries with a procedural intersection function; multi-level instancing; filter callbacks invoked for any hit encountered; motion blur including multi-segment motion blur, deformation blur, and quaternion motion blur; and ray masking.
Intel® Embree contains ray tracing kernels optimized for the latest x86 processors with support for SSE, AVX, AVX2, and AVX-512 instructions, and uses runtime code selection to choose between these kernels. 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) as well as supports for dynamic scenes by implementing high-performance two-level spatial index structure construction algorithms.
Intel® Embree supports applications written with the Intel® Implicit SPMD Program Compiler (Intel® ISPC, https://ispc.github.io/) by providing an ISPC interface to the core ray tracing algorithms. This makes it possible to write a renderer that automatically vectorizes and leverages SSE, AVX, AVX2, and AVX-512 instructions.
Intel® Embree supports Intel GPUs through the SYCL open standard programming language. SYCL allows to write C++ code that can be run on various devices, such as CPUs and GPUs. Using Intel® Embree application developers can write a single source renderer that executes efficiently on CPUs and GPUs. Maintaining just one code base this way can significantly improve productivity and eliminate inconsistencies between a CPU and GPU version of the renderer. Embree supports GPUs based on the Xe HPG and Xe HPC microarchitecture, which support hardware accelerated ray tracing do deliver excellent levels of ray tracing performance.
Embree supports Windows (32-bit and 64-bit), Linux (64-bit), and macOS (64-bit). Under Windows, Linux and macOS x86 based CPUs are supported, while ARM CPUs are currently only supported under Linux and macOS (e.g. Apple M1). ARM support for Windows experimental.
Embree supports Intel GPUs based on the Xe HPG microarchitecture (Intel® Arc™ GPU) under Linux and Windows and Xe HPC microarchitecture (Intel® Data Center GPU Flex Series and Intel® Data Center GPU Max Series) under Linux.
The code compiles with the Intel® Compiler, Intel® oneAPI DPC++ Compiler, GCC, Clang, and the Microsoft Compiler. To use Embree on the GPU the Intel® oneAPI DPC++ Compiler must be used. Please see section [Compiling Embree] for details on tested compiler versions.
Embree requires at least an x86 CPU with support for SSE2 or an Apple M1 CPU.
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.
A pre-built version of Embree for Windows is provided as a ZIP archive
embree-4.4.1.x64.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.
A pre-built version of Embree for Linux is provided as a tar.gz archive:
embree-4.4.1.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-4.4.1.x86_64.linux.tar.gz
source embree-4.4.1.x86_64.linux/embree-vars.sh
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.
The macOS version of Embree is also delivered as a ZIP file:
embree-4.4.1.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-4.4.1.x64.macosx.zip source embree-4.4.1.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.4.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.
The most convenient way to build an Embree application is through
CMake. Just let CMake find your unpacked Embree package using the
FIND_PACKAGE function inside your CMakeLists.txt file:
FIND_PACKAGE(embree 4 REQUIRED)
For CMake to properly find Embree you need to set the embree_DIR variable to
the folder containing the embree_config.cmake file. You might also have to
set the TBB_DIR variable to the path containing TBB-config.cmake of a local
TBB install, in case you do not have TBB installed globally on your system,
e.g:
cmake -D embree_DIR=path_to_embree_package/lib/cmake/embree-4.4.1/ \
-D TBB_DIR=path_to_tbb_package/lib/cmake/tbb/ \
..
The FIND_PACKAGE function will create an embree target that
you can add to your target link libraries:
TARGET_LINK_LIBRARIES(application embree)
For a full example on how to build an Embree application please have a
look at the minimal tutorial provided in the src folder of the
Embree package and also the contained README.txt file.
Building Embree SYCL applications is also best done using CMake. Please first get some compatible SYCL compiler and setup the environment as decribed in sections [Linux SYCL Compilation] and [Windows SYCL Compilation].
Also perform the setup steps from the previous [Building Embree Applications] section.
Please also have a look at the [Minimal] tutorial that is provided with the Embree release, for an example how to build a simple SYCL application using CMake and Embree.
To properly compile your SYCL application you have to add additional SYCL compile flags for each C++ file that contains SYCL device side code or kernels as described next.
We recommend using just in time compilation (JIT compilation) together with [SYCL JIT caching] to compile Embree SYCL applications. For JIT compilation add these options to the compilation phase of all C++ files that contain SYCL code:
-fsycl -Xclang -fsycl-allow-func-ptr -fsycl-targets=spir64
These options enable SYCL two phase compilation (-fsycl option),
enable function pointer support (-Xclang -fsycl-allow-func-ptr
option), and just in time (JIT) compilation only
(-fsycl-targets=spir64 option).
The following link options have to get added to the linking stage of your application when using just in time compilation:
-fsycl -fsycl-targets=spir64
For a full example on how to build an Embree SYCL application please
have a look at the SYCL version of the minimal tutorial provided in
the src folder of the Embree package and also the contained
README.txt file.
Please have a look at the [Compiling Embree] section on how to create an Embree package from sources if required.
Ahead of time compilation (AOT compilation) allows to speed up first application start up time as device binaries are precompiled. We do not recommend using AOT compilation as it does not allow the usage of specialization constants to reduce code complexity.
For ahead of time compilation add these compile options to the compilation phase of all C++ files that contain SYCL code:
-fsycl -Xclang -fsycl-allow-func-ptr -fsycl-targets=spir64_gen
These options enable SYCL two phase compilation (-fsycl option),
enable function pointer support (-Xclang -fsycl-allow-func-ptr
option), and ahead of time (AOT) compilation
(-fsycl-targets=spir64_gen option).
The following link options have to get added to the linking stage of your application when compiling ahead of time for Xe HPG devices:
-fsycl -fsycl-targets=spir64_gen
-Xsycl-target-backend=spir64_gen "-device XE_HPG_CORE"
This in particular configures the devices for AOT compilation to
XE_HPG_CORE.
To get a list of all device supported by AOT compilation look at the help of the device option in ocloc tool:
ocloc compile --help
Embree is released with a bundle of tests in an optional testing package. To run these tests extract the testing package in the same folder as your embree installation. e.g.:
tar -xzf embree-4.4.1-testing.zip -C /path/to/installed/embree
The tests are extracted into a new folder inside you embree installation and can be run with:
cd /path/to/installed/embree/testing
cmake -B build
cmake --build build target=tests
We recommend using the prebuild Embree packages from https://github.com/embree/embree/releases. If you need to compile Embree yourself you need to use CMake as described in the following.
Do not enable fast-math optimizations in your compiler as this mode is not supported by Embree.
To compile Embree you need a modern C++ compiler that supports C++11. Embree is tested with the following compilers:
Linux
macOS x86_64
macOS Arm64
Embree supports using the Intel® Threading Building Blocks (TBB) as the
tasking system. For performance and flexibility reasons we recommend
using 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® Implicit SPMD Program Compiler (Intel® ISPC), which allows
straightforward parallelization of an entire renderer. If you
want to use Intel® ISPC then you can enable EMBREE_ISPC_SUPPORT in
CMake. Download and install the Intel® ISPC binaries from
ispc.github.io. After
installation, put the path to ispc permanently into your PATH environment
variable or you set the EMBREE_ISPC_EXECUTABLE variable to point at the ISPC
executable during CMake configuration.
You additionally have to install CMake 3.10 or higher and the developer version of GLFW version 3.
Under macOS, all these dependencies can be installed using MacPorts:
sudo port install cmake tbb 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 Clang compiler instead of the default GCC on most Linux machines
(g++ and gcc), execute
cmake -DCMAKE_CXX_COMPILER=clang++ -DCMAKE_C_COMPILER=clang ..
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 -j 8
The executables will be generated inside the build folder. We recommend
installing 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
You can also create an Embree package using the following command:
make package
Please see the [Building Embree Applications] section on how to build your application with such an Embree package.
There are two options to compile Embree with SYCL support: The open source "oneAPI DPC++ Compiler" or the "Intel(R) oneAPI DPC++/C++ Compiler". Other SYCL compilers are not supported.
The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI DPC++/C++ Compiler" but less stable. The current tested version of the "oneAPI DPC++ compiler is
The compiler can be downloaded and simply extracted. The oneAPI DPC++ compiler can be set up executing the following commands in a Linux (bash) shell:
export SYCL_BUNDLE_ROOT=path_to_dpcpp_compiler
export PATH=$SYCL_BUNDLE_ROOT/bin:$PATH
export CPATH=$SYCL_BUNDLE_ROOT/include:$CPATH
export LIBRARY_PATH=$SYCL_BUNDLE_ROOT/lib:$LIBRARY_PATH
export LD_LIBRARY_PATH=$SYCL_BUNDLE_ROOT/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH=$SYCL_BUNDLE_ROOT/linux/lib/x64:$LD_LIBRARY_PATH
where the path_to_dpcpp_compiler should point to the unpacked oneAPI DPC++
compiler. This will put clang++ and clang from the oneAPI DPC++ Compiler
into your path.
Please also install all Linux packages described in the previous section.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build \
-DCMAKE_CXX_COMPILER=clang++ \
-DCMAKE_C_COMPILER=clang \
-DEMBREE_SYCL_SUPPORT=ON
This will create a directory build to use as the CMake build directory,
configure the usage of the oneAPI DPC++ Compiler, and turn on SYCL support
through EMBREE_SYCL_SUPPORT=ON.
Alternatively, you can download and run the installer of the
After installation, you can set up the compiler by sourcing the
vars.sh script in the env directory of the compiler install directory, for example,
source /opt/intel/oneAPI/compiler/latest/env/vars.sh
This script will put the icpx and icx compiler executables from the
Intel(R) oneAPI DPC++/C++ Compiler in your path.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build \
-DCMAKE_CXX_COMPILER=icpx \
-DCMAKE_C_COMPILER=icx \
-DEMBREE_SYCL_SUPPORT=ON
More information about setting up the Intel(R) oneAPI DPC++/C++ compiler can be found in the Development Reference Guide. Please note, that the Intel(R) oneAPI DPC++/C++ compiler requires at least CMake version 3.20.5 on Linux.
Independent of the DPC++ compiler choice, you can now build Embree using
cmake --build build -j 8
The executables will be generated inside the build folder. The
executable names of the SYCL versions of the tutorials end with
_sycl.
To run the SYCL code you need to install the latest GPGPU drivers for your Intel Xe HPG/HPC GPUs from here https://dgpu-docs.intel.com/. Follow the driver installation instructions for your graphics card and operating system.
After installing the drivers you have to install an additional package manually using
sudo apt install intel-level-zero-gpu-raytracing
Embree is tested using the following compilers under Windows:
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
using 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
https://github.com/oneapi-src/oneTBB/releases
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® Implicit SPMD Program Compiler (Intel® ISPC), which
allows straightforward parallelization of an entire renderer. When installing
Intel® ISPC, make sure to download an Intel® 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 EMBREE_ISPC_EXECUTABLE variable during CMake configuration to point to
the ISPC executable. If you want to use Intel® ISPC, you have to enable
EMBREE_ISPC_SUPPORT in CMake.
You additionally have to install CMake (version 3.1 or higher). Note that you need a native Windows CMake installation because CMake under Cygwin cannot generate solution files for Visual Studio.
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".
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. The 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 embree4.sln to compile
the project.
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.
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 16 2019" ..
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
You can download and install Embree using the vcpkg dependency manager:
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install embree3
The Embree port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please create an issue or pull request on the vcpkg repository.
There are two options to compile Embree with SYCL support: The open source "oneAPI DPC++ Compiler" or the "Intel(R) oneAPI DPC++/C++ Compiler". Other SYCL compilers are not supported. You will also need an installed version of Visual Studio that supports the C++17 standard, e.g. Visual Studio 2019.
The "oneAPI DPC++ Compiler" is more up-to-date than the "Intel(R) oneAPI DPC++/C++ Compiler" but less stable. The current tested version of the oneAPI DPC++ compiler is
Download and unpack the archive and open the "x64 Native Tools Command Prompt" of Visual Studio and execute the following lines to properly configure the environment to use the oneAPI DPC++ compiler:
set "DPCPP_DIR=path_to_dpcpp_compiler"
set "PATH=%DPCPP_DIR%\bin;%PATH%"
set "PATH=%DPCPP_DIR%\lib;%PATH%"
set "CPATH=%DPCPP_DIR%\include;%CPATH%"
set "INCLUDE=%DPCPP_DIR%\include;%INCLUDE%"
set "LIB=%DPCPP_DIR%\lib;%LIB%"
The path_to_dpcpp_compiler should point to the unpacked oneAPI DPC++
compiler.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build
-G Ninja
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_CXX_COMPILER=clang++
-D CMAKE_C_COMPILER=clang
-D EMBREE_SYCL_SUPPORT=ON
-D TBB_ROOT=path_to_tbb\lib\cmake\tbb
This will create a directory build to use as the CMake build directory, and
configure a release build that uses clang++ and clang from the oneAPI DPC++
compiler.
The Ninja generator is currently the easiest way to use the oneAPI DPC++ compiler.
We also enable SYCL support in Embree using the EMBREE_SYCL_SUPPORT CMake
option.
Alternatively, you can download and run the installer of the
After installation, you can either open a regular Command Prompt and execute
the vars.bat script in the env directory of the compiler install directory,
for example
C:\Program Files (x86)\Intel\oneAPI\compiler\latest\env\vars.bat
or simply open the installed "Intel oneAPI command prompt for Intel 64 for Visual Studio".
Both ways will put the icx compiler executable from the
Intel(R) oneAPI DPC++/C++ compiler in your path.
Now, you can configure Embree using CMake by executing the following command in the Embree root directory:
cmake -B build
-G Ninja
-D CMAKE_BUILD_TYPE=Release
-D CMAKE_CXX_COMPILER=icx
-D CMAKE_C_COMPILER=icx
-D EMBREE_SYCL_SUPPORT=ON
-D TBB_ROOT=path_to_tbb\lib\cmake\tbb
More information about setting up the Intel(R) oneAPI DPC++/C++ compiler can be found in the Development Reference Guide. Please note, that the Intel(R) oneAPI DPC++/C++ compiler requires at least CMake version 3.23 on Windows.
Independent of the DPC++ compiler choice, you can now build Embree using
cmake --build build
If you have problems with Ninja re-running CMake in an infinite loop,
then first remove the "Re-run CMake if any of its inputs changed."
section from the build.ninja file and run the above command again.
You can also create an Embree package using the following command:
cmake --build build --target package
Please see the [Building Embree SYCL Applications] section on how to build your application with such an Embree package.
In order to run the SYCL tutorials on HPG hardware, you first need to install the graphics drivers for your graphics card from https://www.intel.com. Please make sure to have installed version 31.0.101.4644 or newer.
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 Intel® ISPC support of Embree. This option
is OFF by default.
EMBREE_SYCL_SUPPORT: Enables GPU support using SYCL. When this
option is enabled you have to use some DPC++ compiler. Please see
the sections [Linux SYCL Compilation] and [Windows SYCL Compilation]
on supported DPC++ compilers. This option is OFF by default.
EMBREE_SYCL_AOT_DEVICES: Selects a list of GPU devices for
ahead-of-time (AOT) compilation of device code. Possible values are
either, "none" which enables only just in time (JIT) compilation, or
a list of the Embree-supported Xe GPUs for AOT compilation:
One can also specify multiple devices separated by comma to compile ahead of time for multiple devices, e.g. "XE_HPG_CORE,XE_HP_CORE". When enabling AOT compilation for one or multiple devices, JIT compilation will always additionally be enabled in case the code is executed on a device no code is precompiled for.
Execute "ocloc compile --help" for more details of possible devices to pass. Embree is only supported on Xe HPG/HPC and newer devices.
Per default, this option is set to "none" to enable JIT compilation. We recommend using JIT compilation as this enables the use of specialization constants to reduce code complexity.
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. embree4.a, embree4_sse42.a,
embree4_avx.a, embree4_avx2.a, embree4_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
are exported.
EMBREE_LIBRARY_NAME: Specifies the name of the Embree library file
created. By default, the name embree4 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_BACKFACE_CULLING_CURVES: Enables backface culling for curves,
i.e. only surfaces facing a ray can be hit. This option is turned OFF
by default.
EMBREE_BACKFACE_CULLING_SPHERES: Enables backface culling for spheres,
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 appropriate 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 Building Blocks (TBB)
is used as a tasking system, search the library in this directory
tree.
EMBREE_TBB_COMPONENT: The component/library name of Intel® Threading
Building Blocks (TBB). Embree searches for this library name (default: tbb)
when TBB is used as the tasking system.
EMBREE_TBB_POSTFIX: If Intel® Threading 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 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 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 triangle geometries
(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_INSTANCE_ARRAY: Enables support for instance arrays (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_DISC_POINT_SELF_INTERSECTION_AVOIDANCE: Enables self-intersection
avoidance for RTC_GEOMETRY_TYPE_DISC_POINT geometry type (ON by default).
When enabled intersections are skipped if the ray origin lies inside the
sphere defined by the point primitive.
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.
The Embree API is a low-level C99 ray tracing API which can be used to build spatial index structures for 3D scenes and perform ray queries of different types.
The API can get used on the CPU using standard C, C++, and ISPC code and Intel GPUs by using SYCL code.
The Intel® Implicit SPMD Program Compiler (Intel® ISPC) version of the API, is almost identical to the standard C99 version, but contains additional functions that operate on ray packets with a size of the native SIMD width used by Intel® ISPC.
The SYCL version of the API is also mostly identical to the C99 version of the API, with some exceptions listed in section [Embree SYCL API].
For simplicity this document refers to the C99 version of the API functions. For changes when upgrading from the Embree 3 to the current Embree 4 API see Section [Upgrading from Embree 3 to Embree 4].
All API calls carry the prefix rtc (or RTC for types) which stands
for ray tracing core. 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
and ray packets. 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 otherwise.
However, attaching geometries to the same scene and performing ray
queries in a scene is thread-safe.
Starting with Embree 4.4 intersection and occlusion queries on a SYCL
device require the use of the rtcTraversableIntersect-type functions
or the rtcTraversableOccluded-type function respectively. These
functions take a traversable object (RTCTraversable type) which
corresponds to a RTCScene. Traversable objects are not reference
counted and therefore they do not have to be released like the other
handles. Traversable objects grant read-only access to a scene object
on a SYCL device and are valid as long as the corresponding scene
object is valid.
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 (or [rtcNewSYCLDevice] when using SYCL for the GPU). 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.
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.
When using SYCL, calls to rtcCommitScene trigger memory transfers
from the host (CPU) to the device (GPU). Calling rtcCommitScene will
be blocking and return only after the memory transfers are completed.
Embree also provides the function rtcCommitSceneWithQueue which takes
a SYCL queue as argument to which the memory transfer operations are
submitted. Calling rtcCommitSceneWithQueue will trigger the memory
transfers asynchronously and the application is responsible for
sychronizing command on the queue properly to ensure the scene data is
available on a SYCL device when a SYCL kernels performs intersection
queries that rely on the scene data.
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.
Starting with Embree 4.4 scene objects (RTCScene types) are not valid
handles on SYCL devices anymore and therefore can not be used for
Embree API calls in a SYCL kernel. Instead, Embree API calls on a SYCL
kernel have a variation which use traversable objects (RTCTraversable
type).
Traversable objects grant read-only access to a scene object on a SYCL
device and are valid as long as the corresponding scene object is
valid. They can be queried from a scene object using the
rtcGetSceneTraversable function and used in
rtcTraversableIntersect-type functions or the
rtcTraversableOccluded-type function. They can also be used in CPU
code and Embree provides other API calls such as the
rtcTraversablePointQuery (which are not currently implemented for
SYCL) to help write portable code compatible with CPU and SYCL device
execution.
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 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).
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.
On SYCL devices the API functions rtcTraversableIntersect and
rtcTraversableOccluded have to be used.
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]).
Point Queries can currently not be used on SYCL devices.
See Section [rtcPointQuery] for a detailed description of how to set up point queries.
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.
Collision detection can currently not be used on SYCL devices.
See Section [rtcCollide] for a detailed description of how to set up collision detection.
Seen tutorial Collision Detection for a complete example of collision detection being used on a simple cloth solver.
The API supports filter functions that are invoked for each
intersection found during the rtcIntersect-type or rtcOccluded-type
calls.
The filter functions can be set per-geometry using the
rtcSetGeometryIntersectFilterFunction and
rtcSetGeometryOccludedFilterFunction 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.
The filter function can also get passed as arguments directly to the
traversal functions, see section [rtcInitIntersectArguments] and
[rtcInitOccludedArguments] for more details. These argument filter
functions are 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 argument
filter function must be enabled to be used for a scene using the
RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS scene flag. The callback
is only invoked for geometries that enable the callback using the
rtcSetGeometryEnableFilterFunctionFromArguments call, or enabled for
all geometries when the RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER ray
query flag is set.
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.
Embree supports ray tracing on Intel GPUs by using the SYCL programming language. SYCL is a Khronos standardized C++ based language for single source heterogenous programming for acceleration offload, see the SYCL webpage for details.
The Embree SYCL API is designed for photorealistic rendering use cases, where scene setup is performed on the host, and rendering on the device. The Embree SYCL API is very similar to the standard Embree C99 API, and supports most of its features, such as all triangle-type geometries, all curve types and basis functions, point geometry types, user geometries, filter callbacks, multi-level instancing, and motion blur.
To enable SYCL support you have to include the sycl.hpp file before
the Embree API headers:
#include <sycl/sycl.hpp>
#include <embree4/rtcore.h>
Next you need to initializes an Embree SYCL device using the
rtcNewSYCLDevice API function by providing a SYCL context.
Embree provides the rtcIsSYCLDeviceSupported API function to check if
some SYCL device is supported by Embree. You can also use the
rtcSYCLDeviceSelector to conveniently select the first SYCL device
that is supported by Embree, e.g.:
sycl::device device(rtcSYCLDeviceSelector);
sycl::queue queue(device, exception_handler);
sycl::context context(device);
RTCDevice device = rtcNewSYCLDevice(context,"");
Scenes created with an Embree SYCL device can only get used to trace rays using SYCL on the GPU, it is not possible to trace rays on the CPU with such a device. To render on the CPU and GPU in parallel, the user has to create a second Embree device and create a second scene to be used on the CPU.
Starting with Embree 4.4 scene objects (RTCScene types) are not valid
handles on SYCL devices anymore and therefore can not be used for
Embree API calls in a SYCL kernel. Instead, Embree API calls on a SYCL
kernel have a variation which use traversable objects (RTCTraversable
type). To get a traversable object for a scene object the application
can call rtcGetSceneTraversable.
Files containing SYCL code, have to get compiled with the Intel® oneAPI DPC++ compiler. Please see section [Linux SYCL Compilation] and [Windows SYCL Compilation] for supported compilers. The DPC++ compiler performs a two-phase compilation, where host code is compiled in a first phase, and device code compiled in a second compilation phase.
Standard Embree API functions for scene construction can get used on the host but not the device.
Before version 4.4, Embree made heavy use of unified shared memory
(USM) shared memory which simplifies memory management with SYCL
devices by letting the SYCL runtime transfer data from host to device
implicitly. However, some applications require more control over when
and how data is migrated from CPU to GPU. Embree 4.4 allows to use
explicit host and device memory allocations. See for example
rtcSetNewGeometryBufferHostDevice,
rtcSetSharedGeometryBufferHostDevice, rtcNewBufferHostDevice, and
rtcNewSharedBufferHostDevice. It is still possible to share data
buffers with Embree using SYCL USM shared memory by using the API calls
without the HostDevice suffix.
The easiest way to share data buffers with Embree (e.g. for vertex of
index buffers) is to allocate the data as USM shared memory, using the
sycl::malloc or sycl::aligned_alloc calls with
sycl::usm::alloc::shared property, or the sycl::aligned_alloc_shared
call, e.g:
void* ptr = sycl::aligned_alloc(16, bytes, queue, sycl::usm::alloc::shared);
These shared allocations have to be valid during rendering, as Embree may access contained data when tracing rays.
Device side rendering can get invoked by submitting a SYCL
parallel_for to the SYCL queue:
const sycl::specialization_id<RTCFeatureFlags> feature_mask;
RTCFeatureFlags required_features = RTC_FEATURE_FLAG_TRIANGLE;
RTCTraversable traversable = rtcGetSceneTraversable(scene);
queue.submit([=](sycl::handler& cgh)
{
cgh.set_specialization_constant<feature_mask>(required_features);
cgh.parallel_for(sycl::range<1>(1),[=](sycl::id<1> item, sycl::kernel_handler kh)
{
RTCIntersectArguments args;
rtcInitIntersectArguments(&args);
const RTCFeatureFlags features = kh.get_specialization_constant<feature_mask>();
args.feature_mask = features;
struct RTCRayHit rayhit;
rayhit.ray.org_x = ox;
rayhit.ray.org_y = oy;
rayhit.ray.org_z = oz;
rayhit.ray.dir_x = dx;
rayhit.ray.dir_y = dy;
rayhit.ray.dir_z = dz;
rayhit.ray.tnear = 0;
rayhit.ray.tfar = std::numeric_limits<float>::infinity();
rayhit.ray.mask = -1;
rayhit.ray.flags = 0;
rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;
rtcTraversableIntersect1(traversable, &rayhit, &args);
result->geomID = rayhit.hit.geomID;
result->primID = rayhit.hit.primID;
result->tfar = rayhit.ray.tfar;
});
});
queue.wait_and_throw();
This example passes a feature mask using a specialization constant to
the rtcTraversableIntersect1 function, which is recommended for GPU
rendering. For best performance, this feature mask should get used to
enable only features required by the application to render the scene,
e.g. just triangles in this example.
Inside the SYCL parallel_for loop you can use rendering related
functions, such as the rtcTraversableIntersect1 and
rtcTraversableOccluded1 functions to trace rays,
rtcTraversableForwardIntersect1/Ex and
rtcTraversableForwardOccluded1/Ex to continue object traversal from
inside a user geometry callback, and
rtcGetGeometryUserDataFromTraversable to get the user data pointer of
some geometry.
Have a look at the [Minimal] tutorial for a minimal SYCL example and the [Host Device Memory] tutorial shows four different ways in which data buffers can be created by or shared with Embree using explicit host/device data buffers.
Compile times for just in time compilation (JIT compilation) can be
large. To resolve this issue we recommend enabling persistent JIT
compilation caching inside your application, by setting the
SYCL_CACHE_PERSISTENT environment variable to 1, and the
SYCL_CACHE_DIR environment variable to some proper directory where
the JIT cache should get stored. These environment variables have to
get set before the SYCL device is created, e.g:
setenv("SYCL_CACHE_PERSISTENT","1",1);
setenv("SYCL_CACHE_DIR","cache_dir",1);
sycl::device device(rtcSYCLDeviceSelector);
...
Memory Pooling is a mechanism where small USM memory allocations are packed into larger allocation blocks. This mode is required when your application performs many small USM allocations, as otherwise only a small fraction of GPU memory is usable and data transfer performance will be low.
Memory pooling is supported for USM allocations that are read-only by the device. The following example allocated device read-only memory with memory pooling support:
sycl::aligned_alloc_shared(align, bytes, queue,
sycl::ext::oneapi::property::usm::device_read_only());
Embree only supports Xe HPC and HPG GPUs as SYCL devices, thus in particular the CPU and other GPUs cannot get used as a SYCL device. To render on the CPU just use the standard C99 API without relying on SYCL.
The SYCL language spec puts some restrictions to device functions, such
as disallowing: global variable access, malloc, invocation of virtual
functions, function pointers, runtime type information, exceptions,
recursion, etc. See Section
5.4. Language Restrictions for device functions of the SYCL
specification
for more details.
Using Intel's oneAPI DPC++ compiler invoking an indirectly called function is allowed, but we do not recommend this for performance reasons.
Some features are not supported by the Embree SYCL API thus cannot get used on the GPU:
Since Embree 4.4, all the ray query functions that take an
RTCScene object as argument cannot get used in SYCL device side
code. Instead, the API functions taking a RTCTraversable object
(e.g. rtcTraversableIntersect1) have to be used.
The packet tracing functions rtcTraversableIntersect4/8/16 and
rtcTraversableOccluded4/8/16 are not supported in SYCL device
side code. Using these functions makes no sense for SYCL, as the
programming model is implicitly executed in SIMT mode on the GPU
anyway.
Filter and user geometry callbacks stored inside the geometry
objects are not supported on SYCL. Please use the alternative
approach of passing the function pointer through the
RTCIntersectArguments (or RTCOccludedArguments) structures to
the tracing function, which enables inlining on the GPU.
The rtcInterpolate function cannot get used on the the device.
For most primitive types the vertex data interpolation is anyway a
trivial operation, and an API call just introduces overheads. On
the CPU that overhead is acceptable, but on the GPU it is not. The
rtcInterpolate function does not know the geometry type it is
interpolating over, thus its implementation on the GPU would
contain a large switch statement for all potential geometry types.
Tracing rays using rtcTraversableIntersect1 and
rtcTraversableOccluded1 functions from user geometry callbacks is
not supported in SYCL. Please use the tail recursive
rtcTraversableForwardIntersect1 and
rtcTraversableForwardOccluded1 calls instead.
Subdivision surfaces are not supported for Embree SYCL devices.
Collision detection (rtcCollide API call) is not supported in
SYCL device side code.
Point queries (rtcPointQuery API call) are not supported in SYCL
device side code.
This section summarizes API changes between Embree 3 and Embree4. Most of these changes are motivated by GPU performance and having a consistent API that works properly for the CPU and GPU.
The API include folder got renamed from embree3 to embree4, to be able to install Embree 3 and Embree 4 side by side, without having conflicts in API folder.
The RTCIntersectContext is renamed to RTCRayQueryContext and
the RTCIntersectContextFlags got renamed to RTCRayQueryFlags.
There are some changes to the rtcIntersect and rtcOccluded
functions. Most members of the old intersect context have been
moved to some optional RTCIntersectArguments (and
RTCOccludedArguments) structures, which also contains a pointer
to the new ray query context. The argument structs fulfill the task
of providing additional advanced arguments to the traversal
functions. The ray query context can get used to pass additional
data to callbacks, and to maintain an instID stack in case
instancing is done manually inside user geometry callbacks. The
arguments struct is not available inside callbacks. This change was
in particular necessary for SYCL to allow inlining of function
pointers provided to the traversal functions, and to reduce the
amount of state passed to callbacks, which both improves GPU
performance. Most applications can just drop passing the ray query
context to port to Embree 4.
The rtcFilterIntersection and rtcFilterOcclusion API calls that
invoke both, the geometry and argument version of the filter
callback, from a user geometry callback are no longer supported.
Instead applications should use the
rtcInvokeIntersectFilterFromGeometry and
rtcInvokeOccludedFilterFromGeometry API calls that invoke just
the geometry version of the filter function, and invoke the
argument filter function manually if required.
The filter function passed as arguments to rtcIntersect and
rtcOccluded functions is only invoked for some geometry if
enabled through rtcSetGeometryEnableFilterFunctionFromArguments
for that geometry. Alternatively, argument filter functions can get
enabled for all geometries using the
RTC_RAY_QUERY_FLAG_INVOKE_ARGUMENT_FILTER ray query flag.
User geometry callbacks get a valid vector as input to identify valid and invalid rays. In Embree 3 the user geometry callback just had to update the ray hit members when an intersection was found and perform no operation otherwise. In Embree 4 the callback additionally has to return valid=-1 when a hit was found, and valid=0 when no hit was found. This allows Embree to properly pass the new hit distance to the ray tracing hardware only in the case a hit was found.
Further ray masking is enabled by default now as required by most applications and the default ray mask for geometries got changed from 0xFFFFFFFF to 0x1.
The stream tracing functions rtcIntersect1M, rtcIntersect1Mp,
rtcIntersectNM, rtcIntersectNp, rtcOccluded1M,
rtcOccluded1Mp, rtcOccludedNM, and rtcOccludedNp got removed
as they were rarely used and did not provide relevant performance
benefits. As alternative the application can just iterate over
rtcIntersect1 and potentially rtcIntersect4/8/16 to get similar
performance.
To use Embree through SYCL on the CPU and GPU additional changes are required:
Embree 3 allows to use rtcIntersect recursively from a user
geometry or intersection filter callback to continue a ray inside
an instantiated object. In Embree 4 using rtcIntersect
recursively is disallowed on the GPU but still supported on the
CPU. To properly continue a ray inside an instantiated object use
the new rtc(Traversable)ForwardIntersect1 and
rtc(Traversable)ForwardOccluded1 functions.
The geometry object and scene object of Embree 4 are a host side
only objects, thus accessing it during rendering from the GPU is
not allowed. Thus all API functions that take an RTCGeometry object
or RTCScene object as argument cannot get used during rendering. In
particular the rtcGetGeometryUserData(RTCGeometry) call cannot
get used, but there is an alternative function
rtcGetGeometryUserDataFromTraversable(RTCTraversable traversable,uint geomID)
that should get used instead. To perform ray queries on the GPU
(e.g. rtcTraversableIntersect1) the application has to get a
RTCTraversable object first (using rtcGetSceneTraversable) and
pass it to the SYCL kernel.
The user geometry callback and filter callback functions should get
passed through the intersection and occlusion argument structures
to the rtcTraversableIntersect1 and rtcTraversableOccluded1
functions directly to allow inlining. The experimental geometry
version of the callbacks is disabled in SYCL and should not get
used.
The feature flags should get used in SYCL to minimal GPU code for optimal performance.
The rtcInterpolate function cannot get used on the device, and
vertex data interpolation should get implemented by the
application.
Indirectly called functions must be declared with
RTC_SYCL_INDIRECTLY_CALLABLE when used as filter or user geometry
callbacks.
rtcNewDevice - creates a new device
#include <embree4/rtcore.h>
RTCDevice rtcNewDevice(const char* config);
This function creates a new device to be used for CPU ray tracing 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");
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).
[rtcRetainDevice], [rtcReleaseDevice], [rtcNewSYCLDevice]
rtcNewSYCLDevice - creates a new device to be used with SYCL
#include <embree4/rtcore.h>
RTCDevice rtcNewSYCLDevice(sycl::context context, const char* config);
This function creates a new device to be used with SYCL for GPU
rendering and returns a handle to this device. The device object is
reference counted with an initial reference count of 1. The handle can
get released using the rtcReleaseDevice API call.
The passed SYCL context (context argument) is used to allocate GPU
data, thus only devices contained inside this context can be used for
rendering. By default the GPU data is allocated on the first GPU device
of the context, but this behavior can get changed with the
[rtcSetDeviceSYCLDevice] function.
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.
For an overview of configurations that can get passed (config
argument) please see the [rtcNewDevice] function description.
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).
[rtcRetainDevice], [rtcReleaseDevice], [rtcNewDevice]
rtcIsSYCLDeviceSupported - checks if some SYCL device is supported by Embree
#include <embree4/rtcore.h>
bool rtcIsSYCLDeviceSupported(const sycl::device sycl_device);
This function can be used to check if some SYCL device (sycl_device
argument) is supported by Embree.
The function returns true if the SYCL device is supported by Embree and
false otherwise. On failure an error code is set that can get queried
using rtcGetDeviceError.
[rtcSYCLDeviceSelector]
rtcSYCLDeviceSelector - SYCL device selector function to select
devices supported by Embree
#include <embree4/rtcore.h>
int rtcSYCLDeviceSelector(const sycl::device sycl_device);
This function checks if the passed SYCL device (sycl_device
arguments) is supported by Embree or not. This function can be used
directly to select some supported SYCL device by using it as SYCL
device selector function. For instance, the following code sequence
selects an Embree supported SYCL device and creates an Embree device
from it:
sycl::device sycl_device(rtcSYCLDeviceSelector);
sycl::queue sycl_queue(sycl_device);
sycl::context(sycl_device);
RTCDevice device = rtcNewSYCLDevice(sycl_context,nullptr);
The function returns -1 if the SYCL device is supported by Embree and 1
otherwise. On failure an error code is set that can get queried using
rtcGetDeviceError.
[rtcIsSYCLDeviceSupported]
rtcSetDeviceSYCLDevice - sets the SYCL device to be used for memory allocations
#include <embree4/rtcore.h>
void rtcSetDeviceSYCLDevice(RTCDevice device, const sycl::device sycl_device);
This function sets the SYCL device (sycl_device argument) to be used
to allocate GPU memory when using the specified Embree device (device
argument). This SYCL device must be one of the SYCL devices contained
inside the SYCL context used to create the Embree device.
On failure an error code is set that can get queried using
rtcGetDeviceError.
[rtcNewSYCLDevice]
rtcRetainDevice - increments the device reference count
#include <embree4/rtcore.h>
void rtcRetainDevice(RTCDevice device);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice], [rtcReleaseDevice]
rtcReleaseDevice - decrements the device reference count
#include <embree4/rtcore.h>
void rtcReleaseDevice(RTCDevice device);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice], [rtcRetainDevice]
rtcGetDeviceProperty - queries properties of the device
#include <embree4/rtcore.h>
ssize_t rtcGetDeviceProperty(
RTCDevice device,
enum RTCDeviceProperty prop
);
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_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_BACKFACE_CULLING_CURVES_ENABLED: Queries
whether back face culling for curves is enabled. This is only the
case if Embree is compiled with EMBREE_BACKFACE_CULLING_CURVES
enabled.
RTC_DEVICE_PROPERTY_BACKFACE_CULLING_SPHERES_ENABLED: Queries
whether back face culling for spheres is enabled. This is only the
case if Embree is compiled with EMBREE_BACKFACE_CULLING_SPHERES
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:
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.
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 - returns the error code of the device
#include <embree4/rtcore.h>
RTCError rtcGetDeviceError(RTCDevice device);
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.
RTC_ERROR_LEVEL_ZERO_RAYTRACING_SUPPORT_MISSING: This error can
occur when creating an Embree device with SYCL support using
rtcNewSYCLDevice fails. This error probably means that the GPU
driver is to old or not installed properly. Install a new GPU
driver and on Linux make sure that the package
intel-level-zero-gpu-raytracing is installed. For general driver
installation information for Linux refer to
https://dgpu-docs.intel.com.
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.
The API function rtcGetDeviceLastErrorMessage can be used to get more
details about the last RTCError a RTCDevice encountered.
For convenient reporting of a RTCError, the API function
rtcGetErrorString can be used, which returns a string representation
of a given RTCError.
Returns the error code for the device.
[rtcSetDeviceErrorFunction], [rtcGetDeviceLastErrorMessage], [rtcGetErrorString]
rtcGetDeviceLastErrorMessage - returns a message corresponding
to the last error code
#include <embree4/rtcore.h>
const char* rtcGetDeviceLastErrorMessage(RTCDevice device);
This function can be used to get a message corresponding to the last
error code (returned by rtcGetDeviceError) which often provides
details about the error that happened. The message is the same as the
message that will written to console when verbosity is > 0 or which is
passed as the str argument of the RTCErrorFunction (see
[rtcSetDeviceErrorFunction]). However, when device construction fails
this is the only way to get additional information about the error. In
this case, rtcNewDevice returns NULL as device. To query the error
message for such a failed device construction, pass NULL as device to
the rtcGetDeviceLastErrorMessage function. For all other invocations
of rtcGetDeviceLastErrorMessage, a proper device pointer must be
specified.
Returns a message corresponding to the last error code.
[rtcGetDeviceError], [rtcSetDeviceErrorFunction]
rtcGetErrorString - returns a string representation
of a given RTCError
#include <embree4/rtcore.h>
const char* rtcGetErrorString(RTCError code);
Returns a string representation for a RTCError error code. For
example, for the RTCError RTC_ERROR_UNKNOWN this function will return
the string "Unknown Error". This is purely a convenience function for
printing error information on the user side.
The returned strings should not be used for comparing different
RTCError error codes or make other decisions based on the type of
error that occurred. For such things only the RTCError enum values
should be used.
Returns a string representation of a given RTCError error code.
[rtcGetDeviceError]
rtcSetDeviceErrorFunction - sets an error callback function for the device
#include <embree4/rtcore.h>
typedef void (*RTCErrorFunction)(
void* userPtr,
RTCError code,
const char* str
);
void rtcSetDeviceErrorFunction(
RTCDevice device,
RTCErrorFunction error,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetDeviceError]
rtcSetDeviceMemoryMonitorFunction - registers a callback function
to track memory consumption
#include <embree4/rtcore.h>
typedef bool (*RTCMemoryMonitorFunction)(
void* userPtr,
ssize_t bytes,
bool post
);
void rtcSetDeviceMemoryMonitorFunction(
RTCDevice device,
RTCMemoryMonitorFunction memoryMonitor,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewDevice]
rtcNewScene - creates a new scene
#include <embree4/rtcore.h>
RTCScene rtcNewScene(RTCDevice device);
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.
On success a scene handle is returned. On failure NULL is returned
and an error code is set that can be queried using rtcGetDeviceError.
[rtcRetainScene], [rtcReleaseScene]
rtcGetSceneDevice - returns the device the scene got created in
#include <embree4/rtcore.h>
RTCDevice rtcGetSceneDevice(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcReleaseDevice]
rtcRetainScene - increments the scene reference count
#include <embree4/rtcore.h>
void rtcRetainScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene], [rtcReleaseScene]
rtcReleaseScene - decrements the scene reference count
#include <embree4/rtcore.h>
void rtcReleaseScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene], [rtcRetainScene]
rtcAttachGeometry - attaches a geometry to the scene
#include <embree4/rtcore.h>
unsigned int rtcAttachGeometry(
RTCScene scene,
RTCGeometry geometry
);
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 multiple
scenes. 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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryUserData], [rtcGetGeometryUserData]
rtcAttachGeometryByID - attaches a geometry to the scene
using a specified geometry ID
#include <embree4/rtcore.h>
void rtcAttachGeometryByID(
RTCScene scene,
RTCGeometry geometry,
unsigned int geomID
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcAttachGeometry]
rtcDetachGeometry - detaches a geometry from the scene
#include <embree4/rtcore.h>
void rtcDetachGeometry(RTCScene scene, unsigned int geomID);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID]
rtcGetGeometry - returns the geometry bound to
the specified geometry ID
#include <embree4/rtcore.h>
RTCGeometry rtcGetGeometry(RTCScene scene, unsigned int geomID);
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.
This function is not thread safe and thus 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.
If you need a thread safe version of this function please use [rtcGetGeometryThreadSafe].
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometryThreadSafe]
rtcGetGeometryThreadSafe - returns the geometry bound to
the specified geometry ID
#include <embree4/rtcore.h>
RTCGeometry rtcGetGeometryThreadSafe(RTCScene scene, unsigned int geomID);
The rtcGetGeometryThreadSafe 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.
This function is thread safe and should NOT get used during rendering. If you need a fast non-thread safe version during rendering please use the [rtcGetGeometry] function.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcAttachGeometry], [rtcAttachGeometryByID], [rtcGetGeometry]
rtcCommitScene - commits scene changes
#include <embree4/rtcore.h>
void rtcCommitScene(RTCScene scene);
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).
In case the RTCDevice associated with the scene is a SYCL device,
rtcCommitScene will internally create a temporary SYCL queue to issue
memory transfers from host to device memory. In this case, the call to
rtcCommitScene will be blocking and return only after the memory
transfers are completed and SYCL kernels can traverse the scene savely
on the device. The function rtcCommitSceneWithQueue can be used to
commit all changes for the specified scene asynchronously. Handles to
traversal objects (RTCTraversable type) that have been aquired before
a call to rtcCommitScene will be invalidated. Use
rtcGetSceneTraversable to get a valid handle from the scene after
every scene commit.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitSceneWithQueue], [rtcJoinCommitScene]
rtcCommitSceneWithQueue - commits scene changes using a given
SYCL queue for host-to-device memory transfers
#include <embree4/rtcore.h>
void rtcCommitScene(RTCScene scene,
sycl::queue queue,
sycl::event* event);
The rtcCommitSceneWithQueue 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.
The rtcCommitSceneWithQueue function differs from rtcCommitScene
only in that the former uses a SYCL queue passed by the application for
asynchronous host-to-device memory transfers and the latter uses an
internal and temporary SYCL queue and is blocking, i.e. the function
returns after all memory transfers are completed.
The application is responsible for synchronization when using
rtcCommitSceneWithQueue by either calling wait() on the queue or
use the optional event argument to receive a copy of the sycl::event
associated with the last memcpy command that was submitted to the
queue. The argument event can also be a null pointer in which case
the argument will be ignored internally.
A SYCL kernel calling rtcTraversableIntersect or rtcTraversableOccluded
using a RTCTraversable associated with the RTCScene scene has a
dependency on the host-to-device memory transfers and therefore has to
be synchronized properly.
This function is only available when SYCL support is enabled. In case
the RTCDevice associated with the scene is not a SYCL device,
rtcCommitSceneWithQueue will behave the same as rtcCommitScene.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitScene]
rtcJoinCommitScene - commits the scene from multiple threads
#include <embree4/rtcore.h>
void rtcJoinCommitScene(RTCScene scene);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcCommitScene], [rtcGetDeviceProperty]
rtcSetSceneProgressMonitorFunction - registers a callback
to track build progress
#include <embree4/rtcore.h>
typedef bool (*RTCProgressMonitorFunction)(
void* ptr,
double n
);
void rtcSetSceneProgressMonitorFunction(
RTCScene scene,
RTCProgressMonitorFunction progress,
void* userPtr
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewScene]
rtcSetSceneBuildQuality - sets the build quality for
the scene
#include <embree4/rtcore.h>
void rtcSetSceneBuildQuality(
RTCScene scene,
enum RTCBuildQuality quality
);
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. When high quality mode is enabled, filter
callbacks may be invoked multiple times for the same geometry.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryBuildQuality]
rtcSetSceneFlags - sets the flags for the scene
#include <embree4/rtcore.h>
enum RTCSceneFlags
{
RTC_SCENE_FLAG_NONE = 0,
RTC_SCENE_FLAG_DYNAMIC = (1 << 0),
RTC_SCENE_FLAG_COMPACT = (1 << 1),
RTC_SCENE_FLAG_ROBUST = (1 << 2),
RTC_SCENE_FLAG_FILTER_FUNCTION_IN_ARGUMENTS = (1 << 3)
};
void rtcSetSceneFlags(RTCScene scene, enum RTCSceneFlags flags);
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_FILTER_FUNCTION_IN_ARGUMENTS: Enables scene
support for filter functions passed as argument to the traversal
functions. See Section [rtcInitIntersectArguments] and
[rtcInitOccludedArguments] for more details.
Multiple flags can be enabled using an or operation,
e.g. RTC_SCENE_FLAG_COMPACT | RTC_SCENE_FLAG_ROBUST.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneFlags]
rtcGetSceneFlags - returns the flags of the scene
#include <embree4/rtcore.h>
enum RTCSceneFlags rtcGetSceneFlags(RTCScene scene);
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);
On failure RTC_SCENE_FLAG_NONE is returned and an error code is set
that can be queried using rtcGetDeviceError.
[rtcSetSceneFlags]
rtcGetSceneBounds - returns the axis-aligned bounding box of the scene
#include <embree4/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
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneLinearBounds], [rtcCommitScene], [rtcJoinCommitScene]
rtcGetSceneLinearBounds - returns the linear bounds of the scene
#include <embree4/rtcore.h>
struct RTCORE_ALIGN(16) RTCLinearBounds
{
RTCBounds bounds0;
RTCBounds bounds1;
};
void rtcGetSceneLinearBounds(
RTCScene scene,
struct RTCLinearBounds* bounds_o
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetSceneBounds], [rtcCommitScene], [rtcJoinCommitScene]
rtcGetSceneTraversable - gets a read-only hand to a RTCScene object
that is also valid on a SYCL device and can be used for ray queries.
#include <embree4/rtcore.h>
RTCTraversable rtcGetSceneTraversable(RTCScene scene);
The rtcGetSceneTraversable function returns a read-only handle to a
RTCScene object (scene argument). Traversable objects are used for
ray queries on a SYCL device.
Traversable objects can also be used in host/CPU code and Embree
provides other API calls such as the rtcTraversablePointQuery to help
write portable code compatible with CPU and SYCL device execution.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcTraversableIntersect1]
rtcNewGeometry - creates a new geometry object
#include <embree4/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,
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY,
};
RTCGeometry rtcNewGeometry(
RTCDevice device,
enum RTCGeometryType type
);
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), instances (RTC_GEOMETRY_TYPE_INSTANCE),
and instance arrays (RTC_GEOMETRY_TYPE_INSTANCE_ARRAY).
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[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_INSTANCE_ARRAY]
RTC_GEOMETRY_TYPE_TRIANGLE - triangle geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_TRIANGLE);
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:
![][imgTriangleUV]
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.
On failure NULL is returned and an error code is set that be get
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_QUAD - quad geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_QUAD);
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.
![][imgQuadUV]
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_GRID - grid geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_GRID);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_SUBDIVISION - subdivision geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SUBDIVISION);
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.
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 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
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 - discontinuous 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
#include <embree4/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);
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).
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 segment, 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 rendered properly.
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.
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 makes this basis a good choice to construct continuous multi-segment curves, as memory consumption can be kept minimal.
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 using the Hermite basis, by calculating a proper tangent buffer from the control points.
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.
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.
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. We further assume second order derivatives of the center curve to be zero for this construction, as otherwise very large curvatures occurring in corner cases, can thicken the constructed curve significantly.
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 interior 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [RTCCurveFlags]
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
#include <embree4/rtcore.h>
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_SPHERE_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_DISC_POINT);
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_ORIENTED_DISC_POINT);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry]
RTC_GEOMETRY_TYPE_USER - user geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_USER);
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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryUserPrimitiveCount], [rtcSetGeometryUserData], [rtcSetGeometryBoundsFunction], [rtcSetGeometryIntersectFunction], [rtcSetGeometryOccludedFunction]
RTC_GEOMETRY_TYPE_INSTANCE - instance geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE);
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 ray query context to the geometry ID of the instance, then trace
the transformed ray, and finally set the instID field of the ray
query 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.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryInstancedScene], [rtcSetGeometryTransform]
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY - instance array geometry type
#include <embree4/rtcore.h>
RTCGeometry geometry =
rtcNewGeometry(device, RTC_GEOMETRY_TYPE_INSTANCE_ARRAY);
Embree supports instance arrays, which is a more memory efficient way to represent large amounts of instances of the same or a small set of (sub)scenes. The main difference to regular Embree instances is that Embree instance arrays have a buffer of transformations (either affine transformations or quaternion decompositions [RTCQuaternionDecomposition]) that can be allocated by Embree or a shared buffer, similar to vertex buffers for triangle meshes. Optionally, instead of instancing only one scene, an instance array can instance multiple scenes by passing an array of scenes and a corresponding index buffer that specifies which instance of the instance array instances which of the scenes in the scenes array.
Instance arrays are created by passing
RTC_GEOMETRY_TYPE_INSTANCE_ARRAY to the rtcNewGeometry function
call. The instanced scene can be either be set using the
rtcSetGeometryInstancedScene call, or if multiple scenes should be
instanced by passing an array of scenes using
rtcSetGeometryInstancedScenes. The latter also requires to specify an
index buffer using rtcSetNewGeometryBuffer or
rtcSetSharedGeometryBuffer with RTC_BUFFER_TYPE_INDEX as the buffer
type.
Because the transformation information can become large for a large
amount of instances, the instance array allows to share the
transformation buffer between the user application and Embree. It can
be either stored in a buffer created by Embree with
rtcSetNewGeometryBuffer or an already existing buffer can be shared
using rtcSetSharedGeometryBuffer. In either case, the buffer type has
to be RTC_BUFFER_TYPE_TRANSFORM and the allowed formats are
RTC_FORMAT_FLOAT4X4_COLUMN_MAJOR, RTC_FORMAT_FLOAT3X4_COLUMN_MAJOR,
RTC_FORMAT_FLOAT3X4_ROW_MAJOR, and
RTC_FORMAT_QUATERNION_DECOMPOSITION. Embree will not modify the data
in the transformation buffer.
Embree instance arrays support 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.
Please note that rtcCommitScene on the instanced scene(s) should be
called first, followed by rtcCommitGeometry on the instance array,
followed by rtcCommitScene for the top-level scene containing the
instance array.
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. The instID member of the hit is set to the
geometry ID of the instance array in the top-level scene and the
instPrimID member is set to the index of the hit instance of the
instance array.
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
rtcSetNewGeometryBuffer or rtcSetSharedGeometryBuffer function and
passing the time step as the slot parameter of these calls.
See the [Instance Array Geometry] tutorial for an example of how to use instance arrays.
On failure NULL is returned and an error code is set that can be
queried using rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryInstancedScene], [rtcSetGeometryInstancedScenes], [rtcSetNewGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcGetGeometryTransformEx]
RTCCurveFlags - per segment flags for curve geometry
#include <embree4/rtcore.h>
enum RTCCurveFlags
{
RTC_CURVE_FLAG_NEIGHBOR_LEFT = (1 << 0),
RTC_CURVE_FLAG_NEIGHBOR_RIGHT = (1 << 1)
};
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.
[RTC_GEOMETRY_TYPE_CURVE]
rtcRetainGeometry - increments the geometry reference count
#include <embree4/rtcore.h>
void rtcRetainGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcReleaseGeometry]
rtcReleaseGeometry - decrements the geometry reference count
#include <embree4/rtcore.h>
void rtcReleaseGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcRetainGeometry]
rtcCommitGeometry - commits geometry changes
#include <embree4/rtcore.h>
void rtcCommitGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcInterpolate], [rtcCommitScene]
rtcEnableGeometry - enables the geometry
#include <embree4/rtcore.h>
void rtcEnableGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcDisableGeometry], [rtcCommitScene]
rtcDisableGeometry - disables the geometry
#include <embree4/rtcore.h>
void rtcDisableGeometry(RTCGeometry geometry);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcEnableGeometry], [rtcCommitScene]
rtcSetGeometryTimeStepCount - sets the number of time steps of the
geometry
#include <embree4/rtcore.h>
void rtcSetGeometryTimeStepCount(
RTCGeometry geometry,
unsigned int timeStepCount
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcSetGeometryTimeRange]
rtcSetGeometryTimeRange - sets the time range for a motion blur geometry
#include <embree4/rtcore.h>
void rtcSetGeometryTimeRange(
RTCGeometry geometry,
float startTime,
float endTime
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryTimeStepCount]
rtcSetGeometryVertexAttributeCount - sets the number of vertex
attributes of the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryVertexAttributeCount(
RTCGeometry geometry,
unsigned int vertexAttributeCount
);
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).
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [RTCBufferType]
rtcSetGeometryMask - sets the geometry mask
#include <embree4/rtcore.h>
void rtcSetGeometryMask(
RTCGeometry geometry,
unsigned int mask
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[RTCRay], [rtcGetDeviceProperty]
rtcSetGeometryBuildQuality - sets the build quality for the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryBuildQuality(
RTCGeometry geometry,
enum RTCBuildQuality quality
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSceneBuildQuality]
rtcSetGeometryMaxRadiusScale - assigns a maximal curve radius scale factor for min-width feature
#include <embree4/rtcore.h>
void rtcSetGeometryMaxRadiusScale(RTCGeometry geometry, float maxRadiusScale);
The rtcSetMaxGeometryScale function specifies a maximal scaling
factor for curve radii used by the min-width feature.
The min-width feature can increase the radius of curves and points, in order to reduce aliasing and improve render times. The feature is disabled by default and has to get enabled using the EMBREE_MIN_WIDTH cmake option.
To use the feature, one has to specify a maximal curve radius scaling factor using the [rtcSetGeometryMaxRadiusScale] function. This factor should be a small number (e.g. 4) as the constructed BVH bounds get increased in order to bound the curve in the worst case of maximal radii.
One also has to set the minWidthDistanceFactor in the RTCRayQueryContext when tracing a ray. This factor controls the target radius size of a curve or point at some distance away of the ray origin.
For each control point p with radius r of a curve or point primitive, the primitive intersectors first calculate a target radius r' as:
r' = length(p-ray_org) * minWidthDistanceFactor
Typically the minWidthDistanceFactor is set by the application such that the target radius projects to the width of half a pixel (thus primitive diameter is pixel sized).
The target radius r' is then clamped against the minimal bound r and maximal bound maxRadiusScale*r to obtain the final radius r'':
r'' = max(r, min(r', maxRadiusScale*r))
Thus curves or points close to the camera are rendered with a normal radii r, and curves or points far from the camera are not enlarged too much, as this would be very expensive to render.
When rtcSetGeometryMaxRadiusScale function is not invoked for a curve
or point geometry (or if the maximal scaling factor is set to 1.0),
then the curve or point geometry renders normally, with radii not
modified by the min-width feature.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcInitRayQueryContext]
rtcSetGeometryBuffer - assigns a view of a buffer to the geometry
#include <embree4/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
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetSharedGeometryBuffer - assigns a view of a shared data buffer
to a geometry
#include <embree4/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
);
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
rtcSetSharedGeometryBuffer 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.
If using a SYCL Embree device, ptr must be allocated using SYCL USM
shared memory to be accessible on the device. Alternatively the
function rtcSetSharedGeometryBufferHostDevice can be used to pass an
explicitly managed host/device buffer pair.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBufferHostDevice], [rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetSharedGeometryBufferHostDevice - assigns views of shared data buffers
to a geometry using explicit host and device memory
#include <embree4/rtcore.h>
void rtcSetSharedGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
const void* ptr,
const void* dptr,
size_t byteOffset,
size_t byteStride,
size_t itemCount
);
The rtcSetSharedGeometryBufferHostDevice function binds views of a
shared user-managed data buffers to a geometry buffer type and slot
(type and slot argument) of the specified geometry (geometry
argument). The user-managed data buffers are passed using the ptr
argument for the host side allocated memory and the dptr parameter
for the memory allocated on the device.
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
rtcSetSharedGeometryBufferHostDevice 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.
The application is responsible of keeping the host and device memory in
sync. The host memory has to be updated before calls of
rtcCommitScene involving the associated geometry.
If Embree has no SYCL support or the associated Embree device is no
SYCL device the dptr argument must be a null pointer. In this case
the function rtcSetSharedGeometryBufferHostDevice will behave like
rtcSetSharedGeometryBuffer.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetSharedGeometryBuffer], [rtcSetGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcSetNewGeometryBuffer - creates and assigns a new data buffer to
the geometry
#include <embree4/rtcore.h>
void* rtcSetNewGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
size_t byteStride,
size_t itemCount
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer]
rtcSetNewGeometryBufferHostDevice - creates and assigns a new host/device
data buffer pair to the geometry
#include <embree4/rtcore.h>
void rtcSetNewGeometryBufferHostDevice(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot,
enum RTCFormat format,
size_t byteStride,
size_t itemCount,
void** ptr,
void** dptr
);
The rtcSetNewGeometryBufferHostDevice function creates a new
host/device data buffer pair 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 rtcSetNewGeometryBufferHostDevice 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.
If ptr is not null, it will be used to return the address of the host
data buffer. If dptr is not null, it will be used to return the
address of the device data buffer. Either ptr or dptr or both can
be null. In this case rtcGetGeometryBufferData and
rtcGetGeometryBufferDataDevice can be used to get the addresses of
the host and device data buffers.
The application is responsible of keeping the host and device memory in
sync. The host memory has to be updated before calls of
rtcCommitScene involving the associated geometry.
If Embree has no SYCL support or the associated Embree device is no
SYCL device the dptr argument will return the same address as ptr
if on null. In this case the function
rtcSetNewGeometryBufferHostDevice will behave like
rtcSetSharedGeometryBuffer.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetNewGeometryBuffer], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcGetGeometryBufferData], [rtcGetGeometryBufferDataDevice]
RTCFormat - specifies format of data in buffers
#include <embree4/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,
RTC_FORMAT_QUATERNION_DECOMPOSITION
};
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. The RTC_FORMAT_QUATERNION_DECOMPOSITION format
specifies a structure that represents a quaternion decomposition (see
[RTCQuaternionDecomposition]) of an affine transformation. These
formats are used in the [rtcSetGeometryTransform] function or in
geometry buffers with type RTC_BUFFER_TYPE_TRANSFORM in order to set
a transformation matrix for instance and instance array 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]).
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer], [rtcSetGeometryTransform] [RTCQuaternionDecomposition]
RTCFormat - specifies format of data in buffers
#include <embree4/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_TRANSFORM = 23,
RTC_BUFFER_TYPE_FLAGS = 32
};
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_TRANSFORM buffer is used to provide instance
transformation information for instance array geometries (see
[RTC_GEOMETRY_TYPE_INSTANCE_ARRAY]).
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.
[rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcGetGeometryBufferData - gets pointer to
the first buffer view element
#include <embree4/rtcore.h>
void* rtcGetGeometryBufferData(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
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).
If the device associated with geometry is a SYCL device, the returned
pointer only accessible on the host. The function
rtcGetGeometryBufferDataDevice can be used to get a pointer
accessible on the SYCL device. #### EXIT STATUS
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetGeometryBufferDataDevice], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcGetGeometryBufferDataDevice - gets pointer to
the first buffer view element on the device.
#include <embree4/rtcore.h>
void* rtcGetGeometryBufferDataDevice(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
The rtcGetGeometryBufferDataDevice 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) on the device.
If the device associated with geometry is no SYCL device, or if
Embree is executed on a system with host unified memory (e.g., on an
iGPU), the returned pointer is the same as the one returned by
rtcGetGeometryBufferData.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcGetGeometryBufferData], [rtcSetGeometryBuffer], [rtcSetSharedGeometryBuffer], [rtcSetNewGeometryBuffer]
rtcUpdateGeometryBuffer - marks a buffer view bound to the geometry
as modified
#include <embree4/rtcore.h>
void rtcUpdateGeometryBuffer(
RTCGeometry geometry,
enum RTCBufferType type,
unsigned int slot
);
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcNewGeometry], [rtcCommitScene]
rtcSetGeometryIntersectFilterFunction - sets the intersection filter
for the geometry
#include <embree4/rtcore.h>
struct RTCFilterFunctionNArguments
{
int* valid;
void* geometryUserPtr;
const struct RTCRayQueryContext* context;
struct RTCRayN* ray;
struct RTCHitN* hit;
unsigned int N;
};
typedef void (*RTCFilterFunctionN)(
const struct RTCFilterFunctionNArguments* args
);
void rtcSetGeometryIntersectFilterFunction(
RTCGeometry geometry,
RTCFilterFunctionN filter
);
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
ray query 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. When accepting a hit, 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.
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.
On failure an error code is set that can be queried using
rtcGetDeviceError.
[rtcSetGeometryOccludedFilterFunction]
rtcSetGeometryOccludedFilterFunction - sets the occlusion filter
for the geometry
#include <embree4/rtcore.h>
void rtcSetGeometryOccludedFilterFunction(
RTCGeometry geometry,
RTCFilterFunctionN filter
);
Truncated — view the full README on GitHub.
(top 24 of 30)
365 followers · starred Jan 2015
5,731 followers · starred Mar 2026
2,035 followers · starred May 2017
138 followers · starred Apr 2019