Compare commits
4 Commits
67182b4ccd
...
a45fc71a6d
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a45fc71a6d | ||
|
|
f80de943ec | ||
|
|
85d50d3bd4 | ||
|
|
43fb8410c3 |
@@ -5,3 +5,4 @@
|
||||
[node name="DoubleBeds" type="Node3D"]
|
||||
|
||||
[node name="DoubleBeds" parent="." instance=ExtResource("1_kkvf5")]
|
||||
transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -1.83435, 0, 0)
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
[gd_scene load_steps=7 format=3 uid="uid://dim2geqhn6d35"]
|
||||
[gd_scene load_steps=8 format=3 uid="uid://dim2geqhn6d35"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://dhls6unflalvd" path="res://Scripts/cart.gd" id="1_esjgi"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://p3d7iitismhf" path="res://Blends/Cart/cart-bottom.obj" id="1_ux2tx"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://docto7iocves6" path="res://Blends/Cart/wheels.obj" id="2_2wj72"]
|
||||
[ext_resource type="ArrayMesh" uid="uid://cayqoyyq7nbij" path="res://Blends/Cart/cart-top.obj" id="3_2wj72"]
|
||||
[ext_resource type="Script" uid="uid://bcmd74mxocn7e" path="res://Scripts/building_area.gd" id="5_eosii"]
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_esjgi"]
|
||||
size = Vector3(22.2341, 4.23804, 0.494629)
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_eosii"]
|
||||
size = Vector3(17.5376, 0.0286865, 2.28394)
|
||||
size = Vector3(5.40002, 4.29805, 2.28394)
|
||||
|
||||
[node name="Cart" type="Node3D" node_paths=PackedStringArray("cartTop")]
|
||||
script = ExtResource("1_esjgi")
|
||||
@@ -60,15 +61,21 @@ shape = SubResource("BoxShape3D_esjgi")
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.282789, 1.61902, -2.6054)
|
||||
shape = SubResource("BoxShape3D_esjgi")
|
||||
|
||||
[node name="BuildingArea2" type="StaticBody3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 8.23003, 0, 0)
|
||||
script = ExtResource("5_eosii")
|
||||
metadata/is_building_area = true
|
||||
|
||||
[node name="smallBuildingArea2" type="CollisionShape3D" parent="BuildingArea2"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.69414, 1.02766, -1.22106)
|
||||
shape = SubResource("BoxShape3D_eosii")
|
||||
metadata/is_building_area = true
|
||||
|
||||
[node name="BuildingArea" type="StaticBody3D" parent="."]
|
||||
script = ExtResource("5_eosii")
|
||||
metadata/is_building_area = true
|
||||
|
||||
[node name="CollisionShape3D" type="CollisionShape3D" parent="BuildingArea"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.374649, -0.275452, 2.38014)
|
||||
shape = SubResource("BoxShape3D_eosii")
|
||||
metadata/is_building_area = true
|
||||
|
||||
[node name="CollisionShape3D2" type="CollisionShape3D" parent="BuildingArea"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0.374649, -0.275452, -1.22106)
|
||||
[node name="smallBuildingArea2" type="CollisionShape3D" parent="BuildingArea"]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -5.69414, 1.02766, -1.22106)
|
||||
shape = SubResource("BoxShape3D_eosii")
|
||||
metadata/is_building_area = true
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
[gd_scene load_steps=8 format=3 uid="uid://bj7y7q2qkpnci"]
|
||||
[gd_scene load_steps=11 format=3 uid="uid://bj7y7q2qkpnci"]
|
||||
|
||||
[ext_resource type="ArrayMesh" uid="uid://622ethh2pdfa" path="res://Blends/road/road.obj" id="4_jjvhh"]
|
||||
[ext_resource type="PackedScene" uid="uid://dim2geqhn6d35" path="res://Scenes/Prefabs/cart.tscn" id="6_21xkr"]
|
||||
[ext_resource type="PackedScene" uid="uid://dy03tqug33fep" path="res://Blends/ground.blend" id="6_344ge"]
|
||||
[ext_resource type="Script" uid="uid://drrp1k2q71hq2" path="res://Scripts/camera_3d.gd" id="7_6bp64"]
|
||||
|
||||
[sub_resource type="ProceduralSkyMaterial" id="ProceduralSkyMaterial_jjvhh"]
|
||||
sky_top_color = Color(0.654771, 0.60129, 0.578102, 1)
|
||||
sky_horizon_color = Color(0.866942, 0.845822, 0.831025, 1)
|
||||
ground_horizon_color = Color(0.866942, 0.845822, 0.831025, 1)
|
||||
|
||||
[sub_resource type="Sky" id="Sky_kry3j"]
|
||||
sky_material = SubResource("ProceduralSkyMaterial_jjvhh")
|
||||
|
||||
[sub_resource type="Environment" id="Environment_21xkr"]
|
||||
background_mode = 2
|
||||
sky = SubResource("Sky_kry3j")
|
||||
tonemap_mode = 2
|
||||
ssao_enabled = true
|
||||
glow_enabled = true
|
||||
fog_mode = 1
|
||||
fog_density = 1.0
|
||||
fog_depth_curve = 4.75681
|
||||
|
||||
[sub_resource type="ParticleProcessMaterial" id="ParticleProcessMaterial_21xkr"]
|
||||
lifetime_randomness = 0.55
|
||||
emission_shape = 3
|
||||
@@ -18,25 +36,28 @@ size = Vector2(0.5, 0.5)
|
||||
|
||||
[sub_resource type="BoxShape3D" id="BoxShape3D_21xkr"]
|
||||
|
||||
[node name="Node3D" type="Node3D"]
|
||||
[node name="Main" type="Node3D"]
|
||||
|
||||
[node name="WorldEnvironment" type="WorldEnvironment" parent="."]
|
||||
environment = SubResource("Environment_21xkr")
|
||||
|
||||
[node name="DirectionalLight3D" type="DirectionalLight3D" parent="."]
|
||||
transform = Transform3D(-0.866025, -0.5, -2.18557e-08, 0, -4.37114e-08, 1, -0.5, 0.866025, 3.78552e-08, 0, 0, 0)
|
||||
shadow_enabled = true
|
||||
|
||||
[node name="Road2" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(10.951, 0, 0, 0, 1, 0, 0, 0, 1, -54.1402, 37.1464, -56.7411)
|
||||
transform = Transform3D(10.951, 0, 0, 0, 1, 0, 0, 0, 1, -54.1402, 0.738562, -56.7411)
|
||||
mesh = ExtResource("4_jjvhh")
|
||||
skeleton = NodePath("../Road")
|
||||
|
||||
[node name="Road" type="MeshInstance3D" parent="."]
|
||||
transform = Transform3D(10.9512, 0, 0, 0, 1, 0, 0, 0, 1, -53.9758, 37.1737, -62.1734)
|
||||
transform = Transform3D(10.9512, 0, 0, 0, 1, 0, 0, 0, 1, -54.4288, 0.584906, -61.8752)
|
||||
mesh = ExtResource("4_jjvhh")
|
||||
|
||||
[node name="GPUParticles3D" type="GPUParticles3D" parent="."]
|
||||
transform = Transform3D(3.70763, 0, 0, 0, 2.24982, 0, 0, 0, 3.71542, -7.77808, 47.2887, -60.0289)
|
||||
transform = Transform3D(3.70763, 0, 0, 0, 2.24982, 0, 0, 0, 3.71542, -7.77808, 10.8809, -60.0289)
|
||||
emitting = false
|
||||
amount = 500
|
||||
amount = 1006
|
||||
speed_scale = 5.17
|
||||
randomness = 1.0
|
||||
trail_lifetime = 1.01
|
||||
@@ -44,17 +65,17 @@ process_material = SubResource("ParticleProcessMaterial_21xkr")
|
||||
draw_pass_1 = SubResource("QuadMesh_21xkr")
|
||||
|
||||
[node name="SpotLight3D" type="SpotLight3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.64431, 0.764764, 0, -0.764764, 0.64431, -15.9548, 43.2767, -60.5361)
|
||||
transform = Transform3D(1, 0, 0, 0, 0.64431, 0.764764, 0, -0.764764, 0.64431, -15.9548, 6.86886, -60.5361)
|
||||
light_energy = 1.162
|
||||
spot_range = 23.417
|
||||
spot_angle = 89.99
|
||||
|
||||
[node name="Cart" parent="." node_paths=PackedStringArray("mainCamera") instance=ExtResource("6_21xkr")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.31428, 39.9268, -60.2323)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.31428, 3.18503, -60.2323)
|
||||
mainCamera = NodePath("../RigidBody3D/Camera3D")
|
||||
|
||||
[node name="RigidBody3D" type="RigidBody3D" parent="."]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.05618, 41.42, -58.2918)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -8.05618, 5.01216, -58.2918)
|
||||
collision_layer = 128
|
||||
collision_mask = 128
|
||||
axis_lock_angular_x = true
|
||||
@@ -62,7 +83,7 @@ axis_lock_angular_z = true
|
||||
mass = 0.001
|
||||
gravity_scale = 0.0
|
||||
|
||||
[node name="Camera3D" type="Camera3D" parent="RigidBody3D" node_paths=PackedStringArray("ownRigidBody", "endZoom")]
|
||||
[node name="Camera3D" type="Camera3D" parent="RigidBody3D" node_paths=PackedStringArray("ownRigidBody", "endZoom", "particlesSystem", "worldEnvironmentSystem")]
|
||||
transform = Transform3D(1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 17.894, 14)
|
||||
current = true
|
||||
script = ExtResource("7_6bp64")
|
||||
@@ -70,6 +91,8 @@ rayLength = 1000.0
|
||||
camera_speed = 2.0
|
||||
ownRigidBody = NodePath("..")
|
||||
endZoom = NodePath("../endZoom")
|
||||
particlesSystem = NodePath("../../GPUParticles3D")
|
||||
worldEnvironmentSystem = NodePath("../../WorldEnvironment")
|
||||
|
||||
[node name="DebugLabel1" type="Label" parent="RigidBody3D/Camera3D"]
|
||||
offset_right = 40.0
|
||||
@@ -84,7 +107,7 @@ shape = SubResource("BoxShape3D_21xkr")
|
||||
debug_color = Color(0.895552, 0, 0.381247, 1)
|
||||
|
||||
[node name="ground" parent="." instance=ExtResource("6_344ge")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20.3213, 36.9694, -59.4263)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 20.321, 0.384693, -59.426)
|
||||
|
||||
[node name="ground2" parent="." instance=ExtResource("6_344ge")]
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 180.354, 36.969, -59.426)
|
||||
transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 180.354, 0.385, -59.426)
|
||||
|
||||
41
Scripts/building_area.gd
Normal file
@@ -0,0 +1,41 @@
|
||||
extends StaticBody3D
|
||||
|
||||
@onready var beds = preload("res://Scenes/Prefabs/DoubleBeds.tscn")
|
||||
|
||||
var areas
|
||||
var previewObject: Node3D
|
||||
var is_placed = false
|
||||
func _ready() -> void:
|
||||
areas = get_children()
|
||||
Global.exit_build_mode.connect(_on_exit_build_mode)
|
||||
|
||||
|
||||
func _input_event(camera: Camera3D, event: InputEvent, event_position: Vector3, normal: Vector3, shape_idx: int) -> void:
|
||||
if event.is_action_pressed("mouse_click") and Global.build_mode:
|
||||
place_object()
|
||||
|
||||
|
||||
|
||||
func _mouse_enter() -> void:
|
||||
if !is_placed and Global.build_mode:
|
||||
show_preview()
|
||||
|
||||
func _mouse_exit() -> void:
|
||||
if !is_placed and Global.build_mode:
|
||||
hide_preview()
|
||||
|
||||
func show_preview():
|
||||
previewObject = beds.instantiate()
|
||||
areas[0].add_child(previewObject)
|
||||
|
||||
func hide_preview():
|
||||
if is_placed != true:
|
||||
if previewObject != null:
|
||||
previewObject.queue_free()
|
||||
|
||||
func place_object():
|
||||
is_placed = true
|
||||
|
||||
|
||||
func _on_exit_build_mode():
|
||||
hide_preview()
|
||||
1
Scripts/building_area.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://bcmd74mxocn7e
|
||||
@@ -4,6 +4,8 @@ extends Camera3D
|
||||
@export var camera_speed: float
|
||||
@export var ownRigidBody: RigidBody3D
|
||||
@export var endZoom: Node3D
|
||||
@export var particlesSystem: GPUParticles3D
|
||||
@export var worldEnvironmentSystem: WorldEnvironment
|
||||
var debugLabel
|
||||
var global_delta
|
||||
var default_pos
|
||||
@@ -11,9 +13,13 @@ var default_pos
|
||||
func _ready() -> void:
|
||||
default_pos = self.position
|
||||
debugLabel = $DebugLabel1
|
||||
particlesSystem.emitting = true
|
||||
var environment = worldEnvironmentSystem.environment
|
||||
environment.fog_enabled = true
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
debugLabel.text = "Mode: " + str(Global.build_mode)
|
||||
global_delta = delta
|
||||
look_at(ownRigidBody.position)
|
||||
self.position.y = -0.1 * pow(self.position.z,2) + 40
|
||||
|
||||
@@ -5,31 +5,10 @@ extends Node3D
|
||||
@export var cartTop: MeshInstance3D
|
||||
@export var mainCamera: Camera3D
|
||||
|
||||
var build_mode = false
|
||||
var previewObject
|
||||
var targetPos
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_pressed("hide_top"):
|
||||
cartTop.visible = !cartTop.visible
|
||||
if event.is_action_pressed("enter_build_mode"):
|
||||
build_mode = !build_mode
|
||||
add_preview()
|
||||
|
||||
func _process(_delta: float) -> void:
|
||||
if build_mode:
|
||||
targetPos = mainCamera.getGlobalRayTargetObject()
|
||||
#mainCamera.debugLabel.text = targetPos.collider.name
|
||||
|
||||
if is_instance_valid(targetPos):
|
||||
if targetPos.collider.has_meta("is_building_area"):
|
||||
#if targetPos.collider.is_building_area == true:
|
||||
previewObject.visible = true
|
||||
previewObject.global_position = targetPos.position
|
||||
else:
|
||||
previewObject.visible = false
|
||||
|
||||
|
||||
func add_preview():
|
||||
previewObject = beds.instantiate()
|
||||
get_tree().root.get_child(0).add_child(previewObject)
|
||||
#add_preview()
|
||||
|
||||
17
Scripts/global_script.gd
Normal file
@@ -0,0 +1,17 @@
|
||||
extends Node3D
|
||||
@export var debugLabel1: Label
|
||||
|
||||
|
||||
signal exit_build_mode
|
||||
|
||||
var build_mode: bool = false
|
||||
|
||||
|
||||
func _input(event: InputEvent) -> void:
|
||||
if event.is_action_released("enter_build_mode"):
|
||||
if build_mode:
|
||||
exit_build_mode.emit()
|
||||
build_mode = false
|
||||
else:
|
||||
build_mode = true
|
||||
|
||||
1
Scripts/global_script.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://be4romsmai6jd
|
||||
1
Scripts/small_building_area.gd
Normal file
@@ -0,0 +1 @@
|
||||
extends CollisionShape3D
|
||||
1
Scripts/small_building_area.gd.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://c3sewowdqkd83
|
||||
BIN
Terrain_data/terrain3d-01-01.res
Normal file
BIN
Terrain_data/terrain3d-01_00.res
Normal file
BIN
Terrain_data/terrain3d-02-01.res
Normal file
BIN
Terrain_data/terrain3d_00-01.res
Normal file
21
addons/terrain_3d/LICENSE.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
52
addons/terrain_3d/README.md
Normal file
@@ -0,0 +1,52 @@
|
||||

|
||||
|
||||
# Terrain3D
|
||||
A high performance, editable terrain system for Godot 4.
|
||||
|
||||
|
||||
## Features
|
||||
* Written in C++ as a GDExtension addon, which works with official builds of Godot Engine
|
||||
* [Can be accessed](https://terrain3d.readthedocs.io/en/stable/docs/programming_languages.html) by GDScript, C#, and any language Godot supports
|
||||
* Terrains as small as 64x64m up to 65.5x65.5km (4295km^2) in non-contiguous and variable sized regions
|
||||
* Up to 32 textures
|
||||
* Up to 10 levels of detail for the terrain mesh
|
||||
* Foliage instancing, with up to 10 levels of detail, and a shadow impostor
|
||||
* Sculpting, holes, texture painting, texture detiling, painting colors and wetness
|
||||
* Imports heightmaps from [HTerrain](https://github.com/Zylann/godot_heightmap_plugin/), Gaea, World Creator, World Machine, Unity, Unreal and any tool that can export a heightmap. See [heightmaps](https://terrain3d.readthedocs.io/en/stable/docs/heightmaps.html)
|
||||
|
||||
|
||||
## Games Using Terrain3D
|
||||
|
||||
Please see the [featured games using Terrain3D](https://terrain3d.readthedocs.io/en/latest/docs/games.html) for examples of what it can do.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
1. Read the [Introduction](https://terrain3d.readthedocs.io/en/stable/docs/introduction.html) to understand how this terrain system works.
|
||||
|
||||
2. Read the [Installation & Upgrade](https://terrain3d.readthedocs.io/en/stable/docs/installation.html) instructions.
|
||||
|
||||
3. Watch the [tutorial videos](https://terrain3d.readthedocs.io/en/stable/docs/tutorial_videos.html) and read through the documentation.
|
||||
|
||||
4. For support, read [Getting Help](https://terrain3d.readthedocs.io/en/stable/docs/getting_help.html) and join our [Discord server](https://tokisan.com/discord).
|
||||
|
||||
|
||||
## Credit
|
||||
Developed for the Godot community by:
|
||||
|
||||
|||
|
||||
|--|--|
|
||||
| **Cory Petkovsek, Tokisan Games** | [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/twitter.png?raw=true" width="24"/>](https://twitter.com/TokisanGames) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/github.png?raw=true" width="24"/>](https://github.com/TokisanGames) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/www.png?raw=true" width="24"/>](https://tokisan.com/) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/discord.png?raw=true" width="24"/>](https://tokisan.com/discord) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/youtube.png?raw=true" width="24"/>](https://www.youtube.com/@TokisanGames)|
|
||||
| **Roope Palmroos, Outobugi Games** | [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/twitter.png?raw=true" width="24"/>](https://twitter.com/outobugi) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/github.png?raw=true" width="24"/>](https://github.com/outobugi) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/www.png?raw=true" width="24"/>](https://outobugi.com/) [<img src="https://github.com/dmhendricks/signature-social-icons/blob/master/icons/round-flat-filled/35px/youtube.png?raw=true" width="24"/>](https://www.youtube.com/@outobugi)|
|
||||
|
||||
And the contribution team in [AUTHORS.md](https://terrain3d.readthedocs.io/en/stable/docs/authors.html) and on the right of the github page.
|
||||
|
||||
|
||||
## Contributing
|
||||
|
||||
Please see [CONTRIBUTING.md](https://github.com/TokisanGames/Terrain3D/blob/main/CONTRIBUTING.md) if you would like to help make Terrain3D the best terrain system for Godot.
|
||||
|
||||
|
||||
## License
|
||||
|
||||
This addon has been released under the [MIT License](https://github.com/TokisanGames/Terrain3D/blob/main/LICENSE.txt).
|
||||
BIN
addons/terrain_3d/bin/libterrain.android.debug.arm32.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.android.debug.arm64.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.android.release.arm32.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.android.release.arm64.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.ios.debug.universal.dylib
Normal file
BIN
addons/terrain_3d/bin/libterrain.ios.release.universal.dylib
Normal file
BIN
addons/terrain_3d/bin/libterrain.linux.debug.x86_64.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.linux.release.x86_64.so
Normal file
BIN
addons/terrain_3d/bin/libterrain.web.debug.wasm32.wasm
Normal file
BIN
addons/terrain_3d/bin/libterrain.web.release.wasm32.wasm
Normal file
BIN
addons/terrain_3d/bin/libterrain.windows.debug.x86_64.dll
Normal file
BIN
addons/terrain_3d/bin/libterrain.windows.release.x86_64.dll
Normal file
0
addons/terrain_3d/brushes/.gdignore
Normal file
BIN
addons/terrain_3d/brushes/acrylic1.exr
Normal file
BIN
addons/terrain_3d/brushes/circle0.exr
Normal file
BIN
addons/terrain_3d/brushes/circle1.exr
Normal file
BIN
addons/terrain_3d/brushes/circle2.exr
Normal file
BIN
addons/terrain_3d/brushes/circle3.exr
Normal file
BIN
addons/terrain_3d/brushes/circle4.exr
Normal file
BIN
addons/terrain_3d/brushes/hill1.exr
Normal file
BIN
addons/terrain_3d/brushes/hill2.exr
Normal file
BIN
addons/terrain_3d/brushes/mountain1.exr
Normal file
BIN
addons/terrain_3d/brushes/mountain2.exr
Normal file
BIN
addons/terrain_3d/brushes/mountain3.exr
Normal file
BIN
addons/terrain_3d/brushes/mountain4.exr
Normal file
BIN
addons/terrain_3d/brushes/peak1.exr
Normal file
BIN
addons/terrain_3d/brushes/peak2.exr
Normal file
BIN
addons/terrain_3d/brushes/peak3.exr
Normal file
BIN
addons/terrain_3d/brushes/ring1.exr
Normal file
BIN
addons/terrain_3d/brushes/smoke.exr
Normal file
BIN
addons/terrain_3d/brushes/square1.exr
Normal file
BIN
addons/terrain_3d/brushes/square2.exr
Normal file
BIN
addons/terrain_3d/brushes/square3.exr
Normal file
BIN
addons/terrain_3d/brushes/square4.exr
Normal file
BIN
addons/terrain_3d/brushes/square5.exr
Normal file
BIN
addons/terrain_3d/brushes/stones.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain1.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain2.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain3.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain4.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain5.exr
Normal file
BIN
addons/terrain_3d/brushes/terrain6.exr
Normal file
BIN
addons/terrain_3d/brushes/texture1.exr
Normal file
BIN
addons/terrain_3d/brushes/texture2.exr
Normal file
BIN
addons/terrain_3d/brushes/texture3.exr
Normal file
BIN
addons/terrain_3d/brushes/texture4.exr
Normal file
BIN
addons/terrain_3d/brushes/texture5.exr
Normal file
BIN
addons/terrain_3d/brushes/vegetation1.exr
Normal file
42
addons/terrain_3d/extras/3rd_party/import_sgt.gd
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
# Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
# Import From SimpleGrassTextured
|
||||
#
|
||||
# This script demonstrates how to import transforms from SimpleGrassTextured. To use it:
|
||||
#
|
||||
# 1. Setup the mesh asset you wish to use in the asset dock.
|
||||
# 1. Select your Terrain3D node.
|
||||
# 1. In the inspector, click Script (very bottom) and Quick Load import_sgt.gd.
|
||||
# 1. At the very top, assign your SimpleGrassTextured node.
|
||||
# 1. Input the desired mesh asset ID.
|
||||
# 1. Click import. The output window and console will report when finished.
|
||||
# 1. Clear the script from your Terrain3D node, and save your scene.
|
||||
#
|
||||
# The instance transforms are now stored in your region files.
|
||||
#
|
||||
# Use clear_instances to erase all instances that match the assign_mesh_id.
|
||||
#
|
||||
# The add_transforms function (called by add_multimesh) applies the height_offset specified in the
|
||||
# Terrain3DMeshAsset.
|
||||
# Once the transforms are imported, you can reassign any mesh you like into this mesh slot.
|
||||
|
||||
@tool
|
||||
extends Terrain3D
|
||||
|
||||
@export var simple_grass_textured: MultiMeshInstance3D
|
||||
@export var assign_mesh_id: int
|
||||
@export var import: bool = false : set = import_sgt
|
||||
@export var clear_instances: bool = false : set = clear_multimeshes
|
||||
|
||||
|
||||
func clear_multimeshes(value: bool) -> void:
|
||||
get_instancer().clear_by_mesh(assign_mesh_id)
|
||||
|
||||
|
||||
func import_sgt(value: bool) -> void:
|
||||
var sgt_mm: MultiMesh = simple_grass_textured.multimesh
|
||||
var global_xform: Transform3D = simple_grass_textured.global_transform
|
||||
print("Starting to import %d instances from SimpleGrassTextured using mesh id %d" % [ sgt_mm.instance_count, assign_mesh_id])
|
||||
var time: int = Time.get_ticks_msec()
|
||||
get_instancer().add_multimesh(assign_mesh_id, sgt_mm, simple_grass_textured.global_transform)
|
||||
print("Import complete in %.2f seconds" % [ float(Time.get_ticks_msec() - time)/1000. ])
|
||||
|
||||
1
addons/terrain_3d/extras/3rd_party/import_sgt.gd.uid
vendored
Normal file
@@ -0,0 +1 @@
|
||||
uid://bllcuwetve45k
|
||||
137
addons/terrain_3d/extras/3rd_party/project_on_terrain3d.gd
vendored
Normal file
@@ -0,0 +1,137 @@
|
||||
# Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
# This script is an addon for HungryProton's Scatter https://github.com/HungryProton/scatter
|
||||
# It provides a `Project on Terrain3D` modifier, which allows Scatter
|
||||
# to detect the terrain height from Terrain3D without using collision.
|
||||
#
|
||||
# Copy this file into /addons/proton_scatter/src/modifiers
|
||||
# Then uncomment everything below (select, press CTRL+K)
|
||||
# In the editor, add this modifier to Scatter, then set your Terrain3D node
|
||||
|
||||
#@tool
|
||||
#extends "base_modifier.gd"
|
||||
#
|
||||
#
|
||||
#signal projection_completed
|
||||
#
|
||||
#
|
||||
#@export var terrain_node : NodePath
|
||||
#@export var align_with_collision_normal : bool = false
|
||||
#@export_range(0.0, 90.0, 0.1) var max_slope : float = 90.0
|
||||
#@export var enable_texture_filtering : bool = false
|
||||
#@export_range(0, 31) var target_texture_id : int = 0
|
||||
#@export var not_target_texture : bool = false
|
||||
#@export_range(0.0, 1.0, 0.01) var texture_threshold : float = 0.8
|
||||
#
|
||||
#var _terrain: Terrain3D
|
||||
#
|
||||
#
|
||||
#func _init() -> void:
|
||||
#display_name = "Project On Terrain3D"
|
||||
#category = "Edit"
|
||||
#can_restrict_height = false
|
||||
#global_reference_frame_available = true
|
||||
#local_reference_frame_available = true
|
||||
#individual_instances_reference_frame_available = true
|
||||
#use_global_space_by_default()
|
||||
#
|
||||
#documentation.add_paragraph(
|
||||
#"This is a modified version of `Project on Colliders` that queries Terrain3D
|
||||
#for heights without using collision. It constrains placement by slope or texture.
|
||||
#
|
||||
#This modifier must have terrain_node set to a Terrain3D node.")
|
||||
#
|
||||
#var p := documentation.add_parameter("Terrain Node")
|
||||
#p.set_type("NodePath")
|
||||
#p.set_description("Set your Terrain3D node.")
|
||||
#
|
||||
#p = documentation.add_parameter("Align with collision normal")
|
||||
#p.set_type("bool")
|
||||
#p.set_description(
|
||||
#"Rotate the transform to align it with the collision normal in case
|
||||
#the ray cast hit a collider.")
|
||||
#
|
||||
#p = documentation.add_parameter("Enable Texture Filtering")
|
||||
#p.set_type("bool")
|
||||
#p.set_description(
|
||||
#"If enabled, objects will only be placed based on the ground texture specified.")
|
||||
#
|
||||
#p = documentation.add_parameter("Target Texture ID")
|
||||
#p.set_type("int")
|
||||
#p.set_description(
|
||||
#"The ID of the texture to place objects on (0-31). Objects will only be placed on this texture.")
|
||||
#
|
||||
#p = documentation.add_parameter("Not Target Texture")
|
||||
#p.set_type("bool")
|
||||
#p.set_description(
|
||||
#"If true, objects will be placed on all textures EXCEPT the target texture.")
|
||||
#
|
||||
#p = documentation.add_parameter("Texture Threshold")
|
||||
#p.set_type("float")
|
||||
#p.set_description("The blend value required for placement on the texture.")
|
||||
#
|
||||
#
|
||||
#func _process_transforms(transforms, domain, _seed) -> void:
|
||||
#if transforms.is_empty():
|
||||
#return
|
||||
#
|
||||
#if terrain_node:
|
||||
#_terrain = domain.get_root().get_node_or_null(terrain_node)
|
||||
#
|
||||
#if not _terrain:
|
||||
#warning += """No Terrain3D node found"""
|
||||
#return
|
||||
#
|
||||
#if not _terrain.data:
|
||||
#warning += """Terrain3DData is not initialized"""
|
||||
#return
|
||||
#
|
||||
## Review transforms
|
||||
#var gt: Transform3D = domain.get_global_transform()
|
||||
#var gt_inverse := gt.affine_inverse()
|
||||
#var new_transforms_array: Array[Transform3D] = []
|
||||
#var remapped_max_slope: float = remap(max_slope, 0.0, 90.0, 0.0, 1.0)
|
||||
#for i in transforms.list.size():
|
||||
#var t: Transform3D = transforms.list[i]
|
||||
#
|
||||
#var location: Vector3 = (gt * t).origin
|
||||
#var height: float = _terrain.data.get_height(location)
|
||||
#if is_nan(height):
|
||||
#continue
|
||||
#
|
||||
#var normal: Vector3 = _terrain.data.get_normal(location)
|
||||
#if not abs(Vector3.UP.dot(normal)) >= (1.0 - remapped_max_slope):
|
||||
#continue
|
||||
#
|
||||
#if enable_texture_filtering:
|
||||
#var texture_info: Vector3 = _terrain.data.get_texture_id(location)
|
||||
#var base_id: int = int(texture_info.x)
|
||||
#var overlay_id: int = int(texture_info.y)
|
||||
#var blend_value: float = texture_info.z
|
||||
## Skip if overlay or blend != target texture, unless inverted
|
||||
#if ((overlay_id != target_texture_id or blend_value < texture_threshold) and \
|
||||
#(base_id != target_texture_id or blend_value >= texture_threshold)) != not_target_texture:
|
||||
#continue
|
||||
#
|
||||
#if align_with_collision_normal and not is_nan(normal.x):
|
||||
#t.basis.y = normal
|
||||
#t.basis.x = -t.basis.z.cross(normal)
|
||||
#t.basis = t.basis.orthonormalized()
|
||||
#
|
||||
#t.origin.y = height - gt.origin.y
|
||||
#new_transforms_array.push_back(t)
|
||||
#
|
||||
#transforms.list.clear()
|
||||
#transforms.list.append_array(new_transforms_array)
|
||||
#
|
||||
#if transforms.is_empty():
|
||||
#warning += """All transforms have been removed. Possible reasons include: \n"""
|
||||
#if enable_texture_filtering:
|
||||
#warning += """+ No matching texture found at any position.
|
||||
#+ Texture threshold may be too high.
|
||||
#"""
|
||||
#warning += """+ No collider is close enough to the shapes.
|
||||
#+ Ray length is too short.
|
||||
#+ Ray direction is incorrect.
|
||||
#+ Collision mask is not set properly.
|
||||
#+ Max slope is too low.
|
||||
#"""
|
||||
1
addons/terrain_3d/extras/3rd_party/project_on_terrain3d.gd.uid
vendored
Normal file
@@ -0,0 +1 @@
|
||||
uid://g3opjh3m3iww
|
||||
@@ -0,0 +1,25 @@
|
||||
[gd_scene load_steps=5 format=3 uid="uid://d3sr0a7dxfkr8"]
|
||||
|
||||
[ext_resource type="Script" uid="uid://bp7r4ppgq1m0g" path="res://addons/terrain_3d/extras/particle_example/terrain_3D_particles.gd" id="1_gl3qg"]
|
||||
[ext_resource type="Material" uid="uid://el5y10hnh13g" path="res://addons/terrain_3d/extras/particle_example/process_material.tres" id="2_2gon1"]
|
||||
[ext_resource type="Material" uid="uid://ljo1wt61kbkq" path="res://addons/terrain_3d/extras/particle_example/grass_material.tres" id="3_qyjnw"]
|
||||
|
||||
[sub_resource type="RibbonTrailMesh" id="RibbonTrailMesh_fwrtk"]
|
||||
shape = 0
|
||||
section_length = 0.18
|
||||
section_segments = 1
|
||||
|
||||
[node name="Terrain3DParticles" type="Node3D"]
|
||||
script = ExtResource("1_gl3qg")
|
||||
instance_spacing = 0.25
|
||||
cell_width = 24.0
|
||||
grid_width = 5
|
||||
rows = 96
|
||||
amount = 9216
|
||||
process_material = ExtResource("2_2gon1")
|
||||
mesh = SubResource("RibbonTrailMesh_fwrtk")
|
||||
shadow_mode = 0
|
||||
mesh_material_override = ExtResource("3_qyjnw")
|
||||
min_draw_distance = 60.0
|
||||
particle_count = 230400
|
||||
metadata/_edit_lock_ = true
|
||||
69
addons/terrain_3d/extras/particle_example/grass.gdshader
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
|
||||
shader_type spatial;
|
||||
|
||||
render_mode skip_vertex_transform, cull_disabled, blend_mix;
|
||||
|
||||
uniform vec2 wind_direction = vec2(1.0, 1.0);
|
||||
|
||||
varying vec4 data;
|
||||
|
||||
// A lot of hard coded things here atm.
|
||||
void vertex() {
|
||||
// Wind effect from model data, in this case no vertex colors,
|
||||
// so just use vertex Y component, including mesh offset
|
||||
data[2] = (VERTEX.y + 0.55);
|
||||
data[2] *= data[2]; // make non-linear
|
||||
|
||||
// Ribbon used as a grass mesh.. so pinch the top.
|
||||
VERTEX.xz *= (1.0 - data[2]);
|
||||
|
||||
// Brighten tips
|
||||
COLOR = mix(COLOR, vec4(1.0), smoothstep(0.9, 1.0, data[2]));
|
||||
// Darken base, skip is scale is less than threshold, as this means "grow in" is occuring.
|
||||
COLOR *= INSTANCE_CUSTOM[3] < 0.35 ? 1. : mix(1.0, 0.75, smoothstep(0.35, 0.0, data[2]));
|
||||
// Save red/green shift for fragment
|
||||
data.rg = INSTANCE_CUSTOM.rg;
|
||||
|
||||
// World space vertex
|
||||
vec3 w_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
// Get wind force and scale from process()
|
||||
float scale = pow(INSTANCE_CUSTOM[3] * INSTANCE_CUSTOM[3], 0.707);
|
||||
float force = INSTANCE_CUSTOM[2] * data[2] * scale;
|
||||
// Add some cheap jitter at high wind values
|
||||
force -= fract(force * 256.0) * force * 0.05;
|
||||
// Curve the result
|
||||
force = pow(force, 0.707);
|
||||
|
||||
// These 2 combined result in a decent bend without resorting to matrices or pivot data.
|
||||
// Lateral move and wobble
|
||||
float lateral_wobble = sin(TIME * 2.0 * (1.0 + data.r + data.g)) * 0.25 * (1.0 - INSTANCE_CUSTOM[2]);
|
||||
vec2 direction = normalize(wind_direction);
|
||||
w_vertex.xz -= (vec2(-direction.y, direction.x) * lateral_wobble + direction) * force;
|
||||
// Flatten
|
||||
w_vertex.y -= INSTANCE_CUSTOM[2] * force * data[2];
|
||||
|
||||
// Save final wind force value for fragment.
|
||||
data[3] = force;
|
||||
|
||||
VERTEX = (VIEW_MATRIX * vec4(w_vertex, 1.0)).xyz;
|
||||
NORMAL = MODELVIEW_NORMAL_MATRIX * NORMAL;
|
||||
BINORMAL = MODELVIEW_NORMAL_MATRIX * BINORMAL;
|
||||
TANGENT = MODELVIEW_NORMAL_MATRIX * TANGENT;
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// Hard coded color.
|
||||
ALBEDO = vec3(0.20, 0.22, 0.05) * (data[2] * 0.5 + 0.5);
|
||||
ALBEDO.rg *= (data.rg * 0.3 + 0.9);
|
||||
ALBEDO *= pow(COLOR.rgb, vec3(2.2));
|
||||
// Modify roughness / specular based on wind force for added detail
|
||||
float spec_rough = clamp(max(data[2], data[3]), 0., 1.);
|
||||
ROUGHNESS = 1. - spec_rough;
|
||||
SPECULAR = clamp(spec_rough * 0.25, 0., .15);
|
||||
|
||||
BACKLIGHT = vec3(0.33);
|
||||
#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
|
||||
ALBEDO = pow(ALBEDO, vec3(0.4));
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dq3lfyp3u5oxt
|
||||
@@ -0,0 +1,8 @@
|
||||
[gd_resource type="ShaderMaterial" load_steps=2 format=3 uid="uid://ljo1wt61kbkq"]
|
||||
|
||||
[ext_resource type="Shader" uid="uid://dq3lfyp3u5oxt" path="res://addons/terrain_3d/extras/particle_example/grass.gdshader" id="1_nkru0"]
|
||||
|
||||
[resource]
|
||||
render_priority = 0
|
||||
shader = ExtResource("1_nkru0")
|
||||
shader_parameter/wind_direction = Vector2(1, 1)
|
||||
275
addons/terrain_3d/extras/particle_example/particles.gdshader
Normal file
@@ -0,0 +1,275 @@
|
||||
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
|
||||
// This is an example particle shader designed to procedurally place
|
||||
// particles like grass, small rocks, and other ground effects, on the terrain
|
||||
// surface by reading the Terrain3D data maps. It works in tandem with the
|
||||
// provided GDScript.
|
||||
|
||||
shader_type particles;
|
||||
render_mode disable_velocity, disable_force;
|
||||
|
||||
group_uniforms options;
|
||||
uniform sampler2D main_noise;
|
||||
uniform float main_noise_scale = 0.01;
|
||||
uniform vec3 position_offset = vec3(0.);
|
||||
uniform bool align_to_normal = true;
|
||||
uniform float normal_strength : hint_range(0.01, 1.0, 0.01) = 0.3;
|
||||
uniform bool random_rotation = true;
|
||||
uniform float random_spacing : hint_range(0.0, 1.0, 0.01) = 0.5;
|
||||
uniform vec3 min_scale = vec3(1.0);
|
||||
uniform vec3 max_scale = vec3(1.0);
|
||||
|
||||
group_uniforms wind;
|
||||
uniform float noise_scale = 0.0041;
|
||||
uniform float wind_speed = 0.025;
|
||||
uniform float wind_strength : hint_range(0.0, 1.0, 0.01) = 1.0;
|
||||
uniform float wind_dithering = 4.0;
|
||||
uniform vec2 wind_direction = vec2(1.0,1.0);
|
||||
|
||||
group_uniforms shapeing;
|
||||
uniform float clod_scale_boost = 3.0;
|
||||
uniform float clod_min_threshold : hint_range(0.0, 1.0, 0.001) = 0.2;
|
||||
uniform float clod_max_threshold : hint_range(0.0, 1.0, 0.001) = 0.5;
|
||||
uniform float patch_min_threshold : hint_range(0.0, 1.0, 0.001) = 0.025;
|
||||
uniform float patch_max_threshold : hint_range(0.0, 1.0, 0.001) = 0.2;
|
||||
|
||||
group_uniforms filtering;
|
||||
uniform float condition_dither_range : hint_range(0.0, 1.0, 0.01) = 0.15;
|
||||
uniform float surface_slope_min : hint_range(0.0, 1.0, 0.01) = 0.87;
|
||||
uniform float distance_fade_ammount : hint_range(0.0, 1.0, 0.01) = 0.5;
|
||||
|
||||
group_uniforms private;
|
||||
uniform float max_dist = 1.;
|
||||
uniform vec3 camera_position = vec3(0.);
|
||||
uniform uint instance_rows = 1;
|
||||
uniform float instance_spacing = 0.5;
|
||||
uniform uint _background_mode = 0u;
|
||||
uniform float _vertex_spacing = 1.0;
|
||||
uniform float _vertex_density = 1.0; // = 1/_vertex_spacing
|
||||
uniform float _region_size = 1024.0;
|
||||
uniform float _region_texel_size = 0.0009765625; // = 1/REGION_SIZE
|
||||
uniform int _region_map_size = 32;
|
||||
uniform int _region_map[1024];
|
||||
uniform vec2 _region_locations[1024];
|
||||
uniform highp sampler2DArray _height_maps : repeat_disable;
|
||||
uniform highp sampler2DArray _control_maps : repeat_disable;
|
||||
uniform highp sampler2DArray _color_maps : repeat_disable;
|
||||
|
||||
// Defined Constants
|
||||
#define SKIP_PASS 0
|
||||
#define VERTEX_PASS 1
|
||||
#define FRAGMENT_PASS 2
|
||||
|
||||
// Takes in world space XZ (UV) coordinates & search depth (only applicable for background mode none)
|
||||
// Returns ivec3 with:
|
||||
// XY: (0 to _region_size - 1) coordinates within a region
|
||||
// Z: layer index used for texturearrays, -1 if not in a region
|
||||
ivec3 get_index_coord(const vec2 uv, const int search) {
|
||||
vec2 r_uv = round(uv);
|
||||
vec2 o_uv = mod(r_uv,_region_size);
|
||||
ivec2 pos;
|
||||
int bounds, layer_index = -1;
|
||||
for (int i = -1; i < 0; i++) {
|
||||
if ((layer_index == -1 && _background_mode == 0u) || i < 0) {
|
||||
r_uv -= i == -1 ? vec2(0.0) : vec2(float(o_uv.x <= o_uv.y), float(o_uv.y <= o_uv.x));
|
||||
pos = ivec2(floor((r_uv) * _region_texel_size)) + (_region_map_size / 2);
|
||||
bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
|
||||
layer_index = (_region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1);
|
||||
}
|
||||
}
|
||||
return ivec3(ivec2(mod(r_uv,_region_size)), layer_index);
|
||||
}
|
||||
|
||||
#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
|
||||
#define fma(a, b, c) ((a) * (b) + (c))
|
||||
#endif
|
||||
float random(vec2 v) {
|
||||
return fract(1e4 * sin(fma(17.0, v.x, v.y * 0.1)) * (0.1 + abs(sin(fma(v.y, 13.0, v.x)))));
|
||||
}
|
||||
|
||||
mat3 rotation_matrix(vec3 axis, float angle) {
|
||||
float c = cos(angle);
|
||||
float s = sin(angle);
|
||||
float t = 1.0 - c;
|
||||
vec3 n = normalize(axis);
|
||||
float x = n.x;
|
||||
float y = n.y;
|
||||
float z = n.z;
|
||||
|
||||
return mat3(
|
||||
vec3(t * x * x + c, t * x * y - z * s, t * x * z + y * s),
|
||||
vec3(t * x * y + z * s, t * y * y + c, t * y * z - x * s),
|
||||
vec3(t * x * z - y * s, t * y * z + x * s, t * z * z + c));
|
||||
}
|
||||
|
||||
mat3 align_to_vector(vec3 normal) {
|
||||
vec3 up = vec3(0.0, 1.0, 0.0);
|
||||
if (abs(dot(normal, up)) > 0.9999) { // Avoid singularity
|
||||
up = vec3(1.0, 0.0, 0.0);
|
||||
}
|
||||
vec3 tangent = normalize(cross(up, normal));
|
||||
vec3 bitangent = normalize(cross(tangent, normal));
|
||||
return mat3(tangent, normal, bitangent);
|
||||
}
|
||||
|
||||
void start() {
|
||||
// Create centered a grid
|
||||
vec3 pos = vec3(float(INDEX % instance_rows), 0.0, float(INDEX / instance_rows)) - float(instance_rows >> 1u);
|
||||
|
||||
// Apply spcaing
|
||||
pos *= instance_spacing;
|
||||
// Move the grid to the emitter, snapping is handled CPU side
|
||||
pos.xz += EMISSION_TRANSFORM[3].xz;
|
||||
|
||||
// Create random values per-instance, incorporating the seed, mask bits to avoid NAN/INF
|
||||
float seed = fract(uintBitsToFloat(RANDOM_SEED & 0x7EFFFFFFu));
|
||||
vec3 r = fract(vec3(random(pos.xz), random(pos.xz + vec2(0.5)), random(pos.xz - vec2(0.5))) + seed);
|
||||
// Randomize instance spacing
|
||||
pos.x += ((r.x * 2.0) - 1.0) * random_spacing * instance_spacing;
|
||||
pos.z += ((r.z * 2.0) - 1.0) * random_spacing * instance_spacing;
|
||||
|
||||
// Lookup offsets, ID and blend weight
|
||||
const vec3 offsets = vec3(0, 1, 2);
|
||||
vec2 index_id = floor(pos.xz * _vertex_density);
|
||||
vec2 weight = fract(pos.xz * _vertex_density);
|
||||
vec2 invert = 1.0 - weight;
|
||||
vec4 weights = vec4(
|
||||
invert.x * weight.y, // 0
|
||||
weight.x * weight.y, // 1
|
||||
weight.x * invert.y, // 2
|
||||
invert.x * invert.y // 3
|
||||
);
|
||||
|
||||
ivec3 index[4];
|
||||
// Map lookups
|
||||
index[0] = get_index_coord(index_id + offsets.xy, VERTEX_PASS);
|
||||
index[1] = get_index_coord(index_id + offsets.yy, VERTEX_PASS);
|
||||
index[2] = get_index_coord(index_id + offsets.yx, VERTEX_PASS);
|
||||
index[3] = get_index_coord(index_id + offsets.xx, VERTEX_PASS);
|
||||
|
||||
highp float h[8];
|
||||
h[0] = texelFetch(_height_maps, index[0], 0).r; // 0 (0,1)
|
||||
h[1] = texelFetch(_height_maps, index[1], 0).r; // 1 (1,1)
|
||||
h[2] = texelFetch(_height_maps, index[2], 0).r; // 2 (1,0)
|
||||
h[3] = texelFetch(_height_maps, index[3], 0).r; // 3 (0,0)
|
||||
h[4] = texelFetch(_height_maps, get_index_coord(index_id + offsets.yz, VERTEX_PASS), 0).r; // 4 (1,2)
|
||||
h[5] = texelFetch(_height_maps, get_index_coord(index_id + offsets.zy, VERTEX_PASS), 0).r; // 5 (2,1)
|
||||
h[6] = texelFetch(_height_maps, get_index_coord(index_id + offsets.zx, VERTEX_PASS), 0).r; // 6 (2,0)
|
||||
h[7] = texelFetch(_height_maps, get_index_coord(index_id + offsets.xz, VERTEX_PASS), 0).r; // 7 (0,2)
|
||||
vec3 index_normal[4];
|
||||
index_normal[0] = vec3(h[0] - h[1], _vertex_spacing, h[0] - h[7]);
|
||||
index_normal[1] = vec3(h[1] - h[5], _vertex_spacing, h[1] - h[4]);
|
||||
index_normal[2] = vec3(h[2] - h[6], _vertex_spacing, h[2] - h[1]);
|
||||
index_normal[3] = vec3(h[3] - h[2], _vertex_spacing, h[3] - h[0]);
|
||||
vec3 w_normal = normalize(
|
||||
index_normal[0] * weights[0] +
|
||||
index_normal[1] * weights[1] +
|
||||
index_normal[2] * weights[2] +
|
||||
index_normal[3] * weights[3]);
|
||||
|
||||
// Set the height according to the heightmap data
|
||||
pos.y =
|
||||
h[0] * weights[0] +
|
||||
h[1] * weights[1] +
|
||||
h[2] * weights[2] +
|
||||
h[3] * weights[3] ;
|
||||
|
||||
// Offset, Rotation, Alignment.
|
||||
TRANSFORM = mat4(1.0);
|
||||
vec3 orientation = vec3(0., 1., 0.);
|
||||
|
||||
vec2 uv = (pos.xz) * main_noise_scale;
|
||||
float noise = textureLod(main_noise, uv, 0.0).r;
|
||||
float clods = smoothstep(clod_min_threshold, clod_max_threshold, noise) * clod_scale_boost;
|
||||
float patch = smoothstep(patch_min_threshold, patch_max_threshold, noise);
|
||||
float width_modifier = 1.0 + 3.0 * smoothstep(0., max_dist, length(camera_position - pos));
|
||||
|
||||
// Calculate scale
|
||||
vec3 scale = vec3(
|
||||
mix(min_scale.x, max_scale.x, r.x) * width_modifier,
|
||||
mix(min_scale.y, max_scale.y, r.y) + clods,
|
||||
mix(min_scale.z, max_scale.z, r.z) * width_modifier) * patch;
|
||||
|
||||
// Apply scale to offset
|
||||
vec3 offset = position_offset * scale;
|
||||
|
||||
// Apply normal orientation
|
||||
if (align_to_normal) {
|
||||
orientation = mix(orientation, w_normal, normal_strength);
|
||||
mat3 alignment = align_to_vector(orientation);
|
||||
offset = alignment * offset;
|
||||
TRANSFORM = mat4(alignment);
|
||||
}
|
||||
|
||||
// Apply rotation around orientation
|
||||
if (random_rotation) {
|
||||
mat3 rotation = rotation_matrix(orientation, r.x * TAU);
|
||||
TRANSFORM = mat4(rotation) * TRANSFORM;
|
||||
}
|
||||
|
||||
// Filtering - Causes some particles to be rendered as degenerate triangles
|
||||
// via 0./0. - Particles filtered this way are still processed by the GPU.
|
||||
// For compatibility it seems we must shift as well.
|
||||
// Surface slope filtering
|
||||
if (surface_slope_min > w_normal.y + (r.y - 0.5) * condition_dither_range) {
|
||||
pos.y = 0. / 0.;
|
||||
pos.xz = vec2(100000.0);
|
||||
}
|
||||
|
||||
// Read color map
|
||||
highp vec4 c[4];
|
||||
#define COLOR_MAP vec4(1., 1., 1., 0.5)
|
||||
c[0] = index[0].z >= 0 ? texelFetch(_color_maps, index[0], 0) : COLOR_MAP; // 0 (0,1)
|
||||
c[1] = index[1].z >= 0 ? texelFetch(_color_maps, index[1], 0) : COLOR_MAP; // 1 (1,1)
|
||||
c[2] = index[2].z >= 0 ? texelFetch(_color_maps, index[2], 0) : COLOR_MAP; // 2 (1,0)
|
||||
c[3] = index[3].z >= 0 ? texelFetch(_color_maps, index[3], 0) : COLOR_MAP; // 3 (0,0)
|
||||
vec4 color_map =
|
||||
c[0] * weights[0] +
|
||||
c[1] * weights[1] +
|
||||
c[2] * weights[2] +
|
||||
c[3] * weights[3] ;
|
||||
|
||||
COLOR = color_map;
|
||||
|
||||
// Read control map
|
||||
uint control = floatBitsToUint(texelFetch(_control_maps, index[3], 0).r);
|
||||
bool auto = bool(control & 0x1u);
|
||||
int base = int(control >>27u & 0x1Fu);
|
||||
int over = int(control >> 22u & 0x1Fu);
|
||||
float blend = float(control >> 14u & 0xFFu) * 0.003921568627450; // 1. / 255.
|
||||
|
||||
// Hardcoded example, hand painted texture id 0 is filtered out.
|
||||
if (!auto && ((base == 0 && blend < 0.7) || (over == 0 && blend >= 0.3))) {
|
||||
pos.y = 0. / 0.;
|
||||
pos.xz = vec2(100000.0);
|
||||
}
|
||||
|
||||
if (length(camera_position - pos) > max_dist) {
|
||||
pos.y = 0. / 0.;
|
||||
pos.xz = vec2(100000.0);
|
||||
} else {
|
||||
float fade_factor = 1.0 - smoothstep(max_dist * distance_fade_ammount, max_dist + 0.0001, length(camera_position - pos)) + 0.001;
|
||||
scale.y *= fade_factor;
|
||||
offset *= fade_factor;
|
||||
}
|
||||
|
||||
// Apply scale
|
||||
TRANSFORM[0] *= scale.x;
|
||||
TRANSFORM[1] *= scale.y;
|
||||
TRANSFORM[2] *= scale.z;
|
||||
|
||||
// Apply the position
|
||||
TRANSFORM[3].xyz = pos.xyz + offset;
|
||||
|
||||
// Save Fixed 2 Random values for Reg/Green color randomness
|
||||
CUSTOM.rg = r.rg;
|
||||
// Save Y component scale pre-rotation
|
||||
CUSTOM[3] = scale.y;
|
||||
}
|
||||
|
||||
void process() {
|
||||
// Extract world space UV from Transform Matrix
|
||||
vec2 uv = (TRANSFORM[3].xz + CUSTOM.rg * wind_dithering) * noise_scale;
|
||||
// Scaled wind noise, updated per instance, at process FPS. Passed to Vertex()
|
||||
CUSTOM[2] = textureLod(main_noise, uv + TIME * wind_speed * normalize(wind_direction), 0.0).r * wind_strength;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://dce675i014xcn
|
||||
@@ -0,0 +1,237 @@
|
||||
# Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
#
|
||||
# This is an example of using a particle shader with Terrain3D.
|
||||
# To use it, add `Terrain3DParticles.tscn` to your scene and assign the terrain.
|
||||
# Then customize the settings, materials and shader to extend it and make it your own.
|
||||
|
||||
@tool
|
||||
extends Node3D
|
||||
|
||||
|
||||
#region settings
|
||||
## Auto set if attached as a child of a Terrain3D node
|
||||
@export var terrain: Terrain3D:
|
||||
set(value):
|
||||
terrain = value
|
||||
_create_grid()
|
||||
|
||||
|
||||
## Distance between instances
|
||||
@export_range(0.125, 2.0, 0.015625) var instance_spacing: float = 0.5:
|
||||
set(value):
|
||||
instance_spacing = clamp(round(value * 64.0) * 0.015625, 0.125, 2.0)
|
||||
rows = maxi(int(cell_width / instance_spacing), 1)
|
||||
amount = rows * rows
|
||||
_set_offsets()
|
||||
|
||||
|
||||
## Width of an individual cell of the grid
|
||||
@export_range(8.0, 256.0, 1.0) var cell_width: float = 32.0:
|
||||
set(value):
|
||||
cell_width = clamp(value, 8.0, 256.0)
|
||||
rows = maxi(int(cell_width / instance_spacing), 1)
|
||||
amount = rows * rows
|
||||
min_draw_distance = 1.0
|
||||
# Have to update aabb
|
||||
if terrain and terrain.data:
|
||||
var height_range: Vector2 = terrain.data.get_height_range()
|
||||
var height: float = height_range[0] - height_range[1]
|
||||
var aabb: AABB = AABB()
|
||||
aabb.size = Vector3(cell_width, height, cell_width)
|
||||
aabb.position = aabb.size * -0.5
|
||||
aabb.position.y = height_range[1]
|
||||
for p in particle_nodes:
|
||||
p.custom_aabb = aabb
|
||||
_set_offsets()
|
||||
|
||||
|
||||
## Grid width. Must be odd.
|
||||
## Higher values cull slightly better, draw further out.
|
||||
@export_range(1, 15, 2) var grid_width: int = 9:
|
||||
set(value):
|
||||
grid_width = value
|
||||
particle_count = 1
|
||||
min_draw_distance = 1.0
|
||||
_create_grid()
|
||||
|
||||
|
||||
@export_storage var rows: int = 1
|
||||
|
||||
@export_storage var amount: int = 1:
|
||||
set(value):
|
||||
amount = value
|
||||
particle_count = value
|
||||
last_pos = Vector3.ZERO
|
||||
for p in particle_nodes:
|
||||
p.amount = amount
|
||||
|
||||
|
||||
@export_range(1, 256, 1) var process_fixed_fps: int = 30:
|
||||
set(value):
|
||||
process_fixed_fps = maxi(value, 1)
|
||||
for p in particle_nodes:
|
||||
p.fixed_fps = process_fixed_fps
|
||||
p.preprocess = 1.0 / float(process_fixed_fps)
|
||||
|
||||
|
||||
## Access to process material parameters
|
||||
@export var process_material: ShaderMaterial
|
||||
|
||||
## The mesh that each particle will render
|
||||
@export var mesh: Mesh
|
||||
|
||||
@export var shadow_mode: GeometryInstance3D.ShadowCastingSetting = (
|
||||
GeometryInstance3D.ShadowCastingSetting.SHADOW_CASTING_SETTING_ON):
|
||||
set(value):
|
||||
shadow_mode = value
|
||||
for p in particle_nodes:
|
||||
p.cast_shadow = value
|
||||
|
||||
|
||||
## Override material for the particle mesh
|
||||
@export_custom(
|
||||
PROPERTY_HINT_RESOURCE_TYPE,
|
||||
"BaseMaterial3D,ShaderMaterial") var mesh_material_override: Material:
|
||||
set(value):
|
||||
mesh_material_override = value
|
||||
for p in particle_nodes:
|
||||
p.material_override = mesh_material_override
|
||||
|
||||
|
||||
@export_group("Info")
|
||||
## The minimum distance that particles will be drawn upto
|
||||
## If using fade out effects like pixel alpha this is the limit to use.
|
||||
@export var min_draw_distance: float = 1.0:
|
||||
set(value):
|
||||
min_draw_distance = float(cell_width * grid_width) * 0.5
|
||||
|
||||
|
||||
## Displays current total particle count based on Cell Width and Instance Spacing
|
||||
@export var particle_count: int = 1:
|
||||
set(value):
|
||||
particle_count = amount * grid_width * grid_width
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
var offsets: Array[Vector3]
|
||||
var last_pos: Vector3 = Vector3.ZERO
|
||||
var particle_nodes: Array[GPUParticles3D]
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
if not terrain:
|
||||
var parent: Node = get_parent()
|
||||
if parent is Terrain3D:
|
||||
terrain = parent
|
||||
_create_grid()
|
||||
|
||||
|
||||
func _notification(what: int) -> void:
|
||||
if what == NOTIFICATION_PREDELETE:
|
||||
_destroy_grid()
|
||||
|
||||
|
||||
func _physics_process(delta: float) -> void:
|
||||
if terrain:
|
||||
var camera: Camera3D = terrain.get_camera()
|
||||
if camera:
|
||||
if last_pos.distance_squared_to(camera.global_position) > 1.0:
|
||||
var pos: Vector3 = camera.global_position.snapped(Vector3.ONE)
|
||||
_position_grid(pos)
|
||||
RenderingServer.material_set_param(process_material.get_rid(), "camera_position", pos )
|
||||
last_pos = camera.global_position
|
||||
_update_process_parameters()
|
||||
else:
|
||||
set_physics_process(false)
|
||||
|
||||
|
||||
func _create_grid() -> void:
|
||||
_destroy_grid()
|
||||
if not terrain:
|
||||
return
|
||||
set_physics_process(true)
|
||||
_set_offsets()
|
||||
var hr: Vector2 = terrain.data.get_height_range()
|
||||
var height: float = hr.x - hr.y
|
||||
var aabb: AABB = AABB()
|
||||
aabb.size = Vector3(cell_width, height, cell_width)
|
||||
aabb.position = aabb.size * -0.5
|
||||
aabb.position.y = hr.y
|
||||
var half_grid: int = grid_width / 2
|
||||
# Iterating the array like this allows identifying grid position, in case setting
|
||||
# different mesh or materials is desired for LODs etc.
|
||||
for x in range(-half_grid, half_grid + 1):
|
||||
for z in range(-half_grid, half_grid + 1):
|
||||
#var ring: int = maxi(maxi(absi(x), absi(z)), 0)
|
||||
var particle_node = GPUParticles3D.new()
|
||||
particle_node.lifetime = 600.0
|
||||
particle_node.amount = amount
|
||||
particle_node.explosiveness = 1.0
|
||||
particle_node.amount_ratio = 1.0
|
||||
particle_node.process_material = process_material
|
||||
particle_node.draw_pass_1 = mesh
|
||||
particle_node.speed_scale = 1.0
|
||||
particle_node.custom_aabb = aabb
|
||||
particle_node.cast_shadow = shadow_mode
|
||||
particle_node.fixed_fps = process_fixed_fps
|
||||
# This prevent minor grid alignment errors when the camera is moving very fast
|
||||
particle_node.preprocess = 1.0 / float(process_fixed_fps)
|
||||
if mesh_material_override:
|
||||
particle_node.material_override = mesh_material_override
|
||||
particle_node.use_fixed_seed = true
|
||||
if (x > -half_grid and z > -half_grid): # Use the same seed across all nodes
|
||||
particle_node.seed = particle_nodes[0].seed
|
||||
self.add_child(particle_node)
|
||||
particle_node.emitting = true
|
||||
particle_nodes.push_back(particle_node)
|
||||
last_pos = Vector3.ZERO
|
||||
|
||||
|
||||
func _set_offsets() -> void:
|
||||
var half_grid: int = grid_width / 2
|
||||
offsets.clear()
|
||||
for x in range(-half_grid, half_grid + 1):
|
||||
for z in range(-half_grid, half_grid + 1):
|
||||
var offset := Vector3(
|
||||
float(x * rows) * instance_spacing,
|
||||
0.0,
|
||||
float(z * rows) * instance_spacing
|
||||
)
|
||||
offsets.append(offset)
|
||||
|
||||
|
||||
func _destroy_grid() -> void:
|
||||
for node: GPUParticles3D in particle_nodes:
|
||||
if is_instance_valid(node):
|
||||
node.queue_free()
|
||||
particle_nodes.clear()
|
||||
|
||||
|
||||
func _position_grid(pos: Vector3) -> void:
|
||||
for i in particle_nodes.size():
|
||||
var node: GPUParticles3D = particle_nodes[i]
|
||||
var snap = Vector3(pos.x, 0, pos.z).snapped(Vector3.ONE) + offsets[i]
|
||||
node.global_position = (snap / instance_spacing).round() * instance_spacing
|
||||
node.reset_physics_interpolation()
|
||||
node.restart(true) # keep the same seed.
|
||||
|
||||
|
||||
func _update_process_parameters() -> void:
|
||||
if process_material:
|
||||
var process_rid: RID = process_material.get_rid()
|
||||
if terrain and process_rid.is_valid():
|
||||
RenderingServer.material_set_param(process_rid, "_background_mode", terrain.material.world_background)
|
||||
RenderingServer.material_set_param(process_rid, "_vertex_spacing", terrain.vertex_spacing)
|
||||
RenderingServer.material_set_param(process_rid, "_vertex_density", 1.0 / terrain.vertex_spacing)
|
||||
RenderingServer.material_set_param(process_rid, "_region_size", terrain.region_size)
|
||||
RenderingServer.material_set_param(process_rid, "_region_texel_size", 1.0 / terrain.region_size)
|
||||
RenderingServer.material_set_param(process_rid, "_region_map_size", 32)
|
||||
RenderingServer.material_set_param(process_rid, "_region_map", terrain.data.get_region_map())
|
||||
RenderingServer.material_set_param(process_rid, "_region_locations", terrain.data.get_region_locations())
|
||||
RenderingServer.material_set_param(process_rid, "_height_maps", terrain.data.get_height_maps_rid())
|
||||
RenderingServer.material_set_param(process_rid, "_control_maps", terrain.data.get_control_maps_rid())
|
||||
RenderingServer.material_set_param(process_rid, "_color_maps", terrain.data.get_color_maps_rid())
|
||||
RenderingServer.material_set_param(process_rid, "instance_spacing", instance_spacing)
|
||||
RenderingServer.material_set_param(process_rid, "instance_rows", rows)
|
||||
RenderingServer.material_set_param(process_rid, "max_dist", min_draw_distance)
|
||||
@@ -0,0 +1 @@
|
||||
uid://bp7r4ppgq1m0g
|
||||
67
addons/terrain_3d/extras/shaders/hex_grid.gdshaderinc
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
// This shader snippet draws a hex grid
|
||||
|
||||
// To use it, add this line to the top of your shader:
|
||||
// #include "res://addons/terrain_3d/extras/shaders/hex_grid.gdshaderinc"
|
||||
|
||||
// And this line at the bottom of your shader:
|
||||
// draw_hex_grid(uv2, _region_texel_size, w_normal, ALBEDO);
|
||||
|
||||
mat2 rotate2d(float _angle) {
|
||||
return mat2(vec2(cos(_angle),-sin(_angle)), vec2(sin(_angle), cos(_angle)));
|
||||
}
|
||||
|
||||
void draw_hex_grid(vec2 uv, float texel_size, vec3 normal, inout vec3 albedo) {
|
||||
float hex_size = 0.02;
|
||||
float line_thickness = 0.04;
|
||||
|
||||
vec2 guv = (uv - vec2(0.5 * texel_size)) / hex_size;
|
||||
|
||||
// Convert UV to axial hex coordinates
|
||||
float q = (sqrt(3.0) / 3.0 * guv.x - 1.0 / 3.0 * guv.y);
|
||||
float r = (2.0 / 3.0 * guv.y);
|
||||
|
||||
// Cube coordinates for the hex (q, r, -q-r)
|
||||
float x = q;
|
||||
float z = r;
|
||||
float y = -x - z;
|
||||
|
||||
// Round to the nearest hex center
|
||||
vec3 rounded = round(vec3(x, y, z));
|
||||
vec3 diff = abs(vec3(x, y, z) - rounded);
|
||||
|
||||
// Fix rounding errors
|
||||
if (diff.x > diff.y && diff.x > diff.z) {
|
||||
rounded.x = -rounded.y - rounded.z;
|
||||
} else if (diff.y > diff.z) {
|
||||
rounded.y = -rounded.x - rounded.z;
|
||||
} else {
|
||||
rounded.z = -rounded.x - rounded.y;
|
||||
}
|
||||
|
||||
// Find the hex center in UV space
|
||||
vec2 hex_center = vec2(
|
||||
sqrt(3.0) * rounded.x + sqrt(3.0) / 2.0 * rounded.z,
|
||||
3.0 / 2.0 * rounded.z
|
||||
);
|
||||
|
||||
// Relative position within the hex
|
||||
vec2 local_pos = guv - hex_center;
|
||||
vec2 lines_uv = local_pos;
|
||||
float line = 1.0;
|
||||
|
||||
for (int i = 0; i < 6; i++) {
|
||||
vec2 luv = lines_uv * rotate2d(radians(60.0 * float(i) + 30.0));
|
||||
float dist = abs(dot(luv + vec2(0.90), vec2(0.0, 1.0)));
|
||||
line = min(line, dist);
|
||||
}
|
||||
|
||||
// Filter lines by slope
|
||||
float slope = 4.; // Can also assign to (auto_slope * 4.) to match grass placement
|
||||
float slope_factor = clamp(dot(vec3(0., 1., 0.), slope * (normal - 1.) + 1.), 0., 1.);
|
||||
|
||||
// Draw hex grid
|
||||
albedo = mix(albedo, vec3(1.0), smoothstep(line_thickness + 0.02, line_thickness, line) * slope_factor);
|
||||
// Draw Hex center dot
|
||||
albedo = mix(albedo, vec3(0.0, 0.5, 0.5), smoothstep(0.11, 0.10, length(local_pos)) * slope_factor);
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://mri8pfoj2mfk
|
||||
367
addons/terrain_3d/extras/shaders/lightweight.gdshader
Normal file
@@ -0,0 +1,367 @@
|
||||
shader_type spatial;
|
||||
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx,skip_vertex_transform;
|
||||
|
||||
/* This is an example stripped down shader with maximum performance in mind.
|
||||
* Only Autoshader/Base/Over/Blend/Holes/Colormap are supported.
|
||||
* All terrain normal calculations take place in vetex().
|
||||
*
|
||||
* Control map indices are processed such that each ID only requires reading ONCE.
|
||||
* The following features: projection, detiling, and paintable rotation / scale
|
||||
* cannot work with this method, without the additional samples required for blending
|
||||
* between same ID textures with different values across indices.
|
||||
*/
|
||||
|
||||
// Defined Constants
|
||||
#define SKIP_PASS 0
|
||||
#define VERTEX_PASS 1
|
||||
#define FRAGMENT_PASS 2
|
||||
#define COLOR_MAP vec4(1.0, 1.0, 1.0, 0.5)
|
||||
#define DIV_255 0.003921568627450 // 1. / 255.
|
||||
|
||||
// Inline Functions
|
||||
#define DECODE_BLEND(control) float(control >> 14u & 0xFFu) * DIV_255
|
||||
#define DECODE_AUTO(control) bool(control & 0x1u)
|
||||
#define DECODE_BASE(control) int(control >> 27u & 0x1Fu)
|
||||
#define DECODE_OVER(control) int(control >> 22u & 0x1Fu)
|
||||
#define DECODE_HOLE(control) bool(control >>2u & 0x1u)
|
||||
|
||||
#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
|
||||
#define fma(a, b, c) ((a) * (b) + (c))
|
||||
#define dFdxCoarse(a) dFdx(a)
|
||||
#define dFdyCoarse(a) dFdy(a)
|
||||
#endif
|
||||
|
||||
// Private uniforms
|
||||
uniform vec3 _camera_pos = vec3(0.f);
|
||||
uniform float _mesh_size = 48.f;
|
||||
uniform uint _background_mode = 1u; // NONE = 0, FLAT = 1, NOISE = 2
|
||||
uniform uint _mouse_layer = 0x80000000u; // Layer 32
|
||||
uniform float _vertex_spacing = 1.0;
|
||||
uniform float _vertex_density = 1.0; // = 1./_vertex_spacing
|
||||
uniform float _region_size = 1024.0;
|
||||
uniform float _region_texel_size = 0.0009765625; // = 1./region_size
|
||||
uniform int _region_map_size = 32;
|
||||
uniform int _region_map[1024];
|
||||
uniform vec2 _region_locations[1024];
|
||||
uniform float _texture_normal_depth_array[32];
|
||||
uniform float _texture_ao_strength_array[32];
|
||||
uniform float _texture_roughness_mod_array[32];
|
||||
uniform float _texture_uv_scale_array[32];
|
||||
uniform vec4 _texture_color_array[32];
|
||||
uniform highp sampler2DArray _height_maps : repeat_disable;
|
||||
uniform highp sampler2DArray _control_maps : repeat_disable;
|
||||
uniform highp sampler2DArray _color_maps : source_color, filter_linear_mipmap_anisotropic, repeat_disable;
|
||||
uniform highp sampler2DArray _texture_array_albedo : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
|
||||
uniform highp sampler2DArray _texture_array_normal : hint_normal, filter_linear_mipmap_anisotropic, repeat_enable;
|
||||
|
||||
// Public uniforms
|
||||
uniform bool enable_texturing = true;
|
||||
uniform float blend_sharpness : hint_range(0, 1) = 0.5;
|
||||
uniform bool flat_terrain_normals = false;
|
||||
// Autoshader
|
||||
uniform float auto_slope : hint_range(0, 10) = 1.0;
|
||||
uniform float auto_height_reduction : hint_range(0, 1) = 0.1;
|
||||
uniform int auto_base_texture : hint_range(0, 31) = 0;
|
||||
uniform int auto_overlay_texture : hint_range(0, 31) = 1;
|
||||
// Macro Variation
|
||||
uniform bool enable_macro_variation = true;
|
||||
uniform vec3 macro_variation1 : source_color = vec3(1.);
|
||||
uniform vec3 macro_variation2 : source_color = vec3(1.);
|
||||
uniform float macro_variation_slope : hint_range(0., 1.) = 0.333;
|
||||
uniform highp sampler2D noise_texture : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
|
||||
uniform float noise1_scale : hint_range(0.001, 1.) = 0.04; // Used for macro variation 1. Scaled up 10x
|
||||
uniform float noise1_angle : hint_range(0, 6.283) = 0.;
|
||||
uniform vec2 noise1_offset = vec2(0.5);
|
||||
uniform float noise2_scale : hint_range(0.001, 1.) = 0.076; // Used for macro variation 2. Scaled up 10x
|
||||
|
||||
// Varyings & Types
|
||||
varying vec3 v_normal;
|
||||
varying vec3 v_vertex;
|
||||
varying mat3 TBN;
|
||||
|
||||
////////////////////////
|
||||
// Vertex
|
||||
////////////////////////
|
||||
|
||||
// Takes in world space XZ (UV) coordinates & search depth (only applicable for background mode none)
|
||||
// Returns ivec3 with:
|
||||
// XY: (0 to _region_size - 1) coordinates within a region
|
||||
// Z: layer index used for texturearrays, -1 if not in a region
|
||||
ivec3 get_index_coord(const vec2 uv, const int search) {
|
||||
vec2 r_uv = round(uv);
|
||||
vec2 o_uv = mod(r_uv,_region_size);
|
||||
ivec2 pos;
|
||||
int bounds, layer_index = -1;
|
||||
for (int i = -1; i < clamp(search, SKIP_PASS, FRAGMENT_PASS); i++) {
|
||||
if ((layer_index == -1 && _background_mode == 0u ) || i < 0) {
|
||||
r_uv -= i == -1 ? vec2(0.0) : vec2(float(o_uv.x <= o_uv.y), float(o_uv.y <= o_uv.x));
|
||||
pos = ivec2(floor((r_uv) * _region_texel_size)) + (_region_map_size / 2);
|
||||
bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
|
||||
layer_index = (_region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1);
|
||||
}
|
||||
}
|
||||
return ivec3(ivec2(mod(r_uv,_region_size)), layer_index);
|
||||
}
|
||||
|
||||
// Takes in descaled (world_space / region_size) world to region space XZ (UV2) coordinates, returns vec3 with:
|
||||
// XY: (0. to 1.) coordinates within a region
|
||||
// Z: layer index used for texturearrays, -1 if not in a region
|
||||
vec3 get_index_uv(const vec2 uv2) {
|
||||
ivec2 pos = ivec2(floor(uv2)) + (_region_map_size / 2);
|
||||
int bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
|
||||
int layer_index = _region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1;
|
||||
return vec3(uv2 - _region_locations[layer_index], float(layer_index));
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
// Get vertex of flat plane in world coordinates and set world UV
|
||||
v_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
|
||||
// Camera distance to vertex on flat plane
|
||||
float v_vertex_xz_dist = length(v_vertex.xz - _camera_pos.xz);
|
||||
|
||||
// Geomorph vertex, set end and start for linear height interpolate
|
||||
float scale = MODEL_MATRIX[0][0];
|
||||
float vertex_lerp = smoothstep(0.55, 0.95, (v_vertex_xz_dist / scale - _mesh_size - 4.0) / (_mesh_size - 2.0));
|
||||
vec2 v_fract = fract(VERTEX.xz * 0.5) * 2.0;
|
||||
// For LOD0 morph from a regular grid to an alternating grid to align with LOD1+
|
||||
vec2 shift = (scale < _vertex_spacing + 1e-6) ? // LOD0 or not
|
||||
// Shift from regular to symetric
|
||||
mix(v_fract, vec2(v_fract.x, -v_fract.y),
|
||||
round(fract(round(mod(v_vertex.z * _vertex_density, 4.0)) *
|
||||
round(mod(v_vertex.x * _vertex_density, 4.0)) * 0.25))
|
||||
) :
|
||||
// Symetric shift
|
||||
v_fract * round((fract(v_vertex.xz * 0.25 / scale) - 0.5) * 4.0);
|
||||
vec2 start_pos = v_vertex.xz * _vertex_density;
|
||||
vec2 end_pos = (v_vertex.xz - shift * scale) * _vertex_density;
|
||||
v_vertex.xz -= shift * scale * vertex_lerp;
|
||||
|
||||
// UV coordinates in world space. Values are 0 to _region_size within regions
|
||||
UV = v_vertex.xz * _vertex_density;
|
||||
|
||||
// UV coordinates in region space + texel offset. Values are 0 to 1 within regions
|
||||
UV2 = fma(UV, vec2(_region_texel_size), vec2(0.5 * _region_texel_size));
|
||||
|
||||
// Discard vertices for Holes. 1 lookup
|
||||
ivec3 v_region = get_index_coord(start_pos, VERTEX_PASS);
|
||||
uint control = floatBitsToUint(texelFetch(_control_maps, v_region, 0)).r;
|
||||
bool hole = DECODE_HOLE(control);
|
||||
|
||||
// Show holes to all cameras except mouse camera (on exactly 1 layer)
|
||||
if ( !(CAMERA_VISIBLE_LAYERS == _mouse_layer) &&
|
||||
(hole || (_background_mode == 0u && v_region.z == -1))) {
|
||||
v_vertex.x = 0. / 0.;
|
||||
} else {
|
||||
// Set final vertex height & calculate vertex normals. 3 lookups
|
||||
ivec3 uv_a = get_index_coord(start_pos, VERTEX_PASS);
|
||||
ivec3 uv_b = get_index_coord(end_pos, VERTEX_PASS);
|
||||
float h = mix(texelFetch(_height_maps, uv_a, 0).r,texelFetch(_height_maps, uv_b, 0).r,vertex_lerp);
|
||||
v_vertex.y = h;
|
||||
|
||||
// Vertex normals
|
||||
float u = mix(texelFetch(_height_maps, get_index_coord(start_pos + vec2(1,0), VERTEX_PASS), 0).r,
|
||||
texelFetch(_height_maps, get_index_coord(end_pos + vec2(1,0), VERTEX_PASS), 0).r, vertex_lerp);
|
||||
float v = mix(texelFetch(_height_maps, get_index_coord(start_pos + vec2(0,1), VERTEX_PASS), 0).r,
|
||||
texelFetch(_height_maps, get_index_coord(end_pos + vec2(0,1), VERTEX_PASS), 0).r, vertex_lerp);
|
||||
|
||||
v_normal = normalize(vec3(h - u, _vertex_spacing, h - v));
|
||||
}
|
||||
|
||||
// Convert model space to view space w/ skip_vertex_transform render mode
|
||||
VERTEX = (VIEW_MATRIX * vec4(v_vertex, 1.0)).xyz;
|
||||
|
||||
// Apply terrain normals
|
||||
vec3 w_tangent = normalize(cross(v_normal, vec3(0.0, 0.0, 1.0)));
|
||||
vec3 w_binormal = normalize(cross(v_normal, w_tangent));
|
||||
TBN = mat3(w_tangent, w_binormal, v_normal);
|
||||
|
||||
NORMAL = normalize((VIEW_MATRIX * vec4(v_normal, 0.0)).xyz);
|
||||
BINORMAL = normalize((VIEW_MATRIX * vec4(w_binormal, 0.0)).xyz);
|
||||
TANGENT = normalize((VIEW_MATRIX * vec4(w_tangent, 0.0)).xyz);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// Fragment
|
||||
////////////////////////
|
||||
|
||||
mat2 rotate_plane(float angle) {
|
||||
float c = cos(angle), s = sin(angle);
|
||||
return mat2(vec2(c, s), vec2(-s, c));
|
||||
}
|
||||
|
||||
void fragment() {
|
||||
// Recover UVs
|
||||
vec2 uv = UV;
|
||||
vec2 uv2 = UV2;
|
||||
|
||||
// Lookup offsets, ID and blend weight
|
||||
vec3 region_uv = get_index_uv(uv2);
|
||||
const vec3 offsets = vec3(0, 1, 2);
|
||||
vec2 index_id = floor(uv);
|
||||
vec2 weight = fract(uv);
|
||||
vec2 invert = 1.0 - weight;
|
||||
vec4 weights = vec4(
|
||||
invert.x * weight.y, // 0
|
||||
weight.x * weight.y, // 1
|
||||
weight.x * invert.y, // 2
|
||||
invert.x * invert.y // 3
|
||||
);
|
||||
|
||||
ivec3 index[4];
|
||||
// control map lookups, used for some normal lookups as well
|
||||
index[0] = get_index_coord(index_id + offsets.xy, FRAGMENT_PASS);
|
||||
index[1] = get_index_coord(index_id + offsets.yy, FRAGMENT_PASS);
|
||||
index[2] = get_index_coord(index_id + offsets.yx, FRAGMENT_PASS);
|
||||
index[3] = get_index_coord(index_id + offsets.xx, FRAGMENT_PASS);
|
||||
|
||||
vec3 base_ddx = dFdxCoarse(v_vertex);
|
||||
vec3 base_ddy = dFdyCoarse(v_vertex);
|
||||
vec4 base_dd = vec4(base_ddx.xz, base_ddy.xz);
|
||||
// Calculate the effective mipmap for regionspace
|
||||
float region_mip = log2(max(length(base_ddx.xz), length(base_ddy.xz)) * _vertex_density);
|
||||
|
||||
// Color map
|
||||
vec4 color_map = region_uv.z > -1.0 ? textureLod(_color_maps, region_uv, region_mip) : COLOR_MAP;
|
||||
|
||||
if (flat_terrain_normals) {
|
||||
NORMAL = normalize(cross(dFdyCoarse(VERTEX),dFdxCoarse(VERTEX)));
|
||||
TANGENT = normalize(cross(NORMAL, VIEW_MATRIX[2].xyz));
|
||||
BINORMAL = normalize(cross(NORMAL, TANGENT));
|
||||
}
|
||||
|
||||
// defaults
|
||||
vec4 normal_rough = vec4(0., 1., 0., 0.7);
|
||||
vec4 albedo_height = vec4(1.);
|
||||
float normal_map_depth = 1.;
|
||||
float ao_strength = 0.;
|
||||
|
||||
if (enable_texturing) {
|
||||
// set to zero before accumulation
|
||||
albedo_height = vec4(0.);
|
||||
normal_rough = vec4(0.);
|
||||
normal_map_depth = 0.;
|
||||
ao_strength = 0.;
|
||||
float total_weight = 0.;
|
||||
float sharpness = fma(56., blend_sharpness, 8.);
|
||||
|
||||
// Get index control data
|
||||
// 1 - 4 lookups
|
||||
uvec4 control = floatBitsToUint(vec4(
|
||||
texelFetch(_control_maps, index[0], 0).r,
|
||||
texelFetch(_control_maps, index[1], 0).r,
|
||||
texelFetch(_control_maps, index[2], 0).r,
|
||||
texelFetch(_control_maps, index[3], 0).r));
|
||||
|
||||
{
|
||||
// Auto blend calculation
|
||||
float auto_blend = clamp(fma(auto_slope * 2.0, (v_normal.y - 1.0), 1.0)
|
||||
- auto_height_reduction * 0.01 * v_vertex.y, 0.0, 1.0);
|
||||
// Enable Autoshader if outside regions or painted in regions, otherwise manual painted
|
||||
uvec4 is_auto = (control & uvec4(0x1u)) | uvec4(uint(region_uv.z < 0.0));
|
||||
uint u_auto =
|
||||
((uint(auto_base_texture) & 0x1Fu) << 27u) |
|
||||
((uint(auto_overlay_texture) & 0x1Fu) << 22u) |
|
||||
((uint(fma(auto_blend, 255.0 , 0.5)) & 0xFFu) << 14u);
|
||||
control = control * (1u - is_auto) + u_auto * is_auto;
|
||||
}
|
||||
|
||||
|
||||
// Texture weights
|
||||
// Vectorised Deocode of all texture IDs, then swizzle to per index mapping.
|
||||
ivec4 t_id[2] = {ivec4(control >> uvec4(27u) & uvec4(0x1Fu)),
|
||||
ivec4(control >> uvec4(22u) & uvec4(0x1Fu))};
|
||||
ivec2 texture_ids[4] = ivec2[4](
|
||||
ivec2(t_id[0].x, t_id[1].x),
|
||||
ivec2(t_id[0].y, t_id[1].y),
|
||||
ivec2(t_id[0].z, t_id[1].z),
|
||||
ivec2(t_id[0].w, t_id[1].w));
|
||||
|
||||
// interpolated weights.
|
||||
vec4 weights_id_1 = vec4(control >> uvec4(14u) & uvec4(0xFFu)) * DIV_255 * weights;
|
||||
vec4 weights_id_0 = weights - weights_id_1;
|
||||
vec2 t_weights[4] = {vec2(0), vec2(0), vec2(0), vec2(0)};
|
||||
for (int i = 0; i < 4; i++) {
|
||||
vec2 w_0 = vec2(weights_id_0[i]);
|
||||
vec2 w_1 = vec2(weights_id_1[i]);
|
||||
ivec2 id_0 = texture_ids[i].xx;
|
||||
ivec2 id_1 = texture_ids[i].yy;
|
||||
t_weights[0] += fma(w_0, vec2(equal(texture_ids[0], id_0)), w_1 * vec2(equal(texture_ids[0], id_1)));
|
||||
t_weights[1] += fma(w_0, vec2(equal(texture_ids[1], id_0)), w_1 * vec2(equal(texture_ids[1], id_1)));
|
||||
t_weights[2] += fma(w_0, vec2(equal(texture_ids[2], id_0)), w_1 * vec2(equal(texture_ids[2], id_1)));
|
||||
t_weights[3] += fma(w_0, vec2(equal(texture_ids[3], id_0)), w_1 * vec2(equal(texture_ids[3], id_1)));
|
||||
}
|
||||
|
||||
|
||||
// Process control data to determine each texture ID present, so that only
|
||||
// a single sample will be needed later, as all id are contiguous when features
|
||||
// like detiling, scale, rotation, and projection are not present.
|
||||
// 2 to 16 lookups
|
||||
uint id_read = 0u; // 1 bit per possible ID
|
||||
// world normal adjustment requires acess to previous id during next iteration
|
||||
vec4 nrm = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
// adjust uv scale to account for vertex spacing
|
||||
uv *= _vertex_spacing;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
for (int t = 0; t < 2; t++) {
|
||||
int id = texture_ids[i][t];
|
||||
uint mask = 1u << uint(id);
|
||||
if ((id_read & mask) == 0u) {
|
||||
// Set this id bit
|
||||
id_read |= mask;
|
||||
float id_w = t_weights[i][t];
|
||||
float id_scale = _texture_uv_scale_array[id] * 0.5;
|
||||
vec2 id_uv = fma(uv, vec2(id_scale), vec2(0.5));
|
||||
vec4 i_dd = base_dd * id_scale;
|
||||
vec4 alb = textureGrad(_texture_array_albedo, vec3(id_uv, float(id)), i_dd.xy, i_dd.zw);
|
||||
float world_normal = clamp(fma(TBN[0], vec3(nrm.x), fma(TBN[1], vec3(nrm.z), v_normal * vec3(nrm.y))).y, 0., 1.);
|
||||
nrm = textureGrad(_texture_array_normal, vec3(id_uv, float(id)), i_dd.xy, i_dd.zw);
|
||||
alb.rgb *= _texture_color_array[id].rgb;
|
||||
nrm.a = clamp(nrm.a + _texture_roughness_mod_array[id], 0., 1.);
|
||||
// Unpack normal map for blending.
|
||||
nrm.xyz = fma(nrm.xzy, vec3(2.0), vec3(-1.0));
|
||||
// height weight modifier.
|
||||
float id_weight = exp2(sharpness * log2(id_w + alb.a * world_normal));
|
||||
albedo_height += alb * id_weight;
|
||||
normal_rough += nrm * id_weight;
|
||||
normal_map_depth += _texture_normal_depth_array[id] * id_weight;
|
||||
ao_strength += _texture_ao_strength_array[id] * id_weight;
|
||||
total_weight += id_weight;
|
||||
}
|
||||
}
|
||||
}
|
||||
// normalize accumulated values back to 0.0 - 1.0 range.
|
||||
float weight_inv = 1.0 / total_weight;
|
||||
albedo_height *= weight_inv;
|
||||
normal_rough *= weight_inv;
|
||||
normal_map_depth *= weight_inv;
|
||||
ao_strength *= weight_inv;
|
||||
}
|
||||
|
||||
// Macro variation. 2 lookups
|
||||
vec3 macrov = vec3(1.);
|
||||
if (enable_macro_variation) {
|
||||
float noise1 = texture(noise_texture, (uv * noise1_scale * .1 + noise1_offset) * rotate_plane(noise1_angle)).r;
|
||||
float noise2 = texture(noise_texture, uv * noise2_scale * .1).r;
|
||||
macrov = mix(macro_variation1, vec3(1.), noise1);
|
||||
macrov *= mix(macro_variation2, vec3(1.), noise2);
|
||||
macrov = mix(vec3(1.0), macrov, clamp(v_normal.y + macro_variation_slope, 0., 1.));
|
||||
}
|
||||
|
||||
// Wetness/roughness modifier, converting 0 - 1 range to -1 to 1 range, clamped to Godot roughness values
|
||||
float roughness = clamp(fma(color_map.a - 0.5, 2.0, normal_rough.a), 0., 1.);
|
||||
|
||||
// Apply PBR
|
||||
ALBEDO = albedo_height.rgb * color_map.rgb * macrov;
|
||||
ROUGHNESS = roughness;
|
||||
SPECULAR = 1. - normal_rough.a;
|
||||
// Repack final normal map value.
|
||||
NORMAL_MAP = fma(normalize(normal_rough.xzy), vec3(0.5), vec3(0.5));
|
||||
NORMAL_MAP_DEPTH = normal_map_depth;
|
||||
|
||||
// Higher and/or facing up, less occluded.
|
||||
float ao = (1. - (albedo_height.a * log(2.1 - ao_strength))) * (1. - normal_rough.y);
|
||||
AO = clamp(1. - ao * ao_strength, albedo_height.a, 1.0);
|
||||
AO_LIGHT_AFFECT = (1.0 - albedo_height.a) * clamp(normal_rough.y, 0., 1.);
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
uid://bbx2xhanpq5l3
|
||||
217
addons/terrain_3d/extras/shaders/minimum.gdshader
Normal file
@@ -0,0 +1,217 @@
|
||||
// Copyright © 2025 Cory Petkovsek, Roope Palmroos, and Contributors.
|
||||
// This shader is the minimum needed to allow the terrain to function, without any texturing.
|
||||
|
||||
shader_type spatial;
|
||||
render_mode blend_mix,depth_draw_opaque,cull_back,diffuse_burley,specular_schlick_ggx,skip_vertex_transform;
|
||||
|
||||
// Defined Constants
|
||||
#define SKIP_PASS 0
|
||||
#define VERTEX_PASS 1
|
||||
#define FRAGMENT_PASS 2
|
||||
|
||||
#if CURRENT_RENDERER == RENDERER_COMPATIBILITY
|
||||
#define fma(a, b, c) ((a) * (b) + (c))
|
||||
#define dFdxCoarse(a) dFdx(a)
|
||||
#define dFdyCoarse(a) dFdy(a)
|
||||
#endif
|
||||
|
||||
// Private uniforms
|
||||
// Commented uniforms aren't needed for this shader, but are available for your own needs.
|
||||
uniform vec3 _camera_pos = vec3(0.f);
|
||||
uniform float _mesh_size = 48.f;
|
||||
uniform uint _background_mode = 1u; // NONE = 0, FLAT = 1, NOISE = 2
|
||||
uniform uint _mouse_layer = 0x80000000u; // Layer 32
|
||||
uniform float _vertex_spacing = 1.0;
|
||||
uniform float _vertex_density = 1.0; // = 1/_vertex_spacing
|
||||
uniform float _region_size = 1024.0;
|
||||
uniform float _region_texel_size = 0.0009765625; // = 1/1024
|
||||
uniform int _region_map_size = 32;
|
||||
uniform int _region_map[1024];
|
||||
//uniform vec2 _region_locations[1024];
|
||||
//uniform float _texture_uv_scale_array[32];
|
||||
//uniform float _texture_detile_array[32];
|
||||
//uniform vec4 _texture_color_array[32];
|
||||
uniform highp sampler2DArray _height_maps : repeat_disable;
|
||||
uniform highp sampler2DArray _control_maps : repeat_disable;
|
||||
//uniform highp sampler2DArray _color_maps : source_color, filter_linear_mipmap_anisotropic, repeat_disable;
|
||||
//uniform highp sampler2DArray _texture_array_albedo : source_color, filter_linear_mipmap_anisotropic, repeat_enable;
|
||||
//uniform highp sampler2DArray _texture_array_normal : hint_normal, filter_linear_mipmap_anisotropic, repeat_enable;
|
||||
|
||||
// Public Uniforms
|
||||
uniform bool flat_terrain_normals = false;
|
||||
|
||||
// Varyings & Types
|
||||
// Some are required for editor functions
|
||||
varying float v_vertex_xz_dist;
|
||||
varying vec3 v_vertex;
|
||||
|
||||
////////////////////////
|
||||
// Vertex
|
||||
////////////////////////
|
||||
|
||||
// Takes in world space XZ (UV) coordinates & search depth (only applicable for background mode none)
|
||||
// Returns ivec3 with:
|
||||
// XY: (0 to _region_size - 1) coordinates within a region
|
||||
// Z: layer index used for texturearrays, -1 if not in a region
|
||||
ivec3 get_index_coord(const vec2 uv, const int search) {
|
||||
vec2 r_uv = round(uv);
|
||||
vec2 o_uv = mod(r_uv,_region_size);
|
||||
ivec2 pos;
|
||||
int bounds, layer_index = -1;
|
||||
for (int i = -1; i < clamp(search, SKIP_PASS, FRAGMENT_PASS); i++) {
|
||||
if ((layer_index == -1 && _background_mode == 0u ) || i < 0) {
|
||||
r_uv -= i == -1 ? vec2(0.0) : vec2(float(o_uv.x <= o_uv.y), float(o_uv.y <= o_uv.x));
|
||||
pos = ivec2(floor((r_uv) * _region_texel_size)) + (_region_map_size / 2);
|
||||
bounds = int(uint(pos.x | pos.y) < uint(_region_map_size));
|
||||
layer_index = (_region_map[ pos.y * _region_map_size + pos.x ] * bounds - 1);
|
||||
}
|
||||
}
|
||||
return ivec3(ivec2(mod(r_uv,_region_size)), layer_index);
|
||||
}
|
||||
|
||||
void vertex() {
|
||||
// Get vertex of flat plane in world coordinates and set world UV
|
||||
v_vertex = (MODEL_MATRIX * vec4(VERTEX, 1.0)).xyz;
|
||||
|
||||
// Camera distance to vertex on flat plane
|
||||
v_vertex_xz_dist = length(v_vertex.xz - _camera_pos.xz);
|
||||
|
||||
// Geomorph vertex, set end and start for linear height interpolate
|
||||
float scale = MODEL_MATRIX[0][0];
|
||||
float vertex_lerp = smoothstep(0.55, 0.95, (v_vertex_xz_dist / scale - _mesh_size - 4.0) / (_mesh_size - 2.0));
|
||||
vec2 v_fract = fract(VERTEX.xz * 0.5) * 2.0;
|
||||
// For LOD0 morph from a regular grid to an alternating grid to align with LOD1+
|
||||
vec2 shift = (scale < _vertex_spacing + 1e-6) ? // LOD0 or not
|
||||
// Shift from regular to symetric
|
||||
mix(v_fract, vec2(v_fract.x, -v_fract.y),
|
||||
round(fract(round(mod(v_vertex.z * _vertex_density, 4.0)) *
|
||||
round(mod(v_vertex.x * _vertex_density, 4.0)) * 0.25))
|
||||
) :
|
||||
// Symetric shift
|
||||
v_fract * round((fract(v_vertex.xz * 0.25 / scale) - 0.5) * 4.0);
|
||||
vec2 start_pos = v_vertex.xz * _vertex_density;
|
||||
vec2 end_pos = (v_vertex.xz - shift * scale) * _vertex_density;
|
||||
v_vertex.xz -= shift * scale * vertex_lerp;
|
||||
|
||||
// UV coordinates in world space. Values are 0 to _region_size within regions
|
||||
UV = v_vertex.xz * _vertex_density;
|
||||
|
||||
// UV coordinates in region space + texel offset. Values are 0 to 1 within regions
|
||||
UV2 = fma(UV, vec2(_region_texel_size), vec2(0.5 * _region_texel_size));
|
||||
|
||||
// Discard vertices for Holes. 1 lookup
|
||||
ivec3 v_region = get_index_coord(start_pos, VERTEX_PASS);
|
||||
uint control = floatBitsToUint(texelFetch(_control_maps, v_region, 0)).r;
|
||||
bool hole = bool(control >>2u & 0x1u);
|
||||
|
||||
// Show holes to all cameras except mouse camera (on exactly 1 layer)
|
||||
if ( !(CAMERA_VISIBLE_LAYERS == _mouse_layer) &&
|
||||
(hole || (_background_mode == 0u && v_region.z < 0))) {
|
||||
v_vertex.x = 0. / 0.;
|
||||
} else {
|
||||
// Interpolate Geomorph Start & End, set height. 2 Lookups.
|
||||
ivec3 uv_a = get_index_coord(start_pos, VERTEX_PASS);
|
||||
ivec3 uv_b = get_index_coord(end_pos, VERTEX_PASS);
|
||||
float h = mix(texelFetch(_height_maps, uv_a, 0).r, texelFetch(_height_maps, uv_b, 0).r, vertex_lerp);
|
||||
v_vertex.y = h;
|
||||
}
|
||||
|
||||
// Convert model space to view space w/ skip_vertex_transform render mode
|
||||
VERTEX = (VIEW_MATRIX * vec4(v_vertex, 1.0)).xyz;
|
||||
NORMAL = normalize((MODELVIEW_MATRIX * vec4(NORMAL, 0.0)).xyz);
|
||||
BINORMAL = normalize((MODELVIEW_MATRIX * vec4(BINORMAL, 0.0)).xyz);
|
||||
TANGENT = normalize((MODELVIEW_MATRIX * vec4(TANGENT, 0.0)).xyz);
|
||||
}
|
||||
|
||||
////////////////////////
|
||||
// Fragment
|
||||
////////////////////////
|
||||
|
||||
void fragment() {
|
||||
// Recover UVs
|
||||
vec2 uv = UV;
|
||||
//vec2 uv2 = UV2;
|
||||
|
||||
// Lookup offsets, ID and blend weight
|
||||
const vec3 offsets = vec3(0, 1, 2);
|
||||
vec2 index_id = floor(uv);
|
||||
vec2 weight = fract(uv);
|
||||
vec2 invert = 1.0 - weight;
|
||||
vec4 weights = vec4(
|
||||
invert.x * weight.y, // 0
|
||||
weight.x * weight.y, // 1
|
||||
weight.x * invert.y, // 2
|
||||
invert.x * invert.y // 3
|
||||
);
|
||||
|
||||
vec3 base_ddx = dFdxCoarse(v_vertex);
|
||||
vec3 base_ddy = dFdyCoarse(v_vertex);
|
||||
//vec4 base_derivatives = vec4(base_ddx.xz, base_ddy.xz);
|
||||
// Calculate the effective mipmap for regionspace, and if less than 0,
|
||||
// skip all extra lookups required for bilinear blend.
|
||||
float region_mip = log2(max(length(base_ddx.xz), length(base_ddy.xz)) * _vertex_density);
|
||||
bool bilerp = region_mip < 0.0;
|
||||
|
||||
ivec3 index[4];
|
||||
// control map lookups, used for some normal lookups as well
|
||||
index[0] = get_index_coord(index_id + offsets.xy, FRAGMENT_PASS);
|
||||
index[1] = get_index_coord(index_id + offsets.yy, FRAGMENT_PASS);
|
||||
index[2] = get_index_coord(index_id + offsets.yx, FRAGMENT_PASS);
|
||||
index[3] = get_index_coord(index_id + offsets.xx, FRAGMENT_PASS);
|
||||
|
||||
// Terrain normals
|
||||
vec3 index_normal[4];
|
||||
float h[4];
|
||||
// allows additional derivatives, eg world noise, brush previews etc
|
||||
float u = 0.0;
|
||||
float v = 0.0;
|
||||
|
||||
// Re-use index[] for the first lookups, skipping some math. 3 lookups
|
||||
h[3] = texelFetch(_height_maps, index[3], 0).r; // 0 (0,0)
|
||||
h[2] = texelFetch(_height_maps, index[2], 0).r; // 1 (1,0)
|
||||
h[0] = texelFetch(_height_maps, index[0], 0).r; // 2 (0,1)
|
||||
index_normal[3] = normalize(vec3(h[3] - h[2] + u, _vertex_spacing, h[3] - h[0] + v));
|
||||
|
||||
// Set flat world normal - overriden if bilerp is true
|
||||
vec3 w_normal = index_normal[3];
|
||||
|
||||
// Branching smooth normals must be done seperatley for correct normals at all 4 index ids
|
||||
if (bilerp) {
|
||||
// 5 lookups
|
||||
// Fetch the additional required height values for smooth normals
|
||||
h[1] = texelFetch(_height_maps, index[1], 0).r; // 3 (1,1)
|
||||
float h_4 = texelFetch(_height_maps, get_index_coord(index_id + offsets.yz, FRAGMENT_PASS), 0).r; // 4 (1,2)
|
||||
float h_5 = texelFetch(_height_maps, get_index_coord(index_id + offsets.zy, FRAGMENT_PASS), 0).r; // 5 (2,1)
|
||||
float h_6 = texelFetch(_height_maps, get_index_coord(index_id + offsets.zx, FRAGMENT_PASS), 0).r; // 6 (2,0)
|
||||
float h_7 = texelFetch(_height_maps, get_index_coord(index_id + offsets.xz, FRAGMENT_PASS), 0).r; // 7 (0,2)
|
||||
|
||||
// Calculate the normal for the remaining index ids.
|
||||
index_normal[0] = normalize(vec3(h[0] - h[1] + u, _vertex_spacing, h[0] - h_7 + v));
|
||||
index_normal[1] = normalize(vec3(h[1] - h_5 + u, _vertex_spacing, h[1] - h_4 + v));
|
||||
index_normal[2] = normalize(vec3(h[2] - h_6 + u, _vertex_spacing, h[2] - h[1] + v));
|
||||
|
||||
// Set interpolated world normal
|
||||
w_normal =
|
||||
index_normal[0] * weights[0] +
|
||||
index_normal[1] * weights[1] +
|
||||
index_normal[2] * weights[2] +
|
||||
index_normal[3] * weights[3] ;
|
||||
}
|
||||
|
||||
// Apply terrain normals
|
||||
vec3 w_tangent = normalize(cross(w_normal, vec3(0.0, 0.0, 1.0)));
|
||||
vec3 w_binormal = normalize(cross(w_normal, w_tangent));
|
||||
NORMAL = mat3(VIEW_MATRIX) * w_normal;
|
||||
TANGENT = mat3(VIEW_MATRIX) * w_tangent;
|
||||
BINORMAL = mat3(VIEW_MATRIX) * w_binormal;
|
||||
|
||||
if (flat_terrain_normals) {
|
||||
NORMAL = normalize(cross(dFdyCoarse(VERTEX),dFdxCoarse(VERTEX)));
|
||||
TANGENT = normalize(cross(NORMAL, VIEW_MATRIX[2].xyz));
|
||||
BINORMAL = normalize(cross(NORMAL, TANGENT));
|
||||
}
|
||||
|
||||
// Apply PBR
|
||||
ALBEDO = vec3(.2);
|
||||
ROUGHNESS = .7;
|
||||
}
|
||||
1
addons/terrain_3d/extras/shaders/minimum.gdshader.uid
Normal file
@@ -0,0 +1 @@
|
||||
uid://01qauauvd8aa
|
||||
194
addons/terrain_3d/icons/autoshader.svg
Normal file
@@ -0,0 +1,194 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
width="16"
|
||||
version="1.1"
|
||||
id="svg3088"
|
||||
sodipodi:docname="icon_terrain_material.svg"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs3092">
|
||||
<linearGradient
|
||||
id="linearGradient7208"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="8.3533525"
|
||||
x2="8.3533525"
|
||||
y1="8.3028736"
|
||||
y2="12.261972">
|
||||
<stop
|
||||
offset="0.07497349"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7204"
|
||||
style="stop-color:#ffd4d4;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.63987136"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7210"
|
||||
style="stop-color:#e69971;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#a2d2ff"
|
||||
id="stop7206"
|
||||
style="stop-color:#88fc7f;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient7200"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="8.3533525"
|
||||
x2="8.3533525"
|
||||
y1="8.3028736"
|
||||
y2="12.261972">
|
||||
<stop
|
||||
offset="0.0442211"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7186"
|
||||
style="stop-color:#ff4545;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.1382958"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7188"
|
||||
style="stop-color:#ffe345;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.32638258"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7190"
|
||||
style="stop-color:#80ff45;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.5233199"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7192"
|
||||
style="stop-color:#45ffa2;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.69092047"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7194"
|
||||
style="stop-color:#45d7ff;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.85671425"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop7196"
|
||||
style="stop-color:#8045ff;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#a2d2ff"
|
||||
id="stop7198"
|
||||
style="stop-color:#ff4596;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="a-78"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="8.3533525"
|
||||
x2="8.3533525"
|
||||
y1="8.3028736"
|
||||
y2="12.261972">
|
||||
<stop
|
||||
offset="0.04827991"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop974"
|
||||
style="stop-color:#ff4545;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.1382958"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop6790"
|
||||
style="stop-color:#ffe345;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.32638258"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop6861"
|
||||
style="stop-color:#80ff45;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.5233199"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop6932"
|
||||
style="stop-color:#45ffa2;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.69092047"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop6934"
|
||||
style="stop-color:#45d7ff;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="0.85671425"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop6936"
|
||||
style="stop-color:#8045ff;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#a2d2ff"
|
||||
id="stop28-9"
|
||||
style="stop-color:#ff4596;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="linearGradient986"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
x1="8.3533525"
|
||||
x2="8.3533525"
|
||||
y1="8.3028736"
|
||||
y2="12.261972">
|
||||
<stop
|
||||
offset="0.33542365"
|
||||
stop-color="#5fb2ff"
|
||||
id="stop982"
|
||||
style="stop-color:#ffa7a7;stop-opacity:1;" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#a2d2ff"
|
||||
id="stop984"
|
||||
style="stop-color:#fc7f7f;stop-opacity:1;" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7208"
|
||||
id="linearGradient7167"
|
||||
x1="-11.46914"
|
||||
y1="2.1907859"
|
||||
x2="-11.460287"
|
||||
y2="13.545624"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(19.493797)" />
|
||||
<linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient7208"
|
||||
id="linearGradient7202"
|
||||
x1="-14.857841"
|
||||
y1="4.9543786"
|
||||
x2="-14.958795"
|
||||
y2="12.934526"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="translate(19.493797)" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="namedview3090"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
showgrid="false"
|
||||
inkscape:zoom="12.59375"
|
||||
inkscape:cx="-7.5037221"
|
||||
inkscape:cy="12.466501"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg3088" />
|
||||
<path
|
||||
id="path31"
|
||||
style="fill:url(#linearGradient7167);fill-opacity:1;stroke-width:1.11229"
|
||||
d="m 8.0074686,1.7910156 c -1.368915,0.09588 -1.692429,3.8264137 -2.822266,3.7910156 -1.977176,-0.061946 -2.315719,3.0789623 -3.148437,4.6777348 L 0.20278059,11.044922 7.9898906,14.380859 15.775047,11.044922 13.997703,10.283203 C 13.467188,8.6236354 13.491849,7.2829163 12.616843,6.2304688 11.823643,5.2764167 11.444597,3.7773719 8.6637186,1.9941406 8.4200366,1.8378802 8.2030276,1.7773185 8.0074686,1.7910156 Z" />
|
||||
<path
|
||||
d="m 1.6979896,10.77748 c 1.112295,-1.282509 1.320286,-5.8794797 3.544055,-5.8098075 4.6412106,4.5094283 2.498421,3.8179938 4.057225,7.7556465 -3.217392,0.01725 -3.237576,-1.158088 -7.60128,-1.945839 z"
|
||||
fill="url(#a)"
|
||||
id="path978"
|
||||
style="fill:url(#linearGradient7202);fill-opacity:1;stroke-width:1.19437"
|
||||
sodipodi:nodetypes="cccc" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.0 KiB |
38
addons/terrain_3d/icons/autoshader.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bdwolwswwy8wr"
|
||||
path="res://.godot/imported/autoshader.svg-9998e61bbc6afd5b134b767acd17a425.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/autoshader.svg"
|
||||
dest_files=["res://.godot/imported/autoshader.svg-9998e61bbc6afd5b134b767acd17a425.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
175
addons/terrain_3d/icons/color_paint.svg
Normal file
@@ -0,0 +1,175 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="16"
|
||||
height="16"
|
||||
version="1.1"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg2"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="icon_color.svg"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"><metadata
|
||||
id="metadata12"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs10"><linearGradient
|
||||
inkscape:collect="always"
|
||||
id="linearGradient40333"><stop
|
||||
style="stop-color:#fc7f7f;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop40329" /><stop
|
||||
style="stop-color:#7fb0bd;stop-opacity:1;"
|
||||
offset="0.50160772"
|
||||
id="stop40337" /><stop
|
||||
style="stop-color:#7ffc7f;stop-opacity:1;"
|
||||
offset="1"
|
||||
id="stop40331" /></linearGradient><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect8712"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="powerstroke"
|
||||
id="path-effect8643"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
offset_points="0.86174895,0.26516503"
|
||||
not_jump="true"
|
||||
sort_points="true"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
interpolator_beta="0.75"
|
||||
start_linecap_type="round"
|
||||
linejoin_type="spiro"
|
||||
miter_limit="4"
|
||||
scale_width="1"
|
||||
end_linecap_type="round" /><inkscape:path-effect
|
||||
effect="simplify"
|
||||
id="path-effect8641"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
steps="1"
|
||||
threshold="0.0028332064"
|
||||
smooth_angles="0"
|
||||
helper_size="0"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false"
|
||||
step="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect5927"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect5921"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect5163"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4431"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4425"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4419"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4413"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4407"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4401"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4395"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4389"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect2931"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect2925"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect3156"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4245"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect4977"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><inkscape:path-effect
|
||||
effect="spiro"
|
||||
id="path-effect3156-0"
|
||||
is_visible="true"
|
||||
lpeversion="1" /><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient40333"
|
||||
id="linearGradient35201"
|
||||
x1="5.3624678"
|
||||
y1="3.5122564"
|
||||
x2="12.772088"
|
||||
y2="11.423013"
|
||||
gradientUnits="userSpaceOnUse" /></defs><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
id="namedview8"
|
||||
showgrid="false"
|
||||
inkscape:zoom="22.627418"
|
||||
inkscape:cx="7.5793003"
|
||||
inkscape:cy="9.4133584"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:deskcolor="#d1d1d1"><inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4140" /></sodipodi:namedview><path
|
||||
fill="none"
|
||||
d="M -0.76108454,-0.19858458 H 16.761085 V 17.323585 H -0.76108454 Z"
|
||||
id="path34808"
|
||||
style="stroke-width:0.73009" /><path
|
||||
d="M 3.3537048,4.6462952 8,0 12.646295,4.6462952 c 4.13963,4.139681 1.207353,11.2167178 -4.6462951,11.2167178 -5.8536477,0 -8.78592555,-7.0770368 -4.6462951,-11.2167178 z"
|
||||
id="path34810"
|
||||
style="fill:url(#linearGradient35201);fill-opacity:1;stroke-width:0.73009"
|
||||
sodipodi:nodetypes="cccsc" /></svg>
|
||||
|
After Width: | Height: | Size: 5.8 KiB |
38
addons/terrain_3d/icons/color_paint.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://krrmpalen8xu"
|
||||
path="res://.godot/imported/color_paint.svg-2a416ebf35da04135017e5c6ef53ea57.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/color_paint.svg"
|
||||
dest_files=["res://.godot/imported/color_paint.svg-2a416ebf35da04135017e5c6ef53ea57.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
28
addons/terrain_3d/icons/height_add.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1"
|
||||
id="svg2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" sodipodi:docname="icon_height_add.svg" inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<defs>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect4977"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect4245"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect3156"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect2324"></inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="powerstroke" is_visible="true" scale_width="1" miter_limit="4" linejoin_type="spiro" sort_points="true" not_jump="true" offset_points="0.76255776,0.35156248" id="path-effect2285" start_linecap_type="round" end_linecap_type="round" interpolator_type="CentripetalCatmullRom" interpolator_beta="0.75">
|
||||
</inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="simplify" is_visible="true" step="1" helper_size="0" smooth_angles="0" threshold="0.0028332064" steps="1" id="path-effect2283" simplify_individual_paths="false" simplify_just_coalesce="false">
|
||||
</inkscape:path-effect>
|
||||
</defs>
|
||||
<sodipodi:namedview inkscape:cy="12.81631" inkscape:cx="8.1096304" inkscape:zoom="22.627418" showgrid="false" guidetolerance="10" gridtolerance="10" objecttolerance="10" borderopacity="1" pagecolor="#ffffff" bordercolor="#666666" id="namedview8" inkscape:current-layer="path3154" inkscape:window-maximized="1" inkscape:window-y="-8" inkscape:window-x="-8" inkscape:object-nodes="true" inkscape:snap-grids="false" inkscape:window-height="1009" inkscape:window-width="1920" inkscape:pageshadow="2" inkscape:pageopacity="0" inkscape:object-paths="false" inkscape:snap-smooth-nodes="false" inkscape:snap-to-guides="true" inkscape:pagecheckerboard="0" inkscape:showpageshadow="0" inkscape:deskcolor="#d1d1d1" showguides="false">
|
||||
<inkscape:grid type="xygrid" id="grid4140"></inkscape:grid>
|
||||
</sodipodi:namedview>
|
||||
<path fill="#FC7F7F" d="M15.203,9.736c-0.887-0.184-1.725-0.729-2.248-1.467c-0.525-0.739-0.82-1.83-1.424-2.988
|
||||
C11.229,4.7,10.833,4.103,10.26,3.613C9.678,3.116,8.924,2.751,8.064,2.732c-0.908-0.02-1.713,0.354-2.332,0.875
|
||||
C5.124,4.12,4.712,4.752,4.398,5.367c-0.624,1.225-0.924,2.378-1.49,3.139C2.425,9.154,1.684,9.641,0.895,9.82L0,9.979V16h16V9.9
|
||||
L15.203,9.736z M9,10.688v4H7v-4H4l4-5.25l4,5.25H9z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
38
addons/terrain_3d/icons/height_add.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bcmbqryggekg1"
|
||||
path="res://.godot/imported/height_add.svg-9e680ce71fa4c541748e081b99167369.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/height_add.svg"
|
||||
dest_files=["res://.godot/imported/height_add.svg-9e680ce71fa4c541748e081b99167369.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
196
addons/terrain_3d/icons/height_div.svg
Normal file
@@ -0,0 +1,196 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="icon_height_div.svg"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
enable-background="new 0 0 16 16"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2033">
|
||||
|
||||
<inkscape:path-effect
|
||||
id="path-effect6469"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect6463"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect4977"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect4245"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect3156"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect2324"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
|
||||
<inkscape:path-effect
|
||||
offset_points="0.76255776,0.35156248"
|
||||
not_jump="true"
|
||||
sort_points="true"
|
||||
linejoin_type="spiro"
|
||||
miter_limit="4"
|
||||
scale_width="1"
|
||||
id="path-effect2285"
|
||||
is_visible="true"
|
||||
effect="powerstroke"
|
||||
lpeversion="1"
|
||||
interpolator_beta="0.75"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
end_linecap_type="round"
|
||||
start_linecap_type="round">
|
||||
</inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect
|
||||
steps="1"
|
||||
threshold="0.0028332064"
|
||||
smooth_angles="0"
|
||||
helper_size="0"
|
||||
step="1"
|
||||
id="path-effect2283"
|
||||
is_visible="true"
|
||||
effect="simplify"
|
||||
lpeversion="1"
|
||||
simplify_just_coalesce="false"
|
||||
simplify_individual_paths="false">
|
||||
</inkscape:path-effect>
|
||||
<inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4977-4" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4245-1" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect3156-8" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect2324-5" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="powerstroke"
|
||||
is_visible="true"
|
||||
scale_width="1"
|
||||
miter_limit="4"
|
||||
linejoin_type="spiro"
|
||||
sort_points="true"
|
||||
not_jump="true"
|
||||
offset_points="0.76255776,0.35156248"
|
||||
id="path-effect2285-9"
|
||||
start_linecap_type="round"
|
||||
end_linecap_type="round"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
interpolator_beta="0.75">
|
||||
</inkscape:path-effect><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="simplify"
|
||||
is_visible="true"
|
||||
step="1"
|
||||
helper_size="0"
|
||||
smooth_angles="0"
|
||||
threshold="0.0028332064"
|
||||
steps="1"
|
||||
id="path-effect2283-2"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false">
|
||||
</inkscape:path-effect></defs>
|
||||
<sodipodi:namedview
|
||||
showguides="false"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="3.4913396"
|
||||
inkscape:cy="13.788582"
|
||||
id="namedview8"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4140" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
id="path4012"
|
||||
style="fill:#fc7f7f;fill-opacity:1;stroke-width:0.764771"
|
||||
d="M 1.5898438 3.2871094 C 1.0957748 3.280765 0.56716282 3.3249664 0 3.4257812 L 0 15.955078 L 16 15.955078 L 16 12.246094 C 10.09046 15.642843 7.1418918 10.840026 5.1035156 6.2128906 C 6.678498 7.1187996 6.5445981 7.3630122 8.4746094 9.703125 C 11.163354 13.034961 13.74668 11.801049 16 10.460938 L 16 8.2597656 C 8.6991041 14.580269 9.0008764 3.3822748 1.5898438 3.2871094 z " /><path
|
||||
id="path16308"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M8.064,1.4 C7.156,1.38,6.351,1.753,5.732,2.275C5.124,2.788,4.711,3.42,4.398,4.035C3.774,5.26,3.475,6.414,2.908,7.173 c-0.483,0.65-1.224,1.135-2.013,1.315L0,8.646V10.8c1.843,0.457,5.033-1.792,5.506-4.325C6.03,5.322,6.454,3.693,7.883,3.408h0.049 l0.1-0.006c1.329,0.167,1.81,1.646,2.282,2.701c0.816,3.09,3.985,4.793,5.687,4.59V8.568l-0.797-0.166 c-0.888-0.183-1.726-0.729-2.248-1.467c-0.524-0.739-0.819-1.83-1.424-2.988c-0.304-0.581-0.698-1.178-1.271-1.668 C9.678,1.784,8.924,1.418,8.064,1.4z" />
|
||||
<path
|
||||
id="path16308_2_"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M8.064,2.835 C7.156,2.815,6.351,3.188,5.732,3.71c-0.608,0.513-1.021,1.145-1.334,1.76C3.774,6.695,3.475,7.85,2.908,8.608 c-0.483,0.65-1.224,1.136-2.013,1.315L0,10.082v2.153c1.843,0.457,5.033-1.792,5.506-4.325C6.03,6.758,6.454,5.128,7.883,4.844 h0.049l0.1-0.006c1.329,0.167,1.81,1.646,2.282,2.701c0.816,3.09,3.985,4.793,5.687,4.59v-2.125l-0.797-0.166 c-0.888-0.183-1.726-0.729-2.248-1.466c-0.524-0.739-0.819-1.83-1.424-2.988c-0.304-0.581-0.698-1.178-1.271-1.668 C9.678,3.22,8.924,2.854,8.064,2.835z" />
|
||||
<path
|
||||
id="path16308_1_"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M0,6.91v2.139 c1.578,0,16.001,0,16.001,0V6.91H0z" />
|
||||
<path
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M10.064,9.872C9.579,8.813,9.3,6.726,7.882,6.742C6.454,7.026,6.5,8.686,5.976,9.842 C5.39,11.51,1.708,12.982,0,13.574V16c4,0,12,0,16,0v-2.537C14.176,12.84,10.674,11.646,10.064,9.872z"
|
||||
id="path2040" />
|
||||
<path
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M0,8c0,0,0.917,2.709,2.104,2.479S3,5.375,4.063,5.167s0.521,6.083,2.188,5.958 S6.104,4.313,8.458,3.438s-1.583,7.979,0.563,8.688s2.208-8.479,4.521-9.729s-1.292,10.271,1.375,10.75"
|
||||
id="path2042" />
|
||||
|
||||
|
||||
<path
|
||||
d="M 0,0 14.842,0.004 16,0 Z"
|
||||
id="rect12437" /></svg>
|
||||
|
After Width: | Height: | Size: 6.3 KiB |
38
addons/terrain_3d/icons/height_div.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://danh7tb2v6rx7"
|
||||
path="res://.godot/imported/height_div.svg-449a465f9fdd11ab59f2f1c78815408c.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/height_div.svg"
|
||||
dest_files=["res://.godot/imported/height_div.svg-449a465f9fdd11ab59f2f1c78815408c.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
28
addons/terrain_3d/icons/height_flat.svg
Normal file
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1"
|
||||
id="svg2" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:cc="http://creativecommons.org/ns#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:svg="http://www.w3.org/2000/svg" xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" sodipodi:docname="icon_height_flat.svg" inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" width="16px" height="16px"
|
||||
viewBox="0 0 16 16" enable-background="new 0 0 16 16" xml:space="preserve">
|
||||
<defs>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect4977"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect4245"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect3156"></inkscape:path-effect>
|
||||
<inkscape:path-effect lpeversion="1" effect="spiro" is_visible="true" id="path-effect2324"></inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="powerstroke" is_visible="true" scale_width="1" miter_limit="4" linejoin_type="spiro" sort_points="true" not_jump="true" offset_points="0.76255776,0.35156248" id="path-effect2285" start_linecap_type="round" end_linecap_type="round" interpolator_type="CentripetalCatmullRom" interpolator_beta="0.75">
|
||||
</inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect lpeversion="1" effect="simplify" is_visible="true" step="1" helper_size="0" smooth_angles="0" threshold="0.0028332064" steps="1" id="path-effect2283" simplify_individual_paths="false" simplify_just_coalesce="false">
|
||||
</inkscape:path-effect>
|
||||
</defs>
|
||||
<sodipodi:namedview inkscape:cy="6.8059028" inkscape:cx="11.866136" inkscape:zoom="22.627417" showgrid="false" guidetolerance="10" gridtolerance="10" objecttolerance="10" borderopacity="1" pagecolor="#ffffff" bordercolor="#666666" id="namedview8" inkscape:current-layer="svg2" inkscape:window-maximized="1" inkscape:window-y="-8" inkscape:window-x="-8" inkscape:object-nodes="true" inkscape:snap-grids="false" inkscape:window-height="1009" inkscape:window-width="1920" inkscape:pageshadow="2" inkscape:pageopacity="0" inkscape:object-paths="false" inkscape:snap-smooth-nodes="false" inkscape:snap-to-guides="true" inkscape:pagecheckerboard="0" inkscape:showpageshadow="0" inkscape:deskcolor="#d1d1d1" showguides="false">
|
||||
<inkscape:grid type="xygrid" id="grid4140"></inkscape:grid>
|
||||
</sodipodi:namedview>
|
||||
<path id="path3133" sodipodi:nodetypes="cscccccccscc" fill="#FC7F7F" d="M4.398,8.417c-0.624,1.225-0.924,2.378-1.49,3.138
|
||||
c-0.483,0.649-1.225,1.135-2.014,1.314L0,13.027V16l1.158-0.004L16,16v-3.051l-0.797-0.164c-0.887-0.183-1.725-0.729-2.248-1.467
|
||||
c-0.525-0.738-0.82-1.83-1.424-2.988L4.398,8.417z"/>
|
||||
<polygon fill="#FC7F7F" points="3.375,5.331 7.375,5.331 7.375,8.331 12.625,4.331 7.375,0.331 7.375,3.331 3.375,3.331 "/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.2 KiB |
38
addons/terrain_3d/icons/height_flat.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://crj0xfyiyr45u"
|
||||
path="res://.godot/imported/height_flat.svg-be726a006bf06e05a7a8867510f3996e.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/height_flat.svg"
|
||||
dest_files=["res://.godot/imported/height_flat.svg-be726a006bf06e05a7a8867510f3996e.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
201
addons/terrain_3d/icons/height_mul.svg
Normal file
@@ -0,0 +1,201 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
|
||||
sodipodi:docname="icon_height_mul.svg"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
enable-background="new 0 0 16 16"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<defs
|
||||
id="defs2033">
|
||||
|
||||
<inkscape:path-effect
|
||||
id="path-effect6469"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect6463"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect4977"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect4245"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect3156"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
<inkscape:path-effect
|
||||
id="path-effect2324"
|
||||
is_visible="true"
|
||||
effect="spiro"
|
||||
lpeversion="1" />
|
||||
|
||||
<inkscape:path-effect
|
||||
offset_points="0.76255776,0.35156248"
|
||||
not_jump="true"
|
||||
sort_points="true"
|
||||
linejoin_type="spiro"
|
||||
miter_limit="4"
|
||||
scale_width="1"
|
||||
id="path-effect2285"
|
||||
is_visible="true"
|
||||
effect="powerstroke"
|
||||
lpeversion="1"
|
||||
interpolator_beta="0.75"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
end_linecap_type="round"
|
||||
start_linecap_type="round">
|
||||
</inkscape:path-effect>
|
||||
|
||||
<inkscape:path-effect
|
||||
steps="1"
|
||||
threshold="0.0028332064"
|
||||
smooth_angles="0"
|
||||
helper_size="0"
|
||||
step="1"
|
||||
id="path-effect2283"
|
||||
is_visible="true"
|
||||
effect="simplify"
|
||||
lpeversion="1"
|
||||
simplify_just_coalesce="false"
|
||||
simplify_individual_paths="false">
|
||||
</inkscape:path-effect>
|
||||
<inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4977-4" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4245-1" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect3156-8" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect2324-5" /><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="powerstroke"
|
||||
is_visible="true"
|
||||
scale_width="1"
|
||||
miter_limit="4"
|
||||
linejoin_type="spiro"
|
||||
sort_points="true"
|
||||
not_jump="true"
|
||||
offset_points="0.76255776,0.35156248"
|
||||
id="path-effect2285-9"
|
||||
start_linecap_type="round"
|
||||
end_linecap_type="round"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
interpolator_beta="0.75">
|
||||
</inkscape:path-effect><inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="simplify"
|
||||
is_visible="true"
|
||||
step="1"
|
||||
helper_size="0"
|
||||
smooth_angles="0"
|
||||
threshold="0.0028332064"
|
||||
steps="1"
|
||||
id="path-effect2283-2"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false">
|
||||
</inkscape:path-effect></defs>
|
||||
<sodipodi:namedview
|
||||
showguides="false"
|
||||
bordercolor="#666666"
|
||||
pagecolor="#ffffff"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
showgrid="false"
|
||||
inkscape:zoom="11.313709"
|
||||
inkscape:cx="13.832776"
|
||||
inkscape:cy="18.031222"
|
||||
id="namedview8"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1009"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="svg2">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4140" />
|
||||
</sodipodi:namedview>
|
||||
<path
|
||||
style="fill:#fc7f7f;fill-opacity:1;stroke-width:0.764771"
|
||||
d="M 1.5898438,5.5417983 C 1.0957744,5.5354539 0.56716339,5.5780631 0,5.6788781 V 15.955806 H 16 V 10.513229 C 8.6990968,16.833739 9.0008839,5.6369638 1.5898438,5.5417983 Z"
|
||||
id="path4012"
|
||||
sodipodi:nodetypes="sccccs" /><path
|
||||
id="path16308"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M8.064,1.4 C7.156,1.38,6.351,1.753,5.732,2.275C5.124,2.788,4.711,3.42,4.398,4.035C3.774,5.26,3.475,6.414,2.908,7.173 c-0.483,0.65-1.224,1.135-2.013,1.315L0,8.646V10.8c1.843,0.457,5.033-1.792,5.506-4.325C6.03,5.322,6.454,3.693,7.883,3.408h0.049 l0.1-0.006c1.329,0.167,1.81,1.646,2.282,2.701c0.816,3.09,3.985,4.793,5.687,4.59V8.568l-0.797-0.166 c-0.888-0.183-1.726-0.729-2.248-1.467c-0.524-0.739-0.819-1.83-1.424-2.988c-0.304-0.581-0.698-1.178-1.271-1.668 C9.678,1.784,8.924,1.418,8.064,1.4z" />
|
||||
<path
|
||||
id="path16308_2_"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M8.064,2.835 C7.156,2.815,6.351,3.188,5.732,3.71c-0.608,0.513-1.021,1.145-1.334,1.76C3.774,6.695,3.475,7.85,2.908,8.608 c-0.483,0.65-1.224,1.136-2.013,1.315L0,10.082v2.153c1.843,0.457,5.033-1.792,5.506-4.325C6.03,6.758,6.454,5.128,7.883,4.844 h0.049l0.1-0.006c1.329,0.167,1.81,1.646,2.282,2.701c0.816,3.09,3.985,4.793,5.687,4.59v-2.125l-0.797-0.166 c-0.888-0.183-1.726-0.729-2.248-1.466c-0.524-0.739-0.819-1.83-1.424-2.988c-0.304-0.581-0.698-1.178-1.271-1.668 C9.678,3.22,8.924,2.854,8.064,2.835z" />
|
||||
<path
|
||||
id="path16308_1_"
|
||||
sodipodi:nodetypes="sssscccccccccccssss"
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M0,6.91v2.139 c1.578,0,16.001,0,16.001,0V6.91H0z" />
|
||||
<path
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M10.064,9.872C9.579,8.813,9.3,6.726,7.882,6.742C6.454,7.026,6.5,8.686,5.976,9.842 C5.39,11.51,1.708,12.982,0,13.574V16c4,0,12,0,16,0v-2.537C14.176,12.84,10.674,11.646,10.064,9.872z"
|
||||
id="path2040" />
|
||||
<path
|
||||
display="none"
|
||||
fill="#FC7F7F"
|
||||
d="M0,8c0,0,0.917,2.709,2.104,2.479S3,5.375,4.063,5.167s0.521,6.083,2.188,5.958 S6.104,4.313,8.458,3.438s-1.583,7.979,0.563,8.688s2.208-8.479,4.521-9.729s-1.292,10.271,1.375,10.75"
|
||||
id="path2042" />
|
||||
|
||||
|
||||
<path
|
||||
d="M 0,0 14.842,0.004 16,0 Z"
|
||||
id="rect12437" /><path
|
||||
id="path7096"
|
||||
style="fill:#fc7f7f;fill-opacity:1;stroke-width:0.764771"
|
||||
d="M 0,2.0234375 V 3.8085938 C 2.8512164,3.4688215 4.2747356,4.3685854 5.2041205,5.9137947 6.7118368,6.8603322 6.6718914,7.2163955 8.3808594,8.5644531 6.2801351,4.1747406 5.2031416,1.5917313 0,2.0234375 Z"
|
||||
sodipodi:nodetypes="ccccc" /></svg>
|
||||
|
After Width: | Height: | Size: 6.5 KiB |
38
addons/terrain_3d/icons/height_mul.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://bu3q0645kb3el"
|
||||
path="res://.godot/imported/height_mul.svg-2dca20fa42a85408713e9bfe411f3c79.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/height_mul.svg"
|
||||
dest_files=["res://.godot/imported/height_mul.svg-2dca20fa42a85408713e9bfe411f3c79.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||
105
addons/terrain_3d/icons/height_slope.svg
Normal file
@@ -0,0 +1,105 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 16.0.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
version="1.1"
|
||||
id="svg2"
|
||||
sodipodi:docname="icon_height_slope.svg"
|
||||
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
enable-background="new 0 0 16 16"
|
||||
xml:space="preserve"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"> <defs
|
||||
id="defs1"> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4977" /> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect4245" /> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect3156" /> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="spiro"
|
||||
is_visible="true"
|
||||
id="path-effect2324" /> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="powerstroke"
|
||||
is_visible="true"
|
||||
scale_width="1"
|
||||
miter_limit="4"
|
||||
linejoin_type="spiro"
|
||||
sort_points="true"
|
||||
not_jump="true"
|
||||
offset_points="0.76255776,0.35156248"
|
||||
id="path-effect2285"
|
||||
start_linecap_type="round"
|
||||
end_linecap_type="round"
|
||||
interpolator_type="CentripetalCatmullRom"
|
||||
interpolator_beta="0.75"> </inkscape:path-effect> <inkscape:path-effect
|
||||
lpeversion="1"
|
||||
effect="simplify"
|
||||
is_visible="true"
|
||||
step="1"
|
||||
helper_size="0"
|
||||
smooth_angles="0"
|
||||
threshold="0.0028332064"
|
||||
steps="1"
|
||||
id="path-effect2283"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false"> </inkscape:path-effect> </defs> <sodipodi:namedview
|
||||
inkscape:cy="27.665553"
|
||||
inkscape:cx="-14.760854"
|
||||
inkscape:zoom="5.6568543"
|
||||
showgrid="false"
|
||||
guidetolerance="10"
|
||||
gridtolerance="10"
|
||||
objecttolerance="10"
|
||||
borderopacity="1"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
id="namedview8"
|
||||
inkscape:current-layer="svg2"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-x="0"
|
||||
inkscape:object-nodes="true"
|
||||
inkscape:snap-grids="false"
|
||||
inkscape:window-height="1011"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:object-paths="false"
|
||||
inkscape:snap-smooth-nodes="false"
|
||||
inkscape:snap-to-guides="true"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:deskcolor="#d1d1d1"
|
||||
showguides="false"> <inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid4140"
|
||||
originx="0"
|
||||
originy="0"
|
||||
spacingy="1"
|
||||
spacingx="1"
|
||||
units="px"
|
||||
visible="false" /> </sodipodi:namedview> <polygon
|
||||
fill="#fc7f7f"
|
||||
points="3.375,5.331 7.375,5.331 7.375,8.331 12.625,4.331 7.375,0.331 7.375,3.331 3.375,3.331 "
|
||||
id="polygon1"
|
||||
transform="rotate(45,9.0843727,9.1561132)" /> <path
|
||||
style="fill:#fc7f7f;fill-opacity:1;stroke:none;stroke-width:2"
|
||||
d="M 0,0 16,16 H 0 Z"
|
||||
id="path1"
|
||||
sodipodi:nodetypes="cccc" /></svg>
|
||||
|
After Width: | Height: | Size: 3.1 KiB |
38
addons/terrain_3d/icons/height_slope.svg.import
Normal file
@@ -0,0 +1,38 @@
|
||||
[remap]
|
||||
|
||||
importer="texture"
|
||||
type="CompressedTexture2D"
|
||||
uid="uid://0cd7so4kw7da"
|
||||
path="res://.godot/imported/height_slope.svg-e20540c5538d0c57a9d229a772b3d1b3.ctex"
|
||||
metadata={
|
||||
"has_editor_variant": true,
|
||||
"vram_texture": false
|
||||
}
|
||||
|
||||
[deps]
|
||||
|
||||
source_file="res://addons/terrain_3d/icons/height_slope.svg"
|
||||
dest_files=["res://.godot/imported/height_slope.svg-e20540c5538d0c57a9d229a772b3d1b3.ctex"]
|
||||
|
||||
[params]
|
||||
|
||||
compress/mode=0
|
||||
compress/high_quality=false
|
||||
compress/lossy_quality=0.7
|
||||
compress/hdr_compression=1
|
||||
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
|
||||
svg/scale=1.0
|
||||
editor/scale_with_editor_scale=true
|
||||
editor/convert_colors_with_editor_theme=false
|
||||