Could someone help me to figure it out what I'm doing wrong using Immediate Mesh to generate a mesh using a height map? They way I'm doing the quads are drawn separately

The script that I'm using to generate the mesh

@tool
extends MeshInstance3D

@onready var immediate_mesh := ImmediateMesh.new()
@onready var noise = FastNoiseLite.new()

@export var width = 32
@export var height = 32

var vertices := PackedVector3Array()

func _ready():
	create_mesh()

func create_mesh():
	immediate_mesh.clear_surfaces()
	
	for x in range(width):
		for y in range(height):
			create_quad(x, y)
	
	immediate_mesh.surface_begin(Mesh.PRIMITIVE_TRIANGLES)
	
	for v in vertices.size():
		immediate_mesh.surface_add_vertex(vertices[v])
		
	immediate_mesh.surface_end()
	
	self.set_mesh(immediate_mesh)

func create_quad(x, z):
	var y = noise.get_noise_2d(x, z) * 16
	var vert1
	var vert2
	var vert3
	
	#triangle 1
	vert1 = Vector3(x, y, z)
	vert2 = Vector3(x + 1, y, z)
	vert3 = Vector3(x + 1, y, z + 1)
	vertices.push_back(vert1)
	vertices.push_back(vert2)
	vertices.push_back(vert3)
	
	#triangle 2
	vert1 = Vector3(x, y, z)
	vert2 = Vector3(x + 1, y, z + 1)
	vert3 = Vector3(x, y, z + 1)
	vertices.push_back(vert1)
	vertices.push_back(vert2)
	vertices.push_back(vert3)

I try to use SurfaceTool as well, but I not knowing how to set up the vertices to use the height map with falloff map.
The script using SurfaceTool

@tool
extends MeshInstance3D

@export var width = 128
@export var height = 128
@export var amplitude = 2
@export var random_island := false
@export var seed = 717844
@export var noise := FastNoiseLite.new()
@export var texture_rect : TextureRect 

var height_data = {}

func _ready():
	if !random_island:
		noise.seed = seed
		
	generate_heightmap()
	generate_texture()
	generate_mesh()

func evaluate(value : float) -> float:
	var a = float(3)
	var b = float(2.2)
	
	return pow(value, a) / (pow(value, a) + pow(b - b * value, a))

func generate_heightmap() -> void:
	
	if (random_island):
		var rng = RandomNumberGenerator.new()
		noise.seed = rng.randi_range(0, 1000000)
		print(noise.seed)
	
	for x in range(height):
			for y in range (width):
				var xv = x / float(width) * 2 - 1;
				var yv = y / float(height) * 2 - 1;
				var value = maxf(absf(xv), absf(yv));
				var noise_value = noise.get_noise_2d(x,y)
				var height_value = (noise_value - evaluate(value)) * amplitude
				height_data[Vector2(x,y)] = clampf(height_value, 0, 1)

func generate_texture() -> void:	
	var image := Image.new()
	image = Image.create(width, height, false, Image.FORMAT_RGB8)
	
	var texture = ImageTexture.new()
	
	var black = Color(0, 0, 0, 1)
	var white = Color(1, 1, 1, 1)
	
	for y in height:
		for x in width:
			image.set_pixel(x, y, black.lerp(white, height_data[Vector2(x,y)]))
	
	texture = texture.create_from_image(image)
	
	texture_rect.texture = texture

func generate_mesh() -> void:
	var plane_mesh = PlaneMesh.new()
	plane_mesh.size = Vector2(width,height)
	plane_mesh.subdivide_depth = width - 1
	plane_mesh.subdivide_width = height - 1
	
	var surface_tool = SurfaceTool.new()
	surface_tool.create_from(plane_mesh,0)
	
	var data = surface_tool.commit_to_arrays()
	var vertices = data[ArrayMesh.ARRAY_VERTEX]
	
	for z in height:
		for x in width:
			var indice = z * width + x
			#var vertex = vertices[indice]
			vertices[indice].y = height_data[Vector2(x,z)]
			vertices[indice + 1].y = height_data[Vector2(x,z)]
			vertices[indice + 2].y = height_data[Vector2(x,z)]
			
			vertices[indice].y = height_data[Vector2(x,z)]
			vertices[indice + 2].y = height_data[Vector2(x,z)]
			vertices[indice + 3].y = height_data[Vector2(x,z)]
	
	data[ArrayMesh.ARRAY_VERTEX] = vertices
		
	var array_mesh = ArrayMesh.new()
	array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES,data)
	
	surface_tool.create_from(array_mesh,0)
	surface_tool.generate_normals()

	mesh = surface_tool.commit()
  • You used the same y value for all 4 quad vertices. You should sample 4 adjacent values from the noise texture instead.

You used the same y value for all 4 quad vertices. You should sample 4 adjacent values from the noise texture instead.

    xyz Oh boy! I can't believe this it was under my nose all this time, thank you so much!