Visibility range mixes origin and AABB
Godot version
v4.1.stable.official [970459615]
System information
Godot v4.1.stable - Pop!_OS 22.04 LTS - Vulkan (Forward+) - dedicated AMD Radeon RX 580 Series (RADV POLARIS10) () - AMD Ryzen 5 5600G with Radeon Graphics (12 Threads)
Issue description
When using a multimeshinstance3d with visibility range it seems that the visibility and fading are calculated differently. Visibility is calculated from the camera's distance to the origin, while fading is calculated based on the distance from the AABB. I assume this because the fading depends on the viewing direction.
I assume it happens too when the mesh in a meshinstance is not centered at the origin, but I have not tested this yet.
Steps to reproduce
Create a MeshInstance3D Add a plane to it Offset the MeshInstance3D eg +1m in the x direction Create a MeshInstance3D as target mesh. Add arbitrary mesh, eg small capsule Create a MultiMeshInstance3D Populate it with the small capsule on the plane surface. Set 10m as visibility_range_end set 5m as visibility_range_end_margin set self fade mode
Observe as you pan around the center the mmi sometimes fades nicely and sometimes pops out of existence.
https://github.com/godotengine/godot/assets/36245389/51859cb4-e2ef-45de-b1c3-18767365ac5b
Minimal reproduction project
Some additional observations. If fade mode is set to disabled, all is correct. Panning around the aabb center does not change the visibility of the mesh. If fade mode is set to self, the problem occurs even with 0 margin (so basically no fading). If fade mode is set to self with some noticeable margin, the fading is also calculated using the origin instead of the aabb center.
This is where the visibility distance is computed:
https://github.com/godotengine/godot/blob/a7583881af5477cd73110cc859fecf7ceaf39bd7/servers/rendering/renderer_scene_cull.cpp#L2642
I haven't touched the rendering cull code in a while, but there should be a way to get the AABB center instead of the transform origin here.
I tried to look around the code a bit. I have not managed to track down the issue but I think it should be somewhere else. I say this because the same code is applied when fading is disabled (at leas this part of the function) and that case works without any issues.
Actually, the position is cached here:
https://github.com/godotengine/godot/blob/a7583881af5477cd73110cc859fecf7ceaf39bd7/servers/rendering/renderer_scene_cull.cpp#L1384
And it should already be the AABB center, so more investigation is needed.
I tested it with a mesh that is offset from the origin. As expected, the same thing happens as with the multimesh example above.
I'm seeing this as well. It took me a while to figure out what was going on here, but I have the same issue. I only noticed it when I started scaling up these billboards that they would not fade out/fade in at the correct distance (sometimes, not at all, for the trees that were quite a bit taller). Because the origin is at the base of the mesh, when scaling up, the center of the AABB moves up as well.
This is definitely a tricky case to find, but I'm almost certain we do not want to be using the AABB center for any of these calculations. Developers can control the origin point (which has a variety of uses: procedural generation object placement, pivoting objects at the correct location, etc.), but not the center of the AABB, which is typically wrapped around the whole shape.
The docs refer to the instance's origin, not the AABB center: https://docs.godotengine.org/en/stable/tutorials/3d/visibility_ranges.html#how-it-works