-
-
Notifications
You must be signed in to change notification settings - Fork 21.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Use Reverse Z for the depth buffer #88328
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some of these are exposed, and unless they are unchanged by this they break compatibility
2b99383
to
5493a92
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested locally, it mostly works as expected.
Testing project: https://github.com/godotengine/godot-proposals/files/10502399/test_zbuffer_precision.zip
Directional shadows for large objects break, even if the object is subdivided (each plane here is subdivided into 21×21 parts of equal size). I've also tried adjusting Pancake Size in DirectionalLight3D to no avail.
View videos in fullscreen to make the difference more noticeable. Focus on the area between the orange and white planes.
Forward+
Before
no_reverse_z_forward_plus.mp4
After (this PR)
Notice the phantom shadow appearing at the beginning of the video, which isn't visible in master
.
reverse_z_forward_plus.mp4
Mobile
The shadow issues on the cyan spheres also appear in master
without this PR.
reverse_z_mobile.mp4
Compatibility
This PR doesn't seem to affect precision in Compatibility so far.
no_reverse_z_compatibility.mp4
This needs more testing by myself and clay and there are a few change we likely want. But it is important to know that there is consensus within the rendering team that the compatibility breakage is acceptable as this will effect really limited edge cases. |
@Khasehemwy one important change you might be able to do, we don't want the Z-flip to be part of the code for populating the the projection matrix, but only apply this when populating the GPU buffers. So we leave all the setters etc. alone. The Projection class needs a single That has far less impact than doing this early on. |
5493a92
to
11dd85e
Compare
I changed the projection matrix back to normal z, then added reverse z-related operations, and added reverse-related operations where I thought they needed to be added. In addition, I found that there is a problem with the Dual Paraboloid shadow mode of Omni Light in compatibility mode. It seems that the official version also has problems. It may not be caused by my changes. |
core/math/projection.cpp
Outdated
@@ -808,6 +884,10 @@ bool Projection::is_orthogonal() const { | |||
return columns[3][3] == 1.0; | |||
} | |||
|
|||
bool Projection::is_reversed_z() const { | |||
return columns[2][2] > 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The case of far<near is not considered (if far<near, columns[2][2] will be <0 when reversed-z is used). I don't think we need to consider this situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think so either, I think we protect that on Camera3D
anyway but if not, it's an acceptable assumption.
11dd85e
to
485358a
Compare
Will this not be an issue (asking just in case): roalyr#15 ? |
d27cf66
to
485358a
Compare
@Khasehemwy I think it looks good now! We have all been away for the last couple of weeks due to GDC and vacations. The final step before merging is to squash all the commits together so that the whole PR only contains 1 big commit with all your changes. We like to merge one commit at a time to keep the git history clean and navigable. If you don't know how to do that, we have a helpful tutorial in the official documentation https://docs.godotengine.org/en/latest/community/contributing/pr_workflow.html#the-interactive-rebase |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good to me now (pending squash and rebase). I have tested extensively on desktop devices and I trust the testing of Bastiaan and David on VR devices.
Once this is squashed, we can go ahead and merge it for 4.3
Sorry if this is an obvious question but this is a pretty big breaking change (as noted in the OP) that will impact user shaders. I am surprised that a change like this is better in all cases and would have no downsides. If this is true, do all other major engines also use this approach on dx/vulkan? (Should this perhaps be a project setting?) I saw XR mentioned. Are there any interoperability concerns related to submitting reversed depth buffer to OpenXR? |
Most of your shaders should be completely fine, this only has an impact on you if you either manually write to depth or read it. That's why we really want to get this merged before the compositor PR makes writing custom post processing shaders much easier. Should you run into any problems all you need to know is that the depth buffer now goes from
Yes, this is the approach that is used by any recent-ish engine. It has major advantages when it comes to precision and accuracy with 0 downsides, so there is no point in adding a project setting to turn it off (as a matter of fact that would actually be counterproductive, since custom post-processing assets could break depending on the state of that project setting).
Not that I am aware of. As said before, rev depth is the current state of the art and recommended by every hardware vendor out there. I have little experience with developing for VR, but I would be seriously surprised if rev depth was a problem. |
Reverse Z has the following conditions: Much Better in all scenarios if:
Slightly worse if:
Other engines chose to either move to reverse Z as well, or allow for optionally support both. Supporting both options requires a lot of testing and maintenance which is why the Godot team chose not to support the old regular Z at all. Often engines that support both options end up having bugs when using regular Z because very few people actually use that code path (due to the massive superiority of reverse Z).
Godot devs will have to answer you this one. You do make a point that perhaps Godot 4.3 should define "something" to signal user shaders that reverse Z is being used; in case a user wants to support both versions (<= 4.2 + >= 4.3). |
Ok your answers all make sense. I am pretty sold. the main thing then is having some docs on porting shaders. For example one shader here is hardcoded in the godot engine source and probably needs to be edited: In terms of user shaders, godot vrm does something with the projection space z coordinate for outlines: |
I did a little research on this and sadly, non of the APIs in OpenXR that allow us to submit a depth buffer, provide the ability to tell the XR runtime we're storing reverse-Z, meaning they will be incorrectly interpreted. Right now we only use the composition layer depth extension, and that is generally turned off. This discussion actually made me find a bug in that logic that might explain some issues we've had in the past. Metas Application Spacewarp will also be effected by this. That said, seeing many game engines are switching over to this, it's something that I have raised within the working group, hopefully that will lead to discussions to eventually add support for this. |
970a3eb
to
820d43d
Compare
@clayjohn Awesome! Thank you all! All the submissions have been squashed now. |
@lyuma Yes, you can determine whether it's reversed-z in the shader by checking the value of the |
@lyuma Neither of the shaders you linked will need to be modified. The only user shaders that will need to be modified are those that adjust In other words:
|
I amended the commit message to clean the description which still included past fixup commit titles, and retitled it to be clearer, especially regarding the fact that it's changing the convention, not adding a new option. |
Thanks! And congrats for your first – but massive! – merged Godot contribution 🎉 |
Adding a note for the dev blog post:
|
Add support for reverse-z depth buffer resolve godotengine/godot-proposals#3539
@BastiaanOlij @clayjohn
These changes break shader compatibility!
I finished part of it.
Have finished:
Projection
class (set_depth_correction() function).(
directional shadow seems to be some problem, mentioned in the conversation below)(update: clayjohn fixed directional shadow problem)
Unfinished and known issues:
some problems with the xr part when using OpenGL API (mentioned in the conversation below)SSAO is incorrect (most post processing effects will have problems)