godot_heightmap_plugin icon indicating copy to clipboard operation
godot_heightmap_plugin copied to clipboard

A more efficient way of terrain details processing

Open painfulexistence opened this issue 3 years ago • 5 comments

  1. Maintain a dict of AABBs for all detail chunks

  2. Update all chunk AABBs only when necessary:

  • On terrain setup
  • On terrain transform changes
  • On terrain chunks rebuild, which happens when terrain data resolution changes
  1. The number of times of get_region_aabb func calls is now independent of the number of detail layers

painfulexistence avatar Jan 15 '22 21:01 painfulexistence

Nice work @painfulexistence . I did some testing on it.

  • Win10/64 GTX1060
  • 2k terrain, with only a player, directional light, and an hdr
  • Three detail layers: 2D grass plane, 3D grass mesh, 3D rock.

Results w/ 3 Detail Layers

FPS

  • Before: 40-58fps. It seemed fairly consistent, only a few times peaking at 58, mostly around 45-55.
  • After: 38-60fps. It seems to swing a bit more, achieving both higher and lower results.

Script Time

  • Before image

  • After image

Full Scene

w/ day/night cycle, water, trees, animals, houses, etc.

  • Before: 28-45fps
  • After: 28-45fps

8 detail layers

Here I added more 2D textures and 3D meshes for flowers, pinecones and branches.

  • Before: 27-38fps image

  • After: 24-39fps image

Overall, it seems the FPS performance of the old classes is slightly more consistent. I can't tell if the FPS is any faster. We must be bound by the performance of the renderer and MMI. However there is a definite improvement to script time.

I think for our game, we're just going to have to limit the use of grass with sparse ground vegetation so as to not overwhelm the renderer.

TokisanGames avatar Jan 16 '22 08:01 TokisanGames

Hi @Zylann, Sorry if this is a dumb question. But would you mind pointing out to me which signal I can listen to for knowing the terrain being sculpted? I'd tried to find that signal and put a line to recalculate AABBs as the comment above, but didn't know what else I could do.

painfulexistence avatar Feb 13 '22 01:02 painfulexistence

There is the following signal in HTerrainData:

signal region_changed(x, y, w, h, channel)

However it is emitted for other channels than just the heightmap. There is a function in hterrain.gd from where you can call the detailer directly, _on_data_region_changed. Note, this is called everytime the user sculpts, so you will need to implement AABB updates with a region instead of updating them all.

I still have a feeling that extra cache is really just complexity inflicted by GDScript alone, because bounds precomputed inside HTerrainData should have been fast enough to use... I'm also wondering if chunking should also be done via a sliding box algorithm instead of iterating all cells everytime. The idea is to convert viewer coordinates into chunk coordinates, and detect when they change (which is not often). And only then, load chunks only in the new cells, and unload chunks only in the cells out of range. That is a lot less iterations to do. Only downside would be the area would be square instead of circular, so a few chunks would be wasted (due to the shader they would not be visible and yet still drawn).

Zylann avatar Feb 13 '22 02:02 Zylann

@Zylann I've updated the PR to implement AABB updates for a changed region.

Yes, I understand the extra cache of AABBs is somewhat redundant, but I could't come up with other ways to make detail chunk AABBs update faster😭 The sliding box optimization sounds interesting to me, though I need some time to figure it out and I'm kinda busy recently. Is it okay that I leave that for the future updates?

painfulexistence avatar Feb 17 '22 04:02 painfulexistence

Yeah sliding box could be done later

Zylann avatar Feb 17 '22 19:02 Zylann