├── .gitignore ├── LICENSE ├── README.md ├── addons ├── joystick_control │ ├── assets │ │ ├── background.png │ │ ├── background.png.import │ │ ├── ball.png │ │ ├── ball.png.import │ │ ├── circle.gd │ │ └── joystick.gd │ ├── icon.png │ ├── icon.png.import │ ├── plugin.cfg │ └── plugin.gd └── shell_fur │ ├── editor_property.gd │ ├── fur_helper_methods.gd │ ├── fur_node_icon.svg │ ├── fur_node_icon.svg.import │ ├── gui │ ├── gradient_inspector.gd │ └── gradient_inspector.tscn │ ├── inspector_plugin.gd │ ├── noise_patterns │ ├── fine.png │ ├── fine.png.import │ ├── monster.png │ ├── monster.png.import │ ├── rough.png │ ├── rough.png.import │ ├── very_fine.png │ ├── very_fine.png.import │ ├── very_rough.png │ └── very_rough.png.import │ ├── plugin.cfg │ ├── shaders │ ├── gui │ │ └── gradient.shader │ ├── shell_fur.gdshader │ └── shell_fur_mobile.gdshader │ ├── shell_fur.gd │ ├── shell_fur_lod.gd │ ├── shell_fur_manager.gd │ └── shell_fur_physics.gd ├── assets ├── Cottage.tscn ├── FPSLabel.gd ├── LOD_label.gd ├── LOD_label.tscn ├── Log.tscn ├── Rat.tscn ├── Roboto-Regular.ttf ├── ball_boy.tscn ├── ball_boy2.tscn ├── growth_api.gd ├── maujoe.camera_control │ ├── icon.png │ ├── icon.png.import │ └── scripts │ │ ├── camera_control.gd │ │ └── camera_control_gui.gd ├── models │ ├── BallBoyMat.material │ ├── Cottage2.bin │ ├── Cottage2.gltf │ ├── Cottage2.gltf.import │ ├── CottageMat.material │ ├── Log.material │ ├── Rat-animated2.bin │ ├── Rat-animated2.gltf │ ├── Rat-animated2.gltf.import │ ├── Rat2.material │ ├── Rat3.gltf │ ├── Rat3.gltf.import │ ├── ball_boy.bin │ ├── ball_boy.gltf │ ├── ball_boy.gltf.import │ ├── mossy_log.bin │ ├── mossy_log.gltf │ ├── mossy_log.gltf.import │ ├── mossy_log.obj │ └── mossy_log.obj.import ├── mossy_log.bin ├── rat_no_blend.tscn ├── render_scaler.gd ├── scene_mobile.tscn └── textures │ ├── .moss_height.png-autosave.kra │ ├── Cottage_Alb.png │ ├── Cottage_Alb.png.import │ ├── Cottage_Alb.png~ │ ├── Cottage_Nor.png │ ├── Cottage_Nor.png.import │ ├── Cottage_Nor.png~ │ ├── Cottage_Rough.png │ ├── Cottage_Rough.png.import │ ├── Cottage_Rough.png~ │ ├── Log_AORoughMetal.png │ ├── Log_AORoughMetal.png.import │ ├── Log_Albedo.png │ ├── Log_Albedo.png.import │ ├── Log_Depth.png │ ├── Log_Depth.png.import │ ├── Log_Normal.png │ ├── Log_Normal.png.import │ ├── ball_boy_AORoughMetal.png │ ├── ball_boy_AORoughMetal.png.import │ ├── ball_boy_Albedo.png │ ├── ball_boy_Albedo.png.import │ ├── ballboy_fur_ldtg.png │ ├── ballboy_fur_ldtg.png.import │ ├── checker.png │ ├── checker.png.import │ ├── moss.png │ ├── moss.png.import │ ├── moss_ldtg.png │ ├── moss_ldtg.png.import │ ├── rat_None_BaseColor.png │ ├── rat_None_BaseColor.png.import │ ├── rat_None_Normal.png │ ├── rat_None_Normal.png.import │ ├── rat_None_Roughness.png │ ├── rat_None_Roughness.png.import │ ├── rat_fur_height.png~ │ ├── rat_fur_ldtg.png │ └── rat_fur_ldtg.png.import ├── default_env.tres ├── demo_desktop.tscn ├── demo_mobile.tscn ├── icon.png ├── icon.png.import └── project.godot /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Godot-specific ignores 3 | .import/ 4 | export.cfg 5 | export_presets.cfg 6 | 7 | # Mono-specific ignores 8 | .mono/ 9 | data_*/ 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Kasper Arnklit Frandsen 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShellFurGodotDemo 2 | 3 | ![DemoScene](https://user-images.githubusercontent.com/4955051/97077434-8b0f7800-15db-11eb-98eb-7cecf1648304.png) 4 | 5 | Demo for [Shell Fur Add-on](https://github.com/Arnklit/ShellFurGodot) 6 | -------------------------------------------------------------------------------- /addons/joystick_control/assets/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/joystick_control/assets/background.png -------------------------------------------------------------------------------- /addons/joystick_control/assets/background.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/background.png-8c06274204b9d9a53117a6eb798fe289.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/joystick_control/assets/background.png" 13 | dest_files=[ "res://.import/background.png-8c06274204b9d9a53117a6eb798fe289.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/joystick_control/assets/ball.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/joystick_control/assets/ball.png -------------------------------------------------------------------------------- /addons/joystick_control/assets/ball.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/ball.png-a04d1b15889d70dad6b04d12b1ac94f0.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/joystick_control/assets/ball.png" 13 | dest_files=[ "res://.import/ball.png-a04d1b15889d70dad6b04d12b1ac94f0.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/joystick_control/assets/circle.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | var radius:float = 1.0 setget _set_radius 4 | var color:Color = Color.white setget _set_color 5 | 6 | func _init(radius:float = 1.0, color:Color = Color.white): 7 | self.radius = radius 8 | self.color = color 9 | 10 | func _set_radius(value:float): 11 | radius = value 12 | update() 13 | 14 | func _set_color(value:Color): 15 | color = value 16 | update() 17 | 18 | func _draw(): 19 | draw_circle(Vector2.ZERO, radius, color) 20 | -------------------------------------------------------------------------------- /addons/joystick_control/assets/joystick.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends Control 3 | 4 | #emitted when pressed state changes 5 | signal pressed(pressed) 6 | #emitted when force changes 7 | signal updated(force, pressed) 8 | 9 | const DEBUG = false 10 | const INACTIVE_IDX = -100 11 | 12 | #distance from center to get to maximum force 13 | export var radius:float = 64.0 setget _set_radius 14 | #distances from center shorter than deadzone count as zero force 15 | export var deadzone:float = 8.0 setget _set_deadzone 16 | #maximum distance from center that accepts touches, should be a bit larger than radius 17 | export var proximity:float = 96.0 setget _set_proximity 18 | export var background_texture:Texture = preload("background.png") setget _set_bg_tex 19 | export var ball_texture:Texture = preload("ball.png") setget _set_ball_tex 20 | 21 | #action names to use for different axis 22 | export var action_left:String = "ui_left" # -X Axis 23 | export var action_right:String = "ui_right" # +X Axis 24 | export var action_up:String = "ui_up" # -Y Axis 25 | export var action_down:String = "ui_down" # +Y Axis 26 | 27 | #background texture 28 | var bg:TextureRect 29 | #handle texture 30 | var ball:Sprite 31 | 32 | var touches:Array = [] 33 | 34 | var currentTouchIdx = INACTIVE_IDX 35 | 36 | # For visualising in editor 37 | const Circle = preload("circle.gd") 38 | var radius_v:Circle 39 | var deadzone_v:Circle 40 | var proximity_v:Circle 41 | 42 | func is_pressed() -> bool: 43 | return touches.size() > 0 44 | 45 | func _init(): 46 | var container:CenterContainer = CenterContainer.new(); 47 | container.use_top_left = true 48 | add_child(container) 49 | 50 | bg = TextureRect.new() 51 | bg.texture = background_texture 52 | container.add_child(bg) 53 | 54 | ball = Sprite.new() 55 | ball.texture = ball_texture 56 | container.add_child(ball) 57 | 58 | if Engine.editor_hint: _setup_visual_hints(container) 59 | 60 | func _set_radius(value:float): 61 | radius = value 62 | if Engine.editor_hint: radius_v.radius = radius 63 | 64 | func _set_deadzone(value:float): 65 | deadzone = value 66 | if Engine.editor_hint: deadzone_v.radius = value 67 | 68 | func _set_proximity(value:float): 69 | proximity = value 70 | if Engine.editor_hint: proximity_v.radius = value 71 | 72 | func _set_bg_tex(tex:Texture): 73 | background_texture = tex 74 | bg.texture = tex 75 | 76 | func _set_ball_tex(tex:Texture): 77 | ball_texture = tex 78 | ball.texture = tex 79 | 80 | func _input(event): 81 | if event is InputEventScreenTouch or event is InputEventScreenDrag: 82 | _process_input(make_input_local(event)) 83 | 84 | func _process_input(event): 85 | var idx = _get_event_idx(event) 86 | var down = _is_event_down(event) 87 | 88 | if idx == INACTIVE_IDX: return 89 | if down == null: return 90 | 91 | var captured = touches.has(idx) 92 | var was_pressed = is_pressed() 93 | 94 | if down and not captured: 95 | touches.append(idx) 96 | captured = true 97 | elif not down and captured: 98 | touches.erase(idx) 99 | 100 | var pressed = is_pressed() 101 | if captured: 102 | if pressed: 103 | var in_dedzone:bool = event.position.length() <= deadzone 104 | var shift:Vector2 = event.position.clamped(radius) 105 | ball.position = shift 106 | _update_force(Vector2.ZERO if in_dedzone else shift/radius) 107 | elif was_pressed: 108 | ball.position = Vector2.ZERO 109 | _update_force(Vector2.ZERO) 110 | 111 | if was_pressed != pressed: emit_signal("pressed", pressed) 112 | 113 | func _update_force(_force): 114 | if _force.x <= 0: 115 | Input.action_press(action_left, -_force.x) 116 | Input.action_release(action_right) 117 | 118 | if _force.x >= 0: 119 | Input.action_press(action_right, _force.x) 120 | Input.action_release(action_left) 121 | 122 | if _force.y >= 0: 123 | Input.action_press(action_down, _force.y) 124 | Input.action_release(action_up) 125 | 126 | if _force.y <= 0: 127 | Input.action_press(action_up, -_force.y) 128 | Input.action_release(action_down) 129 | 130 | emit_signal("updated", _force, is_pressed()) 131 | 132 | func _get_event_idx(event): 133 | if event is InputEventScreenTouch or event is InputEventScreenDrag: 134 | return event.index 135 | return INACTIVE_IDX 136 | 137 | func _is_event_down(event): 138 | var in_proximity:bool = event.position.length() <= proximity 139 | if event is InputEventScreenTouch: 140 | return event.pressed and in_proximity 141 | elif event is InputEventScreenDrag: 142 | return in_proximity 143 | return null 144 | 145 | func _setup_visual_hints(container): 146 | proximity_v = Circle.new(deadzone, Color("3370ff60")) 147 | radius_v = Circle.new(radius, Color("334050ff")) 148 | deadzone_v = Circle.new(deadzone, Color("33ff5040")) 149 | 150 | proximity_v.radius = proximity 151 | radius_v.radius = radius 152 | deadzone_v.radius = deadzone 153 | 154 | container.add_child(proximity_v) 155 | container.add_child(radius_v) 156 | container.add_child(deadzone_v) 157 | -------------------------------------------------------------------------------- /addons/joystick_control/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/joystick_control/icon.png -------------------------------------------------------------------------------- /addons/joystick_control/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-678387d700b3f67e44f55dada242247c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/joystick_control/icon.png" 13 | dest_files=[ "res://.import/icon.png-678387d700b3f67e44f55dada242247c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=false 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/joystick_control/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Joystick Control" 4 | description="" 5 | author="Andrii Gook" 6 | version="1.0" 7 | script="plugin.gd" 8 | -------------------------------------------------------------------------------- /addons/joystick_control/plugin.gd: -------------------------------------------------------------------------------- 1 | tool 2 | extends EditorPlugin 3 | 4 | func _enter_tree(): 5 | add_custom_type("Joystick", "Control", preload("assets/joystick.gd"), preload("icon.png")) 6 | 7 | func _exit_tree(): 8 | remove_custom_type("Joystick") 9 | -------------------------------------------------------------------------------- /addons/shell_fur/editor_property.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | extends EditorProperty 4 | 5 | var _ui : Control 6 | var _updating := false 7 | 8 | func _init() -> void: 9 | _ui = preload("res://addons/shell_fur/gui/gradient_inspector.tscn").instance() 10 | add_child(_ui) 11 | set_bottom_editor(_ui) 12 | _ui.get_node("Color1").connect("color_changed", self, "gradient_changed") 13 | _ui.get_node("Color2").connect("color_changed", self, "gradient_changed") 14 | 15 | 16 | func gradient_changed(_val) -> void: 17 | if _updating: 18 | return 19 | var value = _ui.get_value() 20 | emit_changed(get_edited_property(), value) 21 | 22 | 23 | func update_property() -> void: 24 | var new_value = get_edited_object()[get_edited_property()] 25 | _updating = true 26 | _ui.set_value(new_value) 27 | _updating = false 28 | -------------------------------------------------------------------------------- /addons/shell_fur/fur_helper_methods.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | 4 | # Static functions used for generation of fur shells 5 | 6 | static func generate_mmi(layers : int, mmi : MultiMeshInstance, mesh : Mesh, material : Material, blendshape_index : int, cast_shadow : bool) -> void: 7 | var mdt = MeshDataTool.new() 8 | 9 | if mmi.multimesh == null: 10 | mmi.multimesh = MultiMesh.new() 11 | mmi.multimesh.transform_format = MultiMesh.TRANSFORM_3D 12 | mmi.multimesh.color_format = MultiMesh.COLOR_FLOAT 13 | mmi.multimesh.custom_data_format = MultiMesh.CUSTOM_DATA_NONE 14 | 15 | var new_mesh : Mesh = mesh.duplicate(true) as Mesh 16 | 17 | if blendshape_index != -1: 18 | new_mesh = _blendshape_to_vertex_color(new_mesh, material, blendshape_index) 19 | else: 20 | new_mesh = _normals_to_vertex_color(new_mesh, material) 21 | 22 | mmi.multimesh.mesh = new_mesh 23 | mmi.multimesh.instance_count = layers 24 | mmi.multimesh.visible_instance_count = layers 25 | for surface in new_mesh.get_surface_count(): 26 | mmi.multimesh.mesh.surface_set_material(surface, material) 27 | 28 | for i in layers: 29 | mmi.multimesh.set_instance_transform(i, Transform(Basis(), Vector3())) 30 | var grey = float(i) / float(layers) 31 | mmi.multimesh.set_instance_color(i, Color(1.0, 1.0, 1.0, grey)) 32 | 33 | mmi.cast_shadow = 1 if cast_shadow else 0 34 | 35 | 36 | # This function compares the base mesh and the chosen blendshape and saves out 37 | # the differences / extrusion vector as vertex colors to be used by the shader 38 | static func _blendshape_to_vertex_color(mesh: Mesh, material : Material, blendshape_index: int) -> Mesh: 39 | var mdt = MeshDataTool.new() 40 | var base_mesh_array : PoolVector3Array 41 | var fur_blend_shape_mesh_array : PoolVector3Array 42 | 43 | for m in mesh.get_surface_count(): 44 | base_mesh_array += mesh.surface_get_arrays(m)[0] 45 | fur_blend_shape_mesh_array += mesh.surface_get_blend_shape_arrays(m)[blendshape_index][0] 46 | 47 | var compare_array = [] 48 | var compare_array_adjusted = [] 49 | var longest_diff_length = 0.0 50 | var longest_diff_vec 51 | 52 | for i in base_mesh_array.size(): 53 | var diffvec = fur_blend_shape_mesh_array[i] - base_mesh_array[i] 54 | compare_array.append(diffvec) 55 | 56 | if abs(diffvec.x) > longest_diff_length: 57 | longest_diff_length = abs(diffvec.x) 58 | longest_diff_vec = diffvec 59 | if abs(diffvec.y) > longest_diff_length: 60 | longest_diff_length = abs(diffvec.y) 61 | longest_diff_vec = diffvec 62 | if abs(diffvec.z) > longest_diff_length: 63 | longest_diff_length = abs(diffvec.z) 64 | longest_diff_vec = diffvec 65 | 66 | for i in compare_array.size(): 67 | var newx = _vertex_diff_to_vertex_color_value(compare_array[i].x, longest_diff_length) 68 | var newy = _vertex_diff_to_vertex_color_value(compare_array[i].y, longest_diff_length) 69 | var newz = _vertex_diff_to_vertex_color_value(compare_array[i].z, longest_diff_length) 70 | compare_array_adjusted.append( Vector3(newx, newy, newz)) 71 | 72 | material.set_shader_param("i_blend_shape_multiplier", longest_diff_length) 73 | 74 | mdt.create_from_surface(_multiple_surfaces_to_single(mesh), 0) 75 | for i in range(mdt.get_vertex_count()): 76 | mdt.set_vertex_color(i, Color(compare_array_adjusted[i].x, compare_array_adjusted[i].y, compare_array_adjusted[i].z)) 77 | var new_mesh = Mesh.new() 78 | mdt.commit_to_surface(new_mesh) 79 | 80 | return new_mesh 81 | 82 | 83 | # This function is used when no blendshape stying will be used, to simply save 84 | # the normals direction as vertex colors, so the same shader code can be used 85 | # regardless of whether a custom extrusion vector is set. 86 | static func _normals_to_vertex_color(mesh: Mesh, material : Material) -> Mesh: 87 | var mdt = MeshDataTool.new() 88 | material.set_shader_param("i_blend_shape_multiplier", 1.0) 89 | 90 | mdt.create_from_surface(_multiple_surfaces_to_single(mesh), 0) 91 | for i in range(mdt.get_vertex_count()): 92 | var normal_scaled = mdt.get_vertex_normal(i) * 0.5 + Vector3(0.5, 0.5, 0.5) 93 | mdt.set_vertex_color(i, Color(normal_scaled.x, normal_scaled.y, normal_scaled.z)) 94 | var new_mesh = Mesh.new() 95 | mdt.commit_to_surface(new_mesh) 96 | 97 | return new_mesh 98 | 99 | 100 | static func reorder_params(unordered_params : Array) -> Array: 101 | var ordered = [] 102 | 103 | for param in unordered_params: 104 | if param.hint_string != "Texture": 105 | ordered.append(param) 106 | else: 107 | #find the last index in ordered with the same 108 | var prefix = param.name.rsplit("_")[0] 109 | var index = last_prefix_occurence(ordered, prefix) 110 | if index != -1: 111 | ordered.insert(index, param) 112 | else: 113 | ordered.append(param) 114 | return ordered 115 | 116 | 117 | static func last_prefix_occurence(array : Array, search : String) -> int: 118 | 119 | var inverted_array = array.duplicate(true) 120 | inverted_array.invert() 121 | 122 | for i in array.size(): 123 | var prefix = inverted_array[i].name.rsplit("_")[0] 124 | if prefix == search: 125 | return array.size() - i 126 | 127 | return -1 128 | 129 | 130 | static func _multiple_surfaces_to_single(mesh : Mesh) -> Mesh: 131 | var st := SurfaceTool.new() 132 | var merging_mesh = Mesh.new() 133 | 134 | for surface in mesh.get_surface_count(): 135 | st.append_from(mesh, surface, Transform.IDENTITY) 136 | merging_mesh = st.commit() 137 | 138 | return merging_mesh 139 | 140 | 141 | static func _vertex_diff_to_vertex_color_value(value : float, factor : float) -> float: 142 | return (value / factor) * 0.5 + 0.5 143 | 144 | 145 | static func generate_mesh_shells(shell_fur_object : Spatial, parent_object : Spatial, layers : int, material : Material, blendshape_index : int): 146 | var mdt = MeshDataTool.new() 147 | var copy_mesh : Mesh = parent_object.mesh.duplicate(true) 148 | 149 | if blendshape_index != -1: 150 | copy_mesh = _blendshape_to_vertex_color(copy_mesh, material, blendshape_index) 151 | else: 152 | copy_mesh = _normals_to_vertex_color(copy_mesh, material) 153 | 154 | var merged_mesh = _multiple_surfaces_to_single(copy_mesh) 155 | 156 | for layer in layers: 157 | var new_object = MeshInstance.new() 158 | new_object.name = "fur_layer_" + str(layer) 159 | shell_fur_object.add_child(new_object) 160 | # Uncomment to debug whether shells are getting created 161 | #new_object.set_owner(shell_fur_object.get_tree().get_edited_scene_root()) 162 | mdt.create_from_surface(merged_mesh, 0) 163 | for i in range(mdt.get_vertex_count()): 164 | var c = mdt.get_vertex_color(i) 165 | c.a = float(layer) / float(layers) 166 | mdt.set_vertex_color(i, c) 167 | var new_mesh := Mesh.new() 168 | mdt.commit_to_surface(new_mesh) 169 | new_object.mesh = new_mesh 170 | 171 | 172 | static func generate_combined(shell_fur_object : Spatial, parent_object : Spatial, material : Material, cast_shadow : bool) -> Spatial: 173 | var st = SurfaceTool.new() 174 | 175 | for child in shell_fur_object.get_children(): 176 | st.append_from(child.mesh, 0, Transform.IDENTITY) 177 | child.free() 178 | 179 | st.index() 180 | var combined_obj := MeshInstance.new() 181 | 182 | combined_obj.name = "CombinedFurMesh" 183 | combined_obj.mesh = st.commit() 184 | shell_fur_object.add_child(combined_obj) 185 | # Uncomment to check whether the object is getting created 186 | #combined_obj.set_owner(shell_fur_object.get_tree().get_edited_scene_root()) 187 | combined_obj.set_surface_material(0, material) 188 | combined_obj.set_skin(parent_object.get_skin()) 189 | combined_obj.set_skeleton_path("../../..") 190 | combined_obj.cast_shadow = 1 if cast_shadow else 0 191 | 192 | return combined_obj 193 | -------------------------------------------------------------------------------- /addons/shell_fur/fur_node_icon.svg: -------------------------------------------------------------------------------- 1 | 2 | 17 | 19 | 39 | 41 | 42 | 44 | image/svg+xml 45 | 47 | 48 | 49 | 50 | 51 | 55 | 60 | 65 | 70 | 71 | 72 | -------------------------------------------------------------------------------- /addons/shell_fur/fur_node_icon.svg.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/fur_node_icon.svg-e36258f5e2232b9188ca7ac73c8b5d1a.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/fur_node_icon.svg" 13 | dest_files=[ "res://.import/fur_node_icon.svg-e36258f5e2232b9188ca7ac73c8b5d1a.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | process/normal_map_invert_y=false 32 | stream=false 33 | size_limit=0 34 | detect_3d=true 35 | svg/scale=1.0 36 | -------------------------------------------------------------------------------- /addons/shell_fur/gui/gradient_inspector.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | tool 4 | extends HBoxContainer 5 | 6 | 7 | func set_value(gradient : Transform): 8 | $Color1.color = Color(gradient[0].x, gradient[0].y, gradient[0].z) 9 | $Color2.color = Color(gradient[1].x, gradient[1].y, gradient[1].z) 10 | $Gradient.material.set_shader_param("color1", $Color1.color) 11 | $Gradient.material.set_shader_param("color2", $Color2.color) 12 | 13 | 14 | func get_value() -> Transform: 15 | var gradient = Transform() 16 | gradient[0] = Vector3($Color1.color.r, $Color1.color.g, $Color1.color.b) 17 | gradient[1] = Vector3($Color2.color.r, $Color2.color.g, $Color2.color.b) 18 | return gradient 19 | -------------------------------------------------------------------------------- /addons/shell_fur/gui/gradient_inspector.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://addons/shell_fur/gui/gradient_inspector.gd" type="Script" id=1] 4 | [ext_resource path="res://addons/shell_fur/shaders/gui/gradient.shader" type="Shader" id=2] 5 | 6 | [sub_resource type="ShaderMaterial" id=1] 7 | shader = ExtResource( 2 ) 8 | shader_param/color1 = Color( 0.43, 0.35, 0.29, 1 ) 9 | shader_param/color2 = Color( 0.78, 0.63, 0.52, 1 ) 10 | 11 | [node name="HBoxContainer" type="HBoxContainer"] 12 | margin_right = 400.0 13 | margin_bottom = 24.0 14 | script = ExtResource( 1 ) 15 | __meta__ = { 16 | "_edit_use_anchors_": false 17 | } 18 | 19 | [node name="Color1" type="ColorPickerButton" parent="."] 20 | margin_right = 130.0 21 | margin_bottom = 24.0 22 | size_flags_horizontal = 3 23 | size_flags_vertical = 3 24 | flat = true 25 | color = Color( 0.25098, 0.25098, 0.701961, 1 ) 26 | edit_alpha = false 27 | 28 | [node name="Gradient" type="ColorRect" parent="."] 29 | material = SubResource( 1 ) 30 | margin_left = 134.0 31 | margin_right = 265.0 32 | margin_bottom = 24.0 33 | size_flags_horizontal = 3 34 | size_flags_vertical = 3 35 | 36 | [node name="Color2" type="ColorPickerButton" parent="."] 37 | margin_left = 269.0 38 | margin_right = 400.0 39 | margin_bottom = 24.0 40 | size_flags_horizontal = 3 41 | size_flags_vertical = 3 42 | flat = true 43 | color = Color( 0.25098, 0.501961, 0.701961, 1 ) 44 | edit_alpha = false 45 | -------------------------------------------------------------------------------- /addons/shell_fur/inspector_plugin.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | extends EditorInspectorPlugin 4 | 5 | const ShellFurManager = preload("res://addons/shell_fur/shell_fur_manager.gd") 6 | var _editor = load("res://addons/shell_fur/editor_property.gd") 7 | 8 | 9 | func can_handle(object: Object) -> bool: 10 | return object is ShellFurManager 11 | 12 | 13 | func parse_property(object: Object, type: int, path: String, hint: int, hint_text: String, usage: int) -> bool: 14 | if type == TYPE_TRANSFORM and "color" in path: 15 | var editor_property = _editor.new() 16 | add_property_editor(path, editor_property) 17 | return true 18 | return false 19 | -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/fine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/shell_fur/noise_patterns/fine.png -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/fine.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/fine.png-5f05f17d9648f49185e971c20a965e25.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/noise_patterns/fine.png" 13 | dest_files=[ "res://.import/fine.png-5f05f17d9648f49185e971c20a965e25.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=2 22 | flags/repeat=true 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=true 26 | flags/srgb=0 27 | process/fix_alpha_border=false 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/monster.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/shell_fur/noise_patterns/monster.png -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/monster.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/monster.png-fad6e7cc6259e8dff2e6101cd99449ba.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/noise_patterns/monster.png" 13 | dest_files=[ "res://.import/monster.png-fad6e7cc6259e8dff2e6101cd99449ba.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=2 22 | flags/repeat=true 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=true 26 | flags/srgb=0 27 | process/fix_alpha_border=false 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/rough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/shell_fur/noise_patterns/rough.png -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/rough.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/rough.png-3f9e19921148e4c1fa351bf2a4599778.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/noise_patterns/rough.png" 13 | dest_files=[ "res://.import/rough.png-3f9e19921148e4c1fa351bf2a4599778.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=2 22 | flags/repeat=true 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=true 26 | flags/srgb=0 27 | process/fix_alpha_border=false 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/very_fine.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/shell_fur/noise_patterns/very_fine.png -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/very_fine.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/very_fine.png-3d3ffe6d044d1d0019e49838a0796f35.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/noise_patterns/very_fine.png" 13 | dest_files=[ "res://.import/very_fine.png-3d3ffe6d044d1d0019e49838a0796f35.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=2 22 | flags/repeat=true 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=true 26 | flags/srgb=0 27 | process/fix_alpha_border=false 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/very_rough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/addons/shell_fur/noise_patterns/very_rough.png -------------------------------------------------------------------------------- /addons/shell_fur/noise_patterns/very_rough.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/very_rough.png-7a742d1e0f6cbe0e8d618b30758bd45c.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://addons/shell_fur/noise_patterns/very_rough.png" 13 | dest_files=[ "res://.import/very_rough.png-7a742d1e0f6cbe0e8d618b30758bd45c.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=2 22 | flags/repeat=true 23 | flags/filter=true 24 | flags/mipmaps=true 25 | flags/anisotropic=true 26 | flags/srgb=0 27 | process/fix_alpha_border=false 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=false 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /addons/shell_fur/plugin.cfg: -------------------------------------------------------------------------------- 1 | [plugin] 2 | 3 | name="Shell Fur Add-on" 4 | description="Add-on that adds a fur node to the Godot engine, using a shell based approach to imitate fur strands." 5 | author="Kasper Arnklit Frandsen" 6 | version="0.3.0" 7 | script="shell_fur.gd" 8 | -------------------------------------------------------------------------------- /addons/shell_fur/shaders/gui/gradient.shader: -------------------------------------------------------------------------------- 1 | shader_type canvas_item; 2 | 3 | uniform vec4 color1 = vec4(0.25, 0.25, 0.70, 1.0); 4 | uniform vec4 color2 = vec4(0.25, 0.50, 0.70, 1.0); 5 | 6 | void fragment() { 7 | vec4 mixed_color = mix(color1, color2, UV.x); 8 | COLOR = mixed_color; 9 | } -------------------------------------------------------------------------------- /addons/shell_fur/shaders/shell_fur.gdshader: -------------------------------------------------------------------------------- 1 | // Copyright © 2022 Kasper Arnklit Frandsen - MIT License 2 | // See `LICENSE.md` included in the source distribution for details. 3 | shader_type spatial; 4 | render_mode diffuse_burley, specular_schlick_ggx, depth_draw_opaque; 5 | 6 | // If you are making your own shader, you can customize or add your own 7 | // parameters below and they will automatically get parsed and displayed in 8 | // the ShellFur inspector. 9 | 10 | // Use prefixes: albedo_, shape_ and custom_ to automatically put your 11 | // parameters into categories in the inspector. 12 | 13 | // mat4´s with "color" in their name will get parsed as gradients. 14 | 15 | // Main 16 | uniform vec4 transmission : hint_color = vec4(0.3, 0.3, 0.3, 1.0); 17 | uniform float ao : hint_range(0.0, 1.0) = 1.0; 18 | uniform float ao_light_affect : hint_range(0.0, 1.0) = 0.0; 19 | uniform float roughness : hint_range(0.0, 1.0) = 1.0; 20 | 21 | // Albedo 22 | uniform mat4 albedo_color = mat4( 23 | vec4(0.43, 0.78, 0.0, 0.0), 24 | vec4(0.35, 0.63, 0.0, 0.0), 25 | vec4(0.29, 0.52, 0.0, 0.0), 26 | vec4(0.0) 27 | ); 28 | uniform vec3 albedo_uv_scale = vec3(1.0, 1.0, 0.0); 29 | uniform sampler2D albedo_texture : hint_albedo; 30 | 31 | // Shape 32 | uniform float shape_length : hint_range(0.0, 5.0) = 0.5; 33 | uniform float shape_length_rand : hint_range(0.0, 1.0) = 0.3; 34 | uniform float shape_density : hint_range(0.0, 1.0) = 1.0; 35 | uniform float shape_thickness_base : hint_range(0.0, 1.0) = 0.75; 36 | uniform float shape_thickness_tip : hint_range(0.0, 1.0) = 0.3; 37 | uniform float shape_thickness_rand : hint_range(0.0, 1.0) = 0.0; 38 | uniform float shape_growth : hint_range(0.0, 2.0) = 1.0; 39 | uniform float shape_growth_rand : hint_range(0.0, 1.0) = 0.0; 40 | uniform vec3 shape_ldtg_uv_scale = vec3(1.0, 1.0, 0.0); 41 | uniform sampler2D shape_ldtg_texture : hint_white; // Length, Desity, Thickness, Growth 42 | 43 | // Internal uniforms - DO NOT CUSTOMIZE THESE IF YOU ARE CLONING THE SHADER 44 | uniform int i_layers = 40; 45 | uniform sampler2D i_pattern_texture : hint_black; 46 | uniform float i_pattern_uv_scale : hint_range(0.0, 100.0) = 5.0; 47 | uniform float i_wind_strength = 0.0; 48 | uniform float i_wind_speed = 1.0; 49 | uniform float i_wind_scale = 1.0; 50 | uniform vec3 i_wind_angle = vec3(1.0, 0.0, 0.0); 51 | uniform float i_normal_bias = 0.0; 52 | uniform float i_LOD = 1.0; 53 | uniform vec3 i_physics_pos_offset; 54 | uniform mat4 i_physics_rot_offset; 55 | uniform float i_blend_shape_multiplier = 1.0; 56 | uniform float i_fur_contract = 0.0; 57 | 58 | varying vec3 extrusion_vec; 59 | varying vec3 forces_vec; 60 | varying float lod_adjusted_layer_value; 61 | 62 | float lin2srgb(float lin) { 63 | return pow(lin, 2.2); 64 | } 65 | 66 | mat4 gradient_lin2srgb(mat4 lin_mat) { 67 | mat4 srgb_mat = mat4( 68 | vec4(lin2srgb(lin_mat[0].x), lin2srgb(lin_mat[0].y), lin2srgb(lin_mat[0].z), lin2srgb(lin_mat[0].w)), 69 | vec4(lin2srgb(lin_mat[1].x), lin2srgb(lin_mat[1].y), lin2srgb(lin_mat[1].z), lin2srgb(lin_mat[1].w)), 70 | vec4(0.0), 71 | vec4(0.0) 72 | ); 73 | return srgb_mat; 74 | } 75 | 76 | vec3 mod289(vec3 x) 77 | { 78 | return x - floor(x * (1.0 / 289.0)) * 289.0; 79 | } 80 | 81 | vec4 mod289_4(vec4 x) 82 | { 83 | return x - floor(x * (1.0 / 289.0)) * 289.0; 84 | } 85 | 86 | vec4 permute(vec4 x) 87 | { 88 | return mod289_4(((x*34.0)+1.0)*x); 89 | } 90 | 91 | vec4 taylorInvSqrt(vec4 r) 92 | { 93 | return 1.79284291400159 - 0.85373472095314 * r; 94 | } 95 | 96 | vec3 fade(vec3 t) { 97 | return t*t*t*(t*(t*6.0-15.0)+10.0); 98 | } 99 | 100 | // Classic Perlin noise by Stefan Gustavson, see README for license 101 | float cnoise(vec3 P) 102 | { 103 | vec3 Pi0 = floor(P); // Integer part for indexing 104 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 105 | Pi0 = mod289(Pi0); 106 | Pi1 = mod289(Pi1); 107 | vec3 Pf0 = fract(P); // Fractional part for interpolation 108 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 109 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); 110 | vec4 iy = vec4(Pi0.yy, Pi1.yy); 111 | vec4 iz0 = Pi0.zzzz; 112 | vec4 iz1 = Pi1.zzzz; 113 | 114 | vec4 ixy = permute(permute(ix) + iy); 115 | vec4 ixy0 = permute(ixy + iz0); 116 | vec4 ixy1 = permute(ixy + iz1); 117 | 118 | vec4 gx0 = ixy0 * (1.0 / 7.0); 119 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; 120 | gx0 = fract(gx0); 121 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); 122 | vec4 sz0 = step(gz0, vec4(0.0)); 123 | gx0 -= sz0 * (step(0.0, gx0) - 0.5); 124 | gy0 -= sz0 * (step(0.0, gy0) - 0.5); 125 | 126 | vec4 gx1 = ixy1 * (1.0 / 7.0); 127 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; 128 | gx1 = fract(gx1); 129 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); 130 | vec4 sz1 = step(gz1, vec4(0.0)); 131 | gx1 -= sz1 * (step(0.0, gx1) - 0.5); 132 | gy1 -= sz1 * (step(0.0, gy1) - 0.5); 133 | 134 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); 135 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); 136 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); 137 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); 138 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); 139 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); 140 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); 141 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); 142 | 143 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); 144 | g000 *= norm0.x; 145 | g010 *= norm0.y; 146 | g100 *= norm0.z; 147 | g110 *= norm0.w; 148 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); 149 | g001 *= norm1.x; 150 | g011 *= norm1.y; 151 | g101 *= norm1.z; 152 | g111 *= norm1.w; 153 | 154 | float n000 = dot(g000, Pf0); 155 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); 156 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); 157 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); 158 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); 159 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); 160 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); 161 | float n111 = dot(g111, Pf1); 162 | 163 | vec3 fade_xyz = fade(Pf0); 164 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); 165 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); 166 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 167 | return 1.1 * n_xyz + 0.5; 168 | } 169 | 170 | vec3 projectOnPlane( vec3 vec, vec3 normal ) { 171 | return vec - normal * dot( vec, normal ); 172 | } 173 | 174 | void vertex() { 175 | if (i_LOD >= COLOR.a) { // Skipping vertex calculations if layer is beyond LOD threshhold 176 | lod_adjusted_layer_value = COLOR.a / i_LOD; 177 | // Rescaling the color values into vectors. 178 | extrusion_vec = ((vec3(COLOR.xyz) * 2.0 - 1.0) * i_blend_shape_multiplier); 179 | 180 | vec3 normal_biased_extrude = mix(NORMAL * i_blend_shape_multiplier, extrusion_vec, lod_adjusted_layer_value); 181 | vec3 interpolated_extrude = mix(extrusion_vec, normal_biased_extrude, smoothstep(0.0, 2.0, i_normal_bias)); 182 | vec3 offset_from_surface = interpolated_extrude * shape_length / float(i_layers); 183 | VERTEX += (vec4(interpolated_extrude * shape_length * lod_adjusted_layer_value + offset_from_surface, 1.0) * i_physics_rot_offset).xyz; 184 | VERTEX -= i_fur_contract * extrusion_vec * shape_length; 185 | 186 | vec3 wind_vec = vec3(0.0); 187 | if (i_wind_strength > 0.01) { // Skipping wind calculations if wind_strength is less than 0.01 188 | vec3 winduv = VERTEX * i_wind_scale; 189 | winduv.y += TIME * i_wind_speed; 190 | vec3 wind_angle_world = (vec4(i_wind_angle, 0) * WORLD_MATRIX).xyz; 191 | vec3 wind_dir_flattened = projectOnPlane(wind_angle_world, NORMAL); 192 | wind_vec = wind_dir_flattened * cnoise(winduv) * i_wind_strength; 193 | } 194 | 195 | vec3 physics_pos_offset_world = (vec4(i_physics_pos_offset, 0.0) * WORLD_MATRIX).xyz; 196 | forces_vec = (physics_pos_offset_world + wind_vec) * length(extrusion_vec) * smoothstep(0.0, 2.0, lod_adjusted_layer_value); 197 | VERTEX += forces_vec; 198 | } 199 | } 200 | 201 | void fragment() { 202 | // Discarding fragment if layer is beyond LOD threshhold 203 | if (i_LOD < COLOR.a) { 204 | discard; 205 | } 206 | 207 | vec4 ldtg_texture_data = texture(shape_ldtg_texture, UV * shape_ldtg_uv_scale.xy); 208 | 209 | vec4 pattern = texture(i_pattern_texture, UV * i_pattern_uv_scale); 210 | // We multiply the thicknesses with ldtg texture's B channel and a random value based on 211 | // the pattern's B channel ids to allow for control of the thickness through texture. 212 | float t_rand = 1.0 - shape_thickness_rand * pattern.b; 213 | float g_rand = 1.0 - shape_growth_rand * ((pattern.g + pattern.b) / 2.0); // We use two random channels to generate an extra "random" for growth 214 | float thickness_base = shape_thickness_base * ldtg_texture_data.b * t_rand; 215 | float thickness_tip = shape_thickness_tip * ldtg_texture_data.b * pattern.b * t_rand; 216 | float scissor_thresh = mix(-thickness_base + 1.0, -thickness_tip + 1.0, lod_adjusted_layer_value) + clamp(1.0 - shape_growth + (1.0 - g_rand * ldtg_texture_data.a), 0.0, 1.0); 217 | 218 | float lod_alpha = float(i_LOD > COLOR.a); 219 | // density is multiplied by the ldtg textures G channel to allow fine control 220 | float density_alpha = float( shape_density * ldtg_texture_data.g * 1.02 > pattern.b + 0.01 ); 221 | float shape_alpha = float(scissor_thresh < pattern.r * ldtg_texture_data.r - pattern.r * ldtg_texture_data.r * pattern.g * shape_length_rand); 222 | 223 | // We use the unique id's in pattern.b to discard if density is under the threshold 224 | // density is multiplied by the ldtg textures G channel to allow fine control 225 | if (shape_density * ldtg_texture_data.g * 1.02 <= pattern.b + 0.01) { 226 | discard; 227 | } 228 | 229 | ALPHA_SCISSOR = scissor_thresh; 230 | ALPHA = pattern.r * ldtg_texture_data.r - pattern.r * ldtg_texture_data.r * pattern.g * shape_length_rand; 231 | 232 | mat4 albedo_color_srgb = gradient_lin2srgb(albedo_color); 233 | vec3 albedo_base_color = vec3(albedo_color_srgb[0].x, albedo_color_srgb[0].y, albedo_color_srgb[0].z); 234 | vec3 albedo_tip_color = vec3(albedo_color_srgb[1].x, albedo_color_srgb[1].y, albedo_color_srgb[1].z); 235 | ALBEDO = (texture(albedo_texture, UV * albedo_uv_scale.xy).rgb * mix(albedo_base_color, albedo_tip_color, lod_adjusted_layer_value)); 236 | TRANSMISSION = transmission.rgb; 237 | ROUGHNESS = roughness; 238 | AO = 1.0 - (-lod_adjusted_layer_value + 1.0) * ao; 239 | AO_LIGHT_AFFECT = ao_light_affect; 240 | } -------------------------------------------------------------------------------- /addons/shell_fur/shaders/shell_fur_mobile.gdshader: -------------------------------------------------------------------------------- 1 | // Copyright © 2022 Kasper Arnklit Frandsen - MIT License 2 | // See `LICENSE.md` included in the source distribution for details. 3 | shader_type spatial; 4 | render_mode shadows_disabled, diffuse_lambert, specular_disabled, depth_draw_opaque; 5 | 6 | // If you are making your own shader, you can customize or add your own 7 | // parameters below and they will automatically get parsed and displayed in 8 | // the ShellFur inspector. 9 | 10 | // Use prefixes: albedo_, shape_ and custom_ to automatically put your 11 | // parameters into categories in the inspector. 12 | 13 | // mat4´s with "color" in their name will get parsed as gradients. 14 | 15 | // Main 16 | uniform vec4 transmission : hint_color = vec4(0.3, 0.3, 0.3, 1.0); 17 | uniform float ao : hint_range(0.0, 1.0) = 1.0; 18 | uniform float ao_light_affect : hint_range(0.0, 1.0) = 0.0; 19 | uniform float roughness : hint_range(0.0, 1.0) = 1.0; 20 | 21 | // Albedo 22 | uniform mat4 albedo_color = mat4( 23 | vec4(0.43, 0.78, 0.0, 0.0), 24 | vec4(0.35, 0.63, 0.0, 0.0), 25 | vec4(0.29, 0.52, 0.0, 0.0), 26 | vec4(0.0) 27 | ); 28 | uniform vec3 albedo_uv_scale = vec3(1.0, 1.0, 0.0); 29 | uniform sampler2D albedo_texture : hint_albedo; 30 | 31 | // Shape 32 | uniform float shape_length : hint_range(0.0, 5.0) = 0.5; 33 | uniform float shape_length_rand : hint_range(0.0, 1.0) = 0.3; 34 | uniform float shape_density : hint_range(0.0, 1.0) = 1.0; 35 | uniform float shape_thickness_base : hint_range(0.0, 1.0) = 0.75; 36 | uniform float shape_thickness_tip : hint_range(0.0, 1.0) = 0.3; 37 | uniform float shape_thickness_rand : hint_range(0.0, 1.0) = 0.0; 38 | uniform float shape_growth : hint_range(0.0, 2.0) = 1.0; 39 | uniform float shape_growth_rand : hint_range(0.0, 1.0) = 0.0; 40 | uniform vec3 shape_ldtg_uv_scale = vec3(1.0, 1.0, 0.0); 41 | uniform sampler2D shape_ldtg_texture : hint_white; // Length, Desity, Thickness, Growth 42 | 43 | // Internal uniforms - DO NOT CUSTOMIZE THESE IF YOU ARE CLONING THE SHADER 44 | uniform int i_layers = 40; 45 | uniform sampler2D i_pattern_texture : hint_black; 46 | uniform float i_pattern_uv_scale : hint_range(0.0, 100.0) = 5.0; 47 | uniform float i_wind_strength = 0.0; 48 | uniform float i_wind_speed = 1.0; 49 | uniform float i_wind_scale = 1.0; 50 | uniform vec3 i_wind_angle = vec3(1.0, 0.0, 0.0); 51 | uniform float i_normal_bias = 0.0; 52 | uniform float i_LOD = 1.0; 53 | uniform vec3 i_physics_pos_offset; 54 | uniform mat4 i_physics_rot_offset; 55 | uniform float i_blend_shape_multiplier = 1.0; 56 | uniform float i_fur_contract = 0.0; 57 | 58 | varying vec3 extrusion_vec; 59 | varying vec3 forces_vec; 60 | varying float lod_adjusted_layer_value; 61 | 62 | float lin2srgb(float lin) { 63 | return pow(lin, 2.2); 64 | } 65 | 66 | mat4 gradient_lin2srgb(mat4 lin_mat) { 67 | mat4 srgb_mat = mat4( 68 | vec4(lin2srgb(lin_mat[0].x), lin2srgb(lin_mat[0].y), lin2srgb(lin_mat[0].z), lin2srgb(lin_mat[0].w)), 69 | vec4(lin2srgb(lin_mat[1].x), lin2srgb(lin_mat[1].y), lin2srgb(lin_mat[1].z), lin2srgb(lin_mat[1].w)), 70 | vec4(0.0), 71 | vec4(0.0) 72 | ); 73 | return srgb_mat; 74 | } 75 | 76 | vec3 mod289(vec3 x) 77 | { 78 | return x - floor(x * (1.0 / 289.0)) * 289.0; 79 | } 80 | 81 | vec4 mod289_4(vec4 x) 82 | { 83 | return x - floor(x * (1.0 / 289.0)) * 289.0; 84 | } 85 | 86 | vec4 permute(vec4 x) 87 | { 88 | return mod289_4(((x*34.0)+1.0)*x); 89 | } 90 | 91 | vec4 taylorInvSqrt(vec4 r) 92 | { 93 | return 1.79284291400159 - 0.85373472095314 * r; 94 | } 95 | 96 | vec3 fade(vec3 t) { 97 | return t*t*t*(t*(t*6.0-15.0)+10.0); 98 | } 99 | 100 | // Classic Perlin noise by Stefan Gustavson, see README for license 101 | float cnoise(vec3 P) 102 | { 103 | vec3 Pi0 = floor(P); // Integer part for indexing 104 | vec3 Pi1 = Pi0 + vec3(1.0); // Integer part + 1 105 | Pi0 = mod289(Pi0); 106 | Pi1 = mod289(Pi1); 107 | vec3 Pf0 = fract(P); // Fractional part for interpolation 108 | vec3 Pf1 = Pf0 - vec3(1.0); // Fractional part - 1.0 109 | vec4 ix = vec4(Pi0.x, Pi1.x, Pi0.x, Pi1.x); 110 | vec4 iy = vec4(Pi0.yy, Pi1.yy); 111 | vec4 iz0 = Pi0.zzzz; 112 | vec4 iz1 = Pi1.zzzz; 113 | 114 | vec4 ixy = permute(permute(ix) + iy); 115 | vec4 ixy0 = permute(ixy + iz0); 116 | vec4 ixy1 = permute(ixy + iz1); 117 | 118 | vec4 gx0 = ixy0 * (1.0 / 7.0); 119 | vec4 gy0 = fract(floor(gx0) * (1.0 / 7.0)) - 0.5; 120 | gx0 = fract(gx0); 121 | vec4 gz0 = vec4(0.5) - abs(gx0) - abs(gy0); 122 | vec4 sz0 = step(gz0, vec4(0.0)); 123 | gx0 -= sz0 * (step(0.0, gx0) - 0.5); 124 | gy0 -= sz0 * (step(0.0, gy0) - 0.5); 125 | 126 | vec4 gx1 = ixy1 * (1.0 / 7.0); 127 | vec4 gy1 = fract(floor(gx1) * (1.0 / 7.0)) - 0.5; 128 | gx1 = fract(gx1); 129 | vec4 gz1 = vec4(0.5) - abs(gx1) - abs(gy1); 130 | vec4 sz1 = step(gz1, vec4(0.0)); 131 | gx1 -= sz1 * (step(0.0, gx1) - 0.5); 132 | gy1 -= sz1 * (step(0.0, gy1) - 0.5); 133 | 134 | vec3 g000 = vec3(gx0.x,gy0.x,gz0.x); 135 | vec3 g100 = vec3(gx0.y,gy0.y,gz0.y); 136 | vec3 g010 = vec3(gx0.z,gy0.z,gz0.z); 137 | vec3 g110 = vec3(gx0.w,gy0.w,gz0.w); 138 | vec3 g001 = vec3(gx1.x,gy1.x,gz1.x); 139 | vec3 g101 = vec3(gx1.y,gy1.y,gz1.y); 140 | vec3 g011 = vec3(gx1.z,gy1.z,gz1.z); 141 | vec3 g111 = vec3(gx1.w,gy1.w,gz1.w); 142 | 143 | vec4 norm0 = taylorInvSqrt(vec4(dot(g000, g000), dot(g010, g010), dot(g100, g100), dot(g110, g110))); 144 | g000 *= norm0.x; 145 | g010 *= norm0.y; 146 | g100 *= norm0.z; 147 | g110 *= norm0.w; 148 | vec4 norm1 = taylorInvSqrt(vec4(dot(g001, g001), dot(g011, g011), dot(g101, g101), dot(g111, g111))); 149 | g001 *= norm1.x; 150 | g011 *= norm1.y; 151 | g101 *= norm1.z; 152 | g111 *= norm1.w; 153 | 154 | float n000 = dot(g000, Pf0); 155 | float n100 = dot(g100, vec3(Pf1.x, Pf0.yz)); 156 | float n010 = dot(g010, vec3(Pf0.x, Pf1.y, Pf0.z)); 157 | float n110 = dot(g110, vec3(Pf1.xy, Pf0.z)); 158 | float n001 = dot(g001, vec3(Pf0.xy, Pf1.z)); 159 | float n101 = dot(g101, vec3(Pf1.x, Pf0.y, Pf1.z)); 160 | float n011 = dot(g011, vec3(Pf0.x, Pf1.yz)); 161 | float n111 = dot(g111, Pf1); 162 | 163 | vec3 fade_xyz = fade(Pf0); 164 | vec4 n_z = mix(vec4(n000, n100, n010, n110), vec4(n001, n101, n011, n111), fade_xyz.z); 165 | vec2 n_yz = mix(n_z.xy, n_z.zw, fade_xyz.y); 166 | float n_xyz = mix(n_yz.x, n_yz.y, fade_xyz.x); 167 | return 1.1 * n_xyz + 0.5; 168 | } 169 | 170 | vec3 projectOnPlane( vec3 vec, vec3 normal ) { 171 | return vec - normal * dot( vec, normal ); 172 | } 173 | 174 | void vertex() { 175 | if (i_LOD >= COLOR.a) { // Skipping vertex calculations if layer is beyond LOD threshhold 176 | lod_adjusted_layer_value = COLOR.a / i_LOD; 177 | // Rescaling the color values into vectors. 178 | extrusion_vec = ((vec3(COLOR.xyz) * 2.0 - 1.0) * i_blend_shape_multiplier); 179 | 180 | vec3 normal_biased_extrude = mix(NORMAL * i_blend_shape_multiplier, extrusion_vec, lod_adjusted_layer_value); 181 | vec3 interpolated_extrude = mix(extrusion_vec, normal_biased_extrude, smoothstep(0.0, 2.0, i_normal_bias)); 182 | vec3 offset_from_surface = interpolated_extrude * shape_length / float(i_layers); 183 | VERTEX += (vec4(interpolated_extrude * shape_length * lod_adjusted_layer_value + offset_from_surface, 1.0) * i_physics_rot_offset).xyz; 184 | VERTEX -= i_fur_contract * extrusion_vec * shape_length; 185 | 186 | vec3 wind_vec = vec3(0.0); 187 | if (i_wind_strength > 0.01) { // Skipping wind calculations if wind_strength is less than 0.01 188 | vec3 winduv = VERTEX * i_wind_scale; 189 | winduv.y += TIME * i_wind_speed; 190 | vec3 wind_angle_world = (vec4(i_wind_angle, 0) * WORLD_MATRIX).xyz; 191 | vec3 wind_dir_flattened = projectOnPlane(wind_angle_world, NORMAL); 192 | wind_vec = wind_dir_flattened * cnoise(winduv) * i_wind_strength; 193 | } 194 | 195 | vec3 physics_pos_offset_world = (vec4(i_physics_pos_offset, 0.0) * WORLD_MATRIX).xyz; 196 | forces_vec = (physics_pos_offset_world + wind_vec) * length(extrusion_vec) * smoothstep(0.0, 2.0, lod_adjusted_layer_value); 197 | VERTEX += forces_vec; 198 | } 199 | } 200 | 201 | void fragment() { 202 | // Discarding fragment if layer is beyond LOD threshhold 203 | if (i_LOD < COLOR.a) { 204 | discard; 205 | } 206 | 207 | vec4 ldtg_texture_data = texture(shape_ldtg_texture, UV * shape_ldtg_uv_scale.xy); 208 | 209 | vec4 pattern = texture(i_pattern_texture, UV * i_pattern_uv_scale); 210 | // We multiply the thicknesses with ldtg texture's B channel and a random value based on 211 | // the pattern's B channel ids to allow for control of the thickness through texture. 212 | float t_rand = 1.0 - shape_thickness_rand * pattern.b; 213 | float g_rand = 1.0 - shape_growth_rand * ((pattern.g + pattern.b) / 2.0); // We use two random channels to generate an extra "random" for growth 214 | float thickness_base = shape_thickness_base * ldtg_texture_data.b * t_rand; 215 | float thickness_tip = shape_thickness_tip * ldtg_texture_data.b * pattern.b * t_rand; 216 | float scissor_thresh = mix(-thickness_base + 1.0, -thickness_tip + 1.0, lod_adjusted_layer_value) + clamp(1.0 - shape_growth + (1.0 - g_rand * ldtg_texture_data.a), 0.0, 1.0); 217 | 218 | // We use the unique id's in pattern.b to discard if density is under the threshold 219 | // density is multiplied by the ldtg textures G channel to allow fine control 220 | if (shape_density * ldtg_texture_data.g * 1.02 <= pattern.b + 0.01) { 221 | discard; 222 | } 223 | 224 | ALPHA_SCISSOR = scissor_thresh; 225 | ALPHA = pattern.r * ldtg_texture_data.r - pattern.r * ldtg_texture_data.r * pattern.g * shape_length_rand; 226 | 227 | mat4 albedo_color_srgb = gradient_lin2srgb(albedo_color); 228 | vec3 albedo_base_color = vec3(albedo_color_srgb[0].x, albedo_color_srgb[0].y, albedo_color_srgb[0].z); 229 | vec3 albedo_tip_color = vec3(albedo_color_srgb[1].x, albedo_color_srgb[1].y, albedo_color_srgb[1].z); 230 | ALBEDO = (texture(albedo_texture, UV * albedo_uv_scale.xy).rgb * mix(albedo_base_color, albedo_tip_color, lod_adjusted_layer_value)); 231 | TRANSMISSION = transmission.rgb; 232 | ROUGHNESS = roughness; 233 | AO = 1.0 - (-lod_adjusted_layer_value + 1.0) * ao; 234 | AO_LIGHT_AFFECT = ao_light_affect; 235 | } -------------------------------------------------------------------------------- /addons/shell_fur/shell_fur.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | tool 4 | extends EditorPlugin 5 | 6 | const GradientInspector = preload("./inspector_plugin.gd") 7 | 8 | var gradient_inspector = GradientInspector.new() 9 | 10 | func _enter_tree() -> void: 11 | add_custom_type("ShellFur", "Spatial", preload("shell_fur_manager.gd"), preload("fur_node_icon.svg")) 12 | add_inspector_plugin(gradient_inspector) 13 | 14 | func _exit_tree() -> void: 15 | remove_custom_type("ShellFur") 16 | remove_inspector_plugin(gradient_inspector) 17 | -------------------------------------------------------------------------------- /addons/shell_fur/shell_fur_lod.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | const ShellFurManager = preload("res://addons/shell_fur/shell_fur_manager.gd") 4 | 5 | var current_LOD : int 6 | 7 | var _shell_fur : ShellFurManager 8 | var _fur_contract := 0.0 9 | 10 | func init(shell_fur_object : ShellFurManager) -> void: 11 | _shell_fur = shell_fur_object 12 | 13 | func process(delta : float) -> void: 14 | var _camera := _shell_fur.get_viewport().get_camera() 15 | if _camera == null: 16 | return 17 | 18 | var distance := _camera.global_transform.origin.distance_to(_shell_fur.global_transform.origin) 19 | if distance <= _shell_fur.lod_LOD0_distance: 20 | current_LOD = 0 21 | if _shell_fur.lod_LOD0_distance < distance and distance <= _shell_fur.lod_LOD1_distance: 22 | current_LOD = 1 23 | if distance > _shell_fur.lod_LOD1_distance: 24 | current_LOD = 2 25 | 26 | # To avoid calls to the fur child object before it's been generated 27 | if _shell_fur.fur_object == null: 28 | return 29 | match current_LOD: 30 | 0: 31 | _shell_fur.set_shader_param("i_LOD", 1.0) 32 | 1: 33 | var lod_value = lerp(1.0, 0.25, (distance - _shell_fur.lod_LOD0_distance) / (_shell_fur.lod_LOD1_distance - _shell_fur.lod_LOD0_distance)) 34 | _shell_fur.set_shader_param("i_LOD", lod_value) 35 | _fur_contract = move_toward(_fur_contract, 0.0, delta) 36 | if _fur_contract < 1.0 and _shell_fur.fur_object.visible == false: 37 | _shell_fur.fur_object.visible = true 38 | 2: 39 | _shell_fur.set_shader_param("i_LOD", 0.25) 40 | _fur_contract = move_toward(_fur_contract, 1.1, delta) 41 | if _fur_contract > 1.0 and _shell_fur.fur_object.visible == true: 42 | _shell_fur.fur_object.visible = false 43 | _shell_fur.set_shader_param("i_fur_contract", _fur_contract) 44 | -------------------------------------------------------------------------------- /addons/shell_fur/shell_fur_manager.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | tool 4 | extends Spatial 5 | # Fur manager node. Is used to generate the fur objects and control it. 6 | # The node will only generate fur if it is set as a direct child to a 7 | # MeshInstance node. 8 | # The node will generate fur in two separate ways based on whether the 9 | # MeshInstance node is a static mesh a skinned mesh. 10 | # For static meshes it use a MultiMeshInstance for skinned meshes it will create 11 | # a multi-layered mesh of its own MeshInstance mesh and place either as a child. 12 | # The node also manages the material of the fur, using a custom shader. 13 | 14 | const FurHelperMethods = preload("res://addons/shell_fur/fur_helper_methods.gd") 15 | 16 | const PATTERNS = [ 17 | "res://addons/shell_fur/noise_patterns/very_fine.png", 18 | "res://addons/shell_fur/noise_patterns/fine.png", 19 | "res://addons/shell_fur/noise_patterns/rough.png", 20 | "res://addons/shell_fur/noise_patterns/very_rough.png", 21 | "res://addons/shell_fur/noise_patterns/monster.png", 22 | ] 23 | 24 | const MATERIAL_CATEGORIES = { 25 | shape_ = "Shape", 26 | albedo_ = "Albedo", 27 | custom_ = "Custom", 28 | } 29 | 30 | enum SHADER_TYPES {REGULAR, MOBILE, CUSTOM} 31 | const BUILTIN_SHADERS = [ 32 | { 33 | name = "Regular", 34 | shader_path = "res://addons/shell_fur/shaders/shell_fur.gdshader", 35 | }, 36 | { 37 | name = "Mobile", 38 | shader_path = "res://addons/shell_fur/shaders/shell_fur_mobile.gdshader", 39 | }, 40 | ] 41 | 42 | const DEFAULT_PARAMETERS = { 43 | shader_type = SHADER_TYPES.REGULAR, 44 | layers = 40, 45 | pattern_selector = 0, 46 | pattern_uv_scale = 5.0, 47 | cast_shadow = false, 48 | mat_shader_type = 0, 49 | physics_custom_physics_pivot = NodePath(), 50 | physics_gravity = 0.1, 51 | physics_spring = 4.0, 52 | physics_damping = 0.1, 53 | physics_wind_strength = 0.0, 54 | physics_wind_speed = 1.0, 55 | physics_wind_scale = 1.0, 56 | physics_wind_angle = 0.0, 57 | styling_blendshape = 0, 58 | styling_normal_bias = 0.0, 59 | lod_LOD0_distance = 10.0, 60 | lod_LOD1_distance = 100.0, 61 | } 62 | 63 | var shader_type := 0 setget set_shader_type 64 | var custom_shader : Shader setget set_custom_shader 65 | var layers := 40 setget set_layers 66 | var pattern_selector := 0 setget set_pattern_selector 67 | var pattern_texture : Texture setget set_pattern_texture 68 | var pattern_uv_scale = 5.0 setget set_pattern_uv_scale 69 | var cast_shadow := false setget set_cast_shadow 70 | 71 | # Material - Note the material inspector gets generated from the shader 72 | 73 | # Physics 74 | var physics_custom_physics_pivot : NodePath setget set_custom_physics_pivot 75 | var physics_gravity := 0.1 76 | var physics_spring := 4.0 77 | var physics_damping := 0.1 78 | var physics_wind_strength := 0.0 setget set_wind_strength 79 | var physics_wind_speed := 1.0 setget set_wind_speed 80 | var physics_wind_scale := 1.0 setget set_wind_scale 81 | var physics_wind_angle := 0.0 setget set_wind_angle 82 | 83 | # Blendshape Styling 84 | var styling_blendshape := 0 setget set_blendshape 85 | var styling_normal_bias := 0.0 setget set_normal_bias 86 | 87 | # Level of Detail 88 | var lod_LOD0_distance := 10.0 setget set_LOD0_distance 89 | var lod_LOD1_distance := 100.0 setget set_LOD1_distance 90 | 91 | # Public variables 92 | var fur_object : Spatial 93 | 94 | # Private variables 95 | var _material: ShaderMaterial = null 96 | var _lod_system 97 | var _physics_system 98 | var _parent_is_mesh_instance = false 99 | var _parent_has_mesh_assigned = false 100 | var _parent_has_skin_assigned = false 101 | var _default_shader: Shader = null 102 | var _multimeshInstance : MultiMeshInstance = null 103 | var _first_enter_tree := true 104 | var _parent_object : Spatial 105 | var _skeleton_object 106 | var _custom_pattern := false 107 | 108 | # Built-in Methods 109 | func _get_property_list() -> Array: 110 | var props = [] 111 | 112 | var shader_type_hint_string = "Regular, Mobile" 113 | if custom_shader != null: 114 | shader_type_hint_string += str(", Custom") 115 | 116 | props.append({ 117 | name = "shader_type", 118 | type = TYPE_INT, 119 | hint = PROPERTY_HINT_ENUM, 120 | hint_string = shader_type_hint_string, 121 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 122 | }) 123 | props.append({ 124 | name = "custom_shader", 125 | type = TYPE_OBJECT, 126 | hint = PROPERTY_HINT_RESOURCE_TYPE, 127 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 128 | hint_string = "Shader" 129 | }) 130 | 131 | props.append({ 132 | name = "layers", 133 | type = TYPE_INT, 134 | hint = PROPERTY_HINT_RANGE, 135 | hint_string = "4, 100", 136 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 137 | }) 138 | 139 | var pattern_selector_hint_string = "Very Fine, Fine, Rough, Very Rough, Monster" 140 | if _custom_pattern or pattern_selector == PATTERNS.size(): 141 | pattern_selector_hint_string += str(", Custom") 142 | 143 | props.append({ 144 | name = "pattern_selector", 145 | type = TYPE_INT, 146 | hint = PROPERTY_HINT_ENUM, 147 | hint_string = pattern_selector_hint_string, 148 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 149 | }) 150 | props.append({ 151 | name = "pattern_texture", 152 | type = TYPE_OBJECT, 153 | hint = PROPERTY_HINT_RESOURCE_TYPE, 154 | hint_string = "Texture", 155 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 156 | }) 157 | props.append({ 158 | name = "pattern_uv_scale", 159 | type = TYPE_REAL, 160 | hint = PROPERTY_HINT_RANGE, 161 | hint_string = "0, 100", 162 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 163 | }) 164 | props.append({ 165 | name = "cast_shadow", 166 | type = TYPE_BOOL, 167 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 168 | }) 169 | props.append({ 170 | name = "Material", 171 | type = TYPE_NIL, 172 | hint_string = "mat_", 173 | usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE, 174 | }) 175 | 176 | var mat_categories = MATERIAL_CATEGORIES.duplicate(true) 177 | if _material.shader != null: 178 | var shader_params := VisualServer.shader_get_param_list(_material.shader.get_rid()) 179 | shader_params = FurHelperMethods.reorder_params(shader_params) 180 | for p in shader_params: 181 | if p.name.begins_with("i_"): 182 | continue 183 | var hit_category = null 184 | for category in mat_categories: 185 | if p.name.begins_with(category): 186 | props.append({ 187 | name = str("Material/", mat_categories[category]), 188 | type = TYPE_NIL, 189 | hint_string = str("mat_", category), 190 | usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE 191 | }) 192 | hit_category = category 193 | break 194 | if hit_category != null: 195 | mat_categories.erase(hit_category) 196 | var cp := {} 197 | for k in p: 198 | cp[k] = p[k] 199 | cp.name = str("mat_", p.name) 200 | props.append(cp) 201 | 202 | props.append({ 203 | name = "Physics", 204 | type = TYPE_NIL, 205 | hint_string = "physics_", 206 | usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE, 207 | }) 208 | props.append({ 209 | name = "physics_custom_physics_pivot", 210 | type = TYPE_NODE_PATH, 211 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 212 | }) 213 | props.append({ 214 | name = "physics_gravity", 215 | type = TYPE_REAL, 216 | hint = PROPERTY_HINT_RANGE, 217 | hint_string = "0.0, 4.0", 218 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 219 | }) 220 | props.append({ 221 | name = "physics_spring", 222 | type = TYPE_REAL, 223 | hint = PROPERTY_HINT_RANGE, 224 | hint_string = "0.0, 10.0", 225 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 226 | }) 227 | props.append({ 228 | name = "physics_damping", 229 | type = TYPE_REAL, 230 | hint = PROPERTY_HINT_RANGE, 231 | hint_string = "0.0, 1.0", 232 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 233 | }) 234 | props.append({ 235 | name = "physics_wind_strength", 236 | type = TYPE_REAL, 237 | hint = PROPERTY_HINT_RANGE, 238 | hint_string = "0.0, 5.0", 239 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 240 | }) 241 | props.append({ 242 | name = "physics_wind_speed", 243 | type = TYPE_REAL, 244 | hint = PROPERTY_HINT_RANGE, 245 | hint_string = "0.0, 5.0", 246 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 247 | }) 248 | props.append({ 249 | name = "physics_wind_scale", 250 | type = TYPE_REAL, 251 | hint = PROPERTY_HINT_RANGE, 252 | hint_string = "0.0, 5.0", 253 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 254 | }) 255 | props.append({ 256 | name = "physics_wind_angle", 257 | type = TYPE_REAL, 258 | hint = PROPERTY_HINT_RANGE, 259 | hint_string = "0.0, 360.0", 260 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 261 | }) 262 | props.append({ 263 | name = "Blendshape Styling", 264 | type = TYPE_NIL, 265 | hint_string = "styling_", 266 | usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE, 267 | }) 268 | 269 | var blendshapes_string := "Disabled" 270 | if _parent_has_mesh_assigned: 271 | if _parent_object.mesh.is_class("ArrayMesh"): 272 | if _parent_object.mesh.get_blend_shape_count() > 0: 273 | var b_shapes = _parent_object.mesh.get_blend_shape_count() 274 | for b in b_shapes: 275 | blendshapes_string += str(", ") + str(_parent_object.mesh.get_blend_shape_name(b)) 276 | 277 | props.append({ 278 | name = "styling_blendshape", 279 | type = TYPE_INT, 280 | hint = PROPERTY_HINT_ENUM, 281 | hint_string = blendshapes_string, 282 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 283 | }) 284 | 285 | if styling_blendshape != 0: 286 | props.append({ 287 | name = "styling_normal_bias", 288 | type = TYPE_REAL, 289 | hint = PROPERTY_HINT_RANGE, 290 | hint_string = "0.0, 1.0", 291 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 292 | }) 293 | 294 | props.append({ 295 | name = "Lod", 296 | type = TYPE_NIL, 297 | hint_string = "lod_", 298 | usage = PROPERTY_USAGE_GROUP | PROPERTY_USAGE_SCRIPT_VARIABLE, 299 | }) 300 | props.append({ 301 | name = "lod_LOD0_distance", 302 | type = TYPE_REAL, 303 | hint = PROPERTY_HINT_RANGE, 304 | hint_string = "0.0, 100.0", 305 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 306 | }) 307 | props.append({ 308 | name = "lod_LOD1_distance", 309 | type = TYPE_REAL, 310 | hint = PROPERTY_HINT_RANGE, 311 | hint_string = "0.0, 1000.0", 312 | usage = PROPERTY_USAGE_DEFAULT | PROPERTY_USAGE_SCRIPT_VARIABLE, 313 | }) 314 | 315 | return props 316 | 317 | 318 | func _set(property: String, value) -> bool: 319 | if property.begins_with("mat_"): 320 | var param_name = property.right(len("mat_")) 321 | set_shader_param(param_name, value) 322 | return true 323 | return false 324 | 325 | 326 | func _get(property : String): 327 | if property.begins_with("mat_"): 328 | var param_name = property.right(len("mat_")) 329 | return get_shader_param(param_name) 330 | 331 | 332 | func property_can_revert(property : String) -> bool: 333 | if property.begins_with("mat_"): 334 | var param_name = property.right(len("mat_")) 335 | return _material.property_can_revert(str("shader_param/", param_name)) 336 | 337 | if not DEFAULT_PARAMETERS.has(property): 338 | return false 339 | if get(property) != DEFAULT_PARAMETERS[property]: 340 | return true 341 | return false 342 | 343 | 344 | func property_get_revert(property : String): 345 | if property.begins_with("mat_"): 346 | var param_name = property.right(len("mat_")) 347 | var revert_value = _material.property_get_revert(str("shader_param/", param_name)) 348 | return revert_value 349 | return DEFAULT_PARAMETERS[property] 350 | 351 | 352 | func _init() -> void: 353 | _material = ShaderMaterial.new() 354 | _material.shader = load(BUILTIN_SHADERS[shader_type].shader_path) as Shader 355 | _lod_system = load("res://addons/shell_fur/shell_fur_lod.gd").new() 356 | _lod_system.init(self) 357 | _physics_system = load("res://addons/shell_fur/shell_fur_physics.gd").new() 358 | _physics_system.init(self) 359 | 360 | 361 | func _enter_tree() -> void: 362 | if Engine.editor_hint and _first_enter_tree: 363 | _first_enter_tree = false 364 | 365 | _analyse_parent() 366 | _physics_system.update_physics_object(0.5) 367 | 368 | if _parent_has_mesh_assigned: 369 | # Delaying the fur update to avoid throwing below error on reparenting 370 | # ERROR "scene/main/node.cpp:1554 - Condition "!owner_valid" is true." 371 | # Not sure why this is thrown, since it's not a problem when first 372 | # adding the node. 373 | _delayed_position_correction() 374 | # We have to manually set the texture as that cannot be defaulted on the 375 | # material, so if it's a new object is has to be set to standard (0) 376 | # otherwise it should be set to something useful already and we can just 377 | # set it. 378 | if pattern_texture == null: 379 | pattern_texture = load(PATTERNS[0]) 380 | set_shader_param("i_pattern_texture", pattern_texture) 381 | # For some reason we have to set some values like colors for them to 382 | # show correctly. Even though we are just setting them to themselves. 383 | # To allow for custom shaders, we simply set all shader params to thier own value. 384 | var shader_params := VisualServer.shader_get_param_list(_material.shader.get_rid()) 385 | for sp in shader_params: 386 | set_shader_param(sp.name, get_shader_param(sp.name)) 387 | 388 | # Updates the fur if it's needed, clears the fur if it's not 389 | _update_fur(0.05) 390 | 391 | 392 | func _ready() -> void: 393 | _physics_system.update_physics_object(0.0) 394 | 395 | 396 | func _physics_process(delta: float) -> void: 397 | _physics_system.process(delta) 398 | if not Engine.editor_hint: 399 | _lod_system.process(delta) 400 | 401 | 402 | func _get_configuration_warning() -> String: 403 | if not _parent_is_mesh_instance: 404 | return "Parent must be a MeshInstance node!" 405 | if not _parent_has_mesh_assigned: 406 | return "Parent MeshInstance has to have a mesh assigned! Assign a mesh to parent and re-parent fur node to recalculate." 407 | return "" 408 | 409 | 410 | func _exit_tree() -> void: 411 | _parent_is_mesh_instance = false 412 | _parent_has_mesh_assigned = false 413 | _parent_has_skin_assigned = false 414 | 415 | 416 | # Getter Methods 417 | func get_current_LOD() -> int: 418 | return _lod_system.current_LOD 419 | 420 | 421 | func get_shader_param(param : String): 422 | return _material.get_shader_param(param) 423 | 424 | 425 | # Setter Methods 426 | func set_shader_param(param : String, value) -> void: 427 | _material.set_shader_param(param, value) 428 | 429 | 430 | func set_layers(new_layers : int) -> void: 431 | layers = new_layers 432 | if _first_enter_tree: 433 | return 434 | set_shader_param("i_layers", new_layers) 435 | _update_fur(0.0) 436 | 437 | 438 | func set_pattern_selector(index : int) -> void: 439 | pattern_selector = index 440 | if _first_enter_tree: 441 | return 442 | if index != PATTERNS.size(): 443 | set_pattern_texture(load(PATTERNS[index]), false) 444 | else: 445 | set_shader_param("i_pattern_texture", pattern_texture) 446 | property_list_changed_notify() 447 | 448 | 449 | func set_pattern_texture(texture : Texture, custom : bool = true) -> void: 450 | pattern_texture = texture 451 | if _first_enter_tree: 452 | return 453 | _custom_pattern = custom 454 | 455 | set_shader_param("i_pattern_texture", texture) 456 | if custom: 457 | set_pattern_selector(PATTERNS.size()) 458 | 459 | 460 | func set_pattern_uv_scale(value : float) -> void: 461 | pattern_uv_scale = value 462 | set_shader_param("i_pattern_uv_scale", value) 463 | 464 | 465 | func set_cast_shadow(value : bool) -> void: 466 | cast_shadow = value 467 | if _first_enter_tree: 468 | return 469 | fur_object.cast_shadow = value 470 | 471 | 472 | func set_shader_type(type: int): 473 | if type == shader_type: 474 | return 475 | shader_type = type 476 | 477 | if shader_type == SHADER_TYPES.CUSTOM: 478 | _material.shader = custom_shader 479 | else: 480 | _material.shader = load(BUILTIN_SHADERS[shader_type].shader_path) 481 | 482 | property_list_changed_notify() 483 | 484 | 485 | func set_custom_shader(shader : Shader) -> void: 486 | if custom_shader == shader: 487 | return 488 | custom_shader = shader 489 | if custom_shader != null: 490 | _material.shader = custom_shader 491 | 492 | if Engine.editor_hint: 493 | # Ability to fork default shader 494 | if shader.code == "": 495 | var selected_shader = load(BUILTIN_SHADERS[shader_type].shader_path) as Shader 496 | shader.code = selected_shader.code 497 | 498 | if shader != null: 499 | set_shader_type(SHADER_TYPES.CUSTOM) 500 | else: 501 | set_shader_type(SHADER_TYPES.REGULAR) 502 | 503 | property_list_changed_notify() 504 | 505 | 506 | func set_custom_physics_pivot(path : NodePath) -> void: 507 | physics_custom_physics_pivot = path 508 | if _first_enter_tree: 509 | return 510 | _physics_system.update_physics_object(0.0) 511 | 512 | 513 | func set_wind_strength(new_wind_strength : float) -> void: 514 | physics_wind_strength = new_wind_strength 515 | set_shader_param("i_wind_strength", physics_wind_strength) 516 | 517 | 518 | func set_wind_speed(new_wind_speed : float) -> void: 519 | physics_wind_speed = new_wind_speed 520 | set_shader_param("i_wind_speed", physics_wind_speed) 521 | 522 | 523 | func set_wind_scale(new_wind_scale : float) -> void: 524 | physics_wind_scale = new_wind_scale 525 | set_shader_param("i_wind_scale", physics_wind_scale) 526 | 527 | 528 | func set_wind_angle(new_wind_angle : float) -> void: 529 | physics_wind_angle = new_wind_angle 530 | var angle_vector := Vector2(cos(deg2rad(physics_wind_angle)), sin(deg2rad(physics_wind_angle))) 531 | set_shader_param("i_wind_angle", Vector3(angle_vector.x, 0.0, angle_vector.y)) 532 | 533 | 534 | func set_blendshape(index: int) -> void: 535 | styling_blendshape = index 536 | if _first_enter_tree: 537 | return 538 | 539 | property_list_changed_notify() 540 | _update_fur(0.1) 541 | 542 | 543 | func set_normal_bias(value : float) -> void: 544 | styling_normal_bias = value 545 | set_shader_param("i_normal_bias", styling_normal_bias) 546 | 547 | 548 | func set_LOD0_distance(value : float) -> void: 549 | if value > lod_LOD1_distance: 550 | lod_LOD0_distance = lod_LOD1_distance 551 | else: 552 | lod_LOD0_distance = value 553 | 554 | 555 | func set_LOD1_distance(value : float) -> void: 556 | if value < lod_LOD0_distance: 557 | lod_LOD1_distance = lod_LOD0_distance 558 | else: 559 | lod_LOD1_distance = value 560 | 561 | 562 | # Private functions 563 | func _analyse_parent() -> void: 564 | var is_arraymesh 565 | _parent_object = get_parent() 566 | if _parent_object.get_class() == "MeshInstance": 567 | _parent_is_mesh_instance = true 568 | if _parent_object.mesh != null: 569 | _parent_has_mesh_assigned = true 570 | is_arraymesh = _parent_object.mesh.is_class("ArrayMesh") 571 | if is_arraymesh: 572 | if _parent_object.mesh.get_blend_shape_count() < styling_blendshape: 573 | push_warning("Blendshape selection is higher than new mesh's amount of blendshapes. Disabling blendshape styling.") 574 | styling_blendshape = 0 575 | 576 | if _parent_object.skin != null: 577 | _parent_has_skin_assigned = true 578 | _skeleton_object = _parent_object.get_parent() 579 | 580 | if not _parent_is_mesh_instance or not _parent_has_mesh_assigned or not is_arraymesh: 581 | if styling_blendshape != 0: 582 | push_warning("Fur is no longer assigned to a valid mesh. Disabling blendshape styling.") 583 | styling_blendshape = 0 584 | 585 | 586 | func _update_fur(delay : float) -> void: 587 | yield(get_tree().create_timer(delay), "timeout") 588 | for child in get_children(): 589 | child.free() 590 | 591 | if not _parent_is_mesh_instance: 592 | return 593 | 594 | if _parent_has_skin_assigned: 595 | FurHelperMethods.generate_mesh_shells(self, _parent_object, layers, _material, styling_blendshape - 1) 596 | fur_object = FurHelperMethods.generate_combined(self, _parent_object, _material, cast_shadow) 597 | else: 598 | _multimeshInstance = MultiMeshInstance.new() 599 | add_child(_multimeshInstance) 600 | # Uncomment to debug whether MMI is created 601 | #_multimeshInstance.set_owner(get_tree().get_edited_scene_root()) 602 | FurHelperMethods.generate_mmi(layers, _multimeshInstance, _parent_object.mesh, _material, styling_blendshape - 1, cast_shadow) 603 | fur_object = _multimeshInstance 604 | 605 | 606 | func _delayed_position_correction() -> void: 607 | # This is delayed because some transform correction appears to be called 608 | # internally after _enter_tree and that overrides this value if it's not 609 | # delayed 610 | yield(get_tree().create_timer(0.1), "timeout") 611 | transform = Transform.IDENTITY 612 | -------------------------------------------------------------------------------- /addons/shell_fur/shell_fur_physics.gd: -------------------------------------------------------------------------------- 1 | # Copyright © 2021 Kasper Arnklit Frandsen - MIT License 2 | # See `LICENSE.md` included in the source distribution for details. 3 | const ShellFurManager = preload("res://addons/shell_fur/shell_fur_manager.gd") 4 | 5 | var _shell_fur_object : ShellFurManager 6 | var _trans_momentum : Vector3 7 | var _rot_momentum : Vector3 8 | var _physics_pos : Vector3 9 | var _physics_rot : Quat 10 | 11 | 12 | func init(shell_fur_object : ShellFurManager) -> void: 13 | _shell_fur_object = shell_fur_object 14 | 15 | 16 | func process(delta) -> void: 17 | var position_diff := _current_physics_object().global_transform.origin - _physics_pos 18 | _trans_momentum += position_diff * _shell_fur_object.physics_spring 19 | _trans_momentum += Vector3(0.0, -1.0 * _shell_fur_object.physics_gravity, 0.0) 20 | _physics_pos += _trans_momentum * delta 21 | _trans_momentum *= _shell_fur_object.physics_damping * -1 + 1 22 | 23 | _shell_fur_object.set_shader_param("i_physics_pos_offset", -position_diff) 24 | 25 | var rot_diff := _physics_rot.inverse() * _current_physics_object().global_transform.basis.get_rotation_quat() 26 | _rot_momentum += rot_diff.get_euler() * _shell_fur_object.physics_spring 27 | _physics_rot *= Quat(_rot_momentum * delta) 28 | _rot_momentum *= _shell_fur_object.physics_damping * -1 + 1 29 | 30 | _shell_fur_object.set_shader_param("i_physics_rot_offset", rot_diff) 31 | 32 | 33 | func _current_physics_object() -> Spatial: 34 | if _shell_fur_object.physics_custom_physics_pivot.is_empty(): 35 | return _shell_fur_object 36 | else: 37 | return _shell_fur_object.get_node(_shell_fur_object.physics_custom_physics_pivot) as Spatial 38 | 39 | 40 | func update_physics_object(delay : float) -> void: 41 | yield(_shell_fur_object.get_tree().create_timer(delay), "timeout") 42 | _physics_pos = _current_physics_object().global_transform.origin 43 | _physics_rot = _current_physics_object().global_transform.basis.get_rotation_quat() 44 | -------------------------------------------------------------------------------- /assets/Cottage.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=4 format=2] 2 | 3 | [ext_resource path="res://assets/models/Cottage2.gltf" type="PackedScene" id=1] 4 | [ext_resource path="res://addons/shell_fur/shell_fur_manager.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/shell_fur/noise_patterns/very_fine.png" type="Texture" id=3] 6 | 7 | [node name="Cottage2" instance=ExtResource( 1 )] 8 | 9 | [node name="ShellFur" type="Spatial" parent="Cottage Fur Roof" index="0"] 10 | script = ExtResource( 2 ) 11 | __meta__ = { 12 | "_editor_description_": "" 13 | } 14 | shader_type = 0 15 | custom_shader = null 16 | layers = 40 17 | pattern_selector = 0 18 | pattern_texture = ExtResource( 3 ) 19 | pattern_uv_scale = 5.0 20 | cast_shadow = false 21 | mat_transmission = Color( 0.3, 0.3, 0.3, 1 ) 22 | mat_ao = 0.5 23 | mat_roughness = 1.0 24 | mat_albedo_color = Transform( 0.803922, 1, 0, 0.552941, 0.745098, 0, 0, 0.168627, 1, 0, 0, 0 ) 25 | mat_albedo_uv_scale = Vector3( 1, 1, 0 ) 26 | mat_albedo_texture = null 27 | mat_shape_length = 1.212 28 | mat_shape_length_rand = 0.22 29 | mat_shape_density = 1.0 30 | mat_shape_thickness_base = 0.75 31 | mat_shape_thickness_tip = 0.411 32 | mat_shape_thickness_rand = 0.0 33 | mat_shape_growth = 1.0 34 | mat_shape_growth_rand = 0.0 35 | mat_shape_ldtg_uv_scale = Vector3( 1, 1, 0 ) 36 | mat_shape_ldtg_texture = null 37 | physics_custom_physics_pivot = NodePath("") 38 | physics_gravity = 0.0 39 | physics_spring = 4.0 40 | physics_damping = 0.1 41 | physics_wind_strength = 0.3 42 | physics_wind_speed = 3.236 43 | physics_wind_scale = 1.0 44 | physics_wind_angle = 0.0 45 | styling_blendshape = 1 46 | styling_normal_bias = 0.0 47 | lod_LOD0_distance = 4.0 48 | lod_LOD1_distance = 25.0 49 | -------------------------------------------------------------------------------- /assets/FPSLabel.gd: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # Copyright (c) 2019 Lupo Dharkael 3 | 4 | class_name FpsLabel 5 | 6 | extends CanvasLayer 7 | 8 | 9 | enum Position {TOP_LEFT, TOP_RIGHT, BOTTOM_LEFT, BOTTOM_RIGHT, NONE} 10 | 11 | export (Position) var position = Position.BOTTOM_LEFT 12 | export(int) var margin : int = 50 13 | 14 | var label : Label 15 | 16 | 17 | func _ready() -> void: 18 | label = Label.new() 19 | label.rect_scale = Vector2(4.0, 4.0) 20 | add_child(label) 21 | get_tree().get_root().connect("size_changed", self, "update_position") 22 | update_position() 23 | 24 | # pos should be of type Position 25 | func set_position(pos : int): 26 | position = pos 27 | update_position() 28 | 29 | 30 | func update_position(): 31 | var viewport_size : Vector2 = get_viewport().size 32 | var label_size : Vector2 = label.rect_size 33 | 34 | match position: 35 | Position.TOP_LEFT: 36 | offset = Vector2(margin, margin) 37 | Position.BOTTOM_LEFT: 38 | offset = Vector2(margin, viewport_size.y - margin - label_size.y) 39 | Position.TOP_RIGHT: 40 | offset = Vector2(viewport_size.x - margin - label_size.x, margin) 41 | Position.BOTTOM_RIGHT: 42 | offset = Vector2(viewport_size.x - margin - label_size.x, viewport_size.y - margin - label_size.y) 43 | 44 | 45 | func _process(_delta : float) -> void: 46 | label.text = "fps: " + str(Engine.get_frames_per_second()) 47 | -------------------------------------------------------------------------------- /assets/LOD_label.gd: -------------------------------------------------------------------------------- 1 | extends Spatial 2 | 3 | export var fur_node : NodePath 4 | onready var _label = get_node("Viewport/Label") 5 | onready var _fur_node = get_node(fur_node) 6 | 7 | func _process(_delta: float) -> void: 8 | _label.text = "LOD: " + str(_fur_node.get_current_LOD()) 9 | -------------------------------------------------------------------------------- /assets/LOD_label.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://assets/LOD_label.gd" type="Script" id=1] 4 | 5 | [sub_resource type="DynamicFontData" id=1] 6 | font_path = "res://assets/Roboto-Regular.ttf" 7 | 8 | [sub_resource type="DynamicFont" id=2] 9 | size = 100 10 | font_data = SubResource( 1 ) 11 | 12 | [sub_resource type="ViewportTexture" id=3] 13 | viewport_path = NodePath("Viewport") 14 | 15 | [sub_resource type="SpatialMaterial" id=4] 16 | resource_local_to_scene = true 17 | params_billboard_mode = 1 18 | params_use_alpha_scissor = true 19 | params_alpha_scissor_threshold = 0.98 20 | albedo_texture = SubResource( 3 ) 21 | 22 | [sub_resource type="QuadMesh" id=5] 23 | resource_local_to_scene = true 24 | material = SubResource( 4 ) 25 | 26 | [node name="LOD_label" type="Spatial"] 27 | script = ExtResource( 1 ) 28 | 29 | [node name="Viewport" type="Viewport" parent="."] 30 | size = Vector2( 512, 512 ) 31 | transparent_bg = true 32 | hdr = false 33 | disable_3d = true 34 | render_target_v_flip = true 35 | 36 | [node name="Label" type="Label" parent="Viewport"] 37 | margin_right = 512.0 38 | margin_bottom = 512.0 39 | size_flags_horizontal = 2 40 | size_flags_vertical = 2 41 | custom_fonts/font = SubResource( 2 ) 42 | custom_colors/font_color = Color( 0, 0, 0, 1 ) 43 | text = "LOD 44 | DISPLAY 45 | " 46 | align = 1 47 | valign = 1 48 | 49 | [node name="billboard" type="MeshInstance" parent="."] 50 | mesh = SubResource( 5 ) 51 | material/0 = null 52 | -------------------------------------------------------------------------------- /assets/Log.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=7 format=2] 2 | 3 | [ext_resource path="res://assets/models/mossy_log.gltf" type="PackedScene" id=1] 4 | [ext_resource path="res://addons/shell_fur/shell_fur_manager.gd" type="Script" id=2] 5 | [ext_resource path="res://assets/textures/moss_ldtg.png" type="Texture" id=3] 6 | [ext_resource path="res://addons/shell_fur/noise_patterns/very_rough.png" type="Texture" id=4] 7 | [ext_resource path="res://assets/models/mossy_log.obj" type="ArrayMesh" id=5] 8 | [ext_resource path="res://assets/textures/moss.png" type="Texture" id=6] 9 | 10 | [node name="mossy_log" instance=ExtResource( 1 )] 11 | 12 | [node name="mossy_log" type="MeshInstance" parent="." index="1"] 13 | layers = 0 14 | mesh = ExtResource( 5 ) 15 | material/0 = null 16 | 17 | [node name="ShellFur" type="Spatial" parent="mossy_log" index="0"] 18 | script = ExtResource( 2 ) 19 | shader_type = 0 20 | custom_shader = null 21 | layers = 20 22 | pattern_selector = 3 23 | pattern_texture = ExtResource( 4 ) 24 | pattern_uv_scale = 20.03 25 | cast_shadow = false 26 | mat_transmission = Color( 0.3, 0.3, 0.3, 1 ) 27 | mat_ao = 0.25 28 | mat_roughness = 1.0 29 | mat_albedo_color = Transform( 0.662745, 1, 0, 0.623529, 1, 0, 0.596078, 1, 1, 0, 0, 0 ) 30 | mat_albedo_uv_scale = Vector3( 1, 1, 0 ) 31 | mat_albedo_texture = ExtResource( 6 ) 32 | mat_shape_length = 0.04 33 | mat_shape_length_rand = 0.3 34 | mat_shape_density = 1.0 35 | mat_shape_thickness_base = 0.75 36 | mat_shape_thickness_tip = 0.3 37 | mat_shape_thickness_rand = 0.0 38 | mat_shape_growth = 1.0 39 | mat_shape_growth_rand = 0.0 40 | mat_shape_ldtg_uv_scale = Vector3( 1, 1, 0 ) 41 | mat_shape_ldtg_texture = ExtResource( 3 ) 42 | physics_custom_physics_pivot = NodePath("") 43 | physics_gravity = 0.0 44 | physics_spring = 4.0 45 | physics_damping = 0.1 46 | physics_wind_strength = 0.0 47 | physics_wind_speed = 1.0 48 | physics_wind_scale = 1.0 49 | physics_wind_angle = 0.0 50 | styling_blendshape = 0 51 | lod_LOD0_distance = 4.0 52 | lod_LOD1_distance = 25.0 53 | -------------------------------------------------------------------------------- /assets/Rat.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://assets/models/Rat-animated2.gltf" type="PackedScene" id=1] 4 | [ext_resource path="res://addons/shell_fur/shell_fur_manager.gd" type="Script" id=2] 5 | [ext_resource path="res://addons/shell_fur/noise_patterns/fine.png" type="Texture" id=3] 6 | [ext_resource path="res://assets/textures/rat_fur_ldtg.png" type="Texture" id=4] 7 | 8 | [node name="Rat-animated2" instance=ExtResource( 1 )] 9 | 10 | [node name="ShellFur" type="Spatial" parent="Armature/Skeleton/Rat Body" index="0"] 11 | script = ExtResource( 2 ) 12 | shader_type = 0 13 | custom_shader = null 14 | layers = 40 15 | pattern_selector = 1 16 | pattern_texture = ExtResource( 3 ) 17 | pattern_uv_scale = 30.0 18 | cast_shadow = false 19 | mat_transmission = Color( 0.3, 0.3, 0.3, 1 ) 20 | mat_ao = 0.5 21 | mat_roughness = 1.0 22 | mat_albedo_color = Transform( 0.415686, 0.807843, 0, 0.403922, 0.752941, 0, 0.392157, 0.709804, 1, 0, 0, 0 ) 23 | mat_albedo_uv_scale = Vector3( 1, 1, 0 ) 24 | mat_albedo_texture = null 25 | mat_shape_length = 1.0 26 | mat_shape_length_rand = 0.204 27 | mat_shape_density = 1.0 28 | mat_shape_thickness_base = 0.775 29 | mat_shape_thickness_tip = 0.396 30 | mat_shape_thickness_rand = 0.0 31 | mat_shape_growth = 2.0 32 | mat_shape_growth_rand = 1.0 33 | mat_shape_ldtg_uv_scale = Vector3( 1, 1, 0 ) 34 | mat_shape_ldtg_texture = ExtResource( 4 ) 35 | physics_custom_physics_pivot = NodePath("") 36 | physics_gravity = 0.0 37 | physics_spring = 4.0 38 | physics_damping = 0.1 39 | physics_wind_strength = 0.192 40 | physics_wind_speed = 3.288 41 | physics_wind_scale = 2.263 42 | physics_wind_angle = 0.0 43 | styling_blendshape = 3 44 | styling_normal_bias = 0.489 45 | lod_LOD0_distance = 4.0 46 | lod_LOD1_distance = 25.0 47 | 48 | [node name="AnimationPlayer" parent="." index="1"] 49 | autoplay = "ArmatureAction" 50 | next/ArmatureAction = "ArmatureAction" 51 | blend_times = [ "ArmatureAction", "ArmatureAction", 0.25 ] 52 | -------------------------------------------------------------------------------- /assets/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/Roboto-Regular.ttf -------------------------------------------------------------------------------- /assets/ball_boy.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://addons/shell_fur/noise_patterns/very_fine.png" type="Texture" id=1] 4 | [ext_resource path="res://addons/shell_fur/shell_fur_manager.gd" type="Script" id=2] 5 | [ext_resource path="res://assets/models/ball_boy.gltf" type="PackedScene" id=3] 6 | [ext_resource path="res://assets/textures/ballboy_fur_ldtg.png" type="Texture" id=4] 7 | 8 | [node name="ball_boy" instance=ExtResource( 3 )] 9 | 10 | [node name="Skeleton" parent="Armature" index="0"] 11 | bones/0/bound_children = [ NodePath("BoneAttachment") ] 12 | 13 | [node name="ShellFur" type="Spatial" parent="Armature/Skeleton/BallBoy" index="0"] 14 | script = ExtResource( 2 ) 15 | shader_type = 0 16 | custom_shader = null 17 | layers = 40 18 | pattern_selector = 0 19 | pattern_texture = ExtResource( 1 ) 20 | pattern_uv_scale = 16.043 21 | cast_shadow = false 22 | mat_transmission = Color( 0.3, 0.3, 0.3, 1 ) 23 | mat_ao = 0.5 24 | mat_roughness = 1.0 25 | mat_albedo_color = Transform( 0.784314, 0.996078, 0, 0.0627451, 0.278431, 0, 0, 0.215686, 1, 0, 0, 0 ) 26 | mat_albedo_uv_scale = Vector3( 1, 1, 0 ) 27 | mat_albedo_texture = null 28 | mat_shape_length = 0.102 29 | mat_shape_length_rand = 0.44 30 | mat_shape_density = 1.0 31 | mat_shape_thickness_base = 0.919 32 | mat_shape_thickness_tip = 0.491 33 | mat_shape_thickness_rand = 0.0 34 | mat_shape_growth = 2.0 35 | mat_shape_growth_rand = 0.385 36 | mat_shape_ldtg_uv_scale = Vector3( 1, 1, 0 ) 37 | mat_shape_ldtg_texture = ExtResource( 4 ) 38 | physics_custom_physics_pivot = NodePath("../../BoneAttachment") 39 | physics_gravity = 0.309 40 | physics_spring = 4.0 41 | physics_damping = 0.1 42 | physics_wind_strength = 0.04 43 | physics_wind_speed = 3.011 44 | physics_wind_scale = 3.609 45 | physics_wind_angle = 0.0 46 | styling_blendshape = 0 47 | lod_LOD0_distance = 4.0 48 | lod_LOD1_distance = 25.0 49 | 50 | [node name="BoneAttachment" type="BoneAttachment" parent="Armature/Skeleton" index="1"] 51 | transform = Transform( -1, -1.64313e-15, 4.5688e-16, -1.66267e-15, 0.99891, -0.0466729, -3.79692e-16, -0.0466729, -0.99891, 4.72455e-16, -0.197239, 0.0788051 ) 52 | bone_name = "spine_1" 53 | 54 | [node name="AnimationPlayer" parent="." index="1"] 55 | autoplay = "ArmatureAction" 56 | next/ArmatureAction = "ArmatureAction" 57 | blend_times = [ "ArmatureAction", "ArmatureAction", 0.25 ] 58 | -------------------------------------------------------------------------------- /assets/ball_boy2.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=3 format=2] 2 | 3 | [ext_resource path="res://assets/ball_boy.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://assets/growth_api.gd" type="Script" id=5] 5 | 6 | [node name="ball_boy" instance=ExtResource( 1 )] 7 | 8 | [node name="Skeleton" parent="Armature" index="0"] 9 | bones/0/bound_children = [ ] 10 | 11 | [node name="BallBoy" parent="Armature/Skeleton" index="0"] 12 | script = ExtResource( 5 ) 13 | 14 | [node name="ShellFur" parent="Armature/Skeleton/BallBoy" index="0"] 15 | mat_albedo_color = Transform( 0.694118, 0.796078, 0, 0, 0.215686, 0, 0.784314, 0.996078, 1, 0, 0, 0 ) 16 | 17 | [node name="BoneAttachment" parent="Armature/Skeleton" index="1"] 18 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) 19 | 20 | [node name="AnimationPlayer" parent="." index="1"] 21 | autoplay = "" 22 | -------------------------------------------------------------------------------- /assets/growth_api.gd: -------------------------------------------------------------------------------- 1 | extends MeshInstance 2 | 3 | var _timer := 0.0 4 | 5 | 6 | func _process(delta : float) -> void: 7 | _timer += delta 8 | var growth := sin(_timer) + 1.0 9 | get_node("ShellFur").set_shader_param("shape_growth", growth) 10 | -------------------------------------------------------------------------------- /assets/maujoe.camera_control/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/maujoe.camera_control/icon.png -------------------------------------------------------------------------------- /assets/maujoe.camera_control/icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-5d9aeb34e4fe76b4f9b5e813feff67e9.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://assets/maujoe.camera_control/icon.png" 13 | dest_files=[ "res://.import/icon.png-5d9aeb34e4fe76b4f9b5e813feff67e9.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /assets/maujoe.camera_control/scripts/camera_control.gd: -------------------------------------------------------------------------------- 1 | # Licensed under the MIT License. 2 | # Copyright (c) 2018 Jaccomo Lorenz (Maujoe) 3 | 4 | extends Camera 5 | 6 | # User settings: 7 | # General settings 8 | export var enabled = true setget set_enabled 9 | export(int, "Visible", "Hidden", "Caputered, Confined") var mouse_mode = 2 10 | 11 | # Mouslook settings 12 | export var mouselook = true 13 | export (float, 0.0, 1.0) var sensitivity = 0.5 14 | export (float, 0.0, 0.999, 0.001) var smoothness = 0.5 setget set_smoothness 15 | export(NodePath) var privot setget set_privot 16 | export var distance = 5.0 setget set_distance 17 | export var rotate_privot = false 18 | export var collisions = true setget set_collisions 19 | export (int, 0, 360) var yaw_limit = 360 20 | export (int, 0, 360) var pitch_limit = 360 21 | 22 | # Movement settings 23 | export var movement = true 24 | export (float, 0.0, 1.0) var acceleration = 1.0 25 | export (float, 0.0, 0.0, 1.0) var deceleration = 0.1 26 | export var max_speed = Vector3(1.0, 1.0, 1.0) 27 | export var local = true 28 | export var forward_action = "ui_up" 29 | export var backward_action = "ui_down" 30 | export var left_action = "ui_left" 31 | export var right_action = "ui_right" 32 | export var up_action = "ui_page_up" 33 | export var down_action = "ui_page_down" 34 | 35 | # Gui settings 36 | export var use_gui = true 37 | export var gui_action = "ui_cancel" 38 | export var mobile = false 39 | 40 | # Intern variables. 41 | var _mouse_position = Vector2(0.0, 0.0) 42 | var _yaw = 0.0 43 | var _pitch = 0.0 44 | var _total_yaw = 0.0 45 | var _total_pitch = 0.0 46 | 47 | var _direction = Vector3(0.0, 0.0, 0.0) 48 | var _speed = Vector3(0.0, 0.0, 0.0) 49 | var _gui 50 | 51 | func _ready(): 52 | _check_actions([forward_action, backward_action, left_action, right_action, gui_action, up_action, down_action]) 53 | 54 | if privot: 55 | privot = get_node(privot) 56 | else: 57 | privot = null 58 | 59 | set_enabled(enabled) 60 | 61 | if use_gui: 62 | _gui = preload("camera_control_gui.gd") 63 | _gui = _gui.new(self, gui_action) 64 | add_child(_gui) 65 | 66 | if mobile: 67 | get_parent().get_parent().get_parent().get_node("CanvasLayer/Joystick Left").connect("updated", self, "_on_left_joystick") 68 | get_parent().get_parent().get_parent().get_node("CanvasLayer/Joystick Right").connect("updated", self, "_on_right_joystick") 69 | 70 | func _on_left_joystick(force, pressed) -> void: 71 | _direction = Vector3(force.x, 0.0, force.y) 72 | 73 | func _on_right_joystick(force, pressed) -> void: 74 | _mouse_position += force 75 | 76 | func _input(event): 77 | if mouselook: 78 | if event is InputEventMouseMotion: 79 | _mouse_position = event.relative 80 | 81 | if movement: 82 | if event.is_action_pressed(forward_action): 83 | _direction.z = -1 84 | elif event.is_action_pressed(backward_action): 85 | _direction.z = 1 86 | elif not Input.is_action_pressed(forward_action) and not Input.is_action_pressed(backward_action): 87 | _direction.z = 0 88 | 89 | if event.is_action_pressed(left_action): 90 | _direction.x = -1 91 | elif event.is_action_pressed(right_action): 92 | _direction.x = 1 93 | elif not Input.is_action_pressed(left_action) and not Input.is_action_pressed(right_action): 94 | _direction.x = 0 95 | 96 | if event.is_action_pressed(up_action): 97 | _direction.y = 1 98 | if event.is_action_pressed(down_action): 99 | _direction.y = -1 100 | elif not Input.is_action_pressed(up_action) and not Input.is_action_pressed(down_action): 101 | _direction.y = 0 102 | 103 | func _process(delta): 104 | if privot: 105 | _update_distance() 106 | if mouselook: 107 | _update_mouselook() 108 | if movement: 109 | _update_movement(delta) 110 | 111 | func _physics_process(delta): 112 | # Called when collision are enabled 113 | _update_distance() 114 | if mouselook: 115 | _update_mouselook() 116 | 117 | var space_state = get_world().get_direct_space_state() 118 | var obstacle = space_state.intersect_ray(privot.get_translation(), get_translation()) 119 | if not obstacle.empty(): 120 | set_translation(obstacle.position) 121 | 122 | func _update_movement(delta): 123 | var offset = max_speed * acceleration * _direction 124 | 125 | _speed.x = clamp(_speed.x + offset.x, -max_speed.x, max_speed.x) 126 | _speed.y = clamp(_speed.y + offset.y, -max_speed.y, max_speed.y) 127 | _speed.z = clamp(_speed.z + offset.z, -max_speed.z, max_speed.z) 128 | 129 | # Apply deceleration if no input 130 | if _direction.x == 0: 131 | _speed.x *= (1.0 - deceleration) 132 | if _direction.y == 0: 133 | _speed.y *= (1.0 - deceleration) 134 | if _direction.z == 0: 135 | _speed.z *= (1.0 - deceleration) 136 | 137 | if local: 138 | translate(_speed * delta) 139 | else: 140 | global_translate(_speed * delta) 141 | 142 | func _update_mouselook(): 143 | _mouse_position *= sensitivity 144 | _yaw = _yaw * smoothness + _mouse_position.x * (1.0 - smoothness) 145 | _pitch = _pitch * smoothness + _mouse_position.y * (1.0 - smoothness) 146 | _mouse_position = Vector2(0, 0) 147 | 148 | if yaw_limit < 360: 149 | _yaw = clamp(_yaw, -yaw_limit - _total_yaw, yaw_limit - _total_yaw) 150 | if pitch_limit < 360: 151 | _pitch = clamp(_pitch, -pitch_limit - _total_pitch, pitch_limit - _total_pitch) 152 | 153 | _total_yaw += _yaw 154 | _total_pitch += _pitch 155 | 156 | if privot: 157 | var target = privot.get_translation() 158 | var offset = get_translation().distance_to(target) 159 | 160 | set_translation(target) 161 | rotate_y(deg2rad(-_yaw)) 162 | rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch)) 163 | translate(Vector3(0.0, 0.0, offset)) 164 | 165 | if rotate_privot: 166 | privot.rotate_y(deg2rad(-_yaw)) 167 | else: 168 | rotate_y(deg2rad(-_yaw)) 169 | rotate_object_local(Vector3(1,0,0), deg2rad(-_pitch)) 170 | 171 | func _update_distance(): 172 | var t = privot.get_translation() 173 | t.z -= distance 174 | set_translation(t) 175 | 176 | func _update_process_func(): 177 | # Use physics process if collision are enabled 178 | if collisions and privot: 179 | set_physics_process(true) 180 | set_process(false) 181 | else: 182 | set_physics_process(false) 183 | set_process(true) 184 | 185 | func _check_actions(actions=[]): 186 | if OS.is_debug_build(): 187 | for action in actions: 188 | if not InputMap.has_action(action): 189 | print('WARNING: No action "' + action + '"') 190 | 191 | func set_privot(value): 192 | privot = value 193 | # TODO: fix parenting. 194 | # if privot: 195 | # if get_parent(): 196 | # get_parent().remove_child(self) 197 | # privot.add_child(self) 198 | _update_process_func() 199 | 200 | func set_collisions(value): 201 | collisions = value 202 | _update_process_func() 203 | 204 | func set_enabled(value): 205 | enabled = value 206 | if enabled: 207 | Input.set_mouse_mode(mouse_mode) 208 | set_process_input(true) 209 | _update_process_func() 210 | else: 211 | set_process(false) 212 | set_process_input(false) 213 | set_physics_process(false) 214 | 215 | func set_smoothness(value): 216 | smoothness = clamp(value, 0.001, 0.999) 217 | 218 | func set_distance(value): 219 | distance = max(0, value) 220 | -------------------------------------------------------------------------------- /assets/maujoe.camera_control/scripts/camera_control_gui.gd: -------------------------------------------------------------------------------- 1 | # Licensed under the MIT License. 2 | # Copyright (c) 2018 Jaccomo Lorenz (Maujoe) 3 | 4 | extends Control 5 | 6 | # Constant Gui Settings 7 | #******************************************************************************* 8 | const GUI_POS = Vector2(10, 10) 9 | const GUI_SIZE = Vector2(200, 0) 10 | const DRAGGABLE = true 11 | 12 | const CUSTOM_BACKGROUND = false 13 | const BACKGROUND_COLOR = Color(0.15, 0.17, 0.23, 0.75) 14 | 15 | const MAX_SPEED = 50 16 | #******************************************************************************* 17 | 18 | var camera 19 | var shortcut 20 | var node_list 21 | var privot 22 | var panel 23 | 24 | var mouse_over = false 25 | var mouse_pressed = false 26 | 27 | func _init(camera, shortcut): 28 | self.camera = camera 29 | self.shortcut = shortcut 30 | 31 | func _ready(): 32 | if camera.enabled: 33 | set_process_input(true) 34 | 35 | # Create Gui 36 | panel = PanelContainer.new() 37 | panel.set_begin(GUI_POS) 38 | panel.set_custom_minimum_size(GUI_SIZE) 39 | 40 | if CUSTOM_BACKGROUND: 41 | var style = StyleBoxFlat.new() 42 | style.set_bg_color(BACKGROUND_COLOR) 43 | style.set_expand_margin_all(5) 44 | panel.add_stylebox_override("panel", style) 45 | 46 | var container = VBoxContainer.new() 47 | 48 | var lbl_mouse = Label.new() 49 | lbl_mouse.set_text("Mousemode") 50 | 51 | var mouse = OptionButton.new() 52 | mouse.add_item("Visible") 53 | mouse.add_item("Hidden") 54 | mouse.add_item("Captured") 55 | mouse.add_item("Confined") 56 | mouse.select(camera.mouse_mode) 57 | mouse.connect("item_selected",self,"_on_opt_mouse_item_selected") 58 | 59 | # Mouselook 60 | var mouselook = CheckButton.new() 61 | mouselook.set_text("Mouselook") 62 | mouselook.set_toggle_mode(true) 63 | mouselook.set_pressed(camera.mouselook) 64 | mouselook.connect("toggled",self,"_on_btn_mouselook_toggled") 65 | 66 | var lbl_sensitivity = Label.new() 67 | lbl_sensitivity.set_text("Sensitivity") 68 | 69 | var sensitivity = HScrollBar.new() 70 | sensitivity.set_max(1) 71 | sensitivity.set_value(camera.sensitivity) 72 | sensitivity.connect("value_changed",self,"_on_hsb_sensitivity_value_changed") 73 | 74 | var lbl_smoothless = Label.new() 75 | lbl_smoothless.set_text("Smoothness") 76 | 77 | var smoothness = HScrollBar.new() 78 | smoothness.set_max(0.999) 79 | smoothness.set_min(0.5) 80 | smoothness.set_value(camera.smoothness) 81 | smoothness.connect("value_changed",self,"_on_hsb_smoothness_value_changed") 82 | 83 | var lbl_privot = Label.new() 84 | lbl_privot.set_text("Privot") 85 | 86 | privot = OptionButton.new() 87 | privot.set_text("Privot") 88 | _update_privots(privot) 89 | privot.connect("item_selected",self,"_on_opt_privot_item_selected") 90 | privot.connect("pressed",self,"_on_opt_privot_pressed") 91 | 92 | var btn_rot_privot = CheckButton.new() 93 | btn_rot_privot.set_text("Rotate Privot") 94 | btn_rot_privot.set_toggle_mode(true) 95 | btn_rot_privot.set_pressed(camera.rotate_privot) 96 | btn_rot_privot.connect("toggled",self,"_on_btn_rot_privot_toggled") 97 | 98 | var lbl_distance = Label.new() 99 | lbl_distance.set_text("Distance") 100 | 101 | var distance = SpinBox.new() 102 | distance.set_value(camera.distance) 103 | distance.connect("value_changed",self,"_on_box_distance_value_changed") 104 | 105 | var lbl_yaw = Label.new() 106 | lbl_yaw.set_text("Yaw Limit") 107 | 108 | var yaw = SpinBox.new() 109 | yaw.set_max(360) 110 | yaw.set_value(camera.yaw_limit) 111 | yaw.connect("value_changed",self,"_on_box_yaw_value_changed") 112 | 113 | var lbl_pitch = Label.new() 114 | lbl_pitch.set_text("Pitch Limit") 115 | 116 | var pitch = SpinBox.new() 117 | pitch.set_max(360) 118 | pitch.set_value(camera.pitch_limit) 119 | pitch.connect("value_changed",self,"_on_box_pitch_value_changed") 120 | 121 | var collisions = CheckButton.new() 122 | collisions.set_text("Collisions") 123 | collisions.set_toggle_mode(true) 124 | collisions.set_pressed(camera.collisions) 125 | collisions.connect("toggled",self,"_on_btn_collisions_toggled") 126 | 127 | # Movement 128 | var lbl_movement = Label.new() 129 | lbl_movement.set_text("Movement") 130 | 131 | var movement = CheckButton.new() 132 | movement.set_pressed(camera.movement) 133 | movement.connect("toggled",self,"_on_btn_movement_toggled") 134 | 135 | var lbl_speed = Label.new() 136 | lbl_speed.set_text("Max Speed") 137 | 138 | var speed = HScrollBar.new() 139 | speed.set_max(MAX_SPEED) 140 | speed.set_value(camera.max_speed.x) 141 | speed.connect("value_changed",self,"_on_hsb_speed_value_changed") 142 | 143 | var lbl_acceleration = Label.new() 144 | lbl_acceleration.set_text("Acceleration") 145 | 146 | var acceleration = HScrollBar.new() 147 | acceleration.set_max(1.0) 148 | acceleration.set_value(camera.acceleration) 149 | acceleration.connect("value_changed", self, "_in_hsb_acceleration_value_changed") 150 | 151 | var lbl_deceleration = Label.new() 152 | lbl_deceleration.set_text("Deceleration") 153 | 154 | var deceleration = HScrollBar.new() 155 | deceleration.set_max(1.0) 156 | deceleration.set_value(camera.deceleration) 157 | deceleration.connect("value_changed", self, "_in_hsb_deceleration_value_changed") 158 | 159 | add_child(panel) 160 | panel.add_child(container) 161 | container.add_child(lbl_mouse) 162 | container.add_child(mouse) 163 | container.add_child(mouselook) 164 | container.add_child(lbl_sensitivity) 165 | container.add_child(sensitivity) 166 | container.add_child(lbl_smoothless) 167 | container.add_child(smoothness) 168 | container.add_child(lbl_privot) 169 | container.add_child(privot) 170 | container.add_child(btn_rot_privot) 171 | container.add_child(lbl_distance) 172 | container.add_child(distance) 173 | container.add_child(lbl_yaw) 174 | container.add_child(yaw) 175 | container.add_child(lbl_pitch) 176 | container.add_child(pitch) 177 | container.add_child(collisions) 178 | container.add_child(lbl_movement) 179 | container.add_child(movement) 180 | container.add_child(lbl_speed) 181 | container.add_child(speed) 182 | container.add_child(lbl_acceleration) 183 | container.add_child(acceleration) 184 | container.add_child(lbl_deceleration) 185 | container.add_child(deceleration) 186 | 187 | if DRAGGABLE: 188 | panel.connect("mouse_entered", self, "_panel_entered") 189 | panel.connect("mouse_exited", self, "_panel_exited") 190 | container.connect("mouse_entered", self, "_panel_entered") 191 | container.connect("mouse_exited", self, "_panel_exited") 192 | 193 | self.hide() 194 | else: 195 | set_process_input(false) 196 | 197 | func _input(event): 198 | if event.is_action_pressed(shortcut): 199 | if camera.enabled: 200 | camera.enabled = false 201 | Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE) 202 | self.show() 203 | else: 204 | camera.enabled = true 205 | self.hide() 206 | 207 | if DRAGGABLE: 208 | if event is InputEventMouseButton and event.button_index == BUTTON_LEFT: 209 | mouse_pressed = event.pressed 210 | 211 | elif event is InputEventMouseMotion and mouse_over and mouse_pressed: 212 | panel.set_begin(panel.get_begin() + event.relative) 213 | 214 | func _update_privots(privot): 215 | privot.clear() 216 | privot.add_item("None") 217 | node_list = _get_spatials_recusiv(get_tree().get_root(), [get_name(), camera.get_name()]) 218 | 219 | var size = node_list.size() 220 | for i in range(0, size): 221 | var node = node_list[i] 222 | privot.add_item(node.get_name()) 223 | if node == camera.privot: 224 | privot.select(i+1) 225 | 226 | if not camera.privot: 227 | privot.select(0) 228 | 229 | 230 | func _get_spatials_recusiv(node, exceptions=[]): 231 | var list = [] 232 | for child in node.get_children(): 233 | if not child.get_name() in exceptions: 234 | if child is Spatial: 235 | list.append(child) 236 | if not child.get_children().empty(): 237 | for subchild in _get_spatials_recusiv(child, exceptions): 238 | list.append(subchild) 239 | return list 240 | 241 | func _panel_entered(): 242 | mouse_over = true 243 | 244 | func _panel_exited(): 245 | mouse_over = false 246 | 247 | func _on_opt_mouse_item_selected(id): 248 | camera.mouse_mode = id 249 | 250 | func _on_btn_mouselook_toggled(pressed): 251 | camera.mouselook = pressed 252 | 253 | func _on_hsb_sensitivity_value_changed(value): 254 | camera.sensitivity = value 255 | 256 | func _on_hsb_smoothness_value_changed(value): 257 | camera.smoothness = value 258 | 259 | func _on_opt_privot_pressed(): 260 | _update_privots(privot) 261 | 262 | func _on_opt_privot_item_selected(id): 263 | if id > 0: 264 | camera.privot = node_list[id-1] 265 | else: 266 | camera.privot = null 267 | privot.select(id) 268 | 269 | func _on_btn_rot_privot_toggled(pressed): 270 | camera.rotate_privot = pressed 271 | 272 | func _on_box_distance_value_changed(value): 273 | camera.distance = value 274 | 275 | func _on_box_yaw_value_changed(value): 276 | camera.yaw_limit = value 277 | 278 | func _on_box_pitch_value_changed(value): 279 | camera.pitch_limit = value 280 | 281 | func _on_btn_collisions_toggled(pressed): 282 | camera.collisions = pressed 283 | 284 | func _on_btn_movement_toggled(pressed): 285 | camera.movement = pressed 286 | 287 | func _on_hsb_speed_value_changed(value): 288 | camera.max_speed.x = value 289 | camera.max_speed.y = value 290 | camera.max_speed.z = value 291 | 292 | func _in_hsb_acceleration_value_changed(value): 293 | camera.acceleration = value 294 | 295 | func _in_hsb_deceleration_value_changed(value): 296 | camera.deceleration = value 297 | -------------------------------------------------------------------------------- /assets/models/BallBoyMat.material: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/BallBoyMat.material -------------------------------------------------------------------------------- /assets/models/Cottage2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/Cottage2.bin -------------------------------------------------------------------------------- /assets/models/Cottage2.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "generator" : "Khronos glTF Blender I/O v1.3.48", 4 | "version" : "2.0" 5 | }, 6 | "scene" : 0, 7 | "scenes" : [ 8 | { 9 | "name" : "Scene", 10 | "nodes" : [ 11 | 0, 12 | 1 13 | ] 14 | } 15 | ], 16 | "nodes" : [ 17 | { 18 | "mesh" : 0, 19 | "name" : "Cottage Combined" 20 | }, 21 | { 22 | "mesh" : 1, 23 | "name" : "Cottage Fur Roof" 24 | } 25 | ], 26 | "materials" : [ 27 | { 28 | "emissiveFactor" : [ 29 | 0, 30 | 0, 31 | 0 32 | ], 33 | "name" : "Cottage Mat", 34 | "normalTexture" : { 35 | "index" : 0, 36 | "texCoord" : 0 37 | }, 38 | "pbrMetallicRoughness" : { 39 | "baseColorTexture" : { 40 | "index" : 1, 41 | "texCoord" : 0 42 | }, 43 | "metallicFactor" : 0, 44 | "metallicRoughnessTexture" : { 45 | "index" : 2, 46 | "texCoord" : 0 47 | } 48 | } 49 | } 50 | ], 51 | "meshes" : [ 52 | { 53 | "name" : "Cube.170", 54 | "primitives" : [ 55 | { 56 | "attributes" : { 57 | "POSITION" : 0, 58 | "NORMAL" : 1, 59 | "TEXCOORD_0" : 2 60 | }, 61 | "indices" : 3, 62 | "material" : 0 63 | } 64 | ] 65 | }, 66 | { 67 | "extras" : { 68 | "targetNames" : [ 69 | "Key 1" 70 | ] 71 | }, 72 | "name" : "Cube.031", 73 | "primitives" : [ 74 | { 75 | "attributes" : { 76 | "POSITION" : 4, 77 | "NORMAL" : 5, 78 | "TEXCOORD_0" : 6 79 | }, 80 | "indices" : 7, 81 | "material" : 0, 82 | "targets" : [ 83 | { 84 | "POSITION" : 8, 85 | "NORMAL" : 9 86 | } 87 | ] 88 | } 89 | ], 90 | "weights" : [ 91 | 0 92 | ] 93 | } 94 | ], 95 | "textures" : [ 96 | { 97 | "source" : 0 98 | }, 99 | { 100 | "source" : 1 101 | }, 102 | { 103 | "source" : 2 104 | } 105 | ], 106 | "images" : [ 107 | { 108 | "mimeType" : "image/png", 109 | "name" : "Cottage_Nor", 110 | "uri" : "Cottage_Nor.png" 111 | }, 112 | { 113 | "mimeType" : "image/png", 114 | "name" : "Cottage_Alb", 115 | "uri" : "Cottage_Alb.png" 116 | }, 117 | { 118 | "mimeType" : "image/png", 119 | "name" : "Cottage_Rough", 120 | "uri" : "Cottage_Rough.png" 121 | } 122 | ], 123 | "accessors" : [ 124 | { 125 | "bufferView" : 0, 126 | "componentType" : 5126, 127 | "count" : 7303, 128 | "max" : [ 129 | 4.543636798858643, 130 | 7.356256484985352, 131 | 1.8922041654586792 132 | ], 133 | "min" : [ 134 | -4.543636798858643, 135 | -4.656612873077393e-10, 136 | -3.298825979232788 137 | ], 138 | "type" : "VEC3" 139 | }, 140 | { 141 | "bufferView" : 1, 142 | "componentType" : 5126, 143 | "count" : 7303, 144 | "type" : "VEC3" 145 | }, 146 | { 147 | "bufferView" : 2, 148 | "componentType" : 5126, 149 | "count" : 7303, 150 | "type" : "VEC2" 151 | }, 152 | { 153 | "bufferView" : 3, 154 | "componentType" : 5123, 155 | "count" : 23622, 156 | "type" : "SCALAR" 157 | }, 158 | { 159 | "bufferView" : 4, 160 | "componentType" : 5126, 161 | "count" : 936, 162 | "max" : [ 163 | 4.1763410568237305, 164 | 6.30999755859375, 165 | 1.8922041654586792 166 | ], 167 | "min" : [ 168 | -4.1763410568237305, 169 | 2.6562535762786865, 170 | -1.8922041654586792 171 | ], 172 | "type" : "VEC3" 173 | }, 174 | { 175 | "bufferView" : 5, 176 | "componentType" : 5126, 177 | "count" : 936, 178 | "type" : "VEC3" 179 | }, 180 | { 181 | "bufferView" : 6, 182 | "componentType" : 5126, 183 | "count" : 936, 184 | "type" : "VEC2" 185 | }, 186 | { 187 | "bufferView" : 7, 188 | "componentType" : 5123, 189 | "count" : 2904, 190 | "type" : "SCALAR" 191 | }, 192 | { 193 | "bufferView" : 8, 194 | "componentType" : 5126, 195 | "count" : 936, 196 | "max" : [ 197 | 0.11801290512084961, 198 | 0.2785172462463379, 199 | 0.3954068422317505 200 | ], 201 | "min" : [ 202 | -0.11801290512084961, 203 | -0.3091726303100586, 204 | -0.3954068422317505 205 | ], 206 | "type" : "VEC3" 207 | }, 208 | { 209 | "bufferView" : 9, 210 | "componentType" : 5126, 211 | "count" : 936, 212 | "type" : "VEC3" 213 | } 214 | ], 215 | "bufferViews" : [ 216 | { 217 | "buffer" : 0, 218 | "byteLength" : 87636, 219 | "byteOffset" : 0 220 | }, 221 | { 222 | "buffer" : 0, 223 | "byteLength" : 87636, 224 | "byteOffset" : 87636 225 | }, 226 | { 227 | "buffer" : 0, 228 | "byteLength" : 58424, 229 | "byteOffset" : 175272 230 | }, 231 | { 232 | "buffer" : 0, 233 | "byteLength" : 47244, 234 | "byteOffset" : 233696 235 | }, 236 | { 237 | "buffer" : 0, 238 | "byteLength" : 11232, 239 | "byteOffset" : 280940 240 | }, 241 | { 242 | "buffer" : 0, 243 | "byteLength" : 11232, 244 | "byteOffset" : 292172 245 | }, 246 | { 247 | "buffer" : 0, 248 | "byteLength" : 7488, 249 | "byteOffset" : 303404 250 | }, 251 | { 252 | "buffer" : 0, 253 | "byteLength" : 5808, 254 | "byteOffset" : 310892 255 | }, 256 | { 257 | "buffer" : 0, 258 | "byteLength" : 11232, 259 | "byteOffset" : 316700 260 | }, 261 | { 262 | "buffer" : 0, 263 | "byteLength" : 11232, 264 | "byteOffset" : 327932 265 | } 266 | ], 267 | "buffers" : [ 268 | { 269 | "byteLength" : 339164, 270 | "uri" : "Cottage2.bin" 271 | } 272 | ] 273 | } 274 | -------------------------------------------------------------------------------- /assets/models/CottageMat.material: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/CottageMat.material -------------------------------------------------------------------------------- /assets/models/Log.material: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/Log.material -------------------------------------------------------------------------------- /assets/models/Rat-animated2.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/Rat-animated2.bin -------------------------------------------------------------------------------- /assets/models/Rat2.material: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/Rat2.material -------------------------------------------------------------------------------- /assets/models/Rat3.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "generator" : "Khronos glTF Blender I/O v1.3.48", 4 | "version" : "2.0" 5 | }, 6 | "scene" : 0, 7 | "scenes" : [ 8 | { 9 | "name" : "Scene" 10 | } 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /assets/models/ball_boy.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/ball_boy.bin -------------------------------------------------------------------------------- /assets/models/mossy_log.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/models/mossy_log.bin -------------------------------------------------------------------------------- /assets/models/mossy_log.gltf: -------------------------------------------------------------------------------- 1 | { 2 | "asset" : { 3 | "generator" : "Khronos glTF Blender I/O v1.3.48", 4 | "version" : "2.0" 5 | }, 6 | "scene" : 0, 7 | "scenes" : [ 8 | { 9 | "name" : "Scene", 10 | "nodes" : [ 11 | 0 12 | ] 13 | } 14 | ], 15 | "nodes" : [ 16 | { 17 | "mesh" : 0, 18 | "name" : "Log" 19 | } 20 | ], 21 | "materials" : [ 22 | { 23 | "doubleSided" : true, 24 | "emissiveFactor" : [ 25 | 0, 26 | 0, 27 | 0 28 | ], 29 | "name" : "Log", 30 | "normalTexture" : { 31 | "index" : 0, 32 | "texCoord" : 0 33 | }, 34 | "pbrMetallicRoughness" : { 35 | "baseColorTexture" : { 36 | "index" : 1, 37 | "texCoord" : 0 38 | }, 39 | "metallicFactor" : 0, 40 | "metallicRoughnessTexture" : { 41 | "index" : 2, 42 | "texCoord" : 0 43 | } 44 | } 45 | } 46 | ], 47 | "meshes" : [ 48 | { 49 | "name" : "LogMesh", 50 | "primitives" : [ 51 | { 52 | "attributes" : { 53 | "POSITION" : 0, 54 | "NORMAL" : 1, 55 | "TEXCOORD_0" : 2 56 | }, 57 | "indices" : 3, 58 | "material" : 0 59 | } 60 | ] 61 | } 62 | ], 63 | "textures" : [ 64 | { 65 | "source" : 0 66 | }, 67 | { 68 | "source" : 1 69 | }, 70 | { 71 | "source" : 2 72 | } 73 | ], 74 | "images" : [ 75 | { 76 | "mimeType" : "image/png", 77 | "name" : "Log_Normal", 78 | "uri" : "Log_Normal.png" 79 | }, 80 | { 81 | "mimeType" : "image/png", 82 | "name" : "Log_Albedo", 83 | "uri" : "Log_Albedo.png" 84 | }, 85 | { 86 | "mimeType" : "image/png", 87 | "name" : "Log_AORoughMetal", 88 | "uri" : "Log_AORoughMetal.png" 89 | } 90 | ], 91 | "accessors" : [ 92 | { 93 | "bufferView" : 0, 94 | "componentType" : 5126, 95 | "count" : 525, 96 | "max" : [ 97 | 2.42887544631958, 98 | 0.696457028388977, 99 | 0.4063585698604584 100 | ], 101 | "min" : [ 102 | -2.3681511878967285, 103 | -0.1621810793876648, 104 | -0.3969557285308838 105 | ], 106 | "type" : "VEC3" 107 | }, 108 | { 109 | "bufferView" : 1, 110 | "componentType" : 5126, 111 | "count" : 525, 112 | "type" : "VEC3" 113 | }, 114 | { 115 | "bufferView" : 2, 116 | "componentType" : 5126, 117 | "count" : 525, 118 | "type" : "VEC2" 119 | }, 120 | { 121 | "bufferView" : 3, 122 | "componentType" : 5123, 123 | "count" : 2688, 124 | "type" : "SCALAR" 125 | } 126 | ], 127 | "bufferViews" : [ 128 | { 129 | "buffer" : 0, 130 | "byteLength" : 6300, 131 | "byteOffset" : 0 132 | }, 133 | { 134 | "buffer" : 0, 135 | "byteLength" : 6300, 136 | "byteOffset" : 6300 137 | }, 138 | { 139 | "buffer" : 0, 140 | "byteLength" : 4200, 141 | "byteOffset" : 12600 142 | }, 143 | { 144 | "buffer" : 0, 145 | "byteLength" : 5376, 146 | "byteOffset" : 16800 147 | } 148 | ], 149 | "buffers" : [ 150 | { 151 | "byteLength" : 22176, 152 | "uri" : "mossy_log.bin" 153 | } 154 | ] 155 | } 156 | -------------------------------------------------------------------------------- /assets/models/mossy_log.obj: -------------------------------------------------------------------------------- 1 | # Blender v2.90.1 OBJ File: 'mossy_log.blend' 2 | # www.blender.org 3 | o Moss_MossMesh 4 | v -2.000000 0.272192 -0.353911 5 | v 2.000000 0.272192 -0.353911 6 | v -1.905005 0.206629 -0.329610 7 | v 2.021631 0.202355 -0.351096 8 | v -2.044343 0.201523 0.355280 9 | v 1.835134 0.209190 0.316737 10 | v -2.000000 0.272192 0.353911 11 | v 2.000000 0.272193 0.353911 12 | v -1.979876 0.340499 0.343403 13 | v 2.158835 0.347058 0.376373 14 | v -1.693179 0.385573 0.273724 15 | v 2.102109 0.414968 0.344692 16 | v -1.516940 0.420613 0.245538 17 | v 1.964546 0.465115 0.288729 18 | v -1.582505 0.495888 0.255529 19 | v 2.061089 0.530559 0.258366 20 | v -2.025274 0.570406 0.199260 21 | v 2.045061 0.573497 0.201325 22 | v -2.063095 0.610113 0.139971 23 | v 2.011652 0.601186 0.136273 24 | v -2.101341 0.637973 0.072758 25 | v 1.982366 0.616054 0.068398 26 | v -1.999999 0.626103 -0.000000 27 | v 2.000001 0.626104 -0.000000 28 | v -1.864530 0.594345 -0.064080 29 | v 2.118620 0.641157 -0.073392 30 | v -1.910214 0.583581 -0.128982 31 | v 2.111963 0.618594 -0.143484 32 | v -2.035530 0.572007 -0.200330 33 | v 2.112993 0.584106 -0.208414 34 | v -2.145309 0.541744 -0.269554 35 | v 2.113312 0.537495 -0.265304 36 | v -2.170698 0.486627 -0.320927 37 | v 2.002818 0.469108 -0.294707 38 | v -2.209101 0.422658 -0.363260 39 | v 1.904915 0.400793 -0.310470 40 | v -2.038534 0.342648 -0.354210 41 | v 1.932881 0.338777 -0.334745 42 | v -1.500000 0.272192 -0.359357 43 | v -1.000000 0.272192 -0.359976 44 | v -0.500000 0.272192 -0.396714 45 | v 0.000000 0.272192 -0.353911 46 | v 0.500000 0.272192 -0.316563 47 | v 1.000000 0.272192 -0.336390 48 | v 1.500000 0.272192 -0.327911 49 | v 1.500000 0.202400 -0.350869 50 | v 1.000000 0.196687 -0.379593 51 | v 0.500000 0.200464 -0.360605 52 | v 0.000000 0.200139 -0.362238 53 | v -0.500000 0.193233 -0.396956 54 | v -1.000000 0.201728 -0.354247 55 | v -1.500000 0.205627 -0.334646 56 | v 1.422479 0.210576 0.309765 57 | v 1.000000 0.206798 0.328760 58 | v 0.500000 0.199472 0.365591 59 | v 0.000000 0.191363 0.406359 60 | v -0.500000 0.195291 0.386612 61 | v -1.000000 0.201798 0.353895 62 | v -1.402277 0.203880 0.343427 63 | v 1.448859 0.272192 0.333481 64 | v 1.000000 0.272192 0.312727 65 | v 0.500000 0.272192 0.325551 66 | v -0.000000 0.272192 0.353911 67 | v -0.500000 0.272192 0.340190 68 | v -1.000000 0.272192 0.344887 69 | v -1.333044 0.272192 0.341136 70 | v 1.500000 0.341176 0.346802 71 | v 1.000000 0.331440 0.297856 72 | v 0.500000 0.334755 0.314522 73 | v -0.000000 0.332404 0.302703 74 | v -0.500000 0.331090 0.296096 75 | v -1.000000 0.335309 0.317307 76 | v -1.287179 0.336283 0.322203 77 | v 1.500000 0.390281 0.285090 78 | v 1.000000 0.398792 0.305639 79 | v 0.500000 0.402983 0.315755 80 | v -0.000000 0.390697 0.286096 81 | v -0.500000 0.395525 0.297752 82 | v -1.000000 0.395435 0.297533 83 | v -1.249201 0.385680 0.273984 84 | v 1.500000 0.439749 0.250766 85 | v 1.000000 0.447569 0.262470 86 | v 0.500000 0.470286 0.296468 87 | v -0.000000 0.463166 0.285812 88 | v -0.500000 0.455590 0.274473 89 | v -1.000000 0.446542 0.260932 90 | v -1.281586 0.426926 0.231576 91 | v 1.500000 0.509390 0.237198 92 | v 1.000000 0.500000 0.227808 93 | v 0.500000 0.535075 0.262882 94 | v -0.000000 0.531343 0.259150 95 | v -0.500000 0.546461 0.274268 96 | v -1.000000 0.537205 0.265013 97 | v -1.306786 0.496919 0.224727 98 | v 1.500000 0.586097 0.209744 99 | v 1.000000 0.584346 0.208574 100 | v 0.500000 0.597805 0.217567 101 | v -0.000000 0.612117 0.227130 102 | v -0.500000 0.625316 0.235950 103 | v -1.000000 0.591269 0.213200 104 | v -1.356672 0.553983 0.188286 105 | v 1.500000 0.617700 0.143114 106 | v 1.000000 0.637893 0.151478 107 | v 0.500000 0.673322 0.166153 108 | v -0.000000 0.674935 0.166821 109 | v -0.500000 0.626086 0.146587 110 | v -1.000000 0.603015 0.137031 111 | v -1.412890 0.576405 0.126009 112 | v 1.500000 0.616390 0.068465 113 | v 1.000000 0.640104 0.073182 114 | v 0.500000 0.696457 0.084390 115 | v -0.000000 0.686454 0.082400 116 | v -0.500000 0.630337 0.071239 117 | v -1.000000 0.600260 0.065257 118 | v -1.465296 0.595480 0.064306 119 | v 1.500000 0.588152 -0.000000 120 | v 1.000000 0.609636 -0.000000 121 | v 0.500000 0.647238 -0.000000 122 | v -0.000000 0.626103 -0.000000 123 | v -0.500000 0.574611 -0.000000 124 | v -1.000000 0.573869 -0.000000 125 | v -1.500000 0.569613 -0.000000 126 | v 1.500000 0.602720 -0.065747 127 | v 1.000000 0.590666 -0.063349 128 | v 0.500000 0.615847 -0.068358 129 | v -0.000000 0.581136 -0.061454 130 | v -0.500000 0.517603 -0.048817 131 | v -1.000000 0.524130 -0.050115 132 | v -1.500000 0.531215 -0.051524 133 | v 1.500000 0.588309 -0.130940 134 | v 1.000000 0.548114 -0.114291 135 | v 0.500000 0.589709 -0.131520 136 | v -0.000000 0.572029 -0.124197 137 | v -0.500000 0.517750 -0.101714 138 | v -1.000000 0.519544 -0.102457 139 | v -1.500000 0.550140 -0.115130 140 | v 1.500000 0.575662 -0.202773 141 | v 1.000000 0.561040 -0.193002 142 | v 0.500000 0.591027 -0.213039 143 | v -0.000000 0.570772 -0.199505 144 | v -0.500000 0.507488 -0.157220 145 | v -1.000000 0.509131 -0.158317 146 | v -1.500000 0.538069 -0.177653 147 | v 1.500000 0.533675 -0.261484 148 | v 1.000000 0.526173 -0.253982 149 | v 0.500000 0.542534 -0.270342 150 | v -0.000000 0.538199 -0.266007 151 | v -0.500000 0.497314 -0.225123 152 | v -1.000000 0.480153 -0.207962 153 | v -1.500000 0.492298 -0.220106 154 | v 1.500000 0.454879 -0.273411 155 | v 1.000000 0.469474 -0.295254 156 | v 0.500000 0.469860 -0.295831 157 | v -0.000000 0.477716 -0.307589 158 | v -0.500000 0.457473 -0.277293 159 | v -1.000000 0.450352 -0.266637 160 | v -1.500000 0.455334 -0.274092 161 | v 1.500000 0.396678 -0.300536 162 | v 1.000000 0.411770 -0.336971 163 | v 0.500000 0.409471 -0.331422 164 | v -0.000000 0.410862 -0.334780 165 | v -0.500000 0.407926 -0.327691 166 | v -1.000000 0.411456 -0.336215 167 | v -1.500000 0.411705 -0.336815 168 | v 1.500000 0.333542 -0.308423 169 | v 1.000000 0.334133 -0.311399 170 | v 0.500000 0.334453 -0.313005 171 | v -0.000000 0.335018 -0.315847 172 | v -0.500000 0.345682 -0.369463 173 | v -1.000000 0.344735 -0.364699 174 | v -1.500000 0.345260 -0.367343 175 | v 1.973086 0.272192 -0.352511 176 | v 1.993552 0.202358 -0.351084 177 | v 1.812922 0.209264 0.316362 178 | v 1.970333 0.272193 0.352811 179 | v 2.123371 0.346741 0.374781 180 | v 2.069699 0.413639 0.341483 181 | v 1.939540 0.463750 0.286685 182 | v 2.030886 0.529420 0.257227 183 | v 2.015721 0.574175 0.201778 184 | v 1.984110 0.602075 0.136641 185 | v 1.956401 0.616072 0.068402 186 | v 1.973087 0.624061 -0.000000 187 | v 2.085321 0.639088 -0.072980 188 | v 2.079022 0.616964 -0.142809 189 | v 2.079997 0.583652 -0.208111 190 | v 2.080298 0.537289 -0.265098 191 | v 1.975752 0.468343 -0.293560 192 | v 1.883119 0.400571 -0.309935 193 | v 1.909580 0.338495 -0.333328 194 | v -1.885044 0.206579 -0.329858 195 | v -2.012697 0.201639 0.354696 196 | v -1.967128 0.272192 0.353281 197 | v -1.945735 0.340292 0.342358 198 | v -1.671296 0.385578 0.273736 199 | v -1.505340 0.420924 0.244850 200 | v -1.568915 0.495939 0.254010 201 | v -1.992321 0.569597 0.198719 202 | v -2.031049 0.608452 0.139283 203 | v -2.069993 0.635879 0.072342 204 | v -1.975356 0.623319 -0.000000 205 | v -1.846564 0.591233 -0.063462 206 | v -1.889996 0.581933 -0.128299 207 | v -2.009135 0.570335 -0.199213 208 | v -2.113503 0.539307 -0.267117 209 | v -2.137641 0.485085 -0.318619 210 | v -2.174151 0.422118 -0.361956 211 | v -2.011992 0.342777 -0.354857 212 | v -1.975357 0.272192 -0.354179 213 | vt 0.911125 0.189576 214 | vt 0.911031 0.180805 215 | vt 0.933607 0.173500 216 | vt 0.933723 0.182605 217 | vt 0.515896 0.243890 218 | vt 0.515753 0.236591 219 | vt 0.538480 0.181729 220 | vt 0.538540 0.191552 221 | vt 0.563777 0.128544 222 | vt 0.563633 0.140391 223 | vt 0.588297 0.148171 224 | vt 0.588088 0.159027 225 | vt 0.610998 0.195398 226 | vt 0.610810 0.203676 227 | vt 0.634420 0.164103 228 | vt 0.634241 0.173935 229 | vt 0.657507 0.169880 230 | vt 0.657363 0.179486 231 | vt 0.680651 0.180954 232 | vt 0.680651 0.189948 233 | vt 0.703297 0.190343 234 | vt 0.703504 0.198833 235 | vt 0.725538 0.183651 236 | vt 0.725841 0.192454 237 | vt 0.748038 0.143815 238 | vt 0.748335 0.154679 239 | vt 0.772041 0.145510 240 | vt 0.772231 0.156265 241 | vt 0.796000 0.144791 242 | vt 0.796165 0.155565 243 | vt 0.820019 0.144318 244 | vt 0.820124 0.155122 245 | vt 0.844616 0.180582 246 | vt 0.844739 0.189495 247 | vt 0.867683 0.212736 248 | vt 0.867802 0.219856 249 | vt 0.889040 0.203143 250 | vt 0.889158 0.210716 251 | vt 0.446329 0.762337 252 | vt 0.435905 0.598182 253 | vt 0.459602 0.597249 254 | vt 0.468177 0.749199 255 | vt 0.432484 0.435535 256 | vt 0.456091 0.435465 257 | vt 0.434690 0.271967 258 | vt 0.460211 0.272785 259 | vt 0.442094 0.108395 260 | vt 0.465676 0.110332 261 | vt 0.908623 0.833059 262 | vt 0.904627 0.670935 263 | vt 0.924748 0.670310 264 | vt 0.932653 0.832847 265 | vt 0.898716 0.508443 266 | vt 0.920574 0.507480 267 | vt 0.891051 0.344472 268 | vt 0.912116 0.343775 269 | vt 0.424990 0.815466 270 | vt 0.412194 0.599257 271 | vt 0.408871 0.435683 272 | vt 0.410153 0.271370 273 | vt 0.416918 0.108392 274 | vt 0.883217 0.833729 275 | vt 0.879719 0.671753 276 | vt 0.872180 0.509741 277 | vt 0.870146 0.344968 278 | vt 0.400147 0.805122 279 | vt 0.387337 0.599929 280 | vt 0.382701 0.435690 281 | vt 0.386965 0.270830 282 | vt 0.393639 0.107394 283 | vt 0.859714 0.834248 284 | vt 0.857204 0.672474 285 | vt 0.849006 0.510285 286 | vt 0.849018 0.345277 287 | vt 0.375939 0.798551 288 | vt 0.366049 0.600524 289 | vt 0.361022 0.435764 290 | vt 0.365425 0.270498 291 | vt 0.369917 0.106420 292 | vt 0.835813 0.834585 293 | vt 0.832595 0.673393 294 | vt 0.825972 0.510910 295 | vt 0.822774 0.345592 296 | vt 0.351405 0.765642 297 | vt 0.345745 0.601507 298 | vt 0.341975 0.435904 299 | vt 0.342964 0.271020 300 | vt 0.346060 0.106620 301 | vt 0.811452 0.835239 302 | vt 0.808717 0.674093 303 | vt 0.802677 0.511555 304 | vt 0.798964 0.345972 305 | vt 0.328181 0.727694 306 | vt 0.324934 0.601641 307 | vt 0.323163 0.435783 308 | vt 0.324575 0.271313 309 | vt 0.321723 0.108130 310 | vt 0.787164 0.836267 311 | vt 0.782740 0.674649 312 | vt 0.776612 0.512116 313 | vt 0.774976 0.346638 314 | vt 0.307134 0.714154 315 | vt 0.303306 0.600923 316 | vt 0.305593 0.435512 317 | vt 0.307416 0.271737 318 | vt 0.301261 0.109065 319 | vt 0.766677 0.837041 320 | vt 0.760952 0.675363 321 | vt 0.754901 0.512683 322 | vt 0.753000 0.347099 323 | vt 0.287863 0.755716 324 | vt 0.282222 0.602253 325 | vt 0.281928 0.435268 326 | vt 0.283212 0.271180 327 | vt 0.276637 0.108580 328 | vt 0.741926 0.837198 329 | vt 0.736919 0.676163 330 | vt 0.732991 0.513336 331 | vt 0.730874 0.347884 332 | vt 0.266827 0.785923 333 | vt 0.258738 0.591916 334 | vt 0.258659 0.434989 335 | vt 0.254094 0.270627 336 | vt 0.243619 0.107932 337 | vt 0.708834 0.837400 338 | vt 0.705908 0.677188 339 | vt 0.706803 0.514425 340 | vt 0.706502 0.348503 341 | vt 0.243920 0.774315 342 | vt 0.236868 0.575155 343 | vt 0.234911 0.434809 344 | vt 0.229757 0.271441 345 | vt 0.216197 0.109497 346 | vt 0.680972 0.837867 347 | vt 0.679123 0.677753 348 | vt 0.680611 0.514669 349 | vt 0.681993 0.348840 350 | vt 0.221005 0.762611 351 | vt 0.214187 0.557187 352 | vt 0.209745 0.434620 353 | vt 0.201171 0.272983 354 | vt 0.188342 0.113011 355 | vt 0.652494 0.838074 356 | vt 0.650119 0.676990 357 | vt 0.654608 0.514115 358 | vt 0.657807 0.348638 359 | vt 0.188411 0.637535 360 | vt 0.188390 0.540785 361 | vt 0.185510 0.435877 362 | vt 0.173375 0.275195 363 | vt 0.160135 0.114820 364 | vt 0.624264 0.837916 365 | vt 0.625458 0.676512 366 | vt 0.626030 0.513060 367 | vt 0.631160 0.348178 368 | vt 0.160598 0.611100 369 | vt 0.163030 0.533895 370 | vt 0.156095 0.439379 371 | vt 0.144154 0.277314 372 | vt 0.136497 0.116101 373 | vt 0.600346 0.837848 374 | vt 0.602001 0.676060 375 | vt 0.605164 0.512685 376 | vt 0.607880 0.348166 377 | vt 0.146725 0.666895 378 | vt 0.142583 0.523938 379 | vt 0.135563 0.440744 380 | vt 0.123567 0.278764 381 | vt 0.113119 0.117591 382 | vt 0.576714 0.838049 383 | vt 0.579449 0.675533 384 | vt 0.583690 0.512344 385 | vt 0.588220 0.347737 386 | vt 0.122431 0.757007 387 | vt 0.119825 0.538044 388 | vt 0.114887 0.442375 389 | vt 0.102891 0.279984 390 | vt 0.093422 0.118719 391 | vt 0.557000 0.837977 392 | vt 0.557297 0.675258 393 | vt 0.561392 0.511460 394 | vt 0.562497 0.346102 395 | vt 0.099832 0.764182 396 | vt 0.097928 0.554204 397 | vt 0.092361 0.443885 398 | vt 0.079217 0.281678 399 | vt 0.067892 0.120053 400 | vt 0.531283 0.838074 401 | vt 0.536656 0.674908 402 | vt 0.541262 0.511065 403 | vt 0.539764 0.363320 404 | vt 0.076701 0.779324 405 | vt 0.075859 0.577827 406 | vt 0.069259 0.445350 407 | vt 0.050142 0.283556 408 | vt 0.036679 0.121770 409 | vt 0.499854 0.838025 410 | vt 0.509566 0.674658 411 | vt 0.519182 0.511046 412 | vt 0.518352 0.372510 413 | vt 0.482433 0.596482 414 | vt 0.488953 0.719181 415 | vt 0.479015 0.435567 416 | vt 0.485762 0.273554 417 | vt 0.489309 0.111375 418 | vt 0.952070 0.669561 419 | vt 0.956256 0.832264 420 | vt 0.948981 0.506264 421 | vt 0.936062 0.342951 422 | vt 0.468642 0.757053 423 | vt 0.489309 0.725546 424 | vt 0.076733 0.789741 425 | vt 0.099894 0.774986 426 | vt 0.122497 0.768188 427 | vt 0.146903 0.674078 428 | vt 0.160430 0.615638 429 | vt 0.188037 0.643463 430 | vt 0.221530 0.773191 431 | vt 0.244250 0.784362 432 | vt 0.267122 0.795624 433 | vt 0.288113 0.763373 434 | vt 0.307356 0.719969 435 | vt 0.328322 0.734147 436 | vt 0.351669 0.774114 437 | vt 0.376424 0.808734 438 | vt 0.400730 0.815653 439 | vt 0.425621 0.826523 440 | vt 0.446996 0.770780 441 | vn -0.0408 0.1548 -0.9871 442 | vn -0.0349 0.0405 -0.9986 443 | vn -0.0256 -0.0381 -0.9989 444 | vn -0.0256 0.0385 -0.9989 445 | vn -0.0265 -0.4098 0.9118 446 | vn -0.0260 -0.4541 0.8905 447 | vn -0.0378 -0.2411 0.9698 448 | vn -0.0331 -0.3209 0.9465 449 | vn -0.0656 0.1991 0.9778 450 | vn -0.0600 0.1310 0.9895 451 | vn -0.0793 0.4231 0.9026 452 | vn -0.0866 0.5750 0.8135 453 | vn -0.0871 0.5539 0.8280 454 | vn -0.0863 0.4875 0.8688 455 | vn -0.0325 0.7065 0.7069 456 | vn -0.0434 0.5884 0.8074 457 | vn 0.0039 0.8481 0.5298 458 | vn 0.0089 0.8146 0.5799 459 | vn 0.0263 0.9489 0.3145 460 | vn 0.0246 0.9601 0.2784 461 | vn -0.0089 0.9867 0.1625 462 | vn -0.0102 0.9988 0.0471 463 | vn -0.0573 0.9927 0.1059 464 | vn -0.0525 0.9956 0.0768 465 | vn -0.0615 0.9788 -0.1952 466 | vn -0.0638 0.9941 -0.0872 467 | vn -0.0469 0.9238 -0.3799 468 | vn -0.0466 0.9412 -0.3346 469 | vn -0.0238 0.8344 -0.5506 470 | vn -0.0239 0.8596 -0.5104 471 | vn -0.0169 0.6923 -0.7213 472 | vn -0.0204 0.6094 -0.7926 473 | vn -0.0295 0.3973 -0.9172 474 | vn -0.0326 0.3021 -0.9527 475 | vn -0.0412 0.3073 -0.9507 476 | vn -0.0419 0.3062 -0.9510 477 | vn -0.0521 0.2645 -0.9630 478 | vn -0.0501 0.2776 -0.9594 479 | vn -0.0032 0.0507 -0.9987 480 | vn -0.0002 0.1086 -0.9941 481 | vn -0.0120 -0.1819 -0.9832 482 | vn -0.0146 -0.2066 -0.9783 483 | vn -0.0080 0.2437 -0.9698 484 | vn -0.0352 -0.0476 -0.9982 485 | vn 0.0258 0.3114 -0.9499 486 | vn 0.0119 0.1522 -0.9883 487 | vn 0.0468 0.1713 -0.9841 488 | vn 0.0616 0.2904 -0.9549 489 | vn 0.0059 0.0058 -0.9999 490 | vn 0.0064 0.3495 -0.9369 491 | vn 0.0070 0.0418 -0.9991 492 | vn -0.0017 0.3751 -0.9269 493 | vn -0.0132 0.1810 -0.9834 494 | vn -0.0097 0.2935 -0.9559 495 | vn 0.0377 0.2907 -0.9560 496 | vn 0.0220 0.5590 -0.8289 497 | vn 0.0032 0.6562 -0.7546 498 | vn 0.0008 0.5203 -0.8539 499 | vn 0.0069 0.2425 -0.9701 500 | vn 0.0040 0.1274 -0.9918 501 | vn 0.0251 0.1789 -0.9836 502 | vn 0.0048 0.2490 -0.9685 503 | vn 0.0776 0.6669 -0.7411 504 | vn 0.0472 0.7918 -0.6089 505 | vn -0.0016 0.8408 -0.5413 506 | vn -0.0450 0.7315 -0.6803 507 | vn -0.0280 0.5358 -0.8438 508 | vn 0.0108 0.4752 -0.8798 509 | vn 0.0247 0.4719 -0.8813 510 | vn 0.0040 0.3793 -0.9252 511 | vn 0.0938 0.7764 -0.6232 512 | vn 0.0659 0.7906 -0.6088 513 | vn 0.0054 0.8655 -0.5009 514 | vn -0.0703 0.8755 -0.4779 515 | vn -0.0619 0.7599 -0.6471 516 | vn 0.0153 0.6619 -0.7494 517 | vn 0.0181 0.6458 -0.7633 518 | vn -0.0134 0.6007 -0.7993 519 | vn 0.0874 0.8874 -0.4525 520 | vn 0.0739 0.8985 -0.4328 521 | vn 0.0257 0.9420 -0.3347 522 | vn -0.0657 0.9731 -0.2208 523 | vn -0.0799 0.9673 -0.2408 524 | vn 0.0152 0.9611 -0.2757 525 | vn 0.0117 0.9638 -0.2662 526 | vn -0.0335 0.9249 -0.3786 527 | vn 0.1029 0.9737 -0.2030 528 | vn 0.0767 0.9947 -0.0690 529 | vn 0.0282 0.9970 -0.0718 530 | vn -0.0576 0.9936 -0.0973 531 | vn -0.0840 0.9904 -0.1092 532 | vn 0.0116 0.9840 -0.1775 533 | vn 0.0068 0.9739 -0.2267 534 | vn -0.0514 0.9654 -0.2557 535 | vn 0.1306 0.9672 -0.2179 536 | vn 0.0761 0.9672 -0.2424 537 | vn 0.0142 0.9341 -0.3568 538 | vn -0.0524 0.9121 -0.4064 539 | vn -0.0824 0.9143 -0.3966 540 | vn 0.0058 0.9096 -0.4153 541 | vn 0.0211 0.9387 -0.3439 542 | vn -0.0439 0.9882 -0.1468 543 | vn 0.1101 0.9702 -0.2155 544 | vn 0.0604 0.9072 -0.4163 545 | vn -0.0060 0.8167 -0.5770 546 | vn -0.0480 0.7699 -0.6363 547 | vn -0.0622 0.8092 -0.5842 548 | vn 0.0159 0.8834 -0.4682 549 | vn 0.0476 0.9494 -0.3103 550 | vn -0.0139 0.9944 -0.1046 551 | vn 0.0754 0.9892 0.1253 552 | vn 0.0304 0.9988 -0.0382 553 | vn -0.0316 0.9803 -0.1948 554 | vn -0.0697 0.9603 -0.2700 555 | vn -0.0588 0.9728 -0.2238 556 | vn 0.0367 0.9853 -0.1665 557 | vn 0.0666 0.9820 -0.1765 558 | vn 0.0162 0.9933 -0.1139 559 | vn 0.0522 0.9112 0.4086 560 | vn -0.0020 0.9587 0.2845 561 | vn -0.0610 0.9904 0.1244 562 | vn -0.0653 0.9875 0.1434 563 | vn -0.0350 0.9215 0.3866 564 | vn 0.0407 0.8621 0.5051 565 | vn 0.0553 0.9157 0.3979 566 | vn 0.0288 0.9614 0.2735 567 | vn 0.0424 0.8201 0.5707 568 | vn -0.0365 0.8270 0.5610 569 | vn -0.0940 0.8383 0.5370 570 | vn -0.0311 0.7923 0.6093 571 | vn 0.0064 0.6328 0.7743 572 | vn 0.0345 0.5408 0.8404 573 | vn 0.0299 0.5553 0.8311 574 | vn 0.0062 0.6830 0.7304 575 | vn 0.0708 0.3539 0.9326 576 | vn -0.0439 0.3280 0.9436 577 | vn -0.0876 0.2977 0.9506 578 | vn -0.0089 0.2873 0.9578 579 | vn 0.0077 0.3663 0.9304 580 | vn 0.0351 0.4479 0.8934 581 | vn 0.0343 0.3894 0.9204 582 | vn -0.0242 0.3901 0.9204 583 | vn 0.0511 0.3638 0.9300 584 | vn -0.0361 0.3552 0.9340 585 | vn -0.0711 0.2797 0.9574 586 | vn -0.0087 0.2011 0.9795 587 | vn -0.0140 0.2244 0.9744 588 | vn 0.0202 0.3865 0.9220 589 | vn 0.0445 0.4932 0.8688 590 | vn -0.0336 0.4861 0.8732 591 | vn 0.0126 0.6878 0.7258 592 | vn -0.0461 0.6304 0.7748 593 | vn -0.0367 0.4531 0.8907 594 | vn 0.0026 0.2313 0.9728 595 | vn -0.0200 0.1387 0.9901 596 | vn -0.0019 0.1707 0.9853 597 | vn 0.0227 0.3740 0.9271 598 | vn -0.0407 0.5631 0.8253 599 | vn 0.0209 0.5323 0.8462 600 | vn 0.0032 0.5084 0.8611 601 | vn 0.0025 0.3884 0.9215 602 | vn 0.0089 0.3590 0.9333 603 | vn -0.0105 0.3392 0.9406 604 | vn 0.0067 0.1816 0.9833 605 | vn -0.0112 0.1527 0.9882 606 | vn -0.0525 0.2120 0.9758 607 | vn 0.0220 0.0914 0.9955 608 | vn 0.0042 0.1613 0.9869 609 | vn -0.0041 0.3268 0.9451 610 | vn -0.0106 0.5072 0.8618 611 | vn 0.0066 0.5325 0.8464 612 | vn 0.0355 0.3904 0.9199 613 | vn -0.0008 0.1435 0.9896 614 | vn -0.0412 -0.1529 0.9874 615 | vn 0.0188 0.0088 0.9998 616 | vn 0.0094 0.0309 0.9995 617 | vn -0.0217 0.2246 0.9742 618 | vn -0.0252 0.4458 0.8948 619 | vn 0.0139 0.5236 0.8518 620 | vn 0.0494 0.4491 0.8921 621 | vn 0.0216 0.1655 0.9860 622 | vn -0.0113 -0.1929 0.9811 623 | vn -0.0159 -0.2866 -0.9579 624 | vn -0.0112 -0.3559 -0.9344 625 | vn -0.0504 -0.1268 -0.9906 626 | vn -0.0013 0.0100 -0.9999 627 | vn 0.0574 0.2004 -0.9780 628 | vn 0.0023 0.4285 -0.9035 629 | vn -0.0001 0.4630 -0.8863 630 | vn 0.0033 0.2855 -0.9583 631 | vn -0.0164 -0.0988 -0.9950 632 | vn -0.0112 -0.3614 -0.9323 633 | vn 0.0188 0.0077 0.9998 634 | vn 0.0212 0.0605 0.9979 635 | vn 0.0245 0.2372 0.9711 636 | vn 0.0135 0.7963 0.6047 637 | vn 0.0468 0.3361 0.9406 638 | vn 0.0561 0.6025 0.7961 639 | vn 0.0422 0.8375 0.5448 640 | vn 0.0551 0.9084 0.4144 641 | vn 0.0718 0.9752 0.2091 642 | vn 0.0941 0.9928 -0.0737 643 | vn 0.1331 0.9669 -0.2174 644 | vn 0.0922 0.9564 -0.2771 645 | vn 0.0901 0.8688 -0.4868 646 | vn 0.0950 0.7082 -0.6995 647 | vn 0.0742 0.5826 -0.8094 648 | vn 0.0490 0.3786 -0.9243 649 | vn 0.0021 -0.0618 -0.9981 650 | s 1 651 | f 172/1/1 2/2/2 4/3/3 173/4/4 652 | f 174/5/5 6/6/6 8/7/7 175/8/8 653 | f 175/8/8 8/7/7 10/9/9 176/10/10 654 | f 176/10/10 10/9/9 12/11/11 177/12/12 655 | f 177/12/12 12/11/11 14/13/13 178/14/14 656 | f 178/14/14 14/13/13 16/15/15 179/16/16 657 | f 179/16/16 16/15/15 18/17/17 180/18/18 658 | f 180/18/18 18/17/17 20/19/19 181/20/20 659 | f 181/20/20 20/19/19 22/21/21 182/22/22 660 | f 182/22/22 22/21/21 24/23/23 183/24/24 661 | f 183/24/24 24/23/23 26/25/25 184/26/26 662 | f 184/26/26 26/25/25 28/27/27 185/28/28 663 | f 185/28/28 28/27/27 30/29/29 186/30/30 664 | f 186/30/30 30/29/29 32/31/31 187/32/32 665 | f 187/32/32 32/31/31 34/33/33 188/34/34 666 | f 188/34/34 34/33/33 36/35/35 189/36/36 667 | f 189/36/36 36/35/35 38/37/37 190/38/38 668 | f 190/38/38 38/37/37 2/2/2 172/1/1 669 | f 208/39/39 171/40/40 39/41/41 209/42/42 670 | f 171/40/40 170/43/43 40/44/44 39/41/41 671 | f 170/43/43 169/45/45 41/46/46 40/44/44 672 | f 169/45/45 168/47/47 42/48/48 41/46/46 673 | f 168/49/47 167/50/49 43/51/50 42/52/48 674 | f 167/50/49 166/53/51 44/54/52 43/51/50 675 | f 166/53/51 165/55/53 45/56/54 44/54/52 676 | f 207/57/55 164/58/56 171/40/40 208/39/39 677 | f 164/58/56 163/59/57 170/43/43 171/40/40 678 | f 163/59/57 162/60/58 169/45/45 170/43/43 679 | f 162/60/58 161/61/59 168/47/47 169/45/45 680 | f 161/62/59 160/63/60 167/50/49 168/49/47 681 | f 160/63/60 159/64/61 166/53/51 167/50/49 682 | f 159/64/61 158/65/62 165/55/53 166/53/51 683 | f 206/66/63 157/67/64 164/58/56 207/57/55 684 | f 157/67/64 156/68/65 163/59/57 164/58/56 685 | f 156/68/65 155/69/66 162/60/58 163/59/57 686 | f 155/69/66 154/70/67 161/61/59 162/60/58 687 | f 154/71/67 153/72/68 160/63/60 161/62/59 688 | f 153/72/68 152/73/69 159/64/61 160/63/60 689 | f 152/73/69 151/74/70 158/65/62 159/64/61 690 | f 205/75/71 150/76/72 157/67/64 206/66/63 691 | f 150/76/72 149/77/73 156/68/65 157/67/64 692 | f 149/77/73 148/78/74 155/69/66 156/68/65 693 | f 148/78/74 147/79/75 154/70/67 155/69/66 694 | f 147/80/75 146/81/76 153/72/68 154/71/67 695 | f 146/81/76 145/82/77 152/73/69 153/72/68 696 | f 145/82/77 144/83/78 151/74/70 152/73/69 697 | f 204/84/79 143/85/80 150/76/72 205/75/71 698 | f 143/85/80 142/86/81 149/77/73 150/76/72 699 | f 142/86/81 141/87/82 148/78/74 149/77/73 700 | f 141/87/82 140/88/83 147/79/75 148/78/74 701 | f 140/89/83 139/90/84 146/81/76 147/80/75 702 | f 139/90/84 138/91/85 145/82/77 146/81/76 703 | f 138/91/85 137/92/86 144/83/78 145/82/77 704 | f 203/93/87 136/94/88 143/85/80 204/84/79 705 | f 136/94/88 135/95/89 142/86/81 143/85/80 706 | f 135/95/89 134/96/90 141/87/82 142/86/81 707 | f 134/96/90 133/97/91 140/88/83 141/87/82 708 | f 133/98/91 132/99/92 139/90/84 140/89/83 709 | f 132/99/92 131/100/93 138/91/85 139/90/84 710 | f 131/100/93 130/101/94 137/92/86 138/91/85 711 | f 202/102/95 129/103/96 136/94/88 203/93/87 712 | f 129/103/96 128/104/97 135/95/89 136/94/88 713 | f 128/104/97 127/105/98 134/96/90 135/95/89 714 | f 127/105/98 126/106/99 133/97/91 134/96/90 715 | f 126/107/99 125/108/100 132/99/92 133/98/91 716 | f 125/108/100 124/109/101 131/100/93 132/99/92 717 | f 124/109/101 123/110/102 130/101/94 131/100/93 718 | f 201/111/103 122/112/104 129/103/96 202/102/95 719 | f 122/112/104 121/113/105 128/104/97 129/103/96 720 | f 121/113/105 120/114/106 127/105/98 128/104/97 721 | f 120/114/106 119/115/107 126/106/99 127/105/98 722 | f 119/116/107 118/117/108 125/108/100 126/107/99 723 | f 118/117/108 117/118/109 124/109/101 125/108/100 724 | f 117/118/109 116/119/110 123/110/102 124/109/101 725 | f 200/120/111 115/121/112 122/112/104 201/111/103 726 | f 115/121/112 114/122/113 121/113/105 122/112/104 727 | f 114/122/113 113/123/114 120/114/106 121/113/105 728 | f 113/123/114 112/124/115 119/115/107 120/114/106 729 | f 112/125/115 111/126/116 118/117/108 119/116/107 730 | f 111/126/116 110/127/117 117/118/109 118/117/108 731 | f 110/127/117 109/128/118 116/119/110 117/118/109 732 | f 199/129/119 108/130/120 115/121/112 200/120/111 733 | f 108/130/120 107/131/121 114/122/113 115/121/112 734 | f 107/131/121 106/132/122 113/123/114 114/122/113 735 | f 106/132/122 105/133/123 112/124/115 113/123/114 736 | f 105/134/123 104/135/124 111/126/116 112/125/115 737 | f 104/135/124 103/136/125 110/127/117 111/126/116 738 | f 103/136/125 102/137/126 109/128/118 110/127/117 739 | f 198/138/127 101/139/128 108/130/120 199/129/119 740 | f 101/139/128 100/140/129 107/131/121 108/130/120 741 | f 100/140/129 99/141/130 106/132/122 107/131/121 742 | f 99/141/130 98/142/131 105/133/123 106/132/122 743 | f 98/143/131 97/144/132 104/135/124 105/134/123 744 | f 97/144/132 96/145/133 103/136/125 104/135/124 745 | f 96/145/133 95/146/134 102/137/126 103/136/125 746 | f 197/147/135 94/148/136 101/139/128 198/138/127 747 | f 94/148/136 93/149/137 100/140/129 101/139/128 748 | f 93/149/137 92/150/138 99/141/130 100/140/129 749 | f 92/150/138 91/151/139 98/142/131 99/141/130 750 | f 91/152/139 90/153/140 97/144/132 98/143/131 751 | f 90/153/140 89/154/141 96/145/133 97/144/132 752 | f 89/154/141 88/155/142 95/146/134 96/145/133 753 | f 196/156/143 87/157/144 94/148/136 197/147/135 754 | f 87/157/144 86/158/145 93/149/137 94/148/136 755 | f 86/158/145 85/159/146 92/150/138 93/149/137 756 | f 85/159/146 84/160/147 91/151/139 92/150/138 757 | f 84/161/147 83/162/148 90/153/140 91/152/139 758 | f 83/162/148 82/163/149 89/154/141 90/153/140 759 | f 82/163/149 81/164/150 88/155/142 89/154/141 760 | f 195/165/151 80/166/152 87/157/144 196/156/143 761 | f 80/166/152 79/167/153 86/158/145 87/157/144 762 | f 79/167/153 78/168/154 85/159/146 86/158/145 763 | f 78/168/154 77/169/155 84/160/147 85/159/146 764 | f 77/170/155 76/171/156 83/162/148 84/161/147 765 | f 76/171/156 75/172/157 82/163/149 83/162/148 766 | f 75/172/157 74/173/158 81/164/150 82/163/149 767 | f 194/174/159 73/175/160 80/166/152 195/165/151 768 | f 73/175/160 72/176/161 79/167/153 80/166/152 769 | f 72/176/161 71/177/162 78/168/154 79/167/153 770 | f 71/177/162 70/178/163 77/169/155 78/168/154 771 | f 70/179/163 69/180/164 76/171/156 77/170/155 772 | f 69/180/164 68/181/165 75/172/157 76/171/156 773 | f 68/181/165 67/182/166 74/173/158 75/172/157 774 | f 193/183/167 66/184/168 73/175/160 194/174/159 775 | f 66/184/168 65/185/169 72/176/161 73/175/160 776 | f 65/185/169 64/186/170 71/177/162 72/176/161 777 | f 64/186/170 63/187/171 70/178/163 71/177/162 778 | f 63/188/171 62/189/172 69/180/164 70/179/163 779 | f 62/189/172 61/190/173 68/181/165 69/180/164 780 | f 61/190/173 60/191/174 67/182/166 68/181/165 781 | f 192/192/175 59/193/176 66/184/168 193/183/167 782 | f 59/193/176 58/194/177 65/185/169 66/184/168 783 | f 58/194/177 57/195/178 64/186/170 65/185/169 784 | f 57/195/178 56/196/179 63/187/171 64/186/170 785 | f 56/197/179 55/198/180 62/189/172 63/188/171 786 | f 55/198/180 54/199/181 61/190/173 62/189/172 787 | f 54/199/181 53/200/182 60/191/174 61/190/173 788 | f 209/42/42 39/41/41 52/201/183 191/202/184 789 | f 39/41/41 40/44/44 51/203/185 52/201/183 790 | f 40/44/44 41/46/46 50/204/186 51/203/185 791 | f 41/46/46 42/48/48 49/205/187 50/204/186 792 | f 42/52/48 43/51/50 48/206/188 49/207/187 793 | f 43/51/50 44/54/52 47/208/189 48/206/188 794 | f 44/54/52 45/56/54 46/209/190 47/208/189 795 | f 165/55/53 190/38/38 172/1/1 45/56/54 796 | f 158/65/62 189/36/36 190/38/38 165/55/53 797 | f 151/74/70 188/34/34 189/36/36 158/65/62 798 | f 144/83/78 187/32/32 188/34/34 151/74/70 799 | f 137/92/86 186/30/30 187/32/32 144/83/78 800 | f 130/101/94 185/28/28 186/30/30 137/92/86 801 | f 123/110/102 184/26/26 185/28/28 130/101/94 802 | f 116/119/110 183/24/24 184/26/26 123/110/102 803 | f 109/128/118 182/22/22 183/24/24 116/119/110 804 | f 102/137/126 181/20/20 182/22/22 109/128/118 805 | f 95/146/134 180/18/18 181/20/20 102/137/126 806 | f 88/155/142 179/16/16 180/18/18 95/146/134 807 | f 81/164/150 178/14/14 179/16/16 88/155/142 808 | f 74/173/158 177/12/12 178/14/14 81/164/150 809 | f 67/182/166 176/10/10 177/12/12 74/173/158 810 | f 60/191/174 175/8/8 176/10/10 67/182/166 811 | f 53/200/182 174/5/5 175/8/8 60/191/174 812 | f 45/56/54 172/1/1 173/4/4 46/209/190 813 | f 1/210/191 209/42/42 191/202/184 3/211/192 814 | f 5/212/193 192/192/175 193/183/167 7/213/194 815 | f 7/213/194 193/183/167 194/174/159 9/214/195 816 | f 9/214/195 194/174/159 195/165/151 11/215/196 817 | f 11/215/196 195/165/151 196/156/143 13/216/197 818 | f 13/216/197 196/156/143 197/147/135 15/217/198 819 | f 15/217/198 197/147/135 198/138/127 17/218/199 820 | f 17/218/199 198/138/127 199/129/119 19/219/200 821 | f 19/219/200 199/129/119 200/120/111 21/220/201 822 | f 21/220/201 200/120/111 201/111/103 23/221/202 823 | f 23/221/202 201/111/103 202/102/95 25/222/203 824 | f 25/222/203 202/102/95 203/93/87 27/223/204 825 | f 27/223/204 203/93/87 204/84/79 29/224/205 826 | f 29/224/205 204/84/79 205/75/71 31/225/206 827 | f 31/225/206 205/75/71 206/66/63 33/226/207 828 | f 33/226/207 206/66/63 207/57/55 35/227/208 829 | f 35/227/208 207/57/55 208/39/39 37/228/209 830 | f 37/228/209 208/39/39 209/42/42 1/210/191 831 | -------------------------------------------------------------------------------- /assets/models/mossy_log.obj.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="wavefront_obj" 4 | type="Mesh" 5 | path="res://.import/mossy_log.obj-1f04f59e68a1ff3cd48e9281f4550ccc.mesh" 6 | 7 | [deps] 8 | 9 | files=[ "res://.import/mossy_log.obj-1f04f59e68a1ff3cd48e9281f4550ccc.mesh" ] 10 | 11 | source_file="res://assets/models/mossy_log.obj" 12 | dest_files=[ "res://.import/mossy_log.obj-1f04f59e68a1ff3cd48e9281f4550ccc.mesh", "res://.import/mossy_log.obj-1f04f59e68a1ff3cd48e9281f4550ccc.mesh" ] 13 | 14 | [params] 15 | 16 | generate_tangents=true 17 | scale_mesh=Vector3( 1, 1, 1 ) 18 | offset_mesh=Vector3( 0, 0, 0 ) 19 | optimize_mesh=true 20 | -------------------------------------------------------------------------------- /assets/mossy_log.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/mossy_log.bin -------------------------------------------------------------------------------- /assets/render_scaler.gd: -------------------------------------------------------------------------------- 1 | extends Control 2 | 3 | # The viewport is displayed using a TextureRect node instead of a ViewportContainer. 4 | # This allows filtering the texture that's displayed in the root viewport. 5 | 6 | # The 3D viewport's scale factor. For instance, 1.0 is full resolution, 7 | # 0.5 is half resolution and 2.0 is double resolution. Higher values look 8 | # sharper but are slower to render. Values above 1 can be used for supersampling 9 | # (SSAA), but filtering must be enabled for this to work. 10 | var scale_factor = 0.50 11 | 12 | onready var texture_rect = $TextureRect 13 | onready var viewport = $Viewport 14 | 15 | func _ready(): 16 | # Required to change the 3D viewport's size when the window is resized. 17 | # warning-ignore:return_value_discarded 18 | viewport.size = get_viewport().size * scale_factor 19 | 20 | # Called when the root's viewport size changes (i.e. when the window is resized). 21 | # This is done to handle multiple resolutions without losing quality. 22 | func _root_viewport_size_changed(): 23 | # The viewport is resized depending on the window height. 24 | # To compensate for the larger resolution, the viewport sprite is scaled down. 25 | viewport.size = get_viewport().size * scale_factor 26 | -------------------------------------------------------------------------------- /assets/scene_mobile.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=5 format=2] 2 | 3 | [ext_resource path="res://demo_desktop.tscn" type="PackedScene" id=1] 4 | [ext_resource path="res://assets/rat_no_blend.tscn" type="PackedScene" id=3] 5 | 6 | [sub_resource type="ProceduralSky" id=1] 7 | sun_longitude = -135.0 8 | 9 | [sub_resource type="Environment" id=2] 10 | background_mode = 2 11 | background_sky = SubResource( 1 ) 12 | tonemap_mode = 2 13 | ssao_radius = 0.3 14 | ssao_radius2 = 0.15 15 | 16 | [node name="World" instance=ExtResource( 1 )] 17 | 18 | [node name="WorldEnvironment" parent="." index="1"] 19 | environment = SubResource( 2 ) 20 | 21 | [node name="DirectionalLight" parent="." index="2"] 22 | shadow_enabled = false 23 | 24 | [node name="Rat Body" parent="Rat/Armature/Skeleton" index="0"] 25 | layers = 0 26 | 27 | [node name="ShellFur" parent="Rat/Armature/Skeleton/Rat Body" index="0"] 28 | mat_ao_light_affect = 0.0 29 | 30 | [node name="Rat Body - No Blend Fix" parent="Rat/Armature/Skeleton" index="1" instance=ExtResource( 3 )] 31 | 32 | [node name="ShellFur" parent="Cottage/Cottage Fur Roof" index="0"] 33 | mat_ao_light_affect = 0.0 34 | 35 | [node name="ShellFur" parent="Mossy_Log/mossy_log" index="0"] 36 | mat_ao_light_affect = 0.0 37 | 38 | [node name="Camera" parent="." index="6"] 39 | mouse_mode = 0 40 | mobile = true 41 | 42 | [node name="ShellFur" parent="Ball_Boy/Armature/Skeleton/BallBoy" index="0"] 43 | mat_ao_light_affect = 0.0 44 | 45 | [node name="BoneAttachment" parent="Ball_Boy/Armature/Skeleton" index="1"] 46 | transform = Transform( -0.999767, 0.00356774, 0.0213088, -0.0035704, 0.945428, -0.32581, -0.0213083, -0.32581, -0.945195, -6.26097e-09, 0.0937309, 2.2632 ) 47 | 48 | [node name="ShellFur" parent="LOD_Sphere" index="1"] 49 | mat_ao_light_affect = 0.0 50 | 51 | [editable path="Rat"] 52 | [editable path="Cottage"] 53 | [editable path="Mossy_Log"] 54 | [editable path="Ball_Boy"] 55 | -------------------------------------------------------------------------------- /assets/textures/.moss_height.png-autosave.kra: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/.moss_height.png-autosave.kra -------------------------------------------------------------------------------- /assets/textures/Cottage_Alb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Alb.png -------------------------------------------------------------------------------- /assets/textures/Cottage_Alb.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Cottage_Alb.png-a4eccd46025060b803a8ef9ccc4d313c.s3tc.stex" 6 | path.etc2="res://.import/Cottage_Alb.png-a4eccd46025060b803a8ef9ccc4d313c.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Cottage_Alb.png" 15 | dest_files=[ "res://.import/Cottage_Alb.png-a4eccd46025060b803a8ef9ccc4d313c.s3tc.stex", "res://.import/Cottage_Alb.png-a4eccd46025060b803a8ef9ccc4d313c.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Cottage_Alb.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Alb.png~ -------------------------------------------------------------------------------- /assets/textures/Cottage_Nor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Nor.png -------------------------------------------------------------------------------- /assets/textures/Cottage_Nor.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Cottage_Nor.png-e95d3ac958a2cb2791ccb483d4b58f3c.s3tc.stex" 6 | path.etc2="res://.import/Cottage_Nor.png-e95d3ac958a2cb2791ccb483d4b58f3c.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Cottage_Nor.png" 15 | dest_files=[ "res://.import/Cottage_Nor.png-e95d3ac958a2cb2791ccb483d4b58f3c.s3tc.stex", "res://.import/Cottage_Nor.png-e95d3ac958a2cb2791ccb483d4b58f3c.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=1 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Cottage_Nor.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Nor.png~ -------------------------------------------------------------------------------- /assets/textures/Cottage_Rough.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Rough.png -------------------------------------------------------------------------------- /assets/textures/Cottage_Rough.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Cottage_Rough.png-88df0b7be9245c1060e32795f9ca8dbd.s3tc.stex" 6 | path.etc2="res://.import/Cottage_Rough.png-88df0b7be9245c1060e32795f9ca8dbd.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Cottage_Rough.png" 15 | dest_files=[ "res://.import/Cottage_Rough.png-88df0b7be9245c1060e32795f9ca8dbd.s3tc.stex", "res://.import/Cottage_Rough.png-88df0b7be9245c1060e32795f9ca8dbd.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Cottage_Rough.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Cottage_Rough.png~ -------------------------------------------------------------------------------- /assets/textures/Log_AORoughMetal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Log_AORoughMetal.png -------------------------------------------------------------------------------- /assets/textures/Log_AORoughMetal.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Log_AORoughMetal.png-42f15d066c963dd8f6d81decb0ba93dc.s3tc.stex" 6 | path.etc2="res://.import/Log_AORoughMetal.png-42f15d066c963dd8f6d81decb0ba93dc.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Log_AORoughMetal.png" 15 | dest_files=[ "res://.import/Log_AORoughMetal.png-42f15d066c963dd8f6d81decb0ba93dc.s3tc.stex", "res://.import/Log_AORoughMetal.png-42f15d066c963dd8f6d81decb0ba93dc.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Log_Albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Log_Albedo.png -------------------------------------------------------------------------------- /assets/textures/Log_Albedo.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Log_Albedo.png-2350dda64588d9fa8b2328d22ebd5da8.s3tc.stex" 6 | path.etc2="res://.import/Log_Albedo.png-2350dda64588d9fa8b2328d22ebd5da8.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Log_Albedo.png" 15 | dest_files=[ "res://.import/Log_Albedo.png-2350dda64588d9fa8b2328d22ebd5da8.s3tc.stex", "res://.import/Log_Albedo.png-2350dda64588d9fa8b2328d22ebd5da8.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Log_Depth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Log_Depth.png -------------------------------------------------------------------------------- /assets/textures/Log_Depth.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Log_Depth.png-c39c6781910070015bbc99de41fc5214.s3tc.stex" 6 | path.etc2="res://.import/Log_Depth.png-c39c6781910070015bbc99de41fc5214.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Log_Depth.png" 15 | dest_files=[ "res://.import/Log_Depth.png-c39c6781910070015bbc99de41fc5214.s3tc.stex", "res://.import/Log_Depth.png-c39c6781910070015bbc99de41fc5214.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/Log_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/Log_Normal.png -------------------------------------------------------------------------------- /assets/textures/Log_Normal.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/Log_Normal.png-0435a2ba6b076eabd735b58ce3f521cf.s3tc.stex" 6 | path.etc2="res://.import/Log_Normal.png-0435a2ba6b076eabd735b58ce3f521cf.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/Log_Normal.png" 15 | dest_files=[ "res://.import/Log_Normal.png-0435a2ba6b076eabd735b58ce3f521cf.s3tc.stex", "res://.import/Log_Normal.png-0435a2ba6b076eabd735b58ce3f521cf.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=1 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/ball_boy_AORoughMetal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/ball_boy_AORoughMetal.png -------------------------------------------------------------------------------- /assets/textures/ball_boy_AORoughMetal.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/ball_boy_AORoughMetal.png-2645916b703c8551bf6de7cc86f53b70.s3tc.stex" 6 | path.etc2="res://.import/ball_boy_AORoughMetal.png-2645916b703c8551bf6de7cc86f53b70.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/ball_boy_AORoughMetal.png" 15 | dest_files=[ "res://.import/ball_boy_AORoughMetal.png-2645916b703c8551bf6de7cc86f53b70.s3tc.stex", "res://.import/ball_boy_AORoughMetal.png-2645916b703c8551bf6de7cc86f53b70.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/ball_boy_Albedo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/ball_boy_Albedo.png -------------------------------------------------------------------------------- /assets/textures/ball_boy_Albedo.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/ball_boy_Albedo.png-c0797f16a54a9ecc3498f9d270fcb5e7.s3tc.stex" 6 | path.etc2="res://.import/ball_boy_Albedo.png-c0797f16a54a9ecc3498f9d270fcb5e7.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/ball_boy_Albedo.png" 15 | dest_files=[ "res://.import/ball_boy_Albedo.png-c0797f16a54a9ecc3498f9d270fcb5e7.s3tc.stex", "res://.import/ball_boy_Albedo.png-c0797f16a54a9ecc3498f9d270fcb5e7.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/ballboy_fur_ldtg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/ballboy_fur_ldtg.png -------------------------------------------------------------------------------- /assets/textures/ballboy_fur_ldtg.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/ballboy_fur_ldtg.png-72c0962954b904d43924f0a725f3172e.s3tc.stex" 6 | path.etc2="res://.import/ballboy_fur_ldtg.png-72c0962954b904d43924f0a725f3172e.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/ballboy_fur_ldtg.png" 15 | dest_files=[ "res://.import/ballboy_fur_ldtg.png-72c0962954b904d43924f0a725f3172e.s3tc.stex", "res://.import/ballboy_fur_ldtg.png-72c0962954b904d43924f0a725f3172e.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/checker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/checker.png -------------------------------------------------------------------------------- /assets/textures/checker.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/checker.png-5e2b6ff6c0c0f48b47257da03e3aea4a.s3tc.stex" 6 | path.etc2="res://.import/checker.png-5e2b6ff6c0c0f48b47257da03e3aea4a.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/checker.png" 15 | dest_files=[ "res://.import/checker.png-5e2b6ff6c0c0f48b47257da03e3aea4a.s3tc.stex", "res://.import/checker.png-5e2b6ff6c0c0f48b47257da03e3aea4a.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/moss.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/moss.png -------------------------------------------------------------------------------- /assets/textures/moss.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/moss.png-737d17828c2e4470a0e767c2c6f2fdee.s3tc.stex" 6 | path.etc2="res://.import/moss.png-737d17828c2e4470a0e767c2c6f2fdee.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/moss.png" 15 | dest_files=[ "res://.import/moss.png-737d17828c2e4470a0e767c2c6f2fdee.s3tc.stex", "res://.import/moss.png-737d17828c2e4470a0e767c2c6f2fdee.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/moss_ldtg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/moss_ldtg.png -------------------------------------------------------------------------------- /assets/textures/moss_ldtg.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/moss_ldtg.png-32936920d5d0eea5d621602a06425d4f.s3tc.stex" 6 | path.etc2="res://.import/moss_ldtg.png-32936920d5d0eea5d621602a06425d4f.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/moss_ldtg.png" 15 | dest_files=[ "res://.import/moss_ldtg.png-32936920d5d0eea5d621602a06425d4f.s3tc.stex", "res://.import/moss_ldtg.png-32936920d5d0eea5d621602a06425d4f.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/rat_None_BaseColor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/rat_None_BaseColor.png -------------------------------------------------------------------------------- /assets/textures/rat_None_BaseColor.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/rat_None_BaseColor.png-4c6d3d42a70072144fd71e6b5c2b7dbc.s3tc.stex" 6 | path.etc2="res://.import/rat_None_BaseColor.png-4c6d3d42a70072144fd71e6b5c2b7dbc.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/rat_None_BaseColor.png" 15 | dest_files=[ "res://.import/rat_None_BaseColor.png-4c6d3d42a70072144fd71e6b5c2b7dbc.s3tc.stex", "res://.import/rat_None_BaseColor.png-4c6d3d42a70072144fd71e6b5c2b7dbc.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=1 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/rat_None_Normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/rat_None_Normal.png -------------------------------------------------------------------------------- /assets/textures/rat_None_Normal.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/rat_None_Normal.png-1e595e9608662ddd9162b5cf1ef0d38a.s3tc.stex" 6 | path.etc2="res://.import/rat_None_Normal.png-1e595e9608662ddd9162b5cf1ef0d38a.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/rat_None_Normal.png" 15 | dest_files=[ "res://.import/rat_None_Normal.png-1e595e9608662ddd9162b5cf1ef0d38a.s3tc.stex", "res://.import/rat_None_Normal.png-1e595e9608662ddd9162b5cf1ef0d38a.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=1 24 | flags/repeat=0 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/rat_None_Roughness.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/rat_None_Roughness.png -------------------------------------------------------------------------------- /assets/textures/rat_None_Roughness.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/rat_None_Roughness.png-8e902cbb1a7c4668821dc7231ccb3ecf.s3tc.stex" 6 | path.etc2="res://.import/rat_None_Roughness.png-8e902cbb1a7c4668821dc7231ccb3ecf.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/rat_None_Roughness.png" 15 | dest_files=[ "res://.import/rat_None_Roughness.png-8e902cbb1a7c4668821dc7231ccb3ecf.s3tc.stex", "res://.import/rat_None_Roughness.png-8e902cbb1a7c4668821dc7231ccb3ecf.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /assets/textures/rat_fur_height.png~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/rat_fur_height.png~ -------------------------------------------------------------------------------- /assets/textures/rat_fur_ldtg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/assets/textures/rat_fur_ldtg.png -------------------------------------------------------------------------------- /assets/textures/rat_fur_ldtg.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path.s3tc="res://.import/rat_fur_ldtg.png-881dab86804ecda3ac3bc6063ca1cdb0.s3tc.stex" 6 | path.etc2="res://.import/rat_fur_ldtg.png-881dab86804ecda3ac3bc6063ca1cdb0.etc2.stex" 7 | metadata={ 8 | "imported_formats": [ "s3tc", "etc2" ], 9 | "vram_texture": true 10 | } 11 | 12 | [deps] 13 | 14 | source_file="res://assets/textures/rat_fur_ldtg.png" 15 | dest_files=[ "res://.import/rat_fur_ldtg.png-881dab86804ecda3ac3bc6063ca1cdb0.s3tc.stex", "res://.import/rat_fur_ldtg.png-881dab86804ecda3ac3bc6063ca1cdb0.etc2.stex" ] 16 | 17 | [params] 18 | 19 | compress/mode=2 20 | compress/lossy_quality=0.7 21 | compress/hdr_mode=0 22 | compress/bptc_ldr=0 23 | compress/normal_map=0 24 | flags/repeat=true 25 | flags/filter=true 26 | flags/mipmaps=true 27 | flags/anisotropic=false 28 | flags/srgb=2 29 | process/fix_alpha_border=true 30 | process/premult_alpha=false 31 | process/HDR_as_SRGB=false 32 | process/invert_color=false 33 | stream=false 34 | size_limit=0 35 | detect_3d=false 36 | svg/scale=1.0 37 | -------------------------------------------------------------------------------- /default_env.tres: -------------------------------------------------------------------------------- 1 | [gd_resource type="Environment" load_steps=2 format=2] 2 | 3 | [sub_resource type="ProceduralSky" id=1] 4 | sun_longitude = -135.0 5 | 6 | [resource] 7 | background_mode = 2 8 | background_sky = SubResource( 1 ) 9 | tonemap_mode = 2 10 | ssao_enabled = true 11 | ssao_radius = 0.3 12 | ssao_radius2 = 0.15 13 | -------------------------------------------------------------------------------- /demo_desktop.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=15 format=2] 2 | 3 | [ext_resource path="res://default_env.tres" type="Environment" id=1] 4 | [ext_resource path="res://assets/rat.tscn" type="PackedScene" id=2] 5 | [ext_resource path="res://addons/shell_fur/noise_patterns/very_fine.png" type="Texture" id=3] 6 | [ext_resource path="res://addons/shell_fur/shell_fur_manager.gd" type="Script" id=4] 7 | [ext_resource path="res://assets/LOD_label.tscn" type="PackedScene" id=5] 8 | [ext_resource path="res://assets/cottage.tscn" type="PackedScene" id=6] 9 | [ext_resource path="res://assets/maujoe.camera_control/scripts/camera_control.gd" type="Script" id=7] 10 | [ext_resource path="res://assets/textures/checker.png" type="Texture" id=8] 11 | [ext_resource path="res://assets/log.tscn" type="PackedScene" id=9] 12 | [ext_resource path="res://assets/ball_boy.tscn" type="PackedScene" id=10] 13 | [ext_resource path="res://assets/ball_boy2.tscn" type="PackedScene" id=11] 14 | 15 | [sub_resource type="SpatialMaterial" id=1] 16 | albedo_color = Color( 0.623529, 0.623529, 0.623529, 1 ) 17 | albedo_texture = ExtResource( 8 ) 18 | uv1_scale = Vector3( 10, 10, 10 ) 19 | 20 | [sub_resource type="PlaneMesh" id=2] 21 | material = SubResource( 1 ) 22 | 23 | [sub_resource type="SphereMesh" id=3] 24 | radius = 0.5 25 | height = 1.0 26 | radial_segments = 16 27 | rings = 12 28 | 29 | [node name="World" type="Spatial"] 30 | 31 | [node name="Ground" type="MeshInstance" parent="."] 32 | transform = Transform( 8, 0, 0, 0, 8, 0, 0, 0, 8, 0, 0, 0 ) 33 | mesh = SubResource( 2 ) 34 | 35 | [node name="WorldEnvironment" type="WorldEnvironment" parent="."] 36 | environment = ExtResource( 1 ) 37 | 38 | [node name="DirectionalLight" type="DirectionalLight" parent="."] 39 | transform = Transform( 1, 0, 0, 0, 0.707107, 0.707107, 0, -0.707107, 0.707107, 0, 40, 0 ) 40 | light_color = Color( 1, 0.960784, 0.854902, 1 ) 41 | shadow_enabled = true 42 | 43 | [node name="Rat" parent="." instance=ExtResource( 2 )] 44 | transform = Transform( 0.707107, 0, -0.707107, 0, 1, 0, 0.707107, 0, 0.707107, 3, 0, -2 ) 45 | 46 | [node name="ShellFur" parent="Rat/Armature/Skeleton/Rat Body" index="0"] 47 | mat_ao_light_affect = 0.0 48 | 49 | [node name="Cottage" parent="." instance=ExtResource( 6 )] 50 | transform = Transform( -0.866025, 0, -0.5, 0, 1, 0, 0.5, 0, -0.866025, -1, 0, -6 ) 51 | 52 | [node name="ShellFur" parent="Cottage/Cottage Fur Roof" index="0"] 53 | mat_ao_light_affect = 0.0 54 | 55 | [node name="Mossy_Log" parent="." instance=ExtResource( 9 )] 56 | transform = Transform( 0.707107, 0, 0.707107, 0, 1, 0, -0.707107, 0, 0.707107, -4, 0, 0 ) 57 | 58 | [node name="Camera" type="Camera" parent="."] 59 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 5 ) 60 | script = ExtResource( 7 ) 61 | acceleration = 0.561 62 | max_speed = Vector3( 2, 2, 2 ) 63 | 64 | [node name="Ball_Boy" parent="." instance=ExtResource( 10 )] 65 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, -2, 0, 0 ) 66 | 67 | [node name="ShellFur" parent="Ball_Boy/Armature/Skeleton/BallBoy" index="0"] 68 | mat_ao_light_affect = 0.0 69 | 70 | [node name="BoneAttachment" parent="Ball_Boy/Armature/Skeleton" index="1"] 71 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) 72 | 73 | [node name="LOD_Sphere" type="MeshInstance" parent="."] 74 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 5, 2, 2 ) 75 | mesh = SubResource( 3 ) 76 | 77 | [node name="LOD_label" parent="LOD_Sphere" instance=ExtResource( 5 )] 78 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0.787408, 0 ) 79 | fur_node = NodePath("../ShellFur") 80 | 81 | [node name="ShellFur" type="Spatial" parent="LOD_Sphere"] 82 | script = ExtResource( 4 ) 83 | shader_type = 0 84 | custom_shader = null 85 | layers = 40 86 | pattern_selector = 0 87 | pattern_texture = ExtResource( 3 ) 88 | pattern_uv_scale = 5.0 89 | cast_shadow = false 90 | mat_transmission = Color( 0.3, 0.3, 0.3, 1 ) 91 | mat_ao = 1.0 92 | mat_ao_light_affect = 0.0 93 | mat_roughness = 1.0 94 | mat_albedo_color = Transform( 0.43, 0.78, 0, 0.35, 0.63, 0, 0.29, 0.52, 0, 0, 0, 0 ) 95 | mat_albedo_uv_scale = Vector3( 1, 1, 0 ) 96 | mat_albedo_texture = null 97 | mat_shape_length = 0.213 98 | mat_shape_length_rand = 0.3 99 | mat_shape_density = 1.0 100 | mat_shape_thickness_base = 0.75 101 | mat_shape_thickness_tip = 0.3 102 | mat_shape_thickness_rand = 0.0 103 | mat_shape_growth = 1.0 104 | mat_shape_growth_rand = 0.0 105 | mat_shape_ldtg_uv_scale = Vector3( 1, 1, 0 ) 106 | mat_shape_ldtg_texture = null 107 | physics_custom_physics_pivot = NodePath("") 108 | physics_gravity = 1.0 109 | physics_spring = 4.0 110 | physics_damping = 0.1 111 | physics_wind_strength = 0.0 112 | physics_wind_speed = 1.0 113 | physics_wind_scale = 1.0 114 | physics_wind_angle = 0.0 115 | styling_blendshape = 0 116 | lod_LOD0_distance = 2.0 117 | lod_LOD1_distance = 5.0 118 | 119 | [node name="ball_boy" parent="." instance=ExtResource( 11 )] 120 | transform = Transform( 0.819742, 0, 0.572733, 0, 1, 0, -0.572733, 0, 0.819742, -1.57937, 0, -2.41692 ) 121 | 122 | [editable path="Rat"] 123 | [editable path="Cottage"] 124 | [editable path="Ball_Boy"] 125 | -------------------------------------------------------------------------------- /demo_mobile.tscn: -------------------------------------------------------------------------------- 1 | [gd_scene load_steps=6 format=2] 2 | 3 | [ext_resource path="res://assets/FPSLabel.gd" type="Script" id=1] 4 | [ext_resource path="res://assets/render_scaler.gd" type="Script" id=2] 5 | [ext_resource path="res://assets/scene_mobile.tscn" type="PackedScene" id=3] 6 | [ext_resource path="res://addons/joystick_control/assets/joystick.gd" type="Script" id=4] 7 | 8 | [sub_resource type="ViewportTexture" id=1] 9 | viewport_path = NodePath("Viewport") 10 | 11 | [node name="DemoMobile" type="Control"] 12 | anchor_right = 1.0 13 | anchor_bottom = 1.0 14 | margin_bottom = 6.10352e-05 15 | script = ExtResource( 2 ) 16 | __meta__ = { 17 | "_editor_description_": "" 18 | } 19 | 20 | [node name="Viewport" type="Viewport" parent="."] 21 | size = Vector2( 1280, 720 ) 22 | handle_input_locally = false 23 | hdr = false 24 | usage = 3 25 | render_target_update_mode = 3 26 | shadow_atlas_size = 4096 27 | 28 | [node name="World" parent="Viewport" instance=ExtResource( 3 )] 29 | 30 | [node name="ShellFur" parent="Viewport/World/Rat/Armature/Skeleton/Rat Body" index="0"] 31 | shader_type = 1 32 | layers = 20 33 | 34 | [node name="ShellFur" parent="Viewport/World/Cottage/Cottage Fur Roof" index="0"] 35 | shader_type = 1 36 | layers = 20 37 | 38 | [node name="ShellFur" parent="Viewport/World/Mossy_Log/mossy_log" index="0"] 39 | shader_type = 1 40 | layers = 10 41 | 42 | [node name="ShellFur" parent="Viewport/World/Ball_Boy/Armature/Skeleton/BallBoy" index="0"] 43 | shader_type = 1 44 | layers = 20 45 | 46 | [node name="BoneAttachment" parent="Viewport/World/Ball_Boy/Armature/Skeleton" index="1"] 47 | transform = Transform( 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0 ) 48 | 49 | [node name="ShellFur" parent="Viewport/World/LOD_Sphere" index="1"] 50 | shader_type = 1 51 | layers = 20 52 | 53 | [node name="Skeleton" parent="Viewport/World/ball_boy/Armature" index="0"] 54 | bones/0/bound_children = [ NodePath("BoneAttachment") ] 55 | 56 | [node name="ShellFur" parent="Viewport/World/ball_boy/Armature/Skeleton/BallBoy" index="0"] 57 | shader_type = 1 58 | layers = 20 59 | mat_ao_light_affect = 0.0 60 | 61 | [node name="TextureRect" type="TextureRect" parent="."] 62 | anchor_right = 1.0 63 | anchor_bottom = 1.0 64 | texture = SubResource( 1 ) 65 | expand = true 66 | flip_v = true 67 | __meta__ = { 68 | "_edit_use_anchors_": false 69 | } 70 | 71 | [node name="CanvasLayer" type="CanvasLayer" parent="."] 72 | scale = Vector2( 4, 4 ) 73 | transform = Transform2D( 4, 0, 0, 4, 0, 0 ) 74 | 75 | [node name="Joystick Left" type="Control" parent="CanvasLayer"] 76 | anchor_left = 0.041 77 | anchor_top = 0.184 78 | anchor_right = 0.064 79 | anchor_bottom = 0.212 80 | margin_top = 6.10352e-05 81 | margin_right = 40.0 82 | margin_bottom = 40.0001 83 | script = ExtResource( 4 ) 84 | __meta__ = { 85 | "_edit_use_anchors_": false 86 | } 87 | 88 | [node name="Joystick Right" type="Control" parent="CanvasLayer"] 89 | anchor_left = 0.211 90 | anchor_top = 0.184 91 | anchor_right = 0.225 92 | anchor_bottom = 0.212 93 | margin_top = 6.10352e-05 94 | margin_right = 40.0 95 | margin_bottom = 40.0001 96 | script = ExtResource( 4 ) 97 | __meta__ = { 98 | "_edit_use_anchors_": false 99 | } 100 | 101 | [node name="FPS Counter" type="CanvasLayer" parent="."] 102 | script = ExtResource( 1 ) 103 | 104 | [editable path="Viewport/World"] 105 | [editable path="Viewport/World/Rat"] 106 | [editable path="Viewport/World/Cottage"] 107 | [editable path="Viewport/World/Mossy_Log"] 108 | [editable path="Viewport/World/Ball_Boy"] 109 | [editable path="Viewport/World/ball_boy"] 110 | -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Arnklit/ShellFurGodotDemo/ca906d71517340e5fd99ff3708930bc0fd4a0a2e/icon.png -------------------------------------------------------------------------------- /icon.png.import: -------------------------------------------------------------------------------- 1 | [remap] 2 | 3 | importer="texture" 4 | type="StreamTexture" 5 | path="res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" 6 | metadata={ 7 | "vram_texture": false 8 | } 9 | 10 | [deps] 11 | 12 | source_file="res://icon.png" 13 | dest_files=[ "res://.import/icon.png-487276ed1e3a0c39cad0279d744ee560.stex" ] 14 | 15 | [params] 16 | 17 | compress/mode=0 18 | compress/lossy_quality=0.7 19 | compress/hdr_mode=0 20 | compress/bptc_ldr=0 21 | compress/normal_map=0 22 | flags/repeat=0 23 | flags/filter=true 24 | flags/mipmaps=false 25 | flags/anisotropic=false 26 | flags/srgb=2 27 | process/fix_alpha_border=true 28 | process/premult_alpha=false 29 | process/HDR_as_SRGB=false 30 | process/invert_color=false 31 | stream=false 32 | size_limit=0 33 | detect_3d=true 34 | svg/scale=1.0 35 | -------------------------------------------------------------------------------- /project.godot: -------------------------------------------------------------------------------- 1 | ; Engine configuration file. 2 | ; It's best edited using the editor UI and not directly, 3 | ; since the parameters that go here are not all obvious. 4 | ; 5 | ; Format: 6 | ; [section] ; section goes between [] 7 | ; param=value ; assign values to parameters 8 | 9 | config_version=4 10 | 11 | _global_script_classes=[ { 12 | "base": "CanvasLayer", 13 | "class": "FpsLabel", 14 | "language": "GDScript", 15 | "path": "res://assets/FPSLabel.gd" 16 | } ] 17 | _global_script_class_icons={ 18 | "FpsLabel": "" 19 | } 20 | 21 | [application] 22 | 23 | config/name="ShellFurTool-Demo" 24 | run/main_scene="res://demo_mobile.tscn" 25 | config/icon="res://icon.png" 26 | 27 | [display] 28 | 29 | window/size/width=1920 30 | window/size/height=1080 31 | window/dpi/allow_hidpi=true 32 | 33 | [editor_plugins] 34 | 35 | enabled=PoolStringArray( "res://addons/joystick_control/plugin.cfg", "res://addons/shell_fur/plugin.cfg" ) 36 | 37 | [global] 38 | 39 | etx=false 40 | etc=false 41 | 42 | [input] 43 | 44 | ui_left={ 45 | "deadzone": 0.5, 46 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777231,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 47 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":14,"pressure":0.0,"pressed":false,"script":null) 48 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":65,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 49 | ] 50 | } 51 | ui_right={ 52 | "deadzone": 0.5, 53 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777233,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 54 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":15,"pressure":0.0,"pressed":false,"script":null) 55 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":68,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 56 | ] 57 | } 58 | ui_up={ 59 | "deadzone": 0.5, 60 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777232,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 61 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":12,"pressure":0.0,"pressed":false,"script":null) 62 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":87,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 63 | ] 64 | } 65 | ui_down={ 66 | "deadzone": 0.5, 67 | "events": [ Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":16777234,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 68 | , Object(InputEventJoypadButton,"resource_local_to_scene":false,"resource_name":"","device":0,"button_index":13,"pressure":0.0,"pressed":false,"script":null) 69 | , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"alt":false,"shift":false,"control":false,"meta":false,"command":false,"pressed":false,"scancode":83,"physical_scancode":0,"unicode":0,"echo":false,"script":null) 70 | ] 71 | } 72 | 73 | [rendering] 74 | 75 | quality/filters/use_fxaa=true 76 | environment/default_environment="res://default_env.tres" 77 | --------------------------------------------------------------------------------