How to make infnite voxel generation in this gd script like minecraft?

Godot Version

4.5.1

Question

I want to make an infinite terrain that it never ends. This is the actual code which needs correction:

extends Node3D

# --- AJUSTES ---
const AREA = 500 # 150x150 = 22,500 columnas (Equivale a millones de bloques de tu script anterior)
var velocidad = 5.0
var sensibilidad = 0.001
var camara : Camera3D 

var yaw = 0.0
var pitch = 0.0

var amplitud = 200.0   # Ajusta esto para la altura máxima
var frecuencia = 0.005 # Menor valor = terreno más estirado horizontalmente
var noise = FastNoiseLite.new()

func _ready():
	# 1. ESTO EVITA QUE EL NARANJA SEA MARRÓN:
	# Forzamos al motor a usar el espacio de color sRGB (Colores vivos)
	# y no el Lineal (Colores realistas/apagados).
	ProjectSettings.set_setting("rendering/textures/canvas_textures/default_texture_filter", 0)
	
	# 2. EL TRUCO "FULL BRIGHT" EN EL READY:
	# Esto hace que la luz ambiental no tenga dirección y no cree sombras sucias.
	var scenario = get_world_3d().scenario
	RenderingServer.scenario_set_fallback_environment(scenario, get_viewport().world_3d.fallback_environment)
	
	# 3. LO QUE BUSCAS DE LOS COLORES:
	# Si usas colores hexadecimales o Color.ORANGE, Godot los oscurece.
	# Esta línea le dice al renderizador que no aplique corrección gamma.
	OS.set_environment("GODOT_SRGB_COLORSPACE_CHECK", "0") 
	
	# Cámara y captura
	camara = Camera3D.new()
	add_child(camara)
	camara.make_current()
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	# 1. Seguridad: Esperar un frame para que el motor inicialice
	await get_tree().process_frame
	
	setup_lighting_and_env()
	generar_mundo_seguro()
	
	# Cámara
	camara = Camera3D.new()
	add_child(camara)
	camara.make_current()
	camara.position = Vector3(AREA/2, 100, AREA/2)
	Input.mouse_mode = Input.MOUSE_MODE_CAPTURED

func _unhandled_input(event):
	# Captura/Liberación de mouse
	if event is InputEventKey and event.pressed and event.keycode == KEY_ESCAPE:
		if Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
			Input.mouse_mode = Input.MOUSE_MODE_VISIBLE
		else:
			Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
	if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
		# Actualizamos los ángulos basados en el movimiento del ratón
		# Invertimos el signo aquí para cambiar la dirección de rotación
		yaw -= event.relative.x * sensibilidad 
		pitch -= event.relative.y * sensibilidad
		
		# Limitamos el ángulo vertical para no dar la vuelta
		pitch = clamp(pitch, deg_to_rad(-89), deg_to_rad(89))

func _process(delta):
	if not camara: return
	# Así es como debe ir dentro del _process:
	camara.position.y = int(2+(noise.get_noise_2d(camara.position.x, camara.position.z) + 1.0) * 0.5 * amplitud) 
	
	# 1. DIRECCIÓN DE LA MIRADA (Seno y Coseno)
	var direccion_mirada = Vector3(
		sin(yaw) * cos(pitch),
		sin(pitch),
		cos(yaw) * cos(pitch)
	)
	
	# 2. APLICAR LOOK_AT
	# Importante: Miramos hacia adelante (sumando la dirección a la posición actual)
	camara.look_at(camara.global_position + direccion_mirada, Vector3.UP)

	# 3. MOVIMIENTO
	var movimiento = Vector3.ZERO
	
	# Calculamos 'adelante' basado solo en el giro horizontal (yaw)
	# Nota: En Godot -Z es hacia adelante, por eso usamos los signos así:
	var adelante = Vector3(sin(yaw), 0, cos(yaw)) 
	var derecha = Vector3(sin(yaw + PI/2), 0, cos(yaw + PI/2))
	
	
	if Input.is_key_pressed(KEY_W): movimiento += adelante # Ir hacia adelante
	if Input.is_key_pressed(KEY_S): movimiento -= adelante # Ir hacia atrás
	if Input.is_key_pressed(KEY_A): movimiento += derecha  # Ir izquierda
	if Input.is_key_pressed(KEY_D): movimiento -= derecha  # Ir derecha
	# 4. APLICAR MOVIMIENTO AL NODO PRINCIPAL
	if movimiento != Vector3.ZERO:
		camara.position += movimiento.normalized() * velocidad * delta

# --- GENERACIÓN ROBUSTA ---
func generar_mundo_seguro():
	noise.seed = randi()
	noise.frequency = 0.01
	
	var mm_instance = MultiMeshInstance3D.new()
	var mm = MultiMesh.new()
	
	# Configuración obligatoria antes de asignar el count
	mm.transform_format = MultiMesh.TRANSFORM_3D
	mm.use_colors = true 
	mm.mesh = BoxMesh.new()
	
	# Importante: El count debe ser exacto
	mm.instance_count = AREA * AREA
	
	# Material con protección por si no tienes la textura "dirt.jpg"
	var mat = StandardMaterial3D.new()
	if FileAccess.file_exists("res://dirt.jpg"):
		mat.albedo_texture = load("res://dirt.jpg")
	else:
		# Color base si falla la textura para evitar el crash de carga
		mat.albedo_color = Color(0.4, 0.3, 0.2)
		
	mat.vertex_color_use_as_albedo = true
	mat.uv1_triplanar = true
	mat.uv1_world_triplanar = true
	mat.texture_filter = BaseMaterial3D.TEXTURE_FILTER_NEAREST
	mm.mesh.material = mat
	
	mm_instance.multimesh = mm
	add_child(mm_instance)
	
	var i = 0
	for x in range(AREA):
		for z in range(AREA):
			noise.frequency = frecuencia 
			# Esta es la función optimizada:
			var h = int((noise.get_noise_2d(x, z) + 1.0) * 0.5 * amplitud)
			
			# Creamos la transformación: Escala en Y = Altura, Posición Y = Altura/2
			var t = Transform3D()
			t = t.scaled(Vector3(1, h, 1))
			t.origin = Vector3(float(x), h / 2.0, float(z))
			
			mm.set_instance_transform(i, t)
			mm.set_instance_color(i, _get_color(h))
			i += 1

func _get_color(y):
	if y > 75: return Color(0.4, 0.3, 0.2) # Piedra
	return Color(0.9, 0.5, 0.0) # Arena.

# --- ILUMINACIÓN ---
func setup_lighting_and_env():
	# 1. LUZ (Sol)
	var sol = DirectionalLight3D.new()
	sol.shadow_enabled = true
	sol.rotation_degrees = Vector3(-45, 0, -45) 
	add_child(sol)
	
	# 2. MATERIAL DEL CIELO (Procedural)
	var sky_material = ProceduralSkyMaterial.new()
	# Colores exactos para el degradado horizontal
	sky_material.sky_top_color = Color(0.0, 0.498, 1.0, 1.0) 
	sky_material.sky_horizon_color = Color(0.0, 1.0, 1.0, 1.0)
	sky_material.ground_bottom_color = Color(0.2, 0.17, 0.15)
	sky_material.ground_horizon_color = Color(0.65, 0.72, 0.81) # Igual al horizonte del cielo
	
	# Creamos el temporizador
	var timer_sol = Timer.new()
	add_child(timer_sol)
	timer_sol.wait_time = 0.1  # Se ejecuta cada 0.1 segundos
	timer_sol.autostart = true
	# Conectamos el timer a la rotación
	timer_sol.timeout.connect(func():
		if sol:
			sol.light_color = Color(2.0, 2.0, 2.0)
			# Rotamos 0.5 grados en cada intervalo
			sol.rotate_x(deg_to_rad(0.01))
			sol.rotate_z(deg_to_rad(0.01))
			# ESTO TE DIRÁ EN LA CONSOLA SI ESTÁ ROTANDO O NO
			print("SOL ROTANDO: ", sol.rotation_degrees.x)
			# 2. Calcular "Factor de Luz" (0.0 es noche total, 1.0 es mediodía)
			# Usamos el seno de la rotación para saber qué tan arriba está el sol
			var angulo_rad = sol.rotation.x
			var factor_luz = clamp(-sin(angulo_rad), 0.0, 1.0)
			
			# 3. Aplicar oscuridad a los colores originales
			# Multiplicamos el color por el factor_luz para que se apague en la noche
			var color_top_base = Color(0.0, 0.498, 1.0)
			var color_hor_base = Color(0.0, 1.0, 1.0)
			
			sky_material.sky_top_color = color_top_base * factor_luz
			sky_material.sky_horizon_color = color_hor_base * factor_luz
			
			# Opcional: El suelo también debe oscurecerse
			sky_material.ground_horizon_color = sky_material.sky_horizon_color
			
			# 4. Ajustar la energía de la luz para que no haya sombras de noche
			sol.light_energy = factor_luz
	)
	
	timer_sol.start()
	
	# 3. CONFIGURACIÓN DEL ENTORNO
	var sky_res = Sky.new()
	sky_res.sky_material = sky_material
	
	var env_res = Environment.new()
	env_res.background_mode = Environment.BG_SKY
	env_res.sky = sky_res
	
	# Iluminación indirecta para que las sombras no sean negras
	env_res.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
	env_res.ambient_light_sky_contribution = 0.5
	env_res.ambient_light_color = Color(1.0, 1.0, 1.0)
	
	var env_node = WorldEnvironment.new()
	env_node.environment = env_res
	add_child(env_node)

So… its possible? Thanks anyway!

It is but it takes quite a bit more than a mere “correction” of a script.

1 Like

Ok… then… idk what to say…
EDIT1:
After compiling this thing it sees like this:

As the player moves you would generate more terrain using the player’s position in addition to this x and z.

Did you write this code? When asking for help it’s important to be brief, lowering the mental load of other by sharing what you’ve tried and where you think the problem lies exactly in code, rather than pasting everything with a short description of your wants.

2 Likes

Yes, i tried with a timer but the results are wrong… im trying it again soon as i can.
And… yes… i used google gemini to write that lines of codes…

Why don’t you ask it to write the rest of what you want?

You want to check the distance to the 9 neighbors center and generate a neighbors if you get close to it.
Also you can use @tool and the editor camera so you dont have to launch the game everytime

Becuase it never writes the code completely, only writes the begining…
and… with it appears me without the terrain texture when i compile it???

I preffer to delete & regenerate terrain…
and… with it appears me without the terrain texture when i compile it???

(i cant delete this post)

Maybe you need to prompt it better.

What the method?

EDIT 1: I reached the texture exportation with the game:

Why guess when we can go directly to the ground truth. In this seminal 2025 tweet whitepaper, the vibe coding inventor and lead expert dr. Karpathy describes it with utmost clarity:

Let me summarize what the highest authority says here - you need to:

  • :gear: fully give in to the vibes
  • :rocket: embrace the exponentials
  • :poultry_leg: forget that the code even exists
  • :light_bulb: barely touch the keyboard
  • :white_check_mark: ask for the dumbest things
  • :hamburger: see stuff, say stuff, run stuff and copy-paste stuff

That’s it. Easy peasy. Judging from the results you’ve got so far, you’re already 80% to the finish line. Just follow these expert instructions to push through the last 20%

If you have any doubts, rest assured that the joint GAMMOX headquarters already debunked each and every conspiracy theory that claimed that dr. K. was high when tweeting writing the above shown foundational scripture of vibe coding.

Smallprint: Doing what you’re trying to do using an LLM is a fool’s errand. Complete a Minecraft terrain video tutorial instead. There’s bajillion of them on Youtube.

2 Likes


I have this terrain now…
But… how to make it infinite???