Pesquisar este blog

gerador de terreno 3d godot

 @tool

extends MeshInstance3D


@export_category("Configurações do Terreno")

@export var terrain_size: Vector2 = Vector2(40, 40):

set(value):

terrain_size = value

_generate_terrain()


@export var subdivision: int = 40:

set(value):

subdivision = value

_generate_terrain()


@export var height_scale: float = 8.0:

set(value):

height_scale = value

_generate_terrain()


@export_category("Configurações do Ruído")

@export var noise_seed: int = 1337:

set(value):

noise_seed = value

noise.seed = value

_generate_terrain()


@export var noise_frequency: float = 0.04:

set(value):

noise_frequency = value

noise.frequency = value

_generate_terrain()


# Botão no Inspector para forçar a regeração e sortear uma semente nova

@export_tool_button("Gerar Novo Terreno (Random)")

var _btn_generate = func():

noise.seed = randi()

noise_seed = noise.seed

_generate_terrain()


@export_category("Texturas dos Biomas")

@export var texture_sand: Texture2D:

set(value):

texture_sand = value

_update_shader_parameters()


@export var texture_grass: Texture2D:

set(value):

texture_grass = value

_update_shader_parameters()


@export var texture_rock: Texture2D:

set(value):

texture_rock = value

_update_shader_parameters()


@export var texture_snow: Texture2D:

set(value):

texture_snow = value

_update_shader_parameters()


@export var texture_scale: float = 10.0:

set(value):

texture_scale = value

_update_shader_parameters()


var noise: FastNoiseLite = FastNoiseLite.new()


func _ready() -> void:

noise.noise_type = FastNoiseLite.TYPE_SIMPLEX

noise.seed = noise_seed

noise.frequency = noise_frequency

_generate_terrain()


func _generate_terrain() -> void:

var plane_mesh = PlaneMesh.new()

plane_mesh.size = terrain_size

plane_mesh.subdivide_width = subdivision

plane_mesh.subdivide_depth = subdivision


var st = SurfaceTool.new()

st.begin(Mesh.PRIMITIVE_TRIANGLES)

st.create_from(plane_mesh, 0)

var st_data = st.commit_to_arrays()

var mesh = ArrayMesh.new()

mesh.add_surface_from_arrays(Mesh.PRIMITIVE_TRIANGLES, st_data)

var mdt = MeshDataTool.new()

mdt.create_from_surface(mesh, 0)

for i in range(mdt.get_vertex_count()):

var vertex = mdt.get_vertex(i)

var n_val = noise.get_noise_2d(vertex.x, vertex.z)

vertex.y = n_val * height_scale

mdt.set_vertex(i, vertex)

mesh.clear_surfaces()

mdt.commit_to_surface(mesh)

self.mesh = mesh

_setup_terrain_shader()

print("Terreno atualizado!")


func _setup_terrain_shader() -> void:

var mat = self.material_override as ShaderMaterial

if not mat:

mat = ShaderMaterial.new()

var shader = Shader.new()

shader.code = """

shader_type spatial;

render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx;


uniform sampler2D tex_sand : source_color, filter_linear_mipmap;

uniform sampler2D tex_grass : source_color, filter_linear_mipmap;

uniform sampler2D tex_rock : source_color, filter_linear_mipmap;

uniform sampler2D tex_snow : source_color, filter_linear_mipmap;

uniform float uv_scale = 10.0;

uniform float max_height = 8.0;


varying float height_factor;


void vertex() {

height_factor = (VERTEX.y / max_height) * 0.5 + 0.5;

}


void fragment() {

vec2 base_uv = UV * uv_scale;

vec4 col_sand = texture(tex_sand, base_uv);

vec4 col_grass = texture(tex_grass, base_uv);

vec4 col_rock = texture(tex_rock, base_uv);

vec4 col_snow = texture(tex_snow, base_uv);

vec4 final_color = col_sand;

float blend1 = smoothstep(0.2, 0.35, height_factor);

final_color = mix(final_color, col_grass, blend1);

float blend2 = smoothstep(0.5, 0.65, height_factor);

final_color = mix(final_color, col_rock, blend2);

float blend3 = smoothstep(0.75, 0.85, height_factor);

final_color = mix(final_color, col_snow, blend3);

ALBEDO = final_color.rgb;

ROUGHNESS = 0.8;

}

"""

mat.shader = shader

self.material_override = mat

_update_shader_parameters()


func _update_shader_parameters() -> void:

var mat = self.material_override as ShaderMaterial

if not mat:

return

if texture_sand: mat.set_shader_parameter("tex_sand", texture_sand)

if texture_grass: mat.set_shader_parameter("tex_grass", texture_grass)

if texture_rock: mat.set_shader_parameter("tex_rock", texture_rock)

if texture_snow: mat.set_shader_parameter("tex_snow", texture_snow)

mat.set_shader_parameter("uv_scale", texture_scale)

mat.set_shader_parameter("max_height", height_scale)