game/terrain/terrain_instance_3d.gd

88 lines
2.1 KiB
GDScript

class_name TerrainInstance3D extends GeometryInstance3D
##
## Identifier constant for a paint slot channel.
##
enum PaintSlot {
ERASE,
RED,
GREEN,
BLUE,
}
const _DETAIL := 2
var _albedo_map_textures: Array[Texture2D] = [null, null, null, null]
var _material := ShaderMaterial.new()
var _normal_map_textures: Array[Texture2D] = [null, null, null, null]
var _mesh := PlaneMesh.new()
##
## The height scale range that is used to determine the minimums and maximums of the terrain map.
##
@export
var height_scale := 100.0:
get:
return height_scale
set(value):
_material.set_shader_parameter("MAX_HEIGHT", value)
height_scale = max(value, 0.0)
var _size := Vector2i.ZERO
func _init() -> void:
_material.shader = preload("res://terrain/terrain.gdshader")
RenderingServer.instance_set_base(get_instance(), _mesh)
_mesh.surface_set_material(0, _material)
##
## Returns the size of the terrain mesh (as in-engine units).
##
func get_size() -> Vector2i:
return _size
##
## Attempts to resize the terrain to be equal to [code]size[/code] (in-engine units), with
## [code]Vector2i.ONE[/code] as the minimum size.
##
func resize(size: Vector2i) -> void:
var width := maxi(size.x, 1)
var height := maxi(size.y, 1)
if (width != _size.x) or (height != _size.y):
_mesh.subdivide_width = width * _DETAIL
_mesh.subdivide_depth = height * _DETAIL
_mesh.size = size
_material.set_shader_parameter("SIZE", Vector2(size))
_size = size
##
## Updates the paint used by the paint channel identified by [code]paint_slot[/code] to
## [code]terrain_paint[/code].
##
func update_paint(paint_slot: PaintSlot, paint: TerrainPaint) -> void:
if paint == null:
_albedo_map_textures[paint_slot] = null
_normal_map_textures[paint_slot] = null
else:
_albedo_map_textures[paint_slot] = paint.albedo_map
_normal_map_textures[paint_slot] = paint.normal_map
_material.set_shader_parameter("ALBEDO_MAPS", _albedo_map_textures)
_material.set_shader_parameter("NORMAL_MAPS", _normal_map_textures)
##
## Updates the terrain map to [code]terrain_map[/code].
##
func update_terrain(terrain_map: Texture2D) -> void:
_material.set_shader_parameter("TERRAIN_MAP", terrain_map)