embree_rtc
Folders and files
Name | Name | Last commit date | ||
---|---|---|---|---|
parent directory.. | ||||
## ======================================================================== ## ## Copyright 2009-2014 Intel Corporation ## ## ## ## Licensed under the Apache License, Version 2.0 (the "License"); ## ## you may not use this file except in compliance with the License. ## ## You may obtain a copy of the License at ## ## ## ## http://www.apache.org/licenses/LICENSE-2.0 ## ## ## ## Unless required by applicable law or agreed to in writing, software ## ## distributed under the License is distributed on an "AS IS" BASIS, ## ## WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. ## ## See the License for the specific language governing permissions and ## ## limitations under the License. ## ## ======================================================================== ## = Embree: High Performance Ray Tracing Kernels 2.3.1 = == Embree Overview == Embree is a collection of high-performance ray tracing kernels, developed at Intel. The target user of Embree are graphics application engineers that want to improve the performance of their application by leveraging the optimized ray tracing kernels of Embree. The kernels are optimized for photo-realistic rendering on the latest Intel® processors with support for SSE, AVX, AVX2, and the 16-wide Xeon Phi[TM] vector instructions. Embree supports runtime code selection to choose the traversal and build algorithms that best matches the instruction set of your CPU. We recommend using Embree through its API to get the highest benefit from future improvements. Embree is released as Open Source under the Apache 2.0 license. Embree supports applications written with the Intel SPMD Programm Compiler (ISPC, http://ispc.github.com) by also providing an ISPC interface to the core ray tracing algorithms. This makes it possible to write a renderer in ISPC that leverages SSE, AVX, AVX2, and Xeon Phi[TM] instructions without any code change. ISPC also supports runtime code selection, thus ISPC will select the best code path for your application, while Embree selects the optimal code path for the ray tracing algorithms. 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). For standard CPUs, the single-ray traversal kernels in Embree provide the best performance for incoherent workloads and are very easy to integrate into existing rendering applications. For Xeon Phi[TM], a renderer written in ISPC using the default hybrid ray/packet traversal algorithms have shown to perform best, but requires writing the renderer in ISPC. In general for coherent workloads, ISPC outperforms the single ray mode on each platform. Embree also supports dynamic scenes by implementing high performance two-level spatial index structure construction algorithms. In addition to the ray tracing kernels, Embree provides some tutorials to demonstrate how to use the Embree API. The example photorealistic renderer that was originally included in the Embree kernel package is now available in a separate GIT repository (see Embree Example Renderer). == Supported Platforms == Embree supports Windows, Linux and Mac OS X, each in 32bit and 64bit modes. The code compiles with the Intel Compiler, the Microsoft Compiler, GCC and CLANG. Using the Intel Compiler improves performance by approximately 10%. Performance also varies across different operating systems. Embree is optimized for Intel CPUs supporting SSE, AVX, and AVX2 instructions, and requires at least a CPU with support for SSE2. The Xeon Phi[TM] version of Embree only works under Linux in 64bit mode. For compilation of the the Xeon Phi[TM] code the Intel Compiler is required. The host side code compiles with GCC, CLANG, and the Intel Compiler. == Installing Embree on Windows == To install the Embree libray on your system add the folder lib/x64 to your PATH. To compile applications with Embree you also have to set the "Include Directories" path in Visual Studio to the include/ folder of Embree. Before you can run the tutorials in the bin/x64 folder you have to install the Embree library. == Installing Embree on Linux and Mac OS X == To install the Embree libray and Embree header files on your system type the following: sudo ./install.sh Instead of installing the Embree library, you can also source the file paths.sh: source ./paths.sh == Embree API == The Embree API is a low level ray tracing API that supports defining and committing of geometry and performing ray queries of different types. Static and dynamic scenes are supported, that may contain triangular geometry (including linear motions for motion blur), instanced geometry, and user defined geometry. Supported ray queries are, finding the closest scene intersection along a ray, and testing a ray segment for any intersection with the scene. Single rays, as well as packets of rays in a struct of array layout can be used for packet sizes of 1, 4, 8, and 16. Filter callback functions are supported, that get invoked for every intersection encountered during traversal. The Embree API exists in a C++ and ISPC version. This document describes the C++ version of the API, the ISPC version is almost identical. The only differences are that the ISPC version needs some ISPC specific uniform type modifiers, and limits the ray packets to the native SIMD size the ISPC code is compiled for. The user is supposed to include the embree2/rtcore.h, and the embree2/ rtcore_ray.h file, but none of the other header files. If using the ISPC version of the API, the user should include embree2/rtcore.isph and embree2/ rtcore_ray.isph. #include <embree2/rtcore.h> #include <embree2/rtcore_ray.h> All API calls carry the prefix rtc which stands for ray tracing core. Before invoking any API call, the Embree ray tracing core has to get initialized through the rtcInit call. Before the application exits it should call rtcExit. Initializing Embree again after an rtcExit is allowed. rtcInit(NULL); ... rtcExit(); The rtcInit call initializes the ray tracing core. An optional configuration string can be passed through this function to configure implementation specific parameters. If this string is NULL, a default configuration is used, that is optimal for most usages. API calls that access geometries are only thread safe as long as different geometries are accessed. Accesses to one geometry have to get sequentialized by the application. All other API calls are thread safe. The rtcIntersect and rtcOccluded calls are re-entrant, but only for other rtcIntersect and rtcOccluded calls. It is thus safe to trace new rays when intersecting a user defined object, but not supported to create new geometry inside the intersect function of a user defined geometry. Each user thread has its own error flag in the API. If an error occurs when invoking some API function, this flag is set to an error code if it stores no previous error. The rtcGetError function reads and returns the currently stored error and clears the error flag again. For performance reasons the ray query functions do not set an error flag in release mode, but do so if Embree is compiled in debug mode. Possible error codes returned by rtcGetError are: Error Code Description RTC_NO_ERROR No error occured. RTC_UNKNOWN_ERROR An unknown error has occured. RTC_INVALID_ARGUMENT An invalid argument was specified. RTC_INVALID_OPERATION The operation is not allowed for the specified object. RTC_OUT_OF_MEMORY There is not enough memory left to complete the operation. RTC_UNSUPPORTED_CPU The CPU is not supported as it does not support SSE2. Using the rtcSetErrorFunction call, it is also possible to set a callback function that is called whenever an error occurs. The callback function gets passed the error code, as well as some string that describes the error further. Passing NULL to rtcSetErrorFunction disables the set callback function again. The previously described error flags are also set if an error callback function is present. === Scene === A scene is a container for a set of geometries of potentially different types. A scene is created using the rtcNewScene function call, and destroyed using the rtcDeleteScene function call. Two types of scenes are supported, dynamic and static scenes. Different flags specify the type of scene to create and the type of ray query operations that can later be performed on the scene. The following example creates a scene that supports dynamic updates and the single ray rtcIntersect and rtcOccluded calls. RTCScene scene = rtcNewScene(RTC_SCENE_DYNAMIC,RTC_INTERSECT1); ... rtcDeleteScene(scene); Using the following scene flags the user can select between creating a static and dynamic scene. Scene Flag Description RTC_SCENE_STATIC scene optimized for static geometry RTC_SCENE_DYNAMIC scene optimized for dynamic geometry A dynamic scene is created by invoking rtcNewScene with the RTC_SCENE_DYNAMIC flag. Different geometries can now be created inside that scene. Geometries are enabled by default. Once the scene geometry is specified, an rtcCommit call will finish the scene description and trigger building of internal data structures. After the rtcCommit call it is safe to perform ray queries of the type specified at scene construction time. Geometries can get disabled (rtcDisable call), enabled again (rtcEnable call), and deleted (rtcDeleteGeometry call). Geometries can also get modified, including their vertex and index arrays. After the modification of some geometry, rtcModified has to get called for that geometry. If geometries got enabled, disabled, deleted, or modified an rtcCommit call has to get invoked before performing any ray queries for the scene, otherwise the effect of the ray query is undefined. A static scene is created by the rtcNewScene call with the RTC_SCENE_STATIC flag. Geometries can only be created and modified until the first rtcCommit call. After the rtcCommit call, each access to any geometry of that static scene is invalid, including enabling, disabling, modifying, and deletion of geometries. Consequently, geometries that got created inside a static scene can only get deleted by deleting the entire scene. The following flags can be used to tune the used acceleration structure. These flags are only hints and may be ignored by the implementation. Scene Flag Description RTC_SCENE_COMPACT Creates a compact data structure and avoids algorithms that consume much memory. RTC_SCENE_COHERENT Optimize for coherent rays (e.g. primary rays) RTC_SCENE_INCOHERENT Optimize for in-coherent rays (e.g. diffuse reflection rays) RTC_SCENE_HIGH_QUALITY Build higher quality spatial data structures. The following flags can be used to tune the traversal algorithm that is used by Embree. These flags are only hints and may be ignored by the implementation. Scene Flag Description RTC_SCENE_ROBUST Avoid optimizations that reduce arithmetic accuracy. The second argument of the rtcNewScene function are algorithm flags, that allow to specify which ray queries are required by the application. Calling for a scene a ray query API function that is different to the ones specified at scene creation time is not allowed. Further, the application should only pass ray query requirements that are really needed, to give Embree most freedom in choosing the best algorithm. E.g. in case Embree implements no packet traversers for some highly optimized data structure for single rays, then this data structure cannot be used if the user specifies any ray packet query. Algorithm Flag Description RTC_INTERSECT1 Enables the rtcIntersect and rtcOccluded functions (single ray interface) for this scene RTC_INTERSECT4 Enables the rtcIntersect4 and rtcOccluded4 functions (4-wide packet interface) for this scene RTC_INTERSECT8 Enables the rtcIntersect8 and rtcOccluded8 functions (8-wide packet interface ) for this scene RTC_INTERSECT16 Enables the rtcIntersect16 and rtcOccluded16 functions (16-wide packet interface) for this scene === Geometries === Geometries are always contained in the scene they are created in. Each geometry is assigned an integer ID at creation time, which is unique for that scene. The current version of the API supports triangle meshes (rtcNewTriangleMesh), single level instances of other scenes (rtcNewInstance), and user defined geometries (rtcNewUserGeometry). The API is designed in a way that easily allows adding new geometry types in later releases. For dynamic scenes, the assigned geometry IDs fulfill the following properties. As long as no geometry got deleted, all IDs are assigned sequentially, starting from 0. If geometries got deleted, the implementation will reuse IDs later on 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. For static scenes, geometry IDs are assigned sequentially starting at 0. This allows the application to use a fixed size array to map from geometry IDs to its own geometry representation. ==== Triangle Meshes ==== Triangle meshes are created using the rtcNewTriangleMesh function call, and potentially deleted using the rtcDeleteGeometry function call. The number of triangles, number of vertices, and number of time steps (1 for normal meshes, and 2 for linear motion blur), have to get specified at construction time of the mesh. The user can also specify additional flags that choose the strategy to handle that mesh in dynamic scenes. The following example demonstrates howto create a triangle mesh without motion blur: unsigned geomID = rtcNewTriangleMesh (scene,geomFlags,numTriangles,numVertices,1); The following geometry flags can be specified at construction time of the triangle mesh: Geometry Flag Description The mesh is considered static and should get modified RTC_GEOMETRY_STATIC rarely by the application. This flag has to get used in static scenes. The mesh is considered to deform in a coherent way, e.g. a skinned character. The connectivity of the mesh RTC_GEOMETRY_DEFORMABLE has to stay constant, thus modifying the index array is not allowed. The implementation is free to choose a BVH refitting approach for handling meshes tagged with that flag. The mesh is considered highly dynamic and changes RTC_GEOMETRY_DYNAMIC frequently, possibly in an unstructured way. Embree will rebuild data structures from scratch for this type of mesh. The triangle indices can be set by mapping and writing to the index buffer (RTC_INDEX_BUFFER) and the triangle vertices can be set by mapping and writing into the vertex buffer (RTC_VERTEX_BUFFER). The index buffer contains an array of three 32 bit indices, while the vertex buffer contains an array of 3 float values aligned to 16 bytes. All buffers have to get unmapped before an rtcCommit call to the scene. struct Vertex { float x,y,z,a; }; struct Triangle { int v0, v1, v2; }; Vertex* vertices = (Vertex*) rtcMapBuffer(scene,geomID,RTC_VERTEX_BUFFER); // fill vertices here rtcUnmapBuffer(scene,geomID,RTC_VERTEX_BUFFER); Triangle* triangles = (Triangle*) rtcMapBuffer (scene,geomID,RTC_INDEX_BUFFER); // fill triangle indices here rtcUnmapBuffer(scene,geomID,RTC_INDEX_BUFFER); Also see tutorial00 for an example of how to create triangle meshes. ==== Hair Geometry ==== Creates a new hair geometry, Hair geometries are supported, which consist of multiple hairs represented as cubic bezier curves with varying radius per control point. Individual hairs are considered to be subpixel sized which allows the implementation to approximate the intersection calculation. This in particular means that zooming onto one hair might show geometric artefacts. Hair geometries are created using the rtcNewHairGeometry function call, and potentially deleted using the rtcDeleteGeometry function call. The number of hair curves, number of vertices, and number of time steps (1 for normal curves, and 2 for linear motion blur), have to get specified at construction time. The curve indices can be set by mapping and writing to the index buffer (RTC_INDEX_BUFFER) and the control vertices can be set by mapping and writing into the vertex buffer (RTC_VERTEX_BUFFER). In case of linear motion blur, two vertex buffers (RTC_VERTEX_BUFFER0 and RTC_VERTEX_BUFFER1) have to get filled, one for each time step. The index buffer contains an array of 32 bit indices pointing to the ID of the first of four control vertices, while the vertex buffer stores all control pointing of a single precision position and radius stored in x,y,z,r order in memory. All buffers have to get unmapped before an rtcCommit call to the scene. Like for triangle meshes, thee user can also specify a geometry mask and additional flags that choose the strategy to handle that mesh in dynamic scenes. The following example demonstrates howto create some hair geometry: unsigned geomID = rtcNewHairGeometry (scene,geomFlags,numCurves,numVertices,1); struct Vertex { float x,y,z,r; }; Vertex* vertices = (Vertex*) rtcMapBuffer(scene,geomID,RTC_VERTEX_BUFFER); // fill vertices here rtcUnmapBuffer(scene,geomID,RTC_VERTEX_BUFFER); int* triangles = (int*) rtcMapBuffer(scene,geomID,RTC_INDEX_BUFFER); // fill indices here rtcUnmapBuffer(scene,geomID,RTC_INDEX_BUFFER); Also see tutorial07 for an example of how to create and use hair geometry. ==== User Defined Geometry ==== User defined geometries make it possible to extend Embree with arbitrary types of geometry. This is achieved by introducing arrays of user geometries as a special geometry type. These objects do not contain a single user geometry, but a set of such geometries, each specified by an index. The user has to provide a user data pointer, bounding function as well as user defined intersect and occluded functions to create a set of user geometries. The user geometry to process is specified by passing its user data pointer and index to each invokation of the bounding, intersect, and occluded function. The bounding function is used to query the bounds of each user geometry. When performing ray queries, Embree will invoke the user intersect (and occluded) functions to test rays for intersection (and occlusion) with the specified user defined geometry. As Embree supports different ray packet sizes, one potentially has to provide different versions of user intersect and occluded function pointers for these packet sizes. However, the ray packet size of the called user function always matches the packet size of the originally invoked ray query function. Consequently, an application only operating on single rays only has to provide single ray intersect and occluded function pointers. User geometries are created using the rtcNewUserGeometry function call, and potentially deleted using the rtcDeleteGeometry function call. The folling example illustrates creating an array with two user geometries: struct UserObject { ... }; void userBoundsFunction(UserObject* userGeom, size_t i, RTCBounds& bounds_o) { bounds_o = bounds of userGeom[i]; } void userIntersectFunction(UserObject* userGeom, RTCRay& ray, size_t i) { if (ray misses userGeom[i]) return; update ray hit information; } void userOccludedFunction(UserObject* userGeom, RTCRay& ray, size_t i) { if (ray misses userGeom[i]) return; geomID = 0; } ... UserObject* userGeom = new UserObject[2]; userGeom[0] = ... userGeom[1] = ... unsigned geomID = rtcNewUserGeometry(scene,2); rtcSetUserData(scene,geomID,userGeom); rtcSetBounds(scene,geomID,userBoundsFunction); rtcSetIntersectFunction(scene,geomID,userIntersectFunction); rtcSetOccludedFunction (scene,geomID,userOccludedFunction); The user intersect function (userIntersectFunction) and user occluded function (userOccludedFunction) get as input the pointer provided through the rtcSetUserData function call, a ray, and the index of the geometry to process. For ray packets, the user intersect and occluded functions also get a pointer to a valid mask as input. The user provided functions should not modify any ray that is disabled by that valid mask. The user intersect function should return without modifying the ray structure if the user geometry is missed. If the geometry is hit, it has to update the hit information of the ray (tfar, u, v, Ng, geomID, primID). Also the user occluded function should return without modifying the ray structure if the user geometry is missed. If the geometry is hit, it shoud set the geomID member of the ray to 0. Is is supported to invoke the rtcIntersect and rtcOccluded function calls inside such user functions. It is not supported to invoke any other API call inside these user functions. See tutorial02 for an example of how to use the user defined geometries. ==== Instances ==== Embree supports instancing of scenes inside another scene by some transformation. As the instanced scene is stored only a single time, even if instanced to multiple locations, this feature can be used to create extremely large scenes. Only single level instancing is supported by Embree natively, however, multi-level instancing can principally be implemented through user geometries. Instances are created using the rtcNewInstance function call, and potentially deleted using the rtcDeleteGeometry function call. To instantiate a scene, one first has to generate the scene B to instantiate. Now one can add an instance of this scene inside a scene A the following way: unsigned instID = rtcNewInstance(sceneA,sceneB); rtcSetTransform(sceneA,instID,RTC_MATRIX_COLUMN_MAJOR,&column_matrix_3x4); One has to call rtcCommit on scene B before one calls rtcCommit on scene A. When modifying scene B one has to call rtcModified for all instances of that scene. Providing a bounding box is not required and also not allowed. If a ray hits the instance, then the geomID and primID members of the ray are set to the geometry ID and primitive ID of the primitive hit in scene B, and the instID member of the ray is set to the instance ID returned from the rtcNewInstance function. The rtcSetTransform call can be passed an affine transformation matrix with different data layouts: Layout Description RTC_MATRIX_ROW_MAJOR The 3x4 float matrix is layed out in row major form. RTC_MATRIX_COLUMN_MAJOR The 3x4 float matrix is layed out in column major form. The 3x4 float matrix is layout out in column RTC_MATRIX_COLUMN_MAJOR_ALIGNED16 major form, with each column padded by an additional 4th component. Passing homogenous 4x4 matrices is possible as long as the last row is (0,0,0,1). If this homogenous matrix is layed out in row major form, use the RTC_MATRIX_ROW_MAJOR layout. If this homogenous matrix is layed out in column major form, use the RTC_MATRIX_COLUMN_MAJOR_ALIGNED16 mode. In both cases, Embree will ignore the last row of the matrix. The transformation passed to rtcSetTransform transforms from the local space of the instantiated scene, to world space. See tutorial04 for an example of how to use instances. === Ray Queries === The API supports finding the closest hit of a ray segment with the scene (rtcIntersect functions), and determining if any hit between a ray segment and the scene exists (rtcOccluded functions). void rtcIntersect ( RTCScene scene, RTCRay& ray); void rtcIntersect4 (const void* valid, RTCScene scene, RTCRay4& ray); void rtcIntersect8 (const void* valid, RTCScene scene, RTCRay8& ray); void rtcIntersect16 (const void* valid, RTCScene scene, RTCRay16& ray); void rtcOccluded ( RTCScene scene, RTCRay& ray); void rtcOccluded4 (const void* valid, RTCScene scene, RTCRay4& ray); void rtcOccluded8 (const void* valid, RTCScene scene, RTCRay8& ray); void rtcOccluded16 (const void* valid, RTCScene scene, RTCRay16& ray); The ray layout to be passed to the ray tracing core is defined in the embree2/ rtcore_ray.h header file. It is up to the user if he wants to use the ray structures defined in that file, or resemble the exact same binary data layout with their own vector classes. The ray layout might change with new Embree releases as new features get added, however, will stay constant as long as the major release number does not change. The ray contains the following data members: Member In/Out Description org in ray origin dir in ray direction (can be unnomalized) tnear in start of ray segment tfar in/out end of ray segment, set to hit distance after intersection time in time used for motion blur mask in ray mask to mask out geometries Ng out unnormalized geometry normal u out barycentric u-coordinate of hit v out barycentric v-coordinate of hit geomID out geometry ID of hit geometry primID out primitive ID of hit primitive instID out instance ID of hit instance This structure is in struct of array layout (SOA) for ray packets. Note that the tfar member functions as an input and output. In the ray packet mode (with packet size of N), the user has to provide a pointer to N 32 bit integers that act as a ray activity mask. If one of these integers is set to 0x00000000 the corresponding ray is considered inactive and if the integer is set to 0xFFFFFFFF, the ray is considered active. Rays that are inactive will not update any hit information. Data alignment requirements for ray query functions operating on single rays is 16 bytes for the ray. Data alignment requirements for query functions operating on AOS packets of 4, 8, or 16 rays, is 16, 32, and 64 bytes respectively, for the valid mask and the ray. To operate on packets of 4 rays, the CPU has to support SSE, to operate on packets of 8 rays, the CPU has to support AVX-256, and to operate on packets of 16 rays, the CPU has to support the Xeon Phi instructions. Additionally, the required ISA has to be enabled in Embree at compile time, to use the desired packet size. Finding the closest hit distance is done through the rtcIntersect functions. These get the activity mask, the scene, and a ray as input. The user has to initialize the ray origin (org), ray direction (dir), and ray segment (tnear, tfar). The ray segment has to be in the range [0,inf], thus ranges that start behind the ray origin are not valid, but ranges can reach to infinity. The geometry ID (geomID member) has to get initialized to RTC_INVALID_GEOMETRY_ID (-1). If the scene contains instances, also the instance ID (instID) has to get initialized to RTC_INVALID_GEOMETRY_ID (-1). If the scene contains linear motion blur, also the ray time (time) has to get initialized to a value in the range [0,1]. If ray masks are enabled at compile time, also the ray mask (mask) has to get initialized. After tracing the ray, the hit distance (tfar), geometry normal (Ng), local hit coordinates (u, v), geometry ID (geomID), and primitive ID (primID) are set. If the scene contains instances, also the instance ID (instID) is set, if an instance is hit. The geometry ID corresponds to the ID returned at creation time of the hit geometry, and the primitive ID corresponds to the nth primitive of that geometry, e.g. nth triangle. The instance ID corresponds to the ID returned at creation time of the instance. The following code properly sets up a ray and traces it through the scene: RTCRay ray; ray.org = ray_origin; ray.dir = ray_direction; ray.tnear = 0.0f; ray.tfar = inf; ray.geomID = RTC_INVALID_GEOMETRY_ID; ray.primID = RTC_INVALID_GEOMETRY_ID; ray.instID = RTC_INVALID_GEOMETRY_ID; ray.mask = 0xFFFFFFFF; ray.time = 0.0f; rtcIntersect(scene,ray); Testing if any geometry intersects with the ray segment is done through the rtcOccluded functions. Initialization has to be done as for rtcIntersect. If some geometry got found along the ray segment, the geometry ID (geomID) will get set to 0. Other hit information of the ray is undefined after calling rtcOccluded. See tutorial00 for an example of how to trace rays. === Buffer Sharing === Embree supports sharing of buffers with the application. Each buffer that can be mapped for a specific geometry can also be shared with the application, by pass a pointer, offset, and stride of the application side buffer using the rtcSetBuffer API function. void rtcSetBuffer(RTCScene scene, unsigned geomID, RTCBufferType type, void* ptr, size_t offset, size_t stride); The rtcSetBuffer function has to get called before any call to rtcMapBuffer for that buffer, otherwise the buffer will get allocated internally and the call to rtcSetBuffer will fail. The buffer has to remain valid as long as the geometry exists, and the user is responsible to free the buffer when the geometry gets deleted. When a buffer is shared, it is safe to modify that buffer without mapping and unmapping it. However, for dynamic scenes one still has to call rtcModified for modified geometries and the buffer data has to stay constant from the rtcCommit call to after the last ray query invokation. The offset parameter specifies a byte offset to the start of the first element and the stride parameter specifies a byte stride between the different elements of the shared buffer. This support for offset and stride allows the application quite some freedom in the data layout of these buffers, however, some restrictions apply. Index buffers always store 32 bit indices and vertex buffers always store single precision floating point data. The start address ptr+offset and stride always have to be aligned to 4 bytes on Xeon CPUs and 16 bytes on Xeon Phi accelerators, otherwise the rtcSetBuffer function will fail. For vertex buffers, the 4 bytes after the z-coordinate of the last vertex have to be readable memory, thus padding is required for some layouts. The following is an example of howto create a mesh with shared index and vertex buffers: unsigned geomID = rtcNewTriangleMesh (scene,geomFlags,numTriangles,numVertices,1); rtcSetBuffer(scene,geomID,RTC_VERTEX_BUFFER,vertexPtr,0,3*sizeof(float)); rtcSetBuffer(scene,geomID,RTC_INDEX_BUFFER ,indexPtr ,0,3*sizeof(int)); Sharing buffers can significantly reduce the memory required by the application, thus we recommend using this feature. When enabling the RTC_COMPACT scene flag, the spatial index structures of Embree might also share the vertex buffer, resulting in even higher memory savings. The support for offset and stride is enabled by default, but can get disabled at compile time using the RTCORE_BUFFER_STRIDE parameter in cmake. Disabling this feature enables the default offset and stride which increases performance of spatial index structure build, thus can be useful for dynamic content. === Linear Motion Blur === A triangle mesh or hair geometry with linear motion blur support is created by setting the number of time steps to 2 at geometry construction time. Specifying a number of time steps of 0 or larger than 2 is invalid. For a triangle mesh or hair geometry with linear motion blur, the user has to set the RTC_VERTEX_BUFFER0 and RTC_VERTEX_BUFFER1 vertex arrays, one for each time step. If a scene contains geometris with linear motion blur, the user has to set the time member of the ray to a value in the range [0,1]. The ray will intersect the scene with the vertices of the two time steps linearly interpolated to this specified time. Each ray can specify a different time, even inside a ray packet. === Geometry Mask === A 32 bit geometry mask can be assigned to triangle meshs and hair geometries using the rtcSetMask call. rtcSetMask(scene,geomID,mask); Only if the bitwise and operation of this mask with the mask stored inside the ray is not 0, primitives of this geometry are hit by a ray. This feature can be used to disable selected triangle mesh or hair geometries for specifically tagged rays, e.g. to disable shadow casting for some geometry. This API feature is disabled in Embree by default at compile time, and can be enabled in cmake through the RTCORE_ENABLE_RAY_MASK parameter. === Filter Functions === The API supports per geometry filter callback functions that are invoked for each intersection found during the rtcIntersect or rtcOccluded calls. The former ones are called intersection filter functions, the latter ones occlusion filter functions. The filter functions can be used to implement various useful features, such as rejecting a hit to implement backface culling, accumulating opacity for shadow shadows, counting the number of surfaces along a ray, collecting all hits along a ray, etc. The filter functions are only supported for triangle mesh geometry, including triangle meshes with motion blur. The filter functions provided by the user have to have the following signature: void FilterFunc ( void* userPtr, RTCRay& ray); void FilterFunc4 (const void* valid, void* userPtr, RTCRay4& ray); void FilterFunc8 (const void* valid, void* userPtr, RTCRay8& ray); void FilterFunc16(const void* valid, void* userPtr, RTCRay16& ray); The valid pointer points to a valid mask of the same format as expected as input by the ray query functions. The userPtr is a user pointer optionally set per geometry through the rtcSetUserData function. The ray passed to the filter function is the ray structure initially provided to the ray query function by the user. For that reason, it is safe to extend the ray by additional data and access this data inside the filter function (e.g. to accumulate opacity). All hit information inside the ray is valid. If the hit geometry is instanced, the instID member of the ray is valid and the ray origin, direction, and geometry normal visible through the ray are in object space. The filter function can reject a hit by setting the geomID member of the ray to RTC_INVALID_GEOMETRY_ID, otherwise the hit is accepted. The filter function is not allowed to modify the ray input data (org, dir, tnear, tfar), but can modify the hit data of the ray (u,v,Ng,geomID,primID). The intersection filter functions for different ray types are set for some geometry of a scene using the following API functions: void rtcSetIntersectionFilterFunction (RTCScene scene, unsigned geomID, RTCFilterFunc func); void rtcSetIntersectionFilterFunction4 (RTCScene scene, unsigned geomID, RTCFilterFunc4 func); void rtcSetIntersectionFilterFunction8 (RTCScene scene, unsigned geomID, RTCFilterFunc8 func); void rtcSetIntersectionFilterFunction16(RTCScene scene, unsigned geomID, RTCFilterFunc16 func); These functions are invoked during execution of the rtcIntersect type queries of the matching ray type. The occlusion filter functions are set using the following API functions: void rtcSetOcclusionFilterFunction (RTCScene scene, unsigned geomID, RTCFilterFunc func); void rtcSetOcclusionFilterFunction4 (RTCScene scene, unsigned geomID, RTCFilterFunc4 func); void rtcSetOcclusionFilterFunction8 (RTCScene scene, unsigned geomID, RTCFilterFunc8 func); void rtcSetOcclusionFilterFunction16 (RTCScene scene, unsigned geomID, RTCFilterFunc16 func); See tutorial05 for an example of how to use the filter functions. == Embree Tutorials == Embree comes with a set of tutorials aimed at helping users understand how embree can be used and extended. All tutorials exist in an ISPC and C version to demonstrate the two versions of the API. Look for files names tutorialXX_device.ispc for the ISPC implementation of the tutorial, and files named tutorialXX_device.cpp for the single ray C version of the tutorial. To start the C++ version use the tutorialXX executables, to start the ISPC version use the tutorialXX_ispc executables. You can select an initial camera using the -vp (camera position), -vi (camera lookat point), -vu (camera up vector), and - fov (vertical field of view) command line parameters: ./tutorial00 -vp 10 10 10 -vi 0 0 0 You can select the initial windows size using the -size command line parameter, or start the tutorials in fullscreen using the -fullscreen parameter: ./tutorial00 -size 1024 1024 ./tutorial00 -fullscreen Implementation specific parameters can be passed to the ray tracing core through the -rtcore command line parameter, e.g.: ./tutorial00 -rtcore verbose=2,threads=1,accel=bvh4.triangle1 The navigation in the interactive display mode follows the camera orbit model, where the camera revolves around the current center of interest. With the left mouse button you can rotate around the center of interest (the point initially set with -vi). Holding Control pressed while klicking the left mouse button rotates the camera around its location. You can also use the arrow keys for navigation. You can use the following keys: F1 Default shading F2 Gray EyeLight shading F3 Ambient occlusion shading F4 UV Coordinate visualization F5 Geometry normal visualization F6 Geometry ID visualization F7 Geometry ID and Primitive ID visualization F8 Simple shading with 16 rays per pixel for benchmarking. F9 Switches to render cost visualization. Pressing again reduces brightness. F10 Switches to render cost visualization. Pressing again increases brightness. f Enters or leaves full screen mode. c Prints camera parameters. ESC Exists the tutorial. q Exists the tutorial. === Tutorial00 === This tutorial demonstrates the creation of a static cube and ground plane using triangle meshes. It also demonstrates the use of the rtcIntersect and rtcOccluded functions to render primary visibility and hard shadows. The cube sides are colored based on the ID of the hit primitive. === Tutorial01 === This tutorial demonstrates the creation of a dynamic scene, consisting of several deformed spheres. Half of the spheres use the RTC_GEOMETRY_DEFORMABLE flag, which allows Embree to use a refitting strategy for these spheres, the other half uses the RTC_GEOMETRY_DYNAMIC flag, causing a rebuild of their spatial data structure each frame. The spheres are colored based on the ID of the hit sphere geometry. === Tutorial02 === This tutorial shows the use of user defined geometry, to re-implement instancing and to add analytic spheres. A two level scene is created, with a triangle mesh as ground plane, and several user geometries, that instance other scenes with a small number of spheres of different kind. The spheres are colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry, instanced in different ways can be distinguished. === Tutorial03 === This tutorial demonstrates a simple OBJ viewer that traces primary visibility rays only. A scene consisting of multiple meshes is created, each mesh sharing the index and vertex buffer with the application. Demonstrated is also how to support additional per vertex data, such as shading normals. === Tutorial04 === This tutorial demonstrates the in-build instancing feature of Embree, by instancing a number of other scenes build from triangulated spheres. The spheres are again colored using the instance ID and geometry ID of the hit sphere, to demonstrate how the same geometry, instanced in different ways can be distinguished. === Tutorial05 === This tutorial demonstrates the use of filter callback functions to efficiently implement transparent objects. The filter function used for primary rays, lets the ray pass through the geometry if it is entirely transparent. Otherwise the shading loop handles the transparency properly, by potentially shooting secondary rays. The filter function used for shadow rays accumulates the transparency of all surfaces along the ray, and terminates traversal if an opaque occluder is hit. === Tutorial06 === This tutorial is a simple path tracer, building on tutorial03. === Tutorial07 === This tutorial demonstrates the use of the hair geometry to render a hairball. === Embree Support and Contact === For questions and bug reports please write us at [email protected]. To receive notifications of updates and new features of Embree please subscribe to the Embree mailing list. For information about compiler optimizations, see our Optimization Notice.