Zylann / godot_heightmap_plugin

HeightMap terrain for Godot implemented in GDScript
Other
1.71k stars 159 forks source link

Optimize VRAM usage with NPOT textures #12

Open Zylann opened 6 years ago

Zylann commented 6 years ago

Copied from https://github.com/Zylann/godot_heightmap_module/issues/13

I realized that the off-by-one required in terrain textures could become dreadful for VRAM usage, because it makes them non-power-of-two (NPOT). For example, the heightmap must be 1025x1025 instead of 1024. On graphics card, NPOT textures may be upscaled to fit the next power of two, and big terrains could end up occupying 4 times more memory to fit that 1-pixel padding... That's yet to be measured though.

Eventually a fix will be to clamp texture fetches so the terrain will have 1 stretched cell on its maximums. However, that could create seams for streamed terrain using multiple chunked textures.

Explanation about the 1-pixel padding: https://github.com/Zylann/godot_heightmap_module/blob/master/height_map_data.cpp#L22

Zylann commented 4 years ago

After some thinking, the following could happen in the future:

Instead of allowing sizes of 513, 1025, 2049 and 4097 like now, sizes would become a bit smaller.

The choice of these sizes comes down to LOD chunk size (used in "clipmaps"). Indeed, chunks are based on the minimal 16x16 basic size at the moment, all larger sizes being multiples of that by powers of two. However, it needs an off-by-one due to vertex sharing, which annoyingly goes just over the power of two. So the idea is to use a base of 15x15, which can be configured higher to 30x30 or 60x60. This leads to the available terrain sizes, which are multiple of this, with the off-by-one:

- 481
- 961
- 1921
- 3841

It looks like a small downgrade, but this may actually be factored in when the plugin gets to the stage of terrain stitching. Size of a single sector won't be an issue, because you'll be able to stitch more sectors around to make it larger. Which may even lead to a reduction in available sector sizes, to make streaming easier on memory.

The reason why it should be considered along with terrain stitching, is because that feature needs extra padding. A margin of 2 pixels on each edge is required: 1 to prevent seams when sampling the maps, and 1 extra to allow calculating normals in parallel (so a given sector won't need to query neighbors each time). Which raises the total margins to 5 pixels, so the sizes become:

- 485
- 965
- 1925 
- 3845