How to make natural procedural terrain?

Hello I’m trying to make a procedurally generated island. I would like to modify this code to make it look more natural. Now I don’t know if what I mean by natural is possible in Godot but what I’m trying to do is generate an island that looks like the one in Fortnite. I heard I needed some things called Rendering, Physics Server and Threading to make it look more natural but I’m unsure what those mean for procedural generation and if that’s actually what I’m looking for.

Here is my main code:

@tool
extends MeshInstance3D

@export var xSize = 20
@export var zSize = 20
@export var noise_offset = 0.5
@export var update = false
@export var clear_vert_vis = false

var min_height = 0
var max_height = 1

# Called when the node enters the scene tree for the first time.
func _ready():
	generate_terrain()

func generate_terrain():
	var a_mesh:ArrayMesh
	var surfTool = SurfaceTool.new()
	var n = FastNoiseLite.new()
	n.noise_type = FastNoiseLite.TYPE_PERLIN
	n.frequency = 0.1
	
	surfTool.begin(Mesh.PRIMITIVE_TRIANGLES)
	
	for z in range(zSize+1):
		for x in range(xSize+1):
			var y = n.get_noise_2d(x*noise_offset,z*noise_offset) * 5
			
			if y < min_height and y != null:
				min_height = y
			if y > min_height and y != null:
				max_height = y
			
			var uv = Vector2()
			uv.x = inverse_lerp(0,xSize,x)
			uv.y = inverse_lerp(0,xSize,z)
			surfTool.set_uv(uv)	
			surfTool.add_vertex(Vector3(x,y,z))
			#draw_sphere(Vector3(x,y,z))
	
	var vert = 0
	for z in zSize:
		for x in xSize:
			surfTool.add_index(vert+0)
			surfTool.add_index(vert+1)
			surfTool.add_index(vert+xSize+1)	
			surfTool.add_index(vert+xSize+1)
			surfTool.add_index(vert+1)
			surfTool.add_index(vert+xSize+2)
			vert+=1
		vert+=1
	surfTool.generate_normals()	
	a_mesh = surfTool.commit()
	mesh = a_mesh
	update_shader()
	
func update_shader():
	var mat = get_active_material(0)
	mat.set_shader_parameter("min_height", min_height)
	mat.set_shader_parameter("max_height", max_height)
	
func draw_sphere(pos:Vector3):
	var ins = MeshInstance3D.new()
	add_child(ins)
	ins.position = pos
	var sphere = SphereMesh.new()
	sphere.radius = 0.1
	sphere.height = 0.2
	ins.mesh = sphere

# Called every frame. 'delta' is the elapsed time since the previous frame.
func _process(delta):
	if update:
		generate_terrain()
		update = false
		
	if clear_vert_vis:
		for i in get_children():
			i.free()

Here is my shader code which you may or may not need:

shader_type spatial;

uniform sampler2D terrain_grass;
uniform sampler2D terrain_rock;
uniform float min_grass_height = -0.30;
uniform float max_rock_height = 1.6;
varying float vertex_y;
uniform vec2 uvscale = vec2(5);

void fragment() {
	float vert_weight = vertex_y;
	
	vec3 grass = texture(terrain_grass,UV*uvscale).rgb;
	vec3 rock = texture(terrain_rock,UV*uvscale).rgb;
	
	float weight = smoothstep(min_grass_height,max_rock_height, vert_weight);
	vec3 final_color = mix(grass,rock,weight);
	ALBEDO = final_color.rgb;
}

void vertex(){
	vertex_y = VERTEX.y;
}

I’d like to see an example of the result you’re getting to see what you mean when you say it doesn’t look natural. The code looks ok at a glance.
RenderingServer is for drawing primitives programatically, PhysicsServer is for physics stuff and Threading can be used for making generation faster, but you probably won’t need it. It is not mandatory.
None of those are mandatory for procgen and honestly, I’m not sure why anyone would say they are used in it without saying exactly how.


sorry i knew i was missing something

That already looks pretty good. You should add a “water” plane and increase the height of points that are closer to the middle of the map and you will get a more “island” feel. Simply figure out the center of the whole mesh (half of each dimension size) and for each point, get the distance to the middle and subtract some hieght the further the point is.
If you want it to look more like real mountains, that take a lot more work and there are very complex simulation to do that, but you can get close enough without that.