godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.44k stars 21.07k forks source link

Godot automatic LOD changing (incorrectly) based on the angle of the camera when using MultiMesh #76436

Closed MagmaGuy closed 1 month ago

MagmaGuy commented 1 year ago

Godot version

4.0 Mono

System information

Windows 11

Issue description

Godot 4 seems to be doing some kind of LOD performance improvement incorrectly.

Here are some screenshots:

image image image

Of note but maybe hard to tell from the screenshot alone, this tiny model is roughly at the same distance from the camera for all 3 screenshots - but as the camera rotates the LOD changes as well.

Steps to reproduce

It is not feasible to provide the entire project, and I am not sure if this will be easily replicable elsewhere. If it is not replicable, I will try to provide further info. You can have the beautiful flower model, free of charge. I know it's surprising to offer these high quality assets for free, but I feel like it is for a good cause.

Minimal reproduction project

flower1.zip

MagmaGuy commented 1 year ago

image Just noticed my shrubs are having the same issue. This screenshot shows the issue even better because it's easy to tell the shrub getting affected by LOD is closer than the one not affected.

Calinou commented 1 year ago

@MagmaGuy Please upload a minimal reproduction project to make this easier to troubleshoot. (We need this to know if there are any unusual settings used, such as using GridMap/MultiMeshInstance3D.)

I thought we had a threshold for vertex count that disabled LOD below a certain vertex count. Your meshes are pretty low-poly and don't benefit much from having LOD variations.

MagmaGuy commented 1 year ago

@MagmaGuy Please upload a minimal reproduction project to make this easier to troubleshoot. (We need this to know if there are any unusual settings used, such as using GridMap/MultiMeshInstance3D.)

I thought we had a threshold for vertex count that disabled LOD below a certain vertex count. Your meshes are pretty low-poly and don't benefit much from having LOD variations.

I can't provide an example right now because the way I'm generating these is a bit involved, but I am indeed using a multimesh. Is this a problem?

Calinou commented 1 year ago

but I am indeed using a multimesh. Is this a problem?

For performance reasons, LOD selection is performed once for the entire MultiMesh. This means all meshes within a MultiMeshInstance3D will use the same LOD level when drawing. If you want better LOD selection, don't use MultiMesh or create smaller lumps of concentrated MultiMeshes instead (e.g. 1 MultiMesh per chunk of 16×16 tiles).

In general, using a single multimesh for the entire level isn't recommended as this prevents all frustum/occlusion culling opportunities.

MagmaGuy commented 1 year ago

In general, using a single multimesh for the entire level isn't recommended as this prevents all frustum/occlusion culling opportunities.

Ah that's fine then, I am using it to group chunks for something with an overhead rts camera style so the camera normally hangs much higher than this anyhow. Thanks for the help.

lyuma commented 1 year ago

LOD generation uses distance along the Z axis of the camera to the front and back of the AABB. It stands to reason that the values returned might vary a bit depending on camera rotation.

What I found, however, as I noted in https://github.com/godotengine/godot/issues/76892#issuecomment-1549415354 is that the code calculates the distance to the shell of the AABB... that is to say, if the camera is within the mesh bounds (for example, an environment/level, or a large character, or due to the skinned bone AABB bug) it will possibly return a very large distance to the border of the AABB.

To the contrary, the correct way to handle the case of the camera being within the mesh bounds should be to always use the original mesh (lod_distance = 0)

See the code at servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp line 948 (// Get the LOD support points on the mesh AABB. and below)

roalyr commented 8 months ago

This addressess the issue: https://github.com/godotengine/godot/issues/88273