From 9a144705f5493705285c9cfb6f6c595cc0285ae0 Mon Sep 17 00:00:00 2001 From: kayomn Date: Tue, 10 Jan 2023 01:36:09 +0000 Subject: [PATCH] Initial commit --- .gitattributes | 7 + .gitignore | 2 + editor.scn | 3 + editor_theme.res | 3 + export_presets.cfg | 79 ++++++++++ icon.png | 3 + icon.png.import | 36 +++++ immortal.ttf | 3 + immortal.ttf.import | 33 ++++ player_controller.gd | 92 +++++++++++ project.godot | 98 ++++++++++++ prototype_tiles_large_albedo.png | 3 + prototype_tiles_large_albedo.png.import | 36 +++++ settings.gd | 20 +++ terrain_cursor_emission.png | 3 + terrain_cursor_emission.png.import | 36 +++++ terrain_instance_3d.gd | 197 ++++++++++++++++++++++++ terrain_shader.gdshader | 55 +++++++ 18 files changed, 709 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 editor.scn create mode 100644 editor_theme.res create mode 100644 export_presets.cfg create mode 100644 icon.png create mode 100644 icon.png.import create mode 100644 immortal.ttf create mode 100644 immortal.ttf.import create mode 100644 player_controller.gd create mode 100644 project.godot create mode 100644 prototype_tiles_large_albedo.png create mode 100644 prototype_tiles_large_albedo.png.import create mode 100644 settings.gd create mode 100644 terrain_cursor_emission.png create mode 100644 terrain_cursor_emission.png.import create mode 100644 terrain_instance_3d.gd create mode 100644 terrain_shader.gdshader diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..5cb4381 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,7 @@ +# Normalize EOL for all files that Git considers text files. +* text=auto eol=lf +# LFS files. +*.png filter=lfs diff=lfs merge=lfs -text +*.ttf filter=lfs diff=lfs merge=lfs -text +*.scn filter=lfs diff=lfs merge=lfs -text +*.res filter=lfs diff=lfs merge=lfs -text diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4709183 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +# Godot 4+ specific ignores +.godot/ diff --git a/editor.scn b/editor.scn new file mode 100644 index 0000000..cbf147f --- /dev/null +++ b/editor.scn @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:332a300c24da15e6ece7e0fe4ee07e394939d953e8ba482613ebc1fd70cc579e +size 5103 diff --git a/editor_theme.res b/editor_theme.res new file mode 100644 index 0000000..8dd9794 --- /dev/null +++ b/editor_theme.res @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:68b3bc205138b626fa79896fd4ae0343ff7c46f660cf060ddd23454f240e9145 +size 390 diff --git a/export_presets.cfg b/export_presets.cfg new file mode 100644 index 0000000..9926f3d --- /dev/null +++ b/export_presets.cfg @@ -0,0 +1,79 @@ +[preset.0] + +name="Windows Desktop" +platform="Windows Desktop" +runnable=true +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="../../../Protectorate.exe" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false +script_export_mode=1 +script_encryption_key="" + +[preset.0.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_script=1 +binary_format/embed_pck=true +texture_format/bptc=false +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +texture_format/no_bptc_fallbacks=true +binary_format/architecture="x86_64" +codesign/enable=false +codesign/identity_type=0 +codesign/identity="" +codesign/password="" +codesign/timestamp=true +codesign/timestamp_server_url="" +codesign/digest_algorithm=1 +codesign/description="" +codesign/custom_options=PackedStringArray() +application/modify_resources=true +application/icon="" +application/console_wrapper_icon="" +application/icon_interpolation=4 +application/file_version="" +application/product_version="" +application/company_name="" +application/product_name="" +application/file_description="" +application/copyright="" +application/trademarks="" + +[preset.1] + +name="Linux/X11" +platform="Linux/X11" +runnable=true +custom_features="" +export_filter="all_resources" +include_filter="" +exclude_filter="" +export_path="../../../Protectorate.x86_64" +encryption_include_filters="" +encryption_exclude_filters="" +encrypt_pck=false +encrypt_directory=false +script_export_mode=1 +script_encryption_key="" + +[preset.1.options] + +custom_template/debug="" +custom_template/release="" +debug/export_console_script=1 +binary_format/embed_pck=true +texture_format/bptc=false +texture_format/s3tc=true +texture_format/etc=false +texture_format/etc2=false +texture_format/no_bptc_fallbacks=true +binary_format/architecture="x86_64" diff --git a/icon.png b/icon.png new file mode 100644 index 0000000..c2967ba --- /dev/null +++ b/icon.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:b647ab1176ec1f091e00db4a7cbbdc6d390f3f999f22074f9900065a77008761 +size 337745 diff --git a/icon.png.import b/icon.png.import new file mode 100644 index 0000000..136e520 --- /dev/null +++ b/icon.png.import @@ -0,0 +1,36 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bqih4uf556hba" +path.s3tc="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.s3tc.ctex" +path.etc2="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.etc2.ctex" +metadata={ +"imported_formats": ["s3tc", "etc2"], +"vram_texture": true +} + +[deps] + +source_file="res://icon.png" +dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.s3tc.ctex", "res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.etc2.ctex"] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=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=0 diff --git a/immortal.ttf b/immortal.ttf new file mode 100644 index 0000000..07492d8 --- /dev/null +++ b/immortal.ttf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fd2edf036588a3be9156c86dee1b54064fb064b716017cfd6f83d9d70edd7011 +size 170508 diff --git a/immortal.ttf.import b/immortal.ttf.import new file mode 100644 index 0000000..a841a96 --- /dev/null +++ b/immortal.ttf.import @@ -0,0 +1,33 @@ +[remap] + +importer="font_data_dynamic" +type="FontFile" +uid="uid://d0yr073mjcs68" +path="res://.godot/imported/immortal.ttf-1429e0fa3f3d49f06937da84431aae4f.fontdata" + +[deps] + +source_file="res://immortal.ttf" +dest_files=["res://.godot/imported/immortal.ttf-1429e0fa3f3d49f06937da84431aae4f.fontdata"] + +[params] + +Rendering=null +antialiasing=1 +generate_mipmaps=false +multichannel_signed_distance_field=false +msdf_pixel_range=8 +msdf_size=48 +allow_system_fallback=true +force_autohinter=false +hinting=1 +subpixel_positioning=1 +oversampling=0.0 +Fallbacks=null +fallbacks=[] +Compress=null +compress=true +preload=[] +language_support={} +script_support={} +opentype_features={} diff --git a/player_controller.gd b/player_controller.gd new file mode 100644 index 0000000..9568283 --- /dev/null +++ b/player_controller.gd @@ -0,0 +1,92 @@ +class_name PlayerController extends Node3D + +const _BACKWARD := "player_controller_backward" + +const _FORWARD := "player_controller_forward" + +const _LEFT := "player_controller_left" + +const _RIGHT := "player_controller_right" + +const _ROTATE_CCW := "player_controller_rotate_ccw" + +const _ROTATE_CW := "player_controller_rotate_cw" + +const _DRAG_SPEED_BASE_MODIFIER := 0.15 + +const _MOVE_SPEED_BASE_MODIFIER := 50.0 + +const _ROTATE_SPEED_BASE := 5.0 + +const _TRANSFORM_DELTA := 10.0 + +var _is_drag_panning := false + +@onready +var _target_position := self.position + +@onready +var _target_orientation := self.global_rotation.y + +@export +var movement_smoothing := 0.5 + +func _input(event: InputEvent) -> void: + if event is InputEventMouseButton: + match event.button_index: + MOUSE_BUTTON_MIDDLE: + self._is_drag_panning = event.is_pressed() + Input.mouse_mode = Input.MOUSE_MODE_CAPTURED if self._is_drag_panning else Input.MOUSE_MODE_VISIBLE + + MOUSE_BUTTON_WHEEL_DOWN: + pass + + MOUSE_BUTTON_WHEEL_UP: + pass + + return + + if (event is InputEventMouseMotion) and self._is_drag_panning: + var global_basis := self.global_transform.basis + var camera_settings := GameSettings.camera_settings + + var dampened_speed :=\ + camera_settings.movement_speed_modifier * _DRAG_SPEED_BASE_MODIFIER + + self._target_position += dampened_speed.y * (-global_basis.z) *\ + event.relative.y * (-1.0 if camera_settings.is_y_inverted else 1.0) + + self._target_position += dampened_speed.x * (-global_basis.x) *\ + event.relative.x * (-1.0 if camera_settings.is_x_inverted else 1.0) + + return + + if event is InputEventScreenDrag: + return + +func _process(delta: float) -> void: + var global_basis := self.global_transform.basis + var camera_settings := GameSettings.camera_settings + var delta_speed := camera_settings.movement_speed_modifier * _MOVE_SPEED_BASE_MODIFIER * delta + + self._target_position += delta_speed.y * (-global_basis.z) *\ + (Input.get_action_strength(_FORWARD) - Input.get_action_strength(_BACKWARD)) *\ + (-1.0 if camera_settings.is_y_inverted else 1.0) + + self._target_position += delta_speed.x * (-global_basis.x) *\ + (Input.get_action_strength(_LEFT) - Input.get_action_strength(_RIGHT)) *\ + (-1.0 if camera_settings.is_y_inverted else 1.0) + + self._target_orientation += (Input.get_action_strength(_ROTATE_CCW) -\ + Input.get_action_strength(_ROTATE_CW)) * _ROTATE_SPEED_BASE *\ + camera_settings.rotation_speed_modifier * delta + + self.global_transform = self.global_transform.interpolate_with( + Transform3D(Basis(Vector3.UP, self._target_orientation), self._target_position), + delta * _TRANSFORM_DELTA * self.movement_smoothing) + +## +## +## +func is_drag_panning() -> bool: + return self._is_drag_panning diff --git a/project.godot b/project.godot new file mode 100644 index 0000000..71b682f --- /dev/null +++ b/project.godot @@ -0,0 +1,98 @@ +; Engine configuration file. +; It's best edited using the editor UI and not directly, +; since the parameters that go here are not all obvious. +; +; Format: +; [section] ; section goes between [] +; param=value ; assign values to parameters + +config_version=5 + +_global_script_classes=[{ +"base": "Node3D", +"class": &"PlayerController", +"language": &"GDScript", +"path": "res://player_controller.gd" +}, { +"base": "Node", +"class": &"Settings", +"language": &"GDScript", +"path": "res://settings.gd" +}, { +"base": "GeometryInstance3D", +"class": &"TerrainInstance3D", +"language": &"GDScript", +"path": "res://terrain_instance_3d.gd" +}] +_global_script_class_icons={ +"PlayerController": "", +"Settings": "", +"TerrainInstance3D": "" +} + +[application] + +config/name="Protectorate" +run/main_scene="res://editor.scn" +config/features=PackedStringArray("4.0", "Forward Plus") +config/icon="res://icon.png" + +[autoload] + +GameSettings="*res://settings.gd" + +[debug] + +gdscript/warnings/assert_always_true=0 +gdscript/warnings/assert_always_false=0 + +[display] + +window/size/viewport_width=1280 +window/size/viewport_height=800 +window/stretch/mode="canvas_items" +window/stretch/aspect="keep_height" + +[input] + +player_controller_left={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"unicode":0,"echo":false,"script":null) +] +} +player_controller_right={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"unicode":0,"echo":false,"script":null) +] +} +player_controller_forward={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"unicode":0,"echo":false,"script":null) +] +} +player_controller_backward={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"unicode":0,"echo":false,"script":null) +] +} +player_controller_rotate_cw={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"unicode":0,"echo":false,"script":null) +] +} +player_controller_rotate_ccw={ +"deadzone": 0.5, +"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":81,"unicode":0,"echo":false,"script":null) +] +} +editor_paint={ +"deadzone": 0.5, +"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":0,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"pressed":false,"double_click":false,"script":null) +] +} + +[rendering] + +lights_and_shadows/directional_shadow/soft_shadow_filter_quality=5 +lights_and_shadows/directional_shadow/16_bits=false +lights_and_shadows/positional_shadow/soft_shadow_filter_quality=5 diff --git a/prototype_tiles_large_albedo.png b/prototype_tiles_large_albedo.png new file mode 100644 index 0000000..4e26acd --- /dev/null +++ b/prototype_tiles_large_albedo.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:affe82474a9ae58431f3e7f576b91cd9dec0479d1d89ab161d719a72c2c644aa +size 637 diff --git a/prototype_tiles_large_albedo.png.import b/prototype_tiles_large_albedo.png.import new file mode 100644 index 0000000..073e101 --- /dev/null +++ b/prototype_tiles_large_albedo.png.import @@ -0,0 +1,36 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://bgpk15qrqxly8" +path.s3tc="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex" +path.etc2="res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex" +metadata={ +"imported_formats": ["s3tc", "etc2"], +"vram_texture": true +} + +[deps] + +source_file="res://prototype_tiles_large_albedo.png" +dest_files=["res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.s3tc.ctex", "res://.godot/imported/prototype_tiles_large_albedo.png-c3984e5db888f4b509766546fda5695b.etc2.ctex"] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=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=0 diff --git a/settings.gd b/settings.gd new file mode 100644 index 0000000..2fbda84 --- /dev/null +++ b/settings.gd @@ -0,0 +1,20 @@ +class_name Settings extends Node + +class CameraSettings: + var is_x_inverted := false + + var is_y_inverted := false + + var movement_speed_modifier := Vector2(0.5, 0.5) + + var rotation_speed_modifier := 0.5 + +## +## +## +var camera_settings := CameraSettings.new(): + get: + return camera_settings + + set(_value): + assert(false, "`camera_settings` is not re-assignable") diff --git a/terrain_cursor_emission.png b/terrain_cursor_emission.png new file mode 100644 index 0000000..bdb6d4e --- /dev/null +++ b/terrain_cursor_emission.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:495e7874b1a3d3c20fbf8644f5ca3242bea67ffe23775d349598876dd130df69 +size 27850 diff --git a/terrain_cursor_emission.png.import b/terrain_cursor_emission.png.import new file mode 100644 index 0000000..96764a5 --- /dev/null +++ b/terrain_cursor_emission.png.import @@ -0,0 +1,36 @@ +[remap] + +importer="texture" +type="CompressedTexture2D" +uid="uid://dmbae0p1ujwcv" +path.s3tc="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex" +path.etc2="res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex" +metadata={ +"imported_formats": ["s3tc", "etc2"], +"vram_texture": true +} + +[deps] + +source_file="res://terrain_cursor_emission.png" +dest_files=["res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.s3tc.ctex", "res://.godot/imported/terrain_cursor_emission.png-242c595842e9c0210b5a4ae1147e42e6.etc2.ctex"] + +[params] + +compress/mode=2 +compress/lossy_quality=0.7 +compress/hdr_compression=1 +compress/bptc_ldr=0 +compress/normal_map=0 +compress/channel_pack=0 +mipmaps/generate=true +mipmaps/limit=-1 +roughness/mode=0 +roughness/src_normal="" +process/fix_alpha_border=true +process/premult_alpha=true +process/normal_map_invert_y=false +process/hdr_as_srgb=false +process/hdr_clamp_exposure=false +process/size_limit=0 +detect_3d/compress_to=0 diff --git a/terrain_instance_3d.gd b/terrain_instance_3d.gd new file mode 100644 index 0000000..ee409da --- /dev/null +++ b/terrain_instance_3d.gd @@ -0,0 +1,197 @@ +@tool +class_name TerrainInstance3D extends GeometryInstance3D + +var _mesh := ArrayMesh.new() + +var _material: ShaderMaterial = (func (): + var material := ShaderMaterial.new() + + material.shader = preload("res://terrain_shader.gdshader") + + return material).call() + +## +## +## +@export +var size: Vector2i = Vector2i.ZERO: + get: + return size + + set(value): + self._mesh.clear_surfaces() + + var width := value.x + var height := value.y + + if (width != 0) and (height != 0): + if (width != size.x) or (height != size.y): + var surface_tool := SurfaceTool.new() + + surface_tool.begin(Mesh.PRIMITIVE_TRIANGLES) + + var center_x := width / 2.0 + var center_y := height / 2.0 + + for y in height + 1: + for x in width + 1: + surface_tool.set_uv(Vector2(x / float(width), y / float(height))) + surface_tool.set_color(Color(0.0, 0.0, 0.0, 0.0)) + surface_tool.set_normal(Vector3.UP) + surface_tool.add_vertex(Vector3(x - center_x, 0.0, y - center_y)) + + var vert := 0 + + for y in height: + for x in width: + surface_tool.add_index(vert + width + 2) + surface_tool.add_index(vert + width + 1) + surface_tool.add_index(vert + 1) + surface_tool.add_index(vert + 1) + surface_tool.add_index(vert + width + 1) + surface_tool.add_index(vert + 0) + + vert += 1 + + vert += 1 + + RenderingServer.instance_set_base(self.get_instance(), + surface_tool.commit(self._mesh).get_rid()) + + self._material.set_shader_parameter("AREA", Vector2(value)) + self._mesh.surface_set_material(0, self._material) + + size = value + +## +## +## +@export +var layer_1_albedo: Texture2D = null: + get: + return layer_1_albedo + + set(value): + self._material.set_shader_parameter("LAYER_1_ALBEDO", value) + + layer_1_albedo = value + +## +## +## +@export +var layer_1_normal_map: Texture2D = null: + get: + return layer_1_normal_map + + set(value): + self._material.set_shader_parameter("LAYER_1_NORMAL_MAP", value) + + layer_1_normal_map = value + +## +## +## +@export +var layer_2_albedo: Texture2D = null: + get: + return layer_2_albedo + + set(value): + self._material.set_shader_parameter("LAYER_2_ALBEDO", value) + + layer_2_albedo = value + +## +## +## +@export +var layer_2_normal_map: Texture2D = null: + get: + return layer_2_normal_map + + set(value): + self._material.set_shader_parameter("LAYER_2_NORMAL_MAP", value) + + layer_2_normal_map = value + +## +## +## +@export +var layer_3_albedo: Texture2D = null: + get: + return layer_3_albedo + + set(value): + self._material.set_shader_parameter("LAYER_3_ALBEDO", value) + + layer_3_albedo = value + +## +## +## +@export +var layer_3_normal_map: Texture2D = null: + get: + return layer_3_normal_map + + set(value): + self._material.set_shader_parameter("LAYER_3_NORMAL_MAP", value) + + layer_3_normal_map = value + +## +## +## +@export +var layer_4_albedo: Texture2D = null: + get: + return layer_4_albedo + + set(value): + self._material.set_shader_parameter("LAYER_4_ALBEDO", value) + + layer_4_albedo = value + +## +## +## +@export +var layer_4_normal_map: Texture2D = null: + get: + return layer_4_normal_map + + set(value): + self._material.set_shader_parameter("LAYER_4_NORMAL_MAP", value) + + layer_4_normal_map = value + +## +## +## +@export +var terrain_map: Texture2D = null: + get: + return terrain_map + + set(value): + self._material.set_shader_parameter("TERRAIN_MAP", value) + + terrain_map = value + +## +## +## +@export +var max_height := 100.0: + get: + return max_height + + set(value): + self._material.set_shader_parameter("MAX_HEIGHT", value) + + max_height = max(value, 0.0) + +func _init() -> void: + RenderingServer.instance_set_base(self.get_instance(), self._mesh) diff --git a/terrain_shader.gdshader b/terrain_shader.gdshader new file mode 100644 index 0000000..6073c56 --- /dev/null +++ b/terrain_shader.gdshader @@ -0,0 +1,55 @@ +shader_type spatial; + +uniform vec2 AREA; + +uniform sampler2D LAYER_1_ALBEDO : hint_default_black; + +uniform sampler2D LAYER_1_NORMAL_MAP : hint_default_black; + +uniform sampler2D LAYER_2_ALBEDO : hint_default_black; + +uniform sampler2D LAYER_2_NORMAL_MAP : hint_default_black; + +uniform sampler2D LAYER_3_ALBEDO : hint_default_black; + +uniform sampler2D LAYER_3_NORMAL_MAP : hint_default_black; + +uniform sampler2D LAYER_4_ALBEDO : hint_default_black; + +uniform sampler2D LAYER_4_NORMAL_MAP : hint_default_black; + +uniform float MAX_HEIGHT = 100.0; + +uniform sampler2D TERRAIN_MAP : hint_default_transparent, repeat_disable; + +void fragment() { + vec2 uv = UV * AREA; + vec2 uv_alt = uv * -0.25; + vec3 splat_map = texture(TERRAIN_MAP, UV).rgb; + float blank = clamp(1.0 - splat_map.r - splat_map.g - splat_map.b, 0.0, 1.0); + + ALBEDO = blank * 0.5 * (texture(LAYER_1_ALBEDO, uv).rgb + texture(LAYER_1_ALBEDO, uv_alt).rgb); + ALBEDO += splat_map.r * 0.5 * (texture(LAYER_2_ALBEDO, uv).rgb + texture(LAYER_2_ALBEDO, uv_alt).rgb); + ALBEDO += splat_map.g * 0.5 * (texture(LAYER_3_ALBEDO, uv).rgb + texture(LAYER_3_ALBEDO, uv_alt).rgb); + ALBEDO += splat_map.b * 0.5 * (texture(LAYER_4_ALBEDO, uv).rgb + texture(LAYER_4_ALBEDO, uv_alt).rgb); + + NORMAL_MAP = blank * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_1_NORMAL_MAP, uv_alt).rgb); + NORMAL_MAP += splat_map.r * 0.5 * (texture(LAYER_1_NORMAL_MAP, uv).rgb + texture(LAYER_2_NORMAL_MAP, uv_alt).rgb); + NORMAL_MAP += splat_map.g * 0.5 * (texture(LAYER_2_NORMAL_MAP, uv).rgb + texture(LAYER_3_NORMAL_MAP, uv_alt).rgb); + NORMAL_MAP += splat_map.b * 0.5 * (texture(LAYER_3_NORMAL_MAP, uv).rgb + texture(LAYER_4_NORMAL_MAP, uv_alt).rgb); +} + +float height(vec2 uv) { + return MAX_HEIGHT * texture(TERRAIN_MAP, uv).a; +} + +void vertex() { + VERTEX.y = height(UV); + + float left = height(vec2(UV.x - 1.0, UV.y)); + float right = height(vec2(UV.x + 1.0, UV.y)); + float forward = height(vec2(UV.x, UV.y + 1.0)); + float backward = height(vec2(UV.x, UV.y - 1.0)); + + NORMAL = normalize(vec3(left - right, 2.0, forward - forward)); +}