diff --git a/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd b/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd new file mode 100644 index 000000000..daf8e5944 --- /dev/null +++ b/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd @@ -0,0 +1,28 @@ +@tool +extends SubViewportContainer + +var orbit_capture: bool = false + +@onready var camera_pivot_yaw: Node3D = $SubViewport/CameraPivotYaw +@onready var camera_pivot_pitch: Node3D = $SubViewport/CameraPivotYaw/CameraPivotPitch +@onready var preview_camera_3d: Camera3D = %PreviewCamera3D + + +func _gui_input(event: InputEvent) -> void: + if event is InputEventMouseButton: + if event.button_index == MOUSE_BUTTON_MIDDLE: + orbit_capture = !orbit_capture + return + elif event.button_index == MOUSE_BUTTON_WHEEL_UP: + preview_camera_3d.fov -= 10 + preview_camera_3d.fov = clamp(preview_camera_3d.fov, 1, 179) + elif event.button_index == MOUSE_BUTTON_WHEEL_DOWN: + preview_camera_3d.fov += 10 + preview_camera_3d.fov = clamp(preview_camera_3d.fov, 1, 179) + + if event is InputEventMouseMotion: + if orbit_capture: + preview_camera_3d.rotation = Vector3.ZERO + camera_pivot_yaw.rotate_y(event.relative.x * 0.01) + camera_pivot_pitch.rotate_x(-event.relative.y * 0.01) + diff --git a/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd.uid b/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd.uid new file mode 100644 index 000000000..81d26d28b --- /dev/null +++ b/project/addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd.uid @@ -0,0 +1 @@ +uid://b7qb3n8btnjmc diff --git a/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader b/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader new file mode 100644 index 000000000..d374bf424 --- /dev/null +++ b/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader @@ -0,0 +1,26 @@ +shader_type spatial; + +render_mode cull_disabled, diffuse_burley; + +uniform sampler2D noise : source_color; +uniform sampler2D normal_map : source_color; +uniform float noise_scale = 10.0; + +float height(vec2 uv) { + return texture(noise, uv).r; +} + +void vertex() { + float k = height(UV) * noise_scale; + VERTEX.y += k ; + NORMAL = texture(normal_map, UV).xyz; +} + +void fragment() { + ALBEDO = vec3(1.0, 1.0, 1.0); + ROUGHNESS = 0.0; + SPECULAR = 0.0; + METALLIC = 0.0; +} + + diff --git a/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader.uid b/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader.uid new file mode 100644 index 000000000..b856ac74f --- /dev/null +++ b/project/addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader.uid @@ -0,0 +1 @@ +uid://bfyq22k30khqd diff --git a/project/addons/terrain_3d/menu/terrain_generation.gd b/project/addons/terrain_3d/menu/terrain_generation.gd new file mode 100644 index 000000000..47f6e2e4c --- /dev/null +++ b/project/addons/terrain_3d/menu/terrain_generation.gd @@ -0,0 +1,154 @@ +@tool +extends Node + +const TERRAIN_GENERATION: String = "res://addons/terrain_3d/menu/terrain_generation.tscn" + +var height_slider: HSlider +var frequency_slider: HSlider +var octaves_spin_box: SpinBox + +var region_count_spin_box: SpinBox +var region_size_option_button: OptionButton + +var mesh_instance_3d: MeshInstance3D +var mat: ShaderMaterial +var preview_camera_3d: Camera3D +var _preview: SubViewportContainer +var generate_button: Button + +var noise_generator: FastNoiseLite +var noise_texture: NoiseTexture2D +var normal_texture: NoiseTexture2D + +var region_size_arr: Array[int] = [256, 512, 1024] +var region_size_idx: int = 0 + +var plugin: EditorPlugin +var terrain: Terrain3D +var dialog: ConfirmationDialog + +func set_up_pop_up() -> void: + if not plugin.terrain: + push_error("Not connected terrain. Click the Terrain3D node first") + return + terrain = plugin.terrain + print("Setting up TerrainGeneration pop up") + dialog = load(TERRAIN_GENERATION).instantiate() + dialog.hide() + + dialog.confirmed.connect(_on_close_requested) + dialog.canceled.connect(_on_close_requested) + dialog.get_ok_button().pressed.connect(_on_ok_pressed) + + mesh_instance_3d = dialog.find_child("MeshInstance3D") + mat = mesh_instance_3d.get_active_material(0) + preview_camera_3d = dialog.find_child("PreviewCamera3D") + _preview = dialog.find_child("SubViewportContainer") + + noise_generator = FastNoiseLite.new() + noise_texture = NoiseTexture2D.new() + normal_texture = NoiseTexture2D.new() + + height_slider = dialog.find_child("HeightSlider") + height_slider.value_changed.connect(set_height_scale) + height_slider.value = 2.0 + + frequency_slider = dialog.find_child("FrequencySlider") + frequency_slider.value_changed.connect(set_frequency) + frequency_slider.value = noise_generator.frequency + + octaves_spin_box = dialog.find_child("OctavesSpinBox") + octaves_spin_box.value_changed.connect(set_octaves) + octaves_spin_box.value = noise_generator.fractal_octaves + + region_size_option_button = dialog.find_child("RegionSizeOptionButton") + region_size_option_button.item_selected.connect(set_region_size) + region_size_option_button.select(region_size_arr.find(int(terrain.region_size))) + set_region_size(region_size_option_button.selected) + generate_button = dialog.find_child("GenerateButton") + generate_button.pressed.connect(_generate_terrain) + + height_slider.value = height_slider.value + frequency_slider.value = height_slider.value + octaves_spin_box.value = octaves_spin_box.value + + noise_texture.noise = noise_generator + noise_texture.seamless = true + set_shader_param("noise", noise_texture) + + normal_texture.noise = noise_generator + normal_texture.as_normal_map = true + normal_texture.invert = true + normal_texture.seamless = true + set_shader_param("normal_map", normal_texture) + + # Popup + EditorInterface.popup_dialog_centered(dialog) + +func _on_close_requested() -> void: + dialog.queue_free() + dialog = null + + +func _on_ok_pressed() -> void: + if not terrain: + push_error("Not connected terrain. Click the Terrain3D node first") + return + _generate_terrain() + + +func _generate_terrain() -> void: + print_debug("Generating Terrain") + if not terrain: + push_error("Not connected terrain. Click the Terrain3D node first") + return + reset_terrain() + var region_size: int = region_size_arr[region_size_idx] + terrain.data.change_region_size(region_size) + var img: Image = noise_texture.get_image() + print_debug("Using image of size ", img.get_size()) + terrain.data.import_images([img, null, null], Vector3(0., 0., 0.), 0.0, height_slider.value * 1.) + terrain.data.save_directory(terrain.data_directory) + print("Generated Terrain") + # Enable the next line and `Debug/Visible Collision Shapes` to see collision + #terrain.collision.mode = Terrain3DCollision.DYNAMIC_EDITOR + + +func reset_terrain() -> void: + if not terrain: + push_error("Not connected terrain. Click the Terrain3D node first") + return + for region:Terrain3DRegion in terrain.data.get_regions_active(): + terrain.data.remove_region(region, false) + terrain.data.save_directory(terrain.data_directory) + + +func set_region_size(item_id: int) -> void: + region_size_idx = item_id + var region_size: int = region_size_arr[region_size_idx] + print("Regionsize = ", region_size) + noise_texture.height = region_size_arr[region_size_idx] + noise_texture.width = region_size_arr[region_size_idx] + normal_texture.height = region_size_arr[region_size_idx] + normal_texture.width = region_size_arr[region_size_idx] + (mesh_instance_3d.mesh as PlaneMesh).size = Vector2(region_size_arr[region_size_idx], region_size_arr[region_size_idx]) + + +func set_height_scale(value: float) -> void: + set_shader_param("noise_scale", value) + height_slider.tooltip_text = str(value) + + +func set_frequency(value: float) -> void: + value *= 0.1 + noise_generator.frequency = value + frequency_slider.tooltip_text = str(value) + + +func set_octaves(value: int) -> void: + noise_generator.fractal_octaves = value + octaves_spin_box.tooltip_text = str(value) + + +func set_shader_param(p_name: String, value: Variant) -> void: + mat.set_shader_parameter(p_name, value) diff --git a/project/addons/terrain_3d/menu/terrain_generation.gd.uid b/project/addons/terrain_3d/menu/terrain_generation.gd.uid new file mode 100644 index 000000000..ee0819fbb --- /dev/null +++ b/project/addons/terrain_3d/menu/terrain_generation.gd.uid @@ -0,0 +1 @@ +uid://bdkxa5pqd0r3x diff --git a/project/addons/terrain_3d/menu/terrain_generation.tscn b/project/addons/terrain_3d/menu/terrain_generation.tscn new file mode 100644 index 000000000..b2f61a3e1 --- /dev/null +++ b/project/addons/terrain_3d/menu/terrain_generation.tscn @@ -0,0 +1,203 @@ +[gd_scene load_steps=16 format=3 uid="uid://c04wuoe5k7oq6"] + +[ext_resource type="Script" uid="uid://bdkxa5pqd0r3x" path="res://addons/terrain_3d/menu/terrain_generation.gd" id="1_1t2g3"] +[ext_resource type="Shader" uid="uid://bfyq22k30khqd" path="res://addons/terrain_3d/extras/TerrainGeneration/terrain_generation.gdshader" id="1_34yxq"] +[ext_resource type="Script" uid="uid://b7qb3n8btnjmc" path="res://addons/terrain_3d/extras/TerrainGeneration/sub_viewport_container.gd" id="2_valc7"] + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_n2mt3"] + +[sub_resource type="Sky" id="Sky_ktjl2"] +sky_material = SubResource("ProceduralSkyMaterial_n2mt3") + +[sub_resource type="Environment" id="Environment_u0a73"] +background_mode = 2 +sky = SubResource("Sky_ktjl2") + +[sub_resource type="World3D" id="World3D_0f0kr"] +resource_local_to_scene = true +environment = SubResource("Environment_u0a73") + +[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_1t2g3"] + +[sub_resource type="Sky" id="Sky_valc7"] +sky_material = SubResource("ProceduralSkyMaterial_1t2g3") + +[sub_resource type="Environment" id="Environment_1t2g3"] +background_mode = 2 +sky = SubResource("Sky_valc7") + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_n2mt3"] +frequency = 0.0075 +fractal_octaves = 7 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_ktjl2"] +width = 1024 +height = 1024 +seamless = true +noise = SubResource("FastNoiseLite_n2mt3") + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_u0a73"] +width = 1024 +height = 1024 +invert = true +seamless = true +as_normal_map = true +noise = SubResource("FastNoiseLite_n2mt3") + +[sub_resource type="ShaderMaterial" id="ShaderMaterial_1t2g3"] +render_priority = 0 +shader = ExtResource("1_34yxq") +shader_parameter/noise = SubResource("NoiseTexture2D_ktjl2") +shader_parameter/normal_map = SubResource("NoiseTexture2D_u0a73") +shader_parameter/noise_scale = 51.0 + +[sub_resource type="PlaneMesh" id="PlaneMesh_34yxq"] +material = SubResource("ShaderMaterial_1t2g3") +size = Vector2(1024, 1024) +subdivide_width = 256 +subdivide_depth = 256 + +[node name="TerrainGeneration" type="ConfirmationDialog"] +title = "Terrain Generation" +initial_position = 1 +size = Vector2i(780, 637) +visible = true +min_size = Vector2i(780, 420) +ok_button_text = "Generate" +script = ExtResource("1_1t2g3") +metadata/_edit_horizontal_guides_ = [17.0, -13.0] + +[node name="MarginContainer" type="MarginContainer" parent="."] +custom_minimum_size = Vector2(700, 500) +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +offset_left = 8.0 +offset_top = 8.0 +offset_right = -8.0 +offset_bottom = -49.0 +grow_horizontal = 2 +grow_vertical = 2 +theme_override_constants/margin_left = 20 +theme_override_constants/margin_top = 20 +theme_override_constants/margin_right = 20 +theme_override_constants/margin_bottom = 20 + +[node name="HBoxContainer" type="HBoxContainer" parent="MarginContainer"] +layout_mode = 2 + +[node name="VBoxContainer2" type="VBoxContainer" parent="MarginContainer/HBoxContainer"] +layout_mode = 2 + +[node name="NoiseControls" type="VBoxContainer" parent="MarginContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +size_flags_horizontal = 0 + +[node name="HeightLabel" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +layout_mode = 2 +text = "Height scale" + +[node name="HeightSlider" type="HSlider" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +unique_name_in_owner = true +custom_minimum_size = Vector2(256, 0) +layout_mode = 2 +min_value = -100.0 + +[node name="FrequencyLabel" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +layout_mode = 2 +text = "Frequency" + +[node name="FrequencySlider" type="HSlider" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +unique_name_in_owner = true +custom_minimum_size = Vector2(256, 0) +layout_mode = 2 +max_value = 1.0 +step = 0.001 + +[node name="OctavesLabel" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +layout_mode = 2 +text = "Octaves" + +[node name="OctavesSpinBox" type="SpinBox" parent="MarginContainer/HBoxContainer/VBoxContainer2/NoiseControls"] +unique_name_in_owner = true +layout_mode = 2 + +[node name="RegionControls" type="VBoxContainer" parent="MarginContainer/HBoxContainer/VBoxContainer2"] +layout_mode = 2 +size_flags_vertical = 10 + +[node name="RegionCountLabel" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer2/RegionControls"] +layout_mode = 2 +text = "Regions" + +[node name="RegionCountSpinBox" type="SpinBox" parent="MarginContainer/HBoxContainer/VBoxContainer2/RegionControls"] +unique_name_in_owner = true +layout_mode = 2 +min_value = 1.0 +max_value = 16.0 +value = 1.0 + +[node name="RegionSizeLabel" type="Label" parent="MarginContainer/HBoxContainer/VBoxContainer2/RegionControls"] +layout_mode = 2 +text = "Region Size" + +[node name="RegionSizeOptionButton" type="OptionButton" parent="MarginContainer/HBoxContainer/VBoxContainer2/RegionControls"] +unique_name_in_owner = true +layout_mode = 2 +selected = 0 +item_count = 3 +popup/item_0/text = "256" +popup/item_0/id = 0 +popup/item_1/text = "512" +popup/item_1/id = 1 +popup/item_2/text = "1024" +popup/item_2/id = 2 + +[node name="GenerateButton" type="Button" parent="MarginContainer"] +unique_name_in_owner = true +visible = false +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 8 +text = "GENERATE" + +[node name="SubViewportContainer" type="SubViewportContainer" parent="MarginContainer"] +unique_name_in_owner = true +custom_minimum_size = Vector2(400, 300) +layout_mode = 2 +size_flags_horizontal = 8 +size_flags_vertical = 0 +stretch = true +script = ExtResource("2_valc7") + +[node name="SubViewport" type="SubViewport" parent="MarginContainer/SubViewportContainer"] +own_world_3d = true +world_3d = SubResource("World3D_0f0kr") +handle_input_locally = false +size = Vector2i(400, 300) +render_target_update_mode = 4 + +[node name="WorldEnvironment" type="WorldEnvironment" parent="MarginContainer/SubViewportContainer/SubViewport"] +environment = SubResource("Environment_1t2g3") + +[node name="DirectionalLight3D" type="DirectionalLight3D" parent="MarginContainer/SubViewportContainer/SubViewport"] +transform = Transform3D(-0.0610486, -0.916043, -0.396407, -3.47198e-08, -0.397148, 0.917754, -0.998135, 0.0560276, 0.0242453, 0, 0, 0) +shadow_enabled = true + +[node name="MeshInstance3D" type="MeshInstance3D" parent="MarginContainer/SubViewportContainer/SubViewport"] +unique_name_in_owner = true +mesh = SubResource("PlaneMesh_34yxq") + +[node name="CameraPivotYaw" type="Node3D" parent="MarginContainer/SubViewportContainer/SubViewport"] +transform = Transform3D(0.707107, 0, 0.707107, 0, 1, 0, -0.707107, 0, 0.707107, 0, 0, 0) + +[node name="CameraPivotPitch" type="Node3D" parent="MarginContainer/SubViewportContainer/SubViewport/CameraPivotYaw"] +transform = Transform3D(1, 0, 0, 0, 0.866025, 0.5, 0, -0.5, 0.866026, 0, 0, 0) + +[node name="PreviewCamera3D" type="Camera3D" parent="MarginContainer/SubViewportContainer/SubViewport/CameraPivotYaw/CameraPivotPitch"] +unique_name_in_owner = true +transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 200) +current = true + +[node name="World" type="Node3D" parent="MarginContainer/SubViewportContainer/SubViewport"] +unique_name_in_owner = true diff --git a/project/addons/terrain_3d/menu/terrain_menu.gd b/project/addons/terrain_3d/menu/terrain_menu.gd index 9d76b3247..87e47ba26 100644 --- a/project/addons/terrain_3d/menu/terrain_menu.gd +++ b/project/addons/terrain_3d/menu/terrain_menu.gd @@ -6,12 +6,14 @@ extends HBoxContainer const DirectoryWizard: Script = preload("res://addons/terrain_3d/menu/directory_setup.gd") const ChannelPacker: Script = preload("res://addons/terrain_3d/menu/channel_packer.gd") const LodBaker: Script = preload("res://addons/terrain_3d/menu/baker.gd") +const TerrainGenerator: Script = preload("res://addons/terrain_3d/menu/terrain_generation.gd") var plugin: EditorPlugin var menu_button: MenuButton = MenuButton.new() var directory_setup: DirectoryWizard = DirectoryWizard.new() var packer: ChannelPacker = ChannelPacker.new() var baker: LodBaker = LodBaker.new() +var terrain_generator: TerrainGenerator = TerrainGenerator.new() # These are IDs and order must be consistent with add_item and set_disabled IDs enum { @@ -23,6 +25,8 @@ enum { MENU_SEPARATOR2, MENU_SET_UP_NAVIGATION, MENU_BAKE_NAV_MESH, + MENU_SEPARATOR3, + MENU_GENERATE_TERRAIN, } @@ -30,6 +34,7 @@ func _enter_tree() -> void: directory_setup.plugin = plugin packer.plugin = plugin baker.plugin = plugin + terrain_generator.plugin = plugin add_child(directory_setup) add_child(baker) @@ -42,6 +47,9 @@ func _enter_tree() -> void: menu_button.get_popup().add_separator("", MENU_SEPARATOR2) menu_button.get_popup().add_item("Set up Navigation...", MENU_SET_UP_NAVIGATION) menu_button.get_popup().add_item("Bake NavMesh...", MENU_BAKE_NAV_MESH) + menu_button.get_popup().add_separator("", MENU_SEPARATOR3) + menu_button.get_popup().add_item("Generate Terrain...", MENU_GENERATE_TERRAIN) + menu_button.get_popup().id_pressed.connect(_on_menu_pressed) menu_button.about_to_popup.connect(_on_menu_about_to_popup) @@ -62,6 +70,8 @@ func _on_menu_pressed(p_id: int) -> void: baker.set_up_navigation_popup() MENU_BAKE_NAV_MESH: baker.bake_nav_mesh() + MENU_GENERATE_TERRAIN: + terrain_generator.set_up_pop_up() func _on_menu_about_to_popup() -> void: @@ -69,15 +79,19 @@ func _on_menu_about_to_popup() -> void: menu_button.get_popup().set_item_disabled(MENU_PACK_TEXTURES, not plugin.terrain) menu_button.get_popup().set_item_disabled(MENU_BAKE_ARRAY_MESH, not plugin.terrain) menu_button.get_popup().set_item_disabled(MENU_BAKE_OCCLUDER, not plugin.terrain) + menu_button.get_popup().set_item_disabled(MENU_GENERATE_TERRAIN, not plugin.terrain) if plugin.terrain: var nav_regions: Array[NavigationRegion3D] = baker.find_terrain_nav_regions(plugin.terrain) menu_button.get_popup().set_item_disabled(MENU_BAKE_NAV_MESH, nav_regions.size() == 0) menu_button.get_popup().set_item_disabled(MENU_SET_UP_NAVIGATION, nav_regions.size() != 0) + menu_button.get_popup().set_item_disabled(MENU_GENERATE_TERRAIN, false) elif plugin.nav_region: var terrains: Array[Terrain3D] = baker.find_nav_region_terrains(plugin.nav_region) menu_button.get_popup().set_item_disabled(MENU_BAKE_NAV_MESH, terrains.size() == 0) menu_button.get_popup().set_item_disabled(MENU_SET_UP_NAVIGATION, true) + menu_button.get_popup().set_item_disabled(MENU_GENERATE_TERRAIN, false) else: menu_button.get_popup().set_item_disabled(MENU_BAKE_NAV_MESH, true) menu_button.get_popup().set_item_disabled(MENU_SET_UP_NAVIGATION, true) + menu_button.get_popup().set_item_disabled(MENU_GENERATE_TERRAIN, true) diff --git a/project/examples/generation_test.tscn b/project/examples/generation_test.tscn new file mode 100644 index 000000000..d3ad32fb3 --- /dev/null +++ b/project/examples/generation_test.tscn @@ -0,0 +1,108 @@ +[gd_scene load_steps=17 format=3 uid="uid://biscji44igfd1"] + +[ext_resource type="Texture2D" uid="uid://c88j3oj0lf6om" path="res://demo/assets/textures/rock023_alb_ht.png" id="1_bn1pt"] +[ext_resource type="PackedScene" uid="uid://d2jihfohphuue" path="res://demo/components/UI.tscn" id="1_ocys8"] +[ext_resource type="Texture2D" uid="uid://c307hdmos4gtm" path="res://demo/assets/textures/rock023_nrm_rgh.png" id="2_tner3"] +[ext_resource type="Texture2D" uid="uid://ddprscrpsofah" path="res://demo/assets/textures/ground037_alb_ht.png" id="3_icstv"] +[ext_resource type="Texture2D" uid="uid://c1ots7w6i0i1q" path="res://demo/assets/textures/ground037_nrm_rgh.png" id="4_ocys8"] +[ext_resource type="PackedScene" uid="uid://domhm87hbhbg1" path="res://demo/components/Player.tscn" id="5_tner3"] +[ext_resource type="PackedScene" uid="uid://bb2lp50sjndus" path="res://demo/components/Environment.tscn" id="7_aeuid"] + +[sub_resource type="Gradient" id="Gradient_bhdbr"] +offsets = PackedFloat32Array(0.2, 1) +colors = PackedColorArray(1, 1, 1, 1, 0, 0, 0, 1) + +[sub_resource type="FastNoiseLite" id="FastNoiseLite_lykh7"] +noise_type = 2 +frequency = 0.03 +cellular_jitter = 3.0 +cellular_return_type = 0 +domain_warp_enabled = true +domain_warp_type = 1 +domain_warp_amplitude = 50.0 +domain_warp_fractal_type = 2 +domain_warp_fractal_lacunarity = 1.5 +domain_warp_fractal_gain = 1.0 + +[sub_resource type="NoiseTexture2D" id="NoiseTexture2D_v7kqh"] +seamless = true +color_ramp = SubResource("Gradient_bhdbr") +noise = SubResource("FastNoiseLite_lykh7") + +[sub_resource type="Terrain3DMaterial" id="Terrain3DMaterial_mvmq4"] +_shader_parameters = { +&"auto_base_texture": 0, +&"auto_height_reduction": 0.1, +&"auto_overlay_texture": 1, +&"auto_shader": null, +&"auto_slope": 1.0, +&"bias_distance": 512.0, +&"blend_sharpness": 0.5, +&"depth_blur": 0.0, +&"flat_terrain_normals": false, +&"general": null, +&"macro_variation": true, +&"macro_variation1": Color(1, 1, 1, 1), +&"macro_variation2": Color(1, 1, 1, 1), +&"macro_variation_slope": 0.333, +&"mipmap_bias": 1.0, +&"mipmaps": null, +&"noise1_angle": 0.0, +&"noise1_offset": Vector2(0.5, 0.5), +&"noise1_scale": 0.04, +&"noise2_scale": 0.076, +&"noise_texture": SubResource("NoiseTexture2D_v7kqh"), +&"projection_threshold": 0.8, +&"vertical_projection": true +} +world_background = 0 +auto_shader_enabled = true + +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_bn1pt"] +transparency = 4 +cull_mode = 2 +vertex_color_use_as_albedo = true +backlight_enabled = true +backlight = Color(0.5, 0.5, 0.5, 1) +distance_fade_mode = 1 +distance_fade_min_distance = 128.0 +distance_fade_max_distance = 96.0 + +[sub_resource type="Terrain3DMeshAsset" id="Terrain3DMeshAsset_tner3"] +height_offset = 0.5 +material_override = SubResource("StandardMaterial3D_bn1pt") +last_lod = 0 +last_shadow_lod = 0 +lod0_range = 128.0 + +[sub_resource type="Terrain3DTextureAsset" id="Terrain3DTextureAsset_aeuid"] +name = "ground037_alb_ht" +albedo_texture = ExtResource("1_bn1pt") +normal_texture = ExtResource("2_tner3") + +[sub_resource type="Terrain3DTextureAsset" id="Terrain3DTextureAsset_ka12a"] +name = "ground037_alb_ht" +id = 1 +albedo_texture = ExtResource("3_icstv") +normal_texture = ExtResource("4_ocys8") + +[sub_resource type="Terrain3DAssets" id="Terrain3DAssets_icstv"] +mesh_list = Array[Terrain3DMeshAsset]([SubResource("Terrain3DMeshAsset_tner3")]) +texture_list = Array[Terrain3DTextureAsset]([SubResource("Terrain3DTextureAsset_aeuid"), SubResource("Terrain3DTextureAsset_ka12a")]) + +[node name="GenerationTest" type="Node3D"] + +[node name="UI" parent="." instance=ExtResource("1_ocys8")] + +[node name="Environment" parent="." instance=ExtResource("7_aeuid")] + +[node name="Player" parent="." instance=ExtResource("5_tner3")] +transform = Transform3D(0.176947, 0, -0.98422, 0, 1, 0, 0.98422, 0, 0.176947, 50, 105.348, 50) + +[node name="Terrain3D" type="Terrain3D" parent="."] +data_directory = "res://demo/data3" +material = SubResource("Terrain3DMaterial_mvmq4") +assets = SubResource("Terrain3DAssets_icstv") +cull_margin = 10000.0 +top_level = true +metadata/_edit_lock_ = true