@tool class_name TerrainInstance3D extends GeometryInstance3D const _DETAIL := 2 const _SHADER := preload("res://terrain/terrain.gdshader") ## ## Slots representing the paintable channels. ## enum PaintSlot { ERASE, PAINT_1, PAINT_2, PAINT_3, } var _albedo_maps: Array[Texture2D] = [] var _material := ShaderMaterial.new() var _mesh := PlaneMesh.new() var _normal_maps: Array[Texture2D] = [] ## ## Range of the height channel value, ranging from [code]0.0[/code] to [code]100.0[/code]. ## @export var height_scale := 100.0: set(value): value = maxf(value, 1.0) if not(is_equal_approx(value, height_scale)): _material.set_shader_parameter("HEIGHT_SCALE", value) height_scale = value ## ## Size of the terrain geometry (in engine units). ## @export var size := Vector2i.ONE: set(value): value = Vector2i(maxi(value.x, 1), maxi(value.y, 1)) if (value.x != size.x) or (value.y != size.y): _mesh.subdivide_width = value.x * _DETAIL _mesh.subdivide_depth = value.y * _DETAIL _mesh.size = value _material.set_shader_parameter("SIZE", value) size = value func _init() -> void: var paint_channels := PaintSlot.values().size() _albedo_maps.resize(paint_channels) _normal_maps.resize(paint_channels) _material.shader = _SHADER _mesh.surface_set_material(0, _material) RenderingServer.instance_set_base(get_instance(), _mesh) ## ## Updates the terrain map being used by the terrain to be [code]terrain_map[/code]. ## func update_map(terrain_map: Texture2D) -> void: _material.set_shader_parameter("TERRAIN_MAP", terrain_map) ## ## Updates the [TerrainPaint] being used by the terrain in [code]paint_slot[/code] to be ## [code]terrain_paint[/code]. ## func update_paint(paint_slot: PaintSlot, terrain_paint: TerrainPaint) -> void: if _albedo_maps[paint_slot] != terrain_paint.albedo_map: _albedo_maps[paint_slot] = terrain_paint.albedo_map _material.set_shader_parameter("ALBEDO_MAPS", _albedo_maps) if _normal_maps[paint_slot] != terrain_paint.normal_map: _normal_maps[paint_slot] = terrain_paint.normal_map _material.set_shader_parameter("NORMAL_MAPS", _normal_maps)