Tie breaker for when ray hits 2 triangles exactly on edge?

One of the minor issues I have noticed with Optix Prime is that shooting the same rays at the same set of triangles can lead to slightly different results every time the same set of rays are launched. In a problem involving 500k triangles and 5 million rays, this might happen a handful of times. I tracked this down to the fact that occasionally some ray is lucky enough to hit exactly on an edge shared by two triangles. While the effective hit point is the same, the triangle ID in the result is prone to changing. I can imagine why this would happen, given that different threads on the device might arrive at the same hit “t” for their respective triangle(s) at ever so slightly different times, and then there is no telling which of them will win and record that “t” and triangle ID first.

This can have effects down the road, for instance, if a reflected ray were launched from such a hit point. The reflected ray could very well go left one time or right the other, depending on how different the two triangles’ normals are. Neither result is more correct than the other, but it does lead to repeatability concerns.

One way that the repeatability issue could be settled is to institute a tie breaker. In other words, if a certain t is found and matches the lowest t already found, then use the triangle ID as the tie breaker and update the hit info if the new ID is lower. I can see that this might lead to performance concerns, especially for rendering applications. But for applications that are heavy on the physics and numerical analysis, this would be useful, especially for testing purposes.

So my question is whether or not Optix 7 has some mechanism through which I could set up such a tie breaker that would override the default behavior from:

if (tNew < hit.t) {
  // Record new hit
}

to:

if (tNew < hit.t || tNew == hit.T && idNew < hit.triId) {
  // Record new hit
}

Thanks!

Hi @catcondo,

OptiX 7 has a feature that OptiX Prime did not have, which we call “water-tight meshes”. This feature is a default tie-breaker that guarantees a ray hitting a shared edge will choose exactly one of the two triangles on either side of the edge. To get this feature in OptiX 7, you have to use the built-in triangles API, and it’s a good idea to have your mesh share the vertex indices (not just the position values), and also probably have a consistent winding, e.g., all triangles clock-wise. There may be other variations that work too, but vertex sharing and consistent winding will guarantee it. The hardware triangle intersector with RTX hardware respects water-tightness by default and always.


David.

Thanks for the detailed answer. I will do some experiments with my model in OptiX 7. One more question: how does the behavior of OptiX 7 water tight criterion differ from the RTP_QUERY_HINT_WATERTIGHT hint that can be used in OptiX Prime?

The main difference in OptiX 7 is water-tightness is on by default, cannot be disabled, and is included in the RTX hardware triangle intersector. There might be very minor implementation differences, or behavior differences in extreme corner cases that have been fixed in OptiX 7 and supercede the OptiX Prime implementation. I think doing some experiments using your model to see how it compares is a good idea!


David.

Okay. I migrated from Prime to Optix 7, and I think the tie breaker issue is still there. Just to confirm, I am using the built-in triangles API and employ shared vertex indices and all triangles are consistent in winding.

The model is a trihedral consisting of 3 triangular facets that form a 90 deg corner, like a corner inside a room…

Roughly 5000 rays are shot at the trihedral and anywhere from 0-3 rays will vary from run to run. The rays that exhibit variation do yield identical t values and hit points but vary in the triangle ID.

So back to my original question, is there a way for me to employ a “tie breaker” so that I can maintain more consistency from one run to another of the same model? Thanks.