Merge pull request 'Editor Terrain Brush' (#2) from editor-terrain-brush into main
Reviewed-on: #2
This commit is contained in:
commit
e72698ffcd
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cj72ibo3c6x8e"
|
||||||
|
path="res://.godot/imported/black.png-19a8df0b1a4edb74ea2eecb66d46d03d.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://black.png"
|
||||||
|
dest_files=["res://.godot/imported/black.png-19a8df0b1a4edb74ea2eecb66d46d03d.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
BIN
editor.scn (Stored with Git LFS)
BIN
editor.scn (Stored with Git LFS)
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="image"
|
||||||
|
type="Image"
|
||||||
|
uid="uid://drok88h02tdre"
|
||||||
|
path="res://.godot/imported/brush_hard_circle_mask.png-e647df7b970f00cdf2f3f2ac38ad8257.image"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://editor/brush_hard_circle_mask.png"
|
||||||
|
dest_files=["res://.godot/imported/brush_hard_circle_mask.png-e647df7b970f00cdf2f3f2ac38ad8257.image"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
Binary file not shown.
|
@ -0,0 +1,14 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="image"
|
||||||
|
type="Image"
|
||||||
|
uid="uid://bbdh4btpg08do"
|
||||||
|
path="res://.godot/imported/brush_soft_circle_mask.png-5af527bedd556c2d7ed38b029e34527e.image"
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://editor/brush_soft_circle_mask.png"
|
||||||
|
dest_files=["res://.godot/imported/brush_soft_circle_mask.png-5af527bedd556c2d7ed38b029e34527e.image"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
BIN
editor_theme.res (Stored with Git LFS)
BIN
editor_theme.res (Stored with Git LFS)
Binary file not shown.
|
@ -72,6 +72,7 @@ var movement_smoothing := 0.5
|
||||||
##
|
##
|
||||||
## Whether or not player movement input processed by the controller should be ignored.
|
## Whether or not player movement input processed by the controller should be ignored.
|
||||||
##
|
##
|
||||||
|
@export
|
||||||
var frozen := false
|
var frozen := false
|
||||||
|
|
||||||
func _input(event: InputEvent) -> void:
|
func _input(event: InputEvent) -> void:
|
||||||
|
|
|
@ -9,6 +9,16 @@
|
||||||
config_version=5
|
config_version=5
|
||||||
|
|
||||||
_global_script_classes=[{
|
_global_script_classes=[{
|
||||||
|
"base": "TerrainInstance3D",
|
||||||
|
"class": &"DynamicTerrainInstance3D",
|
||||||
|
"language": &"GDScript",
|
||||||
|
"path": "res://terrain/dynamic_terrain_instance_3d.gd"
|
||||||
|
}, {
|
||||||
|
"base": "HFlowContainer",
|
||||||
|
"class": &"ItemSelection",
|
||||||
|
"language": &"GDScript",
|
||||||
|
"path": "res://user_interface/button_selection.gd"
|
||||||
|
}, {
|
||||||
"base": "Node3D",
|
"base": "Node3D",
|
||||||
"class": &"PlayerController",
|
"class": &"PlayerController",
|
||||||
"language": &"GDScript",
|
"language": &"GDScript",
|
||||||
|
@ -22,18 +32,27 @@ _global_script_classes=[{
|
||||||
"base": "GeometryInstance3D",
|
"base": "GeometryInstance3D",
|
||||||
"class": &"TerrainInstance3D",
|
"class": &"TerrainInstance3D",
|
||||||
"language": &"GDScript",
|
"language": &"GDScript",
|
||||||
"path": "res://terrain_instance_3d.gd"
|
"path": "res://terrain/terrain_instance_3d.gd"
|
||||||
|
}, {
|
||||||
|
"base": "Resource",
|
||||||
|
"class": &"TerrainPaint",
|
||||||
|
"language": &"GDScript",
|
||||||
|
"path": "res://terrain/paints/terrain_paint.gd"
|
||||||
}]
|
}]
|
||||||
_global_script_class_icons={
|
_global_script_class_icons={
|
||||||
|
"DynamicTerrainInstance3D": "",
|
||||||
|
"ItemSelection": "",
|
||||||
"PlayerController": "",
|
"PlayerController": "",
|
||||||
"Settings": "",
|
"Settings": "",
|
||||||
"TerrainInstance3D": ""
|
"TerrainInstance3D": "",
|
||||||
|
"TerrainPaint": ""
|
||||||
}
|
}
|
||||||
|
|
||||||
[application]
|
[application]
|
||||||
|
|
||||||
config/name="Protectorate"
|
config/name="Protectorate"
|
||||||
run/main_scene="res://editor.scn"
|
run/main_scene="res://editor.scn"
|
||||||
|
config/use_custom_user_dir=true
|
||||||
config/features=PackedStringArray("4.0", "Forward Plus")
|
config/features=PackedStringArray("4.0", "Forward Plus")
|
||||||
config/icon="res://icon.png"
|
config/icon="res://icon.png"
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
class_name DynamicTerrainInstance3D extends TerrainInstance3D
|
||||||
|
|
||||||
|
##
|
||||||
|
## Blank sample value.
|
||||||
|
##
|
||||||
|
const BLANK := Color(0.0, 0.0, 0.0, 0.0)
|
||||||
|
|
||||||
|
var _editable_image: Image
|
||||||
|
|
||||||
|
var _editable_texture: ImageTexture
|
||||||
|
|
||||||
|
func _get_brush_area(point: Vector2i, mask_size: Vector2i, mask_scale: float) -> Rect2i:
|
||||||
|
# Convert worldspace point to image-space coordinates for mask.
|
||||||
|
var scaled_mask_size := Vector2i(mask_size * mask_scale)
|
||||||
|
|
||||||
|
return Rect2i((point + Vector2i(get_size() * 0.5)) - Vector2i(scaled_mask_size * 0.5), scaled_mask_size)
|
||||||
|
|
||||||
|
func _init() -> void:
|
||||||
|
super._init()
|
||||||
|
|
||||||
|
_editable_image = Image.create(1, 1, false, Image.FORMAT_RGBAF)
|
||||||
|
_editable_texture = ImageTexture.create_from_image(_editable_image)
|
||||||
|
|
||||||
|
super.resize(Vector2i.ONE)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Clears the terrain map to the value of [code]clear_elevation[/code].
|
||||||
|
##
|
||||||
|
func clear(clear_elevation: float) -> void:
|
||||||
|
_editable_image.fill(Color(0.0, 0.0, 0.0, clampf(clear_elevation, 0.0, 1.0)))
|
||||||
|
_editable_texture.update(_editable_image)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Oscillates the height of terrain toward a value of [member height_scale] (multiplied by
|
||||||
|
## [code]level[/code]) around the area of [code]point[/code] determined by [code]mask[/code]
|
||||||
|
## multiplied by [code]mask_scale[/code] at a rate of [code]intensity[/code].
|
||||||
|
##
|
||||||
|
func oscillate(point: Vector2i, level: float, mask: Image, mask_scale: float, intensity: float) -> void:
|
||||||
|
var mask_size := mask.get_size()
|
||||||
|
var brush_source := _get_brush_area(point, mask_size, mask_scale)
|
||||||
|
|
||||||
|
if brush_source.has_area():
|
||||||
|
var brush_target := Rect2i(Vector2i.ZERO, get_size()).intersection(brush_source)
|
||||||
|
|
||||||
|
if brush_target.has_area():
|
||||||
|
var mask_ratio := mask_size / brush_source.size
|
||||||
|
var offset := brush_target.position - brush_source.position
|
||||||
|
|
||||||
|
for y in brush_target.size.y:
|
||||||
|
var mask_y := int((offset.y + y) * mask_ratio.y)
|
||||||
|
|
||||||
|
for x in brush_target.size.x:
|
||||||
|
var coord := brush_target.position + Vector2i(x, y)
|
||||||
|
var pixel := _editable_image.get_pixelv(coord)
|
||||||
|
|
||||||
|
_editable_image.set_pixelv(coord, Color(pixel.r, pixel.g, pixel.b,
|
||||||
|
lerpf(pixel.a, level, intensity *\
|
||||||
|
mask.get_pixel(int((offset.x + x) * mask_ratio.x), mask_y).a)).clamp())
|
||||||
|
|
||||||
|
_editable_texture.update(_editable_image)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Paints the texture of the terrain toward a value of [code]color[/code] multiplied by
|
||||||
|
## [code]intensity[/code] around the area of [code]point[/code] determined by [code]mask[/code]
|
||||||
|
## multiplied by [code]mask_scale[/code] at a rate of [code]intensity[/code].
|
||||||
|
##
|
||||||
|
func paint(point: Vector2i, color: Color, mask: Image, mask_scale: float, intensity: float) -> void:
|
||||||
|
var mask_size := mask.get_size()
|
||||||
|
var brush_source := _get_brush_area(point, mask_size, mask_scale)
|
||||||
|
|
||||||
|
if brush_source.has_area():
|
||||||
|
var brush_target := Rect2i(Vector2i.ZERO, get_size()).intersection(brush_source)
|
||||||
|
|
||||||
|
if brush_target.has_area():
|
||||||
|
var mask_ratio := mask_size / brush_source.size
|
||||||
|
var offset := brush_target.position - brush_source.position
|
||||||
|
|
||||||
|
for y in brush_target.size.y:
|
||||||
|
var mask_y := int((offset.y + y) * mask_ratio.y)
|
||||||
|
|
||||||
|
for x in brush_target.size.x:
|
||||||
|
var coord := brush_target.position + Vector2i(x, y)
|
||||||
|
var pixel := _editable_image.get_pixelv(coord)
|
||||||
|
|
||||||
|
var mask_intensity_delta := intensity *\
|
||||||
|
mask.get_pixel(int((offset.x + x) * mask_ratio.x), mask_y).a
|
||||||
|
|
||||||
|
_editable_image.set_pixelv(coord, Color(
|
||||||
|
lerpf(pixel.r, color.r, mask_intensity_delta),
|
||||||
|
lerpf(pixel.g, color.g, mask_intensity_delta),
|
||||||
|
lerpf(pixel.b, color.b, mask_intensity_delta), pixel.a).clamp())
|
||||||
|
|
||||||
|
_editable_texture.update(_editable_image)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Attempts to resize the terrain geometry and map to be equal to [code]size[/code] (in-engine
|
||||||
|
## units), with [code]Vector2i.ONE[/code] as the minimum size.
|
||||||
|
##
|
||||||
|
## In the process of growing the terrain map, existing edge data will be copied to fill it out.
|
||||||
|
##
|
||||||
|
func resize(size: Vector2i) -> void:
|
||||||
|
super.resize(size)
|
||||||
|
|
||||||
|
var actual_size := get_size()
|
||||||
|
|
||||||
|
_editable_image.resize(actual_size.x, actual_size.y)
|
||||||
|
|
||||||
|
_editable_texture = ImageTexture.create_from_image(_editable_image)
|
||||||
|
|
||||||
|
update_terrain(_editable_texture)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Samples the color value in the editable terrain at the worldspace [code]point[/code], returning
|
||||||
|
## its respective [Color] value.
|
||||||
|
##
|
||||||
|
## For sample coordinates outside of the terrain map worldspace, [code]BLANK[/code] is returned
|
||||||
|
## instead.
|
||||||
|
##
|
||||||
|
func sample(point: Vector2i) -> Color:
|
||||||
|
var size := get_size()
|
||||||
|
var image_point := point + Vector2i(size * 0.5)
|
||||||
|
|
||||||
|
if Rect2i(Vector2i.ZERO, size).has_point(image_point):
|
||||||
|
return _editable_image.get_pixelv(image_point)
|
||||||
|
|
||||||
|
return BLANK
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://jcmf7j3qo6ea"
|
||||||
|
path="res://.godot/imported/arid_grass_albedo.png-532bc188063dc524e2c08228bed13fa7.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/arid_grass_albedo.png"
|
||||||
|
dest_files=["res://.godot/imported/arid_grass_albedo.png-532bc188063dc524e2c08228bed13fa7.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://co0jompch208v"
|
||||||
|
path="res://.godot/imported/arid_grass_displacement.png-cad938b62195c0b0f41099d596594b8b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/arid_grass_displacement.png"
|
||||||
|
dest_files=["res://.godot/imported/arid_grass_displacement.png-cad938b62195c0b0f41099d596594b8b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bh141jkgbmya8"
|
||||||
|
path="res://.godot/imported/arid_grass_normal.png-7bf9fdf5f927fea47a2f86a9ffab326e.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/arid_grass_normal.png"
|
||||||
|
dest_files=["res://.godot/imported/arid_grass_normal.png-7bf9fdf5f927fea47a2f86a9ffab326e.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://jdq8kwjo3uap"
|
||||||
|
path="res://.godot/imported/arid_grass_roughness.png-40299cbb0e24b392d013d45af79f5444.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/arid_grass_roughness.png"
|
||||||
|
dest_files=["res://.godot/imported/arid_grass_roughness.png-40299cbb0e24b392d013d45af79f5444.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://cs06oiwrord6t"
|
||||||
|
path="res://.godot/imported/cobblestone_albedo.png-f0ce6b9d25b0c6c4130e70ff660bcbd6.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/cobblestone_albedo.png"
|
||||||
|
dest_files=["res://.godot/imported/cobblestone_albedo.png-f0ce6b9d25b0c6c4130e70ff660bcbd6.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://mkxbjfwdwkaq"
|
||||||
|
path="res://.godot/imported/cobblestone_displacement.png-bcf2e2194862b85cb002d9559d57903b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/cobblestone_displacement.png"
|
||||||
|
dest_files=["res://.godot/imported/cobblestone_displacement.png-bcf2e2194862b85cb002d9559d57903b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://ukk0161x3eg2"
|
||||||
|
path="res://.godot/imported/cobblestone_normal.png-5130e667fa81f7452d15808908f4cb99.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/cobblestone_normal.png"
|
||||||
|
dest_files=["res://.godot/imported/cobblestone_normal.png-5130e667fa81f7452d15808908f4cb99.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bcybapft8tl2x"
|
||||||
|
path="res://.godot/imported/cobblestone_roughness.png-2f09da1d7000b898b80d7b177062e509.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/cobblestone_roughness.png"
|
||||||
|
dest_files=["res://.godot/imported/cobblestone_roughness.png-2f09da1d7000b898b80d7b177062e509.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -3,8 +3,8 @@
|
||||||
importer="texture"
|
importer="texture"
|
||||||
type="CompressedTexture2D"
|
type="CompressedTexture2D"
|
||||||
uid="uid://bgpk15qrqxly8"
|
uid="uid://bgpk15qrqxly8"
|
||||||
path.s3tc="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex"
|
path.s3tc="res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.s3tc.ctex"
|
||||||
path.etc2="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex"
|
path.etc2="res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.etc2.ctex"
|
||||||
metadata={
|
metadata={
|
||||||
"imported_formats": ["s3tc", "etc2"],
|
"imported_formats": ["s3tc", "etc2"],
|
||||||
"vram_texture": true
|
"vram_texture": true
|
||||||
|
@ -12,8 +12,8 @@ metadata={
|
||||||
|
|
||||||
[deps]
|
[deps]
|
||||||
|
|
||||||
source_file="res://prototype_tiles_large_albedo.png"
|
source_file="res://terrain/paints/default_albedo.png"
|
||||||
dest_files=["res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex", "res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex"]
|
dest_files=["res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.s3tc.ctex", "res://.godot/imported/default_albedo.png-ec7b9bee606a4c8482c5f21d50eaafb2.etc2.ctex"]
|
||||||
|
|
||||||
[params]
|
[params]
|
||||||
|
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://b8cv4q43fsglu"
|
||||||
|
path="res://.godot/imported/desert_sand_albedo.png-1f8394c37b6df0b83ddc4964049fe1fb.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/desert_sand_albedo.png"
|
||||||
|
dest_files=["res://.godot/imported/desert_sand_albedo.png-1f8394c37b6df0b83ddc4964049fe1fb.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bdacir1igfinb"
|
||||||
|
path="res://.godot/imported/desert_sand_displacement.png-de6822961a581feed0d45f5f34fbb048.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/desert_sand_displacement.png"
|
||||||
|
dest_files=["res://.godot/imported/desert_sand_displacement.png-de6822961a581feed0d45f5f34fbb048.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c40cc5b5sq4yu"
|
||||||
|
path="res://.godot/imported/desert_sand_normal.png-4882d77c1942a502a8d07cd8761a392c.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/desert_sand_normal.png"
|
||||||
|
dest_files=["res://.godot/imported/desert_sand_normal.png-4882d77c1942a502a8d07cd8761a392c.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bwkcsnjetn5wr"
|
||||||
|
path="res://.godot/imported/desert_sand_roughness.png-0c32daf878e9b29d36631441877f21ac.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/desert_sand_roughness.png"
|
||||||
|
dest_files=["res://.godot/imported/desert_sand_roughness.png-0c32daf878e9b29d36631441877f21ac.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://eqbk8dx3px02"
|
||||||
|
path="res://.godot/imported/dry_mud_albedo.png-6844f23cea910070ff2cf0d2e02e4e06.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/dry_mud_albedo.png"
|
||||||
|
dest_files=["res://.godot/imported/dry_mud_albedo.png-6844f23cea910070ff2cf0d2e02e4e06.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://bwqtubithbfsy"
|
||||||
|
path="res://.godot/imported/dry_mud_displacement.png-84ac0ae4e00848577ccfe89d2c4787e8.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/dry_mud_displacement.png"
|
||||||
|
dest_files=["res://.godot/imported/dry_mud_displacement.png-84ac0ae4e00848577ccfe89d2c4787e8.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://c86r5niid1hp1"
|
||||||
|
path="res://.godot/imported/dry_mud_normal.png-6211d1992b291d2e0174ec9de201218d.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/dry_mud_normal.png"
|
||||||
|
dest_files=["res://.godot/imported/dry_mud_normal.png-6211d1992b291d2e0174ec9de201218d.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://7xnkstxa6q65"
|
||||||
|
path="res://.godot/imported/dry_mud_roughness.png-35dfe15111e09484a06efd2f6e55b73b.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://terrain/paints/dry_mud_roughness.png"
|
||||||
|
dest_files=["res://.godot/imported/dry_mud_roughness.png-35dfe15111e09484a06efd2f6e55b73b.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Binary file not shown.
|
@ -0,0 +1,13 @@
|
||||||
|
class_name TerrainPaint extends Resource
|
||||||
|
|
||||||
|
##
|
||||||
|
## Terrain albedo map data.
|
||||||
|
##
|
||||||
|
@export
|
||||||
|
var albedo_map: Texture2D = null
|
||||||
|
|
||||||
|
##
|
||||||
|
## Terrain normal map data.
|
||||||
|
##
|
||||||
|
@export
|
||||||
|
var normal_map: Texture2D = null
|
|
@ -0,0 +1,57 @@
|
||||||
|
shader_type spatial;
|
||||||
|
|
||||||
|
const int MAP_COUNT = 4;
|
||||||
|
|
||||||
|
uniform sampler2D[MAP_COUNT] ALBEDO_MAPS;
|
||||||
|
|
||||||
|
uniform float MAX_HEIGHT = 100.0;
|
||||||
|
|
||||||
|
uniform sampler2D[MAP_COUNT] NORMAL_MAPS;
|
||||||
|
|
||||||
|
uniform vec2 SIZE;
|
||||||
|
|
||||||
|
uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
vec2 uv = UV * (SIZE / 2.0);
|
||||||
|
vec2 uv_alt = uv * -0.5;
|
||||||
|
vec3 splat_map = texture(TERRAIN_MAP, UV).rgb;
|
||||||
|
float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0);
|
||||||
|
|
||||||
|
ALBEDO = blank * 0.5 * (texture(ALBEDO_MAPS[0], uv).rgb + texture(ALBEDO_MAPS[0], uv_alt).rgb);
|
||||||
|
|
||||||
|
for (int i = 0; i < (MAP_COUNT - 1); i += 1) {
|
||||||
|
int map_index = i + 1;
|
||||||
|
|
||||||
|
ALBEDO += splat_map[i] * 0.5 * (texture(ALBEDO_MAPS[map_index], uv).rgb +
|
||||||
|
texture(ALBEDO_MAPS[map_index], uv_alt).rgb);
|
||||||
|
}
|
||||||
|
|
||||||
|
NORMAL_MAP = blank * 0.5 *
|
||||||
|
(texture(NORMAL_MAPS[0], uv).rgb + texture(NORMAL_MAPS[0], uv_alt).rgb);
|
||||||
|
|
||||||
|
for (int i = 0; i < (MAP_COUNT - 1); i += 1) {
|
||||||
|
int map_index = i + 1;
|
||||||
|
|
||||||
|
NORMAL_MAP += splat_map[i] * 0.5 * (texture(NORMAL_MAPS[map_index], uv).rgb +
|
||||||
|
texture(NORMAL_MAPS[map_index], uv_alt).rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float height(vec2 uv) {
|
||||||
|
return MAX_HEIGHT * texture(TERRAIN_MAP, uv).a;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vertex() {
|
||||||
|
VERTEX.y = height(UV);
|
||||||
|
|
||||||
|
vec2 texel_size = UV / SIZE;
|
||||||
|
|
||||||
|
vec4 h = vec4(
|
||||||
|
height(UV + (texel_size * vec2(0, -1))),
|
||||||
|
height(UV + (texel_size * vec2(-1, 0))),
|
||||||
|
height(UV + (texel_size * vec2( 1, 0))),
|
||||||
|
height(UV + (texel_size * vec2( 0, 1))));
|
||||||
|
|
||||||
|
NORMAL = normalize(vec3(h.y - h.z, 2.0, h.x - h.w));
|
||||||
|
}
|
|
@ -0,0 +1,87 @@
|
||||||
|
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)
|
BIN
terrain_cursor_emission.png (Stored with Git LFS)
BIN
terrain_cursor_emission.png (Stored with Git LFS)
Binary file not shown.
|
@ -1,36 +0,0 @@
|
||||||
[remap]
|
|
||||||
|
|
||||||
importer="texture"
|
|
||||||
type="CompressedTexture2D"
|
|
||||||
uid="uid://dmbae0p1ujwcv"
|
|
||||||
path.s3tc="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex"
|
|
||||||
path.etc2="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex"
|
|
||||||
metadata={
|
|
||||||
"imported_formats": ["s3tc", "etc2"],
|
|
||||||
"vram_texture": true
|
|
||||||
}
|
|
||||||
|
|
||||||
[deps]
|
|
||||||
|
|
||||||
source_file="res://terrain_cursor_emission.png"
|
|
||||||
dest_files=["res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex", "res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex"]
|
|
||||||
|
|
||||||
[params]
|
|
||||||
|
|
||||||
compress/mode=2
|
|
||||||
compress/lossy_quality=0.7
|
|
||||||
compress/hdr_compression=1
|
|
||||||
compress/bptc_ldr=0
|
|
||||||
compress/normal_map=0
|
|
||||||
compress/channel_pack=0
|
|
||||||
mipmaps/generate=true
|
|
||||||
mipmaps/limit=-1
|
|
||||||
roughness/mode=0
|
|
||||||
roughness/src_normal=""
|
|
||||||
process/fix_alpha_border=true
|
|
||||||
process/premult_alpha=true
|
|
||||||
process/normal_map_invert_y=false
|
|
||||||
process/hdr_as_srgb=false
|
|
||||||
process/hdr_clamp_exposure=false
|
|
||||||
process/size_limit=0
|
|
||||||
detect_3d/compress_to=0
|
|
|
@ -1,169 +0,0 @@
|
||||||
@tool
|
|
||||||
class_name TerrainInstance3D extends GeometryInstance3D
|
|
||||||
|
|
||||||
const _DETAIL := 2
|
|
||||||
|
|
||||||
var _mesh := PlaneMesh.new()
|
|
||||||
|
|
||||||
var _material := ShaderMaterial.new()
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var size: Vector2i = Vector2i.ZERO:
|
|
||||||
get:
|
|
||||||
return size
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
var width := maxi(value.x, 0)
|
|
||||||
var height := maxi(value.y, 0)
|
|
||||||
|
|
||||||
if (width != size.x) or (height != size.y):
|
|
||||||
if (width == 0) and (height == 0):
|
|
||||||
RenderingServer.instance_set_base(self.get_instance(), RID())
|
|
||||||
|
|
||||||
else:
|
|
||||||
self._mesh.subdivide_width = width * _DETAIL
|
|
||||||
self._mesh.subdivide_depth = height * _DETAIL
|
|
||||||
self._mesh.size = value
|
|
||||||
|
|
||||||
self._material.set_shader_parameter("SIZE", Vector2(value))
|
|
||||||
RenderingServer.instance_set_base(self.get_instance(), self._mesh)
|
|
||||||
|
|
||||||
size = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_1_albedo: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_1_albedo
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_1_ALBEDO", value)
|
|
||||||
|
|
||||||
layer_1_albedo = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_1_normal_map: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_1_normal_map
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_1_NORMAL_MAP", value)
|
|
||||||
|
|
||||||
layer_1_normal_map = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_2_albedo: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_2_albedo
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_2_ALBEDO", value)
|
|
||||||
|
|
||||||
layer_2_albedo = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_2_normal_map: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_2_normal_map
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_2_NORMAL_MAP", value)
|
|
||||||
|
|
||||||
layer_2_normal_map = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_3_albedo: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_3_albedo
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_3_ALBEDO", value)
|
|
||||||
|
|
||||||
layer_3_albedo = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_3_normal_map: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_3_normal_map
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_3_NORMAL_MAP", value)
|
|
||||||
|
|
||||||
layer_3_normal_map = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_4_albedo: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_4_albedo
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_4_ALBEDO", value)
|
|
||||||
|
|
||||||
layer_4_albedo = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var layer_4_normal_map: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return layer_4_normal_map
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("LAYER_4_NORMAL_MAP", value)
|
|
||||||
|
|
||||||
layer_4_normal_map = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var terrain_map: Texture2D = null:
|
|
||||||
get:
|
|
||||||
return terrain_map
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("TERRAIN_MAP", value)
|
|
||||||
|
|
||||||
terrain_map = value
|
|
||||||
|
|
||||||
##
|
|
||||||
##
|
|
||||||
##
|
|
||||||
@export
|
|
||||||
var max_height := 100.0:
|
|
||||||
get:
|
|
||||||
return max_height
|
|
||||||
|
|
||||||
set(value):
|
|
||||||
self._material.set_shader_parameter("MAX_HEIGHT", value)
|
|
||||||
|
|
||||||
max_height = max(value, 0.0)
|
|
||||||
|
|
||||||
func _init() -> void:
|
|
||||||
self._material.shader = preload("res://terrain_shader.gdshader")
|
|
||||||
|
|
||||||
self._mesh.surface_set_material(0, self._material)
|
|
|
@ -1,58 +0,0 @@
|
||||||
shader_type spatial;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_1_ALBEDO : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_1_NORMAL_MAP : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_2_ALBEDO : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_2_NORMAL_MAP : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_3_ALBEDO : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_3_NORMAL_MAP : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_4_ALBEDO : hint_default_black;
|
|
||||||
|
|
||||||
uniform sampler2D LAYER_4_NORMAL_MAP : hint_default_black;
|
|
||||||
|
|
||||||
uniform float MAX_HEIGHT = 100.0;
|
|
||||||
|
|
||||||
uniform vec2 SIZE;
|
|
||||||
|
|
||||||
uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable;
|
|
||||||
|
|
||||||
void fragment() {
|
|
||||||
vec2 uv = UV * SIZE;
|
|
||||||
vec2 uv_alt = uv * -0.25;
|
|
||||||
vec3 splat_map = texture(TERRAIN_MAP, UV).rgb;
|
|
||||||
float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0);
|
|
||||||
|
|
||||||
ALBEDO = blank * 0.5 * (texture(LAYER_1_ALBEDO, uv).rgb + texture(LAYER_1_ALBEDO, uv_alt).rgb);
|
|
||||||
ALBEDO += splat_map.r * 0.5 * (texture(LAYER_2_ALBEDO, uv).rgb + texture(LAYER_2_ALBEDO, uv_alt).rgb);
|
|
||||||
ALBEDO += splat_map.g * 0.5 * (texture(LAYER_3_ALBEDO, uv).rgb + texture(LAYER_3_ALBEDO, uv_alt).rgb);
|
|
||||||
ALBEDO += splat_map.b * 0.5 * (texture(LAYER_4_ALBEDO, uv).rgb + texture(LAYER_4_ALBEDO, uv_alt).rgb);
|
|
||||||
|
|
||||||
NORMAL_MAP = blank * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_1_NORMAL_MAP, uv_alt).rgb);
|
|
||||||
NORMAL_MAP += splat_map.r * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_2_NORMAL_MAP, uv_alt).rgb);
|
|
||||||
NORMAL_MAP += splat_map.g * 0.5 * (texture(LAYER_2_NORMAL_MAP, uv).rgb + texture(LAYER_3_NORMAL_MAP, uv_alt).rgb);
|
|
||||||
NORMAL_MAP += splat_map.b * 0.5 * (texture(LAYER_3_NORMAL_MAP, uv).rgb + texture(LAYER_4_NORMAL_MAP, uv_alt).rgb);
|
|
||||||
}
|
|
||||||
|
|
||||||
float height(vec2 uv) {
|
|
||||||
return MAX_HEIGHT * texture(TERRAIN_MAP, uv).a;
|
|
||||||
}
|
|
||||||
|
|
||||||
void vertex() {
|
|
||||||
VERTEX.y = height(UV);
|
|
||||||
|
|
||||||
vec2 texel_size = UV / SIZE;
|
|
||||||
|
|
||||||
vec4 h = vec4(
|
|
||||||
height(UV + (texel_size * vec2(0, -1))),
|
|
||||||
height(UV + (texel_size * vec2(-1, 0))),
|
|
||||||
height(UV + (texel_size * vec2( 1, 0))),
|
|
||||||
height(UV + (texel_size * vec2( 0, 1))));
|
|
||||||
|
|
||||||
NORMAL = normalize(vec3(h.y - h.z, 2.0, h.x - h.w));
|
|
||||||
}
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
@tool
|
||||||
|
class_name ItemSelection extends HFlowContainer
|
||||||
|
|
||||||
|
##
|
||||||
|
## An item has been selected via GUI selection or [method select_item].
|
||||||
|
##
|
||||||
|
signal item_selected(index: int)
|
||||||
|
|
||||||
|
var _button_group := ButtonGroup.new()
|
||||||
|
|
||||||
|
##
|
||||||
|
## Number of items in the selection.
|
||||||
|
##
|
||||||
|
var item_count: int:
|
||||||
|
get:
|
||||||
|
return _button_group.get_buttons().size()
|
||||||
|
|
||||||
|
func _get_configuration_warnings() -> PackedStringArray:
|
||||||
|
return PackedStringArray()
|
||||||
|
|
||||||
|
##
|
||||||
|
## Adds a new item with no text and only [code]icon[/code] as the icon to the selection.
|
||||||
|
##
|
||||||
|
func add_icon_item(icon: Texture2D) -> void:
|
||||||
|
var child_count := get_child_count()
|
||||||
|
var button := Button.new()
|
||||||
|
|
||||||
|
button.icon = icon
|
||||||
|
button.icon_alignment = HORIZONTAL_ALIGNMENT_CENTER
|
||||||
|
button.toggle_mode = true
|
||||||
|
button.button_group = _button_group
|
||||||
|
button.button_pressed = child_count == 0
|
||||||
|
|
||||||
|
button.pressed.connect(func () -> void: select_item(child_count))
|
||||||
|
add_child(button)
|
||||||
|
|
||||||
|
##
|
||||||
|
## Returns the icon used by the item at [code]index[/code].
|
||||||
|
##
|
||||||
|
## An assertion is raised if [code]index[/code] is out of bounds from the item count.
|
||||||
|
##
|
||||||
|
func get_item_icon(index: int) -> Texture2D:
|
||||||
|
var buttons := _button_group.get_buttons()
|
||||||
|
|
||||||
|
assert(index < buttons.size(), "index out of range")
|
||||||
|
|
||||||
|
var button := buttons[index] as Button
|
||||||
|
|
||||||
|
return null if (button == null) else button.icon
|
||||||
|
|
||||||
|
##
|
||||||
|
## Returns the currently selected item index or [code]-1[/code] if no item is selected.
|
||||||
|
##
|
||||||
|
func get_selected_item() -> int:
|
||||||
|
var pressed_button := _button_group.get_pressed_button()
|
||||||
|
|
||||||
|
return -1 if (pressed_button == null) else pressed_button.get_index()
|
||||||
|
|
||||||
|
##
|
||||||
|
## Selects the item at [code]index[/code], emitting [signal item_selected] at the end.
|
||||||
|
##
|
||||||
|
## An assertion is raised if [code]index[/code] is out of bounds from the item count.
|
||||||
|
##
|
||||||
|
func select_item(index: int) -> void:
|
||||||
|
var buttons := _button_group.get_buttons()
|
||||||
|
|
||||||
|
assert(index < buttons.size(), "index out of range")
|
||||||
|
|
||||||
|
var pressed_button := _button_group.get_pressed_button()
|
||||||
|
|
||||||
|
if pressed_button != null:
|
||||||
|
pressed_button.set_pressed_no_signal(false)
|
||||||
|
|
||||||
|
buttons[index].set_pressed_no_signal(true)
|
||||||
|
item_selected.emit(index)
|
Binary file not shown.
|
@ -0,0 +1,34 @@
|
||||||
|
[remap]
|
||||||
|
|
||||||
|
importer="texture"
|
||||||
|
type="CompressedTexture2D"
|
||||||
|
uid="uid://crt8tmxbpu1hl"
|
||||||
|
path="res://.godot/imported/screen_cursor.png-46ebd33cd7dfb4c0211a698e6d39e483.ctex"
|
||||||
|
metadata={
|
||||||
|
"vram_texture": false
|
||||||
|
}
|
||||||
|
|
||||||
|
[deps]
|
||||||
|
|
||||||
|
source_file="res://user_interface/screen_cursor.png"
|
||||||
|
dest_files=["res://.godot/imported/screen_cursor.png-46ebd33cd7dfb4c0211a698e6d39e483.ctex"]
|
||||||
|
|
||||||
|
[params]
|
||||||
|
|
||||||
|
compress/mode=0
|
||||||
|
compress/lossy_quality=0.7
|
||||||
|
compress/hdr_compression=1
|
||||||
|
compress/bptc_ldr=0
|
||||||
|
compress/normal_map=0
|
||||||
|
compress/channel_pack=0
|
||||||
|
mipmaps/generate=false
|
||||||
|
mipmaps/limit=-1
|
||||||
|
roughness/mode=0
|
||||||
|
roughness/src_normal=""
|
||||||
|
process/fix_alpha_border=true
|
||||||
|
process/premult_alpha=false
|
||||||
|
process/normal_map_invert_y=false
|
||||||
|
process/hdr_as_srgb=false
|
||||||
|
process/hdr_clamp_exposure=false
|
||||||
|
process/size_limit=0
|
||||||
|
detect_3d/compress_to=1
|
Loading…
Reference in New Issue