jdolan / quetoo

Quetoo ("Q2") is a free first person shooter based on id Tech2. GPL v2 license.
http://quetoo.org
204 stars 28 forks source link

Programmatically generate occlusion queries #679

Closed jdolan closed 1 year ago

jdolan commented 1 year ago

The goal of this PR is to completely remove the burden of placing occlusion queries from the mapper, while also improving performance. This approach is inspired by this article: https://developer.nvidia.com/gpugems/gpugems2/part-i-geometric-complexity/chapter-6-hardware-occlusion-queries-made-useful

The general idea is to select nodes from the BSP that satisfy a heuristic (some general size threshold, configurable by cvar), and create queries spanning the visible bounds of those nodes. Since the selection produces a completely contiguous graph, where every valid point in the map is covered by exactly one query, the actual occlusion check changes from:

find a query that fully contains the box in question, and if that query is occluded, we can skip the object

To:

find all queries that intersect the box in question, and if all of those queries are occluded, we can skip the object

This is actually a significant improvement for things like dynamic lights and even large sprites which often exceed the solid world bounds (where the mapper had likely not placed an occlusion query).

Lastly, because the occlusion queries are derived from the BSP tree, we can make some optimizations when we receive a query result: a positive result (visible) should propagate up the tree, and a negative result (occluded) should propagate down. This reduces the latency of query results by a frame or two, and allows us to skip certain queries entirely for certain frames. There's still more work to be done to improve this optimization.

Assuming we stick with this approach, I'll update the code and editor configurations to remove all occurrences of CONTENTS_OCCLUSION_QUERY since it will no longer be required / supported. This will require stripping these brushes from our maps, too.

This change itself is a BSP format update, because I extended the BSP node struct to include visible bounds (which is often a subset of collision bounds).