Glusoft

Make a terrain with perlin noise using FastNoiseLite

Result of the terrain generation using FastNoiseLite

Make a 2D texture with FastNoiseLite

The first thing to do is generate texture with perlin noise, to do that create a new project and add a Sprite2d node.
Then add a script to the root node too use the library FastNoiseLite to generate a texture with some noise on it:

extends Node2D

@onready var sprite = $Sprite

func _ready():
    var fast_noise_lite = FastNoiseLite.new();
    
    # Set noise parameters
    fast_noise_lite.noise_type = FastNoiseLite.TYPE_PERLIN
    fast_noise_lite.frequency = 0.02
    fast_noise_lite.fractal_type = FastNoiseLite.FRACTAL_FBM
    fast_noise_lite.fractal_octaves = 5
    
    # Set the size of the texture
    var texture_size = 1024

    # Generate the noise image
    var noise_image = fast_noise_lite.get_image(texture_size, texture_size)
    
    # Create a new ImageTexture and set the image
    var noise_texture = ImageTexture.create_from_image(noise_image)
    
    # Apply the texture to a sprite
    sprite.texture = noise_texture

Make a 3D terrain with MeshInstance and FastNoiseLite

Here is an example with MeshInstance to use the perlin noise, you can attach this script to a Node3D node.
For the child node pick a MeshInstance3D and also a Camera3D to have something like that:

Here is the script to add to the Node3D:

extends Node3D

@onready var mesh_instance = $MeshInstance

var width = 256
var depth = 256
var height = 50

func _ready():
    var fast_noise_lite = FastNoiseLite.new();
    
    # Set noise parameters
    fast_noise_lite.noise_type = FastNoiseLite.TYPE_PERLIN
    fast_noise_lite.frequency = 0.02
    fast_noise_lite.fractal_type = FastNoiseLite.FRACTAL_FBM
    fast_noise_lite.fractal_octaves = 5
    
    # Create a PlaneMesh and generate terrain
    var plane_mesh = PlaneMesh.new()
    plane_mesh.size = Vector2(width, depth)
    plane_mesh.subdivide_depth = width - 1
    plane_mesh.subdivide_width = depth - 1

    var array_mesh = ArrayMesh.new()
    array_mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, plane_mesh.surface_get_arrays(0))

    # Create SurfaceTool
    var surface_tool = SurfaceTool.new()
    surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES)

    # Generate vertices based on noise
    for z in range(depth):
        for x in range(width):
            var vertex_position = Vector3(x - width/2, 0, z - depth/2)
            vertex_position.y = fast_noise_lite.get_noise_2d(x, z) * height
            surface_tool.add_vertex(vertex_position)

    # Connect the vertices to form triangles
    for z in range(depth - 1):
        for x in range(width - 1):
            var idx = z * width + x
            surface_tool.add_index(idx)
            surface_tool.add_index(idx + 1)
            surface_tool.add_index(idx + width)
            
            surface_tool.add_index(idx + 1)
            surface_tool.add_index(idx + width + 1)
            surface_tool.add_index(idx + width)

    # Commit the mesh to the MeshInstance3D
    var generated_mesh = surface_tool.commit()
    mesh_instance.mesh = generated_mesh
    
    var light = DirectionalLight3D.new()
    light.position = Vector3(0, 300, 0)
    light.rotation_degrees = Vector3(45, 0, 45)  # Adjust the angle as needed
    light.light_energy = 1.5  # Adjust the intensity of the light
    light.shadow_enabled = true
    light.shadow_bias = 0.05 # Set shadow bias to reduce shadow artifacts like acne
    light.shadow_normal_bias = 0.3 # Adjust shadow normal bias to deal with self-shadowing issues
    light.shadow_blur = 0.3  # Adjust from 0 to 1, where 0 is sharp and 1 is very soft

    add_child(light)
    
    var environment = WorldEnvironment.new()
    var env_resource = Environment.new()
    env_resource.set_ambient_light_color(Color(0.5, 0.5, 0.5))
    env_resource.set_ambient_light_energy(0.5)  # Adjust for stronger or weaker ambient light
    environment.environment = env_resource
    add_child(environment)
    
    var material = StandardMaterial3D.new()
    material.albedo_color = Color(0.4, 0.8, 0.2)  # A greenish color for grass, for example
    material.roughness = 1.0  # Matte finish
    mesh_instance.material_override = material

You can then attach this script to the Camera3D, it will add some control to naviguate the terrain.

extends Camera3D

var speed = 10.0
var mouse_sensitivity = 0.1
var yaw = 0.0
var pitch = 0.0

func _ready():
    self.position = Vector3(0, 10, 100)
    self.look_at(Vector3(0, 0, 0), Vector3.UP)
    # Lock the mouse cursor to the center of the screen
    Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)

func _input(event):
    # Handle mouse motion for looking around
    if event is InputEventMouseMotion:
        yaw -= event.relative.x * mouse_sensitivity
        pitch -= event.relative.y * mouse_sensitivity
        pitch = clamp(pitch, -89, 89)
        rotation_degrees = Vector3(pitch, yaw, 0)
        
        # Exit the game if Escape is pressed
    if Input.is_action_pressed("escape"):
        get_tree().quit()

func _process(delta):
    var direction = Vector3()
    
    # Movement controls (WASD)
    if Input.is_action_pressed("ui_up"):
        direction -= transform.basis.z
    if Input.is_action_pressed("ui_down"):
        direction += transform.basis.z
    if Input.is_action_pressed("ui_left"):
        direction -= transform.basis.x
    if Input.is_action_pressed("ui_right"):
        direction += transform.basis.x

    # Normalize direction and apply movement
    if direction.length() > 0:
        direction = direction.normalized() * speed * delta
        translate(direction)

Full Project

You can download the full project: Node.7z