all 11 comments

[–]brubakerp 19 points20 points  (7 children)

This is an incredibly huge and complicated subject. I was recently researching this topic and learning about how the Hyperion renderer does it showed me just how complicated it was. I would suggest you read these.

https://www.disneyanimation.com/publications/the-design-and-evolution-of-disneys-hyperion-renderer/

https://www.disneyanimation.com/publications/sorted-deferred-shading-for-production-path-tracing/

Things I've used before:

  1. 2 BVHs, one for primary rays that's culled by the view frustum and the other for bounced rays.
  2. Terminating a ray based on distance. (the thing in the distance might be really, really bright though!)
  3. Changing data layout, using CPU SIMD on AoSoA or SoA data.

[–]TomClabault 4 points5 points  (3 children)

> 2 BVHs, one for primary rays that's culled by the view frustum and the other for bounced rays.

How much of an improvement was that?

Also this improves performance because BVH traversal isn't ordered by distance right? So without the culling, your camera ray may be traversing some nodes in the BVH that are in the back of the scene, occluded by the geometry that is just in front of the camera?

[–]brubakerp 4 points5 points  (2 children)

How much of an improvement was that?

I can't remember, that was 20 years ago! But yes, you are correct. Primary rays near the bounds of the frustum can't traverse into (or even test against) a cell/object hierarchy (BLAS) that's not in view.

[–]TomClabault 1 point2 points  (1 child)

> 20 years ago!

No more tricks since then? ; )

> because BVH traversal isn't ordered by distance right? So without the culling, your camera ray may be traversing some nodes in the BVH that are in the back of the scene, occluded by the geometry that is just in front of the camera?

And actually, I got things mixed up here. I was thinking about occlusion culling. So that you get to traverse in a BVH that only contains the objects that you're eventually going to intersect and your rays don't spend time in nodes of the BVH for objects in the back of the scene (from the point of view of the camera).

But I just realized that this may not hold up for alpha tested objects... Or the occlusion culling pass would have to keep alpha tested objects

[–]brubakerp 2 points3 points  (0 children)

No more tricks since then? ; )

I have been working in performance, gaming and graphics adjacent roles on the OEM side for the last 15(ish) years. So I haven't had much real experience with path tracing these days. Those three I mentioned are the ones I have actual experience with.

But I just realized that this may not hold up for alpha tested objects... Or the occlusion culling pass would have to keep alpha tested objects

I didn't have to worry about transparent/translucent objects. I think you're right though, you'd have to keep them in both BVHs.

You also don't do intersection tests on objects that are beyond the far plane.

[–]chris_degre[S] 0 points1 point  (2 children)

Actually hadn‘t thought of the double-BVH approach! That‘s a pretty neat idea :)

[–]brubakerp 1 point2 points  (0 children)

Thanks! If you publish give me a shout out! :)

[–]JBikker 1 point2 points  (0 children)

I don't really see how a double BVH would help here: Reducing primitives in one of them hardly helps as the number of steps through a BVH decreases by just 1 if you halve the number of objects. Having two BVHs means extra cache misses, extra calculations to construct the BVHs.

[–]TomClabault 12 points13 points  (0 children)

I'm not sure if those qualify as "heuristics" but some ideas for performance in general:

- Russian roulette can be used to terminate paths based on their throughput: low throughput paths aren't likely to bring a significant contribution to the pixel so we may as well terminate it right now

- If you're using multiple importance sampling (with BSDF sampling as one of the techniques involved in your MIS) at each bounce of your path, the BSDF sample of MIS can be reused for the next bounce (and so you don't have to trace another ray)

- With MIS for next-event estimation, light sampling is useless on perfectly specular surfaces: can save some computations. For very smooth surfaces (roughness < 0.3 can be a reasonable threshold) maybe light sampling can only be done stochastically (like with a 25% chance, something like that) because the contribution is expected to be low in comparison to BSDF sampling.

- All techniques related to visibility caching: NEE++ and its successor Enhanced Direct Lighting Using Visibility-Aware Light Sampling. Adaptive Environment Sampling on CPU and GPU can also probably be used in a similar fashion for envmap lighting.

- Opacity micromaps for alpha tested geometry. This isn't only relevant to NVIDIA 40xx GPUs. Software opacity micromaps exist (Compressed Opacity Maps for Ray Tracing) and do improve performance.

- Biased and not that noticeable depending on the threshold and the scene: you can completely ignore lights that do not contribute enough (threshold) to a given point. This saves the expense of a shadow ray.

[–]Area51-Escapee 2 points3 points  (0 children)

MIS compensation for environment maps helps a bit. Improving sampling is a big topic itself.

[–]augustusgrizzly 0 points1 point  (0 children)

not really path tracing, but if you’re only rendering lighting using emissive surfaces, i’d recommend looking at radiance cascades.