This is a post I wrote a little while ago internally for the team I was on all about reverse z (it took me longer than I'd like to admit to wrap my head around it 😅🙈). Hopefully, someone finds it helpful! https://tomhultonharrop.com/mathematics/graphics/2023/08/06/reverse-z.html

Heavily inspired by the work of @reedbeta and @benjamin

Reverse Z (and why it’s so awesome)

Topic

Tom Hulton-Harrop
Also big thanks to @ninepoints who helped review and give feedback on the initial drafts!
@tom_h_h @reedbeta @benjamin
As used in Dreamcast (and, sort of, PowerVR series 1)
@tom_h_h @reedbeta @benjamin
Had a quick skim through the article but couldn’t see whether you mentioned that setting the far clip plane to infinity has negligible effect on the precision which means you can avoid doing the far clip.
Just replace it with a far cull and stick in a full screen polygon at that distance.
@simonf @reedbeta @benjamin Ah you're totally right I didn't cover that (though some of the links at the bottom do go into more detail about it). It would definitely be a good idea to add an addendum about it for sure. I do allude to it a little if you see the Desmos links and see what impact modifying the far clip plane has on the graphs, but an explicit mention would definitely be helpful. I'll have a think and add something before too long! 🙂 Thanks for the suggestion!
@tom_h_h @simonf @reedbeta @benjamin Yup - if you're messing with non-standard projection matrices, infinite far clip is well worth rolling into the whole thing.

@tom_h_h @reedbeta @benjamin
" (using C++20’s bitcast"

TIL about bitcast. This also works just fine despite what the language lawyers bleat:

uint32_t fromi = *(uint32_t*)(&from);

@TomF @tom_h_h @reedbeta @benjamin it does stop working if you have strict aliasing on in gcc/clang (but yeah, if you value your sanity you’d have strict aliasing off)
@aras @TomF @reedbeta @benjamin Thanks again for the feedback. My knowledge on this comes from a fantastic talk by @timur_audio from CppCon 2019 that's well worth a watch - https://youtu.be/_qzMpk-22cc
@aras @TomF @tom_h_h @reedbeta @benjamin
yeah, but it is on by default, so it sure is a footgun
@tom_h_h @reedbeta @benjamin nice article! My only question is why hasn’t it always been reverse Z?
@jaysteen @reedbeta @benjamin Thanks! And in answer to your question I'm honestly not sure! 😅 I think it is likely down to it being a little less intuitive but yeah it feels like it definitely should be the default 😝
@tom_h_h @jaysteen @benjamin Floating point depth buffers are a relatively recent development; before that it was all integer depth buffers and there was no strong reason to use reverse Z with those, so people probably found it more intuitive to have a Z buffer that increased with distance. And then when floating-point depth buffers came along we all just kept doing it the way we already knew. That's my guess anyway!
@reedbeta @tom_h_h @benjamin ahh yeah that makes sense. Presumably this is most useful for increased shadow resolution - is that going to be superseded by ray traced lighting soon? Asking as an audio person who is GPU curious 😅

@tom_h_h Thanks for the article! Yet another example of how we ignore the details of a given numerical representation at our peril.

This is coming to me at the perfect time as I just read the section on this in Lengyel's book on rendering, and am about to implement it. I'll likely use your article as a reference.

BTW, that book has the best visualization of this that I've seen:

https://foundationsofgameenginedev.com/figures/FGED2-Figure6.8.png

@aminom Pleasure! 🙂 Thanks for the feedback, and that reference is great, I think I have a copy of that kicking around somewhere! 😅 At the end of the article there are a couple of links to working implementations of this (one in OpenGL and one in Metal) that could be helpful to refer to. I also have a project using it in Vulkan if you'd like to see that too. Thanks again!