Vanilla Quake's software renderer does have a pretty bad case of Z-fighting, which only happens between different BSP entities (be it external BSP entities, such as item boxes, or entities built internally into the map, such as doors and moving platforms).
Vanilla Quake only performs worldspace geometry clipping between individual BSP entities and the world, while worldspace geometry intersections between multiple BSP entities are ignored by the renderer. This makes the screenspace per-span depth checks to fail, with the spans containing the nearest on-screen edges obscuring the other spans all the way to the end of the object's on-screen projection.
Putting it simple, take a look at this WinQuake screenshot: The lines where the megahealth obscures the ammo are the lines where the obscuring megahealth's polygon have an edge closer to the screen, while the lines where the ammo obscures the megahealth are the lines where the obscuring ammo's polygon have an edge closer to the screen.
The simplest solution is to use per-pixel depth checks, which is generally slower than worldspace geometry clipping. Also, per-pixel depth checks are prone to per-pixel Z-fighting between polygons sharing the same plane (see the last pic); this is something that always happens in hardware-accelerated 3D games, and hardware-accelerated Quake ports usually employs several different methods to try to mitigate that.
The solution I'm working on is still not ideal, because of its impact on performance. The ideal solution should be to perform geometry clipping between different BSP entities, but this would be very difficult to do on rotated entities (I still haven't figured out how to cast raytraced shadows between multiple rotated BSP entities). I'll likely end up implementing geometry clipping between non-rotated BSP entities only, and use depth checks on rotated BSP entities.
mankrip
2024-04-09 16:18:16 +0000 UTCIronhell
2024-04-09 10:33:12 +0000 UTC