Heightmap based terrain returning abnormal values

Godot Version

4.2 stable


I’m currently trying to make chunked terrain from heightmap.
Feel free to download my project and test it yourself: Mega link
I practically automated the script, just change constant chunk size to test different chunks amounts. Standard FreeCam steering (tab, mouse, scroll, wsad)

The problem is, that final vertices at edges of the chunk are going into strange values shooting downwards or upwards. I wanted to make common vertices at edges and try to build a navmesh on it but its impossible to do it with what’s happening. Even if I try to do it with no chunks I can still see slight
abnormalities on vertices at edges. Any idea why it’s happening and how to fix it?


extends Node

var terrain_global_height_map := preload("res://Resources/World Map/global_height_map.exr")
var terrain_chunk_scene := preload("res://Scenes/World Map/terrain_chunk.tscn")

const CHUNK_SIZE: int = 128
		#in meters | chunk is cube
		# value in power of 2 | not larger than heightmap
var map_size: int = (terrain_global_height_map.get_height() / CHUNK_SIZE) as int
		#one side in chunks | map is square

func _ready():

func regenerate_chunks():
	for x in map_size:
		for y in map_size:
			var new_terrain_chunk_image := Image.create(CHUNK_SIZE,CHUNK_SIZE, true ,Image.FORMAT_RF)
			new_terrain_chunk_image.blit_rect(terrain_global_height_map,Rect2i(x * CHUNK_SIZE, 
					y * CHUNK_SIZE, (x + 1) * CHUNK_SIZE, (y + 1) * CHUNK_SIZE), Vector2i(0,0))
			var new_terrain_chunk = terrain_chunk_scene.instantiate()
			new_terrain_chunk.initial_setup(CHUNK_SIZE, Vector2i(x,y), 

chunk scene:

extends StaticBody3D

var size: int
var grid_position: Vector2i

func initial_setup(_size: int, _grid_position: Vector2i, _height_map: ImageTexture):
	size = _size
	grid_position = _grid_position
	$MeshInstance3D.mesh.set("size", Vector2(size, size))
	$MeshInstance3D.mesh.set("subdivide_width", size)
	$MeshInstance3D.mesh.set("subdivide_depth", size)
	$MeshInstance3D.mesh.material.set("shader_parameter/height_map", _height_map)
	translate(Vector3(size * grid_position.x, 0, size * grid_position.y))


shader_type spatial;
render_mode wireframe;
uniform sampler2D height_map;

void vertex() {
	VERTEX.y = texture(height_map, UV).r * 512.0;

void fragment() {
	ALBEDO = vec3(0.2, 0.7, 0.2);

Gonna do a blind wild guess and oracle this: You are subdividing by the size (128), which makes 128 cuts in your mesh, leaving you with 129 vertices on each dimension, thus the last vertices on the side just get an interpolated value between the heightmap and whatever the edge is beyond the texture side, or literally a value from wrapping around.

Thanks for correting my math error.

Unfortunately that doesn’t fix the issue.
I could subdivide by (size -1), by 10, by a 1000 - the result is exactly the same in all situations. Vectices at edges suddenly get very high or low values.

This idea got me curious. I looked again at my generated scene and I can say that in fact this could be wrapping around. Whenever chunk is sloped, the lower vertices always shoot upwards and higher ones shoot downwards. And the steeper the slope, the further they go (but not as high as highest vertices - around half of this height (which I guess makes sense if they are interpolating) )
But what’s causing this and how do I prevent it from happening?

Ok, that was it. Didn’t know reapeat was enabled by deafult. Quick google search helped me fix it.

uniform sampler2D height_map: repeat_disable;

Still there is a little problem. At edges of each chunk there is a little fall-off. No idea what’s causing it. I guess thats the only thing now preventing me from joining my chunks vertices.

Ok, I implemented a common pixel and it no longer occures between chunks.
(It still appears on the edges of the map, but in my project edges are not visible anyway)

Thank you @Efi for giving me a hint where to look.

(Sorry for lot’s of posts, my brain works this way ;/ )

1 Like

how did u do the common pixel @Kraker?

Sorry, I didn’t open the forum for some time.

When creating new chunk image, just make it one pixel bigger, but read them at the same coordinates so they can overlap with this one pixel. Dont make chunks mesh bigger, they dont need (and actually shouldn’t) overlap, because their vetices already touch each other. We just make sure they touch at the same height.

When making HeightMapShape3D, make it size + 1.

So heightmap image (size + 1), mesh just (size) and HeightMapShape3D (size + 1)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.