Cameras and Frustums

Looks like we can’t attach images to pull request comments, so I’ll reply here to Dan’s question on pull request #196 -

I changed the frustums to use the compute planes function and store it in a public planes property. Should there be a separate object that contains the planes and tests for intersections like getVisibility on the frustums?

Short answer - yes.

However, this prompted to me think about renderer-level cameras, frustums, and culling volumes in general (I am not talking about scene-level cameras like spindles, flights, etc.; they remain unchanged). My current best thinking on the architecture is attached. There’s three main players:

  • Camera - knows how to compute a view matrix. (position/direction/up/transform).
  • Frustum - knows how to compute a projection matrix, and knows how to create a Cull Volume.
  • Specific frustums - Perspective, Perspective Off Center, and Orthographic
  • Cull Volume - an object (or functions?) that knows how to do an intersection test with a Bounding Volume.
    So this is exactly what we have now with the decoupling of frustums from their ability to cull as you suggest.

From looking at a few other engines, other architectures are in use: a single object that combines our concept of Camera and Frustum, or even a single object that combines our concept of Camera, Frustum, and Cull Volume. Our separation is not cosmetic; it is based on use cases:

  • We decouple Camera and Frustum, so we can change the Frustum to orthographic when switching to 2D and to perspective when switching to 3D.
  • We decouple Cull Volume from Frustum, so we can use different frustums for culling independent of the frustum used to compute the projection matrix. In particular, when picking we want to render with the current frustum’s project matrix, but we want to cull with an off-center frustum just encompassing the picked pixels.
    I also considered not introducing the idea of a Cull Volume, and instead just using a Bounding Volume. A frustum is a bounding volume, right? I didn’t go down this road because that would imply that any bounding volume knows how to determine an intersection with any other bounding volume. I suspect this will be useful in the future, but I don’t want to commit to us writing all the code just yet.