Intel® Embree Ray Tracing Kernels
Discussion forum on the open source ray tracing kernels for fast photo-realistic rendering on Intel® CPU(s)
281 Discussions

Issue with flase Geometry IDs when intersecting RTC_GEOMETRY_TYPE_USER with Embree



I am a beginner with Embree and I would not call myself an experienced programmer too. I have an issue, which I was not able to resolve by myself, I hope it is okay to seek for help in this forum.

Currently, I am working on integrating Embree into our own rendering engine. My issue is, that Embree seemingly confuses the Geometry IDs.

For example, I have a simple scene, including a sphere with an infinite diameter and a cube at the world origin. Here is an extract of what I get when I print some intersection information:


The primitive IDs and the values for tfar in the red rectangle are correct, however, the geometry IDs are wrong (they should be 0 instead of 1). 


This is causing some visual artifacts, e.g.  like in this scene:


On the left side is my scene how it is supposed to look like and on the right, how it actually looks.


The geometries I want to intersect are of type RTC_GEOMETRY_TYPE_USER. In the intersection callback function I am passing to Embree I just set the geometry ID of the intersected geometry, so I can calculate the intersection with our renderer's intern intersection function outside the callback function (calculating the intersection with our own function in the callback function caused some bugs, but that is an issue of our renderer).

What I noticed during debugging was that when I enter the first line of the intersection callback function, the tfar value of the "geomID" of the "RTCIntersectFunctionArguments* args" was not the same as the "geomID" of the rayHit of "RTCIntersectFunctionArguments* args" (if that helps or makes sense).


Here are my functions. They are written in C and Objective-C.


The general intersect function:

- (ArcIntersection *) intersect
: (ArnRayCaster *) raycaster
: (Range) range_of_t
: (ArNode <ArpRayCasting> *) araWorld
// set up embree intersection context
struct RTCIntersectContext context;
struct RTCRayHit rayhit;

// convert Ray3D to embree ray
rayhit.ray.org_x = (float) raycaster->intersection_test_world_ray3d.point.c.x[0];
rayhit.ray.org_y = (float) raycaster->intersection_test_world_ray3d.point.c.x[1];
rayhit.ray.org_z = (float) raycaster->intersection_test_world_ray3d.point.c.x[2];
rayhit.ray.dir_x = (float) raycaster->intersection_test_world_ray3d.vector.c.x[0];
rayhit.ray.dir_y = (float) raycaster->intersection_test_world_ray3d.vector.c.x[1];
rayhit.ray.dir_z = (float) raycaster->intersection_test_world_ray3d.vector.c.x[2];
rayhit.ray.tnear = 0;
rayhit.ray.tfar = INFINITY;
rayhit.ray.mask = (unsigned int) -1;
rayhit.ray.flags = 0;
rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID;
// rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID;

// do the intersection
rtcIntersect1(scene, &context, &rayhit);

// if we did not hit anything, we are done here
if (rayhit.hit.geomID == RTC_INVALID_GEOMETRY_ID)
return NULL;

// [...] more code


 The Embree callback function:

void embree_intersect(const struct RTCIntersectFunctionNArguments* args) {
struct RTCRayHit * rayHit = (struct RTCRayHit *) args->rayhit;

args->valid, args->geometryUserPtr, args->geomID,
args->context->instID[0], &rayHit->ray,

And the function "embree_intersect_geometry":


void embree_intersect_geometry(const int * valid,
void * geometryUserPtr,
unsigned int geomID,
unsigned int instID,
struct RTCRay * rtc_ray,
struct RTCHit * rtc_hit) {
if (!valid[0])

rtc_hit->geomID = geomID;



I know for certain, that I am doing something really wrong here with Embree, but I am unfortunately not able to resolve this on my own.

Thank you very much for letting me post my problem here, and thank you very much in advance for any helpful hint or push in the right direction!

Have a nice day!




0 Kudos
2 Replies

When using a user geometry, you have to perform the ray/primitive intersection inside the callback.

You currently just store the geomID into the hit field, but you also have to properly update the tfar field, and therefore you have no other choice than performing the primitive intersection.

If you do not set the tfar value, traversal will just continue and not stop at the first hit and you will get just some geomID reported (and not necessarily the one of the closest hit).

As this example just uses triangles, it will be much more efficient to directly use Embree's triangle geometries.

0 Kudos

Dear Dr. Woop,

thank you very much for taking the time to help me out and thank you for the clarification.

Have a nice day!


Best regards


0 Kudos