Casting rays best practice suggestion

Casting rays best practice suggestion

I am casting a large number of rays from a compact ray-casting source into a static geometry scene. This is not for rendering. The geometry may have a very large # of triangles.

Each ray can 'reflect' a fixed number of times ( unless of course it misses geometry entirely) . The angle of reflection of each ray from the surface might need to be adjusted from the exact form based on some surface characteristics.

I collect information about each ray "segment" for later processing such as how far in total the ray traveled and was attenuated.

At the moment I have a fairly naive algorithm with a outer loop over Nrefl ( # of reflections) and an inner loop over N rays. In the inner loop I call rtcIntersect to intersect each ray with the scene. At an intersection, I change the direction of the ray ( the reflection off the surface)

Before using embree I used my own custom code using a kd-tree and OpenMP to keep a multicore machine busy. So I am looking for suggestions on how to optimize my use of embree. For example, should I cast packets of rays?

can you tell us how many rays are in each reflection "ray stream" and what the value of N is?

OpenMP should be fine for getting good thread parallelism, you might also give TBB a try as it is very good for irregular work distributions. Do you see a linear scaling in the number of cores on your machine? That's the first thing I would check before doing anything else.

Next would be to determine whether you always need to check for the closest distance (rtcIntersect) or whether any-hit queries (rtcOccluded) would be sufficient. The latter is quite a bit faster than the former.

You could also try APIs for ray packets or ray streams. If your simulation app can easily create ray packets or streams of rays/packets it is definitely worth a try to get some more performance. That obviously assumes that the bottleneck in your app is the ray tracing part. Could you do a quick profile run to check how much time is spent within Embree compared to the rest of your application?

It is likely that the ray-tracing will become a factor when we are using complex geometries. We could have millions of triangles in the geometry, and millions of rays being traced. The faster the ray tracing, the more complex models can be 'solved' in a reasonable amount of time. The parts of the algorithm outside the raytracing are going to scale in a linear manner, so I assuming that the more complex the geometry the more raytracing will become the bottleneck.

I must admit to just one little bit of confusion when using the API and intersection filter functions.

I assume one use of the intersection "RTCFilterFunc" routine is that you can , for example, "filter" the intersection of a ray with a geometry so that when it intersects a geometry you can capture the information you need, modify the direction of the ray ( e.g. reflection) then let the ray "continue on it's way" to the next intersection until 'done'.

The filter function are intended to "ignore" intersections for the same ray (origin and direction must not be modified), e.g. handling transparent geometry (alpha transparency in textures attached to the geometry) is one use case while collecting the N-closest hits along the ray would be another.

So I would be correct in saying that reflections/refractions can only be handled by first calling rtcIntersect and then casting a new rtcRay with a new direction from the intersection point? That is , there is no 'in-built' support for reflection/refraction.

Creating reflection/refraction rays or any kind of secondary rays is typically part of the renderer/shader layer which is build on top of Embree. Embree's main purpose is to efficiently perform ray tracing queries. Just have a look our tutorials, e.g. our example path tracer on how to create reflection/refraction rays.