Examples of Participating Media/Volumes in OptiX?

Are there any examples of how to render Volumes/Participating Media(like fog) with OptiX? I considered using an AnyHit program but I don’t really know where to begin. I checked the samples but I didn’t see anything of the sort.

We have the advanced sample on particle volumes mentioned in this recent thread: https://devtalk.nvidia.com/default/topic/1045381/optix/how-to-set-a-ray-pass-through-in-closet-hit-/

Aside from that, we don’t have a sample for participating media. Are you hoping to use a 3d brick of volume grid data, or procedural volumes, or something simpler like a constant OpenGL style fog effect?

AnyHit shaders give you potentially out of order intersections for surfaces that you register with OptiX, which can be useful for visibility queries and some transparency effects and things like that, but they may not be the ideal mechanism for traversing your volume data. If you have a typical 3d brick of volume data with varying opacity & color values throughout, you might want to look into using CUDA to design your own kernel that does some kind of volume ray casting (https://en.wikipedia.org/wiki/Volume_ray_casting). If you want to mix volume data with surface rendering, I mentioned a really basic approach in thread linked above. You could use OptiX with a ray gen shader that coordinates between your next closest surface hit and your volume traversal.

Something simpler, yes. I’m actually working on an OptiX version of Peter Shirley’s Ray Tracing The Next Week(http://www.realtimerendering.com/raytracing/Ray%20Tracing_%20The%20Next%20Week.pdf), and in Chapter 8(page 45 onward) he introduces a volume of constant density, basically a geometry that ‘contains’ the constant volume/fog.

Oh, okay! Well I haven’t thought through this all the way, but let me see if I can suggest a way forward. The way Pete structured it, you have a boundary intersection test, and then a separate volume intersection test that you call if your ray hits the boundary.

I think you can use something similar to Pete’s function constant_medium::hit() stuffed inside your box closest hit shader. The important part is that you will combine the boundary intersection test and the medium intersection test into a single closest hit function for your box-volume primitive. First, check if the boundary is hit, then check if the medium is hit, and return the interior volume hit point plus whatever other info you need.

If you are path tracing with a recursive algorithm, then you can compute and trace your scattered ray from inside your closest hit shader. If instead you started with something like the optixPathTracer sample, and you are coordinating your recursive trace calls from your ray gen shader (which is the recommended approach), then you might want to return some information about which volume you hit in your payload from your box-volume closest hit shader. That way the ray gen shader can compute the scattered ray and iterate, fire off the next path segment & composite using the correct color & opacity. In any case, you want to keep your ray payload as small as possible for best performance.

Does that make sense & seem reasonable? I haven’t tried this yet, so I’m not sure I’m giving solid advice here. Let me know if you see or bump into issues. And we’d love to see the results of your OptiX version of Pete’s book! Please send links if you get pictures or do a blog post.

HUGE thanks, dhart! Your suggestion was exactly what I needed. Here’s the final image of my OptiX port of “The Next Week”:

I just finished a blog post about it, as well. I included resource links to everything I used while implementing this project. There’s also some relevant source code, pics and links to Git releases of each chapter. Feedback is appreciated!


Thanks again!

@joaovbs96 Great Blog Tutorial! I also tried to implement it in my engine.

in Chapter 8 of your blog you initialize “distance_inside_boundary”, but you don’t use it

I would recommened to add something like this:

if (hit_distance > (distance_inside_boundary - 0.01f))  return;

cause tmax = RT_DEFAULT_MAX); and so if (rtPotentialIntersection(temp)) gives true even if out of the sphere

(in my post https://devtalk.nvidia.com/default/topic/1057855/optix/-solved-constant-medium-sphere/
I tried your code without that change and so the blue fog caused a blue color even when density was very low;
with that change here in this post that problem was solved;)