Zylann/godot_heightmap_plugin

[3.x] Visible LOD switch due to physics interpolation

Closed this issue · 4 comments

Describe the bug
In my game, there is currently a test level that uses HTerrain. I'm astonished by the amount of work put into this plugin, i would never expect it to be that easy to make a solid base for huge levels. I'd love to make some levels like that to diversify the corridoric-ness of the game... However, during testing of that level, me and my tester, we noticed that LOD of terrain chunk have a very noticeable switch, basically terrain chunk disappear for a moment until it shows up again

To Reproduce

  1. Enable physics interpolation and asynchronous shader compilation in project settings
  2. Make a decently huge terrain to test
  3. Launch the game and fly around with your own controller. That is a runtime-only bug

Expected behavior
Basically... A terrain, yeah, with no holes in chunks during switch

Screenshots
A video of me flying around the level to reproduce the bug

terrain_report.mp4

Environment

  • OS: Windows 11
  • Graphics card: Nvidia Geforce GT1030
  • Godot version 3.5.3.
  • Plugin version: The latest one from godot3 branch
  • Renderer used: GLES3

Additional Notes
I've been trying to investigate the issue on my own and i suspect it to be connected to asynchronous shader compilation. Basically, when you see the terrain's chunk mesh for first time, it is invisible, but if you see the switch of that one mesh again, it has no disappearance. For now i'm thinking how to force rendering of all possible terrain chunks during loading screen in order to force shader compilation of the given chunks. If you don't mind, i'd love to get some code to get these meshes from HTerrain with properly assigned material

Edit: Fixing the video preview

If that was async shader compilation, the problem would be gone after a few seconds of gameplay, rather than constantly happening. All chunks use the same shader so that doesn't make sense. Even if it was caused by async shader compilation, there would be nothing I can do to prevent it, as it's something Godot does on its own.

Enable physics interpolation

I suspect this is the problem, and unfortunately I don't know how to workaround this because if I remember correctly it's something directly integrated into the renderer, and I can't find any API to add "exceptions" to it... it flickers like this the first time because chunks are pooled and when they spawn the renderer "thinks" that they moved from the origin of the world to where they spawn within 1 frame and applies some "smoothing" to the "movement", which would make sense for a rigid body, but somehow applies to terrain chunks which is completely wrong.

Also you're using a version I'm no longer maintaining.

Also you're using a version I'm no longer maintaining.

Yep! Just opening an issue because i couldn't find anything similar, i wouldn't ask you to support it, because, let's be real, who would really go back to ancient 3.x.. I'm using it because the project was started long ago and conversion isn't worth it, so for the most part i'm just trying to investigate it and, potentially, find a fix applicable for other users of the addon

the problem would be gone after a few seconds of gameplay, rather than constantly happening.

Weird. Basically, it happens once for each individual LOD variation as much as i've noticed it, but, yeah, it does seem to be not an issue with async shader compilation because it would use a fallback shader (but who knows, right)

but somehow applies to terrain chunks which is completely wrong.

Hmm, alright, i may take a look into internals of the addon. I did some modifications for this project so i hope i'll be able to make something.

And, yeah, sorry for bothering you with an older version, i'll close the issue as soon as i'll find a fix

Edit: Fixing tags

From reading the docs, I see that for teleporting objects (which is NOT what I'm doing, I SPAWN them but whatever xD) you could call reset_physics_interpolation. The bad news is, the plugin doesn't use nodes to render the chunks. It directly uses VisualServer. You'd think that this would give better control, with nothing in the way of simply rendering terrain. Nope! reset_physics_interpolation triggers changes in Spatial nodes (which I dont use), but also inside VisualInstance nodes (which I also don't use) and calls VisualServer.instance_reset_physics_interpolation, which... is not exposed in 3.5.

Turns out I reported this a while ago godotengine/godot#64905

There was a PR recently that finally exposed this stuff, but I didn't look into it because I'm no longer working in Godot 3. The function to call would be VisualServer.instance_set_interpolated, which is not present in 3.5.
However, it is present in 3.6.
If you can confirm that physics interpolation is indeed the cause, then you would have to patch the plugin in hterrain_chunk.gd and add this in _init:

vs.instance_set_interpolated(_mesh_instance, false)

In theory a more complete implementation would react to node notifications that come with this, but that feature isn't even present in Godot 4 and terrains are typically static so it's probably not worth it

Thank you very much for answering all my questions, i'm going to wait for 3.6. and apply it as soon as it comes out. I'm going to close the issue because i'm pretty sure that will fix it!

Edit: Sorry for not clarifying, but i can confirm, that is a problem of physics interpolation and it is not related to async shader mode in any way