I have an application that runs a trace against one mesh, and then in the closest_hit program, runs a second trace against a different more-or-less co-located mesh. As suggested to me in a previous post, I’m using a Selector node to pick between the meshes, but I’m wondering if the hack I used in the visit program is necessary. Since attributes aren’t exposed to visit programs, variables are read-only, and the objects are in the same general space, the only way I could come up with to pass index information from closest_hit to visit was to embed a hint in the ray’s tmax property–specifically, an offset based on the intended object (100000.0 to use node 0, 200000.0 to use node1).

This hack is harmless and works fine for my application, but is there any easier/prettier way? Or is the visit program specifically and only intended for ray-based decision-making?

When recommending the selector I misinterpreted the trace as full launch and switching the whole mesh for one invocation of the ray generation program. What you describe is more dynamic and could be done in multiple ways.

There should be no need to abuse the rtCurrentRay data for the mesh selection like you did. Table 5 Semantic Values in the OptiX Programming Guide describes which internal semantics are available to which program domain.

Write a visit program which decides which child to take dynamically (per ray) by passing the desired child index (0, 1, …) through a field in your per ray payload.
Example: If your base mesh is at child index 0, set that inside the per ray payload at the ray generation program. In the closest hit program which shoots rays to the other mesh, change that index to 1 before the rtTrace.
(Which anyhit and closest hit programs are hit then? Make sure to handle recursions correctly.)

Previously you used different rtObjects for the individual meshes and you used the respective rtObject as top object for the different rtTrace calls. That should also work if these objects are all under the root group during acceleration structure build and you pick the resp. sub-tree with the individual child object. If it didn’t, you might have missed some initialization.

You can write visit programs which work per ray (e.g. LOD or your case) or are controlled by the application per launch, like it’s used for switch nodes in scene graphs. Latter could implement [i]one of many /i or multiple of many child nodes (DIP switch).

Ah! I had actually tried that first (a legitimate field in the payload struct), but a bug led me to suspect that the rtPayload semantic wasn’t available in the visit program, especially since the sole selector sample in the SDK used only the ray itself for switching. That bug later turned out to be a trivial stack overflow–also the cause of the errors when using multiple rtObjects. I’ll trust the docs implicitly from here on. Optix just works.

Thanks again, Detlef.