Skip to content
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

Extreme z-far value yields empty far plane due to precision rerror when reconstructing from matrix #15

Closed
roalyr opened this issue Aug 3, 2023 · 11 comments

Comments

@roalyr
Copy link
Owner

roalyr commented Aug 3, 2023

Godot version:
3.x and 4.x

OS/device including version:
Mobile and desktop (Android, linux).

Issue description:
When z-far is below 1e6 (which is the cap value on stock Godot 3) everything renders properly.
Otherwise - arbitrary culling occurs because z-far Plane which is returned by normalize() function - is empty.
image

Steps to reproduce:
Open MRP and navigate the view in editor at different z-far values as on the video:
https://youtu.be/sY_DiETtkl8
Also in-game video:
https://youtu.be/ukl9RUnHEOw

Minimal reproduction project:
cull_bug_test_for_zfar_above_1e6.tar.gz

@roalyr
Copy link
Owner Author

roalyr commented Aug 3, 2023

Workaround is to set rooms, because they disable other partitioning methods:
https://youtu.be/5E0b7g0za3M

Rooms are limited in size. Also doesn't address z-far plane issue.

@roalyr roalyr closed this as completed Aug 3, 2023
@roalyr
Copy link
Owner Author

roalyr commented Aug 4, 2023

Properly solved the issue (culling z-far is now a constant of 1e19, maybe it will be adjustable later on).
ddf5b01

This fixes z-far in place, not flexible.

@roalyr
Copy link
Owner Author

roalyr commented Dec 19, 2023

image

This is the source of an error for large z-far values.
Properly fixed in 3171bea
Do not change the Projection class size, store the value outside, otherwise it breaks API.

@roalyr
Copy link
Owner Author

roalyr commented Dec 20, 2023

For 4.x afdcb393e559ffa0ca1a6b9478fa086b50fb0eeb
Do not change the Projection class size, store the value outside, otherwise it breaks API.

@roalyr roalyr reopened this Dec 20, 2023
@roalyr
Copy link
Owner Author

roalyr commented Jan 6, 2024

8b6982a4210041b0ee85ce54ca6bdeb489dd6ed0 another attempt, but better use a helper class (?)
Calinou asked to not to use extern for it is not safe.

@roalyr roalyr changed the title Random object culling when z-far is more than 1e6 units Extreme z-far value yields empty far plane due to precision rerror when reconstructing from matrix Jan 6, 2024
@roalyr
Copy link
Owner Author

roalyr commented Jan 20, 2024

@Flarkk
Copy link

Flarkk commented Aug 24, 2024

@roalyr any chance you can check whether this PR godotengine#95944 solves the issue ?
Seems like I came down to the same idea as you, but my implementation is different and looks more straightforward.

@roalyr
Copy link
Owner Author

roalyr commented Aug 24, 2024

@roalyr any chance you can check whether this PR godotengine#95944 solves the issue ?
Seems like I came down to the same idea as you, but my implementation is different and looks more straightforward.

Sure, will check.
Also, if that PR can go into 3.x and 4.x it would be for the best.

@Flarkk
Copy link

Flarkk commented Aug 24, 2024

I don't see a reason it couldn't.
Except before 4.3 there is no reverse z which will make infinite far distance of limited interest.

Will create PRs for other branches whenever I get reviews from maintainers.

@roalyr
Copy link
Owner Author

roalyr commented Aug 24, 2024

If editor and far plane limits are set to 1e19 (I didn't try inf), it then doesn't matter what kind of depth buffer you use, because you can have custom shader log depth, but precision-proofing far plane is just a logical decision. In fact, my godot for 3d open worlds does exactly that: 1e19 far plane and editor zoom limit, a bit increased editor zoom increment, and my makeshift far plane fix. That's all. In 3.x and 4.x you can just implement log depth via custom shader if normal depth or reverse z depth is not enough:

// Add this before your vertex shader.
// Edit "Fcoef" to adjust for desirable view distance. Lesser number means further distance limit.
uniform float Fcoef = 0.001;
varying float gl_Position_z;

// Add this to your vertex shader.
void vertex()
{
	vec4 gl_Position = MODELVIEW_MATRIX*vec4(VERTEX, 1.0);
	gl_Position_z = gl_Position.z;
}

//Add this to your fragment shader.
void fragment()
{
	DEPTH = log2(max(1e-6, 1.0 -gl_Position_z)) * Fcoef;
}

@roalyr
Copy link
Owner Author

roalyr commented Aug 24, 2024

The only difference the ordinary user sees is increased far plane limit in editor and camera settings. Other than that there is no difference from upstream 3.x or 4.x in terms of UX.
If those could be implemented as PRs into main godot then I wouldn't need to upkeep this fork, and that is what I am looking forward to.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants