When rendering VR ( stereo view ) environments, do you guys recommend just doing 2 frustum checks for determining what is to be drawn during the frustum culling pass or is there some other check that would be able to combine both frusta?
3 Answers
It's pretty easy to create a single frustum that encloses both of the individual eye frusta, as shown in this diagram created by Cass Everitt at Oculus. You just have to place the vertex of this frustum between the eyes and behind them a little bit. You can also increase the near plane distance to match the original near plane of the eye frusta.
Such a frustum includes a little space that wasn't in the union of the original two frusta. There's a small volume horizontally between the two eyes; also, the diagram doesn't show the vertical dimension, but pulling the frustum vertex back makes it include some space above and below the original frusta. However, for practical culling purposes it probably doesn't matter. Frustum culling is usually conservative anyway, and the extra space is only a few centimeters in thickness.
It's also possible to simply cull against the original frustum top and bottom planes (which are shared between eyes) together with the outer side planes. These planes don't form a frustum, technically, but if using "the usual" culling algorithm that tests against one plane at a time, the algorithm will happily work on any set of planes you care to give it.
Sharing frustum culling, LOD selection, etc. between eyes, rather than re-doing it twice every frame, is a great way to optimize the CPU cost of stereo rendering. This is also a prerequisite if you want to use a rendering method that draws both eyes in a single pass, such as instanced stereo rendering.
-
2$\begingroup$ Thanks Nathan that's exactly what I was after, where did you get this diagram may I ask, is it in any public documentation from oculus ? $\endgroup$ Nov 19, 2015 at 5:34
-
2
I've generalized Everitt's results if that's needed.
As a bonus, a way to extract left0/right0 from the eyes perspective matrices:
left0 = n0 * (Mle13 - 1) / Mle11;
right1 = n1 * (Mre13 + 1) / Mre11;
If you have row major. transpose for column major. c.f. this answer
Be careful, using a single frustum for culling only works if the combined field of view of the eyes is less than 180 degrees. There are now VR headsets with a larger field of view around 200 degrees, i.e. the Pimax 5k+ and StarVR. It's impossible to construct a traditional view frustum or single projection matrix for a field of view over 180 degrees.
These headsets use angled screens, so the projection planes and the forward vectors in view space are not parallel. The equations from the other answers here assume that they are parallel, and would produce incorrect results when that assumption is wrong.
A single combined view frustum can still be useful, but your code should be prepared to deal with cases where this can't be constructed to ensure that it's future proof. Alternatively, consider doing culling per eye view, or switch to angle-based culling which can express a larger-than-180-degree FOV.