Optix 7 Spheres

Can I change the intersection program so that it always returns a hit if it intersects a bounding box. In other words, I want the bounding boxes to be calculated using the sphereinput type (so I don’t have to manually calculate them for each sphere), but I don’t want the default intersection program.

No, the built-in sphere primitives must use the built-in sphere intersection program you get via optixBuiltinISModuleGet.

If you want to use a custom intersection program for whatever primitive type a ray should intersect with, that would only be called on custom primitives and that in turn gets AABBs as build-inputs.

Calculating AABBs from sphere primitives is trivial.

float3 minimum = center - radius; 
float3 maximum = center + radius;

I want the intersection test to be only with the bounding box and not with the sphere inside (which should be much simpler and hopefully faster). What is the recommended way of doing this? Should I create a simple __ intersect__ function that always reports an intersection?

The task of the intersection program is to calculate the closest intersection distance with a geometric primitive.
The intersection program changes the ray tmax program on accepted intersections (ones where no anyhit is calling optixIgnoreIntersection). That shrinks the ray interval [tmin, tmax] each time until there is no closer intersection tmax value.
Meaning even if you’re implementing a custom AABB intersection program, the intersection program needs to be able to calculate the closest intersection distance with that box.
Since that is part of most ray tracer implementations you’ll find tons of examples doing that on the internet.
e.g. in the second of these three books: https://raytracing.github.io/ or here https://pbr-book.org/ in chapter https://pbr-book.org/3ed-2018/Shapes/Basic_Shape_Interface#RayndashBoundsIntersections

Would that be unnecessarily going back to the SM every time it traverses a leaf in the BVH?

All OptiX device code you provide will run on the SMs.
There wouldn’t be much difference between a custom intersection program and one of the built-in ones in principle, except for triangles which use the RT cores on RTX boards for ray-triangle intersections.
(The OptiX built-in intersection programs are tuned for performance and precision a lot though, so they should be preferred when possible.)

That said, if memory isn’t a concern, it would also be possible to build these boxes with 12 built-in triangles and let the RT cores do the intersection in hardware. (When building these boxes, mind the winding, always use counter-clockwise vertex winding in a right-handed coordinate system to let the front and back face result be consistent.
Example from one of my OptiX 7 examples: https://github.com/NVIDIA/OptiX_Apps/blob/master/apps/rtigo10/src/Box.cpp)

If you only need the information which box you selected that would also be simple, and trivial when there is only one GAS with these boxes. Then the triangle primitiveId defines that: boxID = primitiveID / 12;

None of these things will result in getting multiple hits for coplanar faces though, so the behavior of the initial question is still the same for any primitive type with a single ray. Two rays, one intersecting front faces and one intersecting back faces would be able to fully resolve coplanar faces with opposite orientations, e.g. two adjacent boxes with a shared face.
See links in these threads:
https://forums.developer.nvidia.com/t/ray-mesh-intersections/170090/5
https://forums.developer.nvidia.com/t/how-to-adapt-optixtrace-considering-previous-intersections/253961/2

1 Like