diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..b3e9312 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,22 @@ + +The MIT License (MIT) + +Copyright (c) 2021 João Marinheiro + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/project.godot b/project.godot index 2be809e..42ff1a3 100644 --- a/project.godot +++ b/project.godot @@ -9,11 +9,16 @@ config_version=4 _global_script_classes=[ { -"base": "Camera", +"base": "CameraOutline", "class": "CameraController", "language": "GDScript", "path": "res://utils/camera/CameraController.gd" }, { +"base": "Camera", +"class": "CameraOutline", +"language": "GDScript", +"path": "res://utils/camera/outline.gd" +}, { "base": "Reference", "class": "Delaunator", "language": "GDScript", @@ -31,6 +36,7 @@ _global_script_classes=[ { } ] _global_script_class_icons={ "CameraController": "", +"CameraOutline": "", "Delaunator": "", "PoissonDiscSampling": "", "Terrain": "" @@ -46,6 +52,10 @@ config/icon="res://icon.png" Global="*res://utils/Global.gd" +[editor_plugins] + +enabled=PoolStringArray( ) + [gui] common/drop_mouse_on_gui_input_disabled=true diff --git a/utils/camera/CamBase.tscn b/utils/camera/CamBase.tscn index 7e9ecb6..beda4a5 100644 --- a/utils/camera/CamBase.tscn +++ b/utils/camera/CamBase.tscn @@ -15,10 +15,6 @@ size = 20.0 near = 0.01 far = 8192.0 script = ExtResource( 3 ) -movement_speed = 70.017 -min_zoom = 51.0 -zoom_sensibility = 2.818 -rotation_sensibility = 1.0 [node name="Node" type="Node" parent="Camera"] script = ExtResource( 4 ) diff --git a/utils/camera/CameraController.gd b/utils/camera/CameraController.gd index 52597ef..7ddf252 100644 --- a/utils/camera/CameraController.gd +++ b/utils/camera/CameraController.gd @@ -1,4 +1,4 @@ -extends Camera +extends CameraOutline class_name CameraController signal camera_moved(new_location) @@ -8,7 +8,7 @@ enum CAMERA_ACTIONS{ ROTATING_VIEW, } -export(float,1,100) var movement_speed = 30 +export(float,1,100) var movement_speed = 48 export(float,0.01,0.99) var movement_damping = 0.74 export(float,0.01, 3.1415) var max_rotation = 1.2 export(float,0.01, 3.1415) var min_rotation = 0.5 @@ -18,10 +18,10 @@ export(float,0.01, 3.1415) var min_rotation = 0.5 export(float, 0.0,1.0) var edge_size = 0.0 #EDIT HERE--->**,***<--- ZOOM MIN AND MAX LIMITS -export(float, 10,100) var min_zoom = 25 +export(float, 10,100) var min_zoom = 10 export(float, 10,100) var max_zoom = 100 -export(float, 1,3) var zoom_sensibility = 2.5 +export(float, 1,3) var zoom_sensibility = 1.4 export(float, 1,3) var rotation_sensibility = 2.3 export(float, 1.0, 10.0) var height = 5.0 diff --git a/utils/camera/outline.gd b/utils/camera/outline.gd new file mode 100644 index 0000000..e2e9316 --- /dev/null +++ b/utils/camera/outline.gd @@ -0,0 +1,156 @@ +tool +extends Camera + +class_name CameraOutline + +var screen_mesh : MeshInstance; + +var global_post_process_material : ShaderMaterial = preload("post_process_outlines_material.tres"); +var instance_post_process_material : ShaderMaterial = global_post_process_material.duplicate(); + +#Size of color outlines +export (float) var color_outline_scale = 0.0 setget set_color_scale, get_color_scale + +#Size of depth outlines +export (float) var depth_outline_scale = 2.0 setget set_depth_scale, get_depth_scale + +#Controls sensitivity to depth changes (lower values mean more outlines, but more artifacts too) +export (float,0,10) var depth_threshold = 0.1 setget set_depth_thres, get_depth_thres + +#Multiplier for depth values +export (float) var depth_multiplier = 99999.0 setget set_depth_multiplier, get_depth_multiplier + +#General threshold for values to be considered as edges +export (float,0,1) var edge_threshold = 0.332 setget set_edge_threshold, get_edge_threshold + +#Max edge alpha, lower values means edges blend more with background +export (float,0,1) var max_edge_alpha = 0.791 setget set_max_edge_alpha, get_max_edge_alpha + +#General multiplier for edge alpha value, higher values mean harder edges +export (float) var edge_alpha_multiplier = 3.0 setget set_alpha_multiplier, get_alpha_multiplier + +#Outlines color +export (Color) var edge_color = Color(0.4,0.4,0.4,1) setget set_edge_color, get_edge_color + +#Sets depth edges to use the laplace operator instead of sobel +export (Texture) var background_tex setget set_bg_tex, get_bg_tex + +#Sets depth edges to use the laplace operator instead of sobel +export (bool) var depth_use_laplace = true setget set_depth_use_laplace, get_depth_use_laplace + +#Sets color edges to use the laplace operator instead of sobel +export (bool) var color_use_laplace = false setget set_color_use_laplace, get_color_use_laplace + +#Sets shader to use render the BG behind the edges +export (bool) var use_bg_texture = false setget set_use_bg_texture, get_use_bg_texture + +func set_color_scale(value): + color_outline_scale = value; + instance_post_process_material.set_shader_param("color_outline_scale", value); + +func get_color_scale(): + return color_outline_scale; + +func set_depth_scale(value): + depth_outline_scale = value; + instance_post_process_material.set_shader_param("depth_outline_scale", value); + +func get_depth_scale(): + return depth_outline_scale; + +func set_depth_thres(value): + depth_threshold = value; + instance_post_process_material.set_shader_param("depth_threshold", value); + +func get_depth_thres(): + return depth_threshold; + +func set_depth_multiplier(value): + depth_multiplier = value; + instance_post_process_material.set_shader_param("depth_multiplier", value); + +func get_depth_multiplier(): + return depth_multiplier; + +func set_edge_threshold(value): + edge_threshold = value; + instance_post_process_material.set_shader_param("edge_threshold", value); + +func get_edge_threshold(): + return edge_threshold; + +func set_max_edge_alpha(value): + max_edge_alpha = value; + instance_post_process_material.set_shader_param("max_edge_alpha", value); + +func get_max_edge_alpha(): + return max_edge_alpha; + +func set_alpha_multiplier(value): + edge_alpha_multiplier = value; + instance_post_process_material.set_shader_param("edge_alpha_multiplier", value); + +func get_alpha_multiplier(): + return edge_alpha_multiplier; + +func set_edge_color(value): + edge_color = value; + instance_post_process_material.set_shader_param("edge_color", value); + +func get_edge_color(): + return edge_color; + +func set_bg_tex(value): + background_tex = value; + instance_post_process_material.set_shader_param("bgTex", value); + +func get_bg_tex(): + return background_tex; + +func set_depth_use_laplace(value): + depth_use_laplace = value; + instance_post_process_material.set_shader_param("depth_use_laplace", value); + +func get_depth_use_laplace(): + return depth_use_laplace; + +func set_color_use_laplace(value): + color_use_laplace = value; + instance_post_process_material.set_shader_param("color_use_laplace", value); + +func get_color_use_laplace(): + return color_use_laplace; + +func set_use_bg_texture(value): + use_bg_texture = value; + instance_post_process_material.set_shader_param("use_bg_texture", value); + +func get_use_bg_texture(): + return use_bg_texture; + +func _ready(): + screen_mesh = MeshInstance.new(); + var quad : QuadMesh = QuadMesh.new(); + quad.size = Vector2(2,2); + screen_mesh.mesh = quad; + screen_mesh.material_override = instance_post_process_material; + screen_mesh.extra_cull_margin = 16000; + add_child(screen_mesh); + + set_color_scale(color_outline_scale) + set_depth_scale(depth_outline_scale) + set_alpha_multiplier(edge_alpha_multiplier) + set_depth_thres(depth_threshold) + set_depth_multiplier(depth_multiplier) + set_edge_threshold(edge_threshold) + set_max_edge_alpha(max_edge_alpha) + set_edge_color(edge_color) + set_bg_tex(background_tex) + set_use_bg_texture(use_bg_texture) + set_depth_use_laplace(depth_use_laplace) + set_color_use_laplace(color_use_laplace) + + +# Called every frame. 'delta' is the elapsed time since the previous frame. +#func _process(delta): +# pass diff --git a/utils/camera/post_process_outlines.shader b/utils/camera/post_process_outlines.shader new file mode 100644 index 0000000..b200433 --- /dev/null +++ b/utils/camera/post_process_outlines.shader @@ -0,0 +1,134 @@ +shader_type spatial; +render_mode depth_draw_never, depth_test_disable, unshaded; + +uniform float color_outline_scale = 2.0; // Size of color outlines +uniform float depth_outline_scale = 2.0; // Size of depth outlines +uniform float depth_threshold : hint_range(0,10) = 2.5; // Controls sensitivity to depth changes (lower values mean more outlines, but more artifacts too) +uniform float depth_multiplier = 1000.0; // Multiplier for depth values +uniform float edge_threshold : hint_range(0,1) = 0.04; // General threshold for values to be considered as edges +uniform float max_edge_alpha : hint_range(0,1) = 0.8; // Max edge alpha, lower values means edges blend more with background +uniform float edge_alpha_multiplier = 3.0; // General multiplier for edge alpha value, higher values mean harder edges + +uniform vec4 edge_color : hint_color = vec4(0,0,0,1); // Outlines color +uniform sampler2D bgTex : hint_albedo; // BG texture + +uniform bool depth_use_laplace = true; // Sets depth edges to use the laplace operator instead of sobel +uniform bool color_use_laplace = false; // Sets color edges to use the laplace operator instead of sobel +uniform bool use_bg_texture = false; // Sets shader to use render the BG behind the edges + +varying mat4 CAMERA; + +void vertex() { + POSITION = vec4(VERTEX, 1.0); + CAMERA = CAMERA_MATRIX; +} + +float getDepthVal(sampler2D depthTex, vec2 depthUV, mat4 invProjMat) { + float depth = texture(depthTex, depthUV).r; + return depth; +} + +void fragment() { + float halfScaleFloor_c = floor(color_outline_scale * 0.5); + float halfScaleCeil_c = ceil(color_outline_scale * 0.5); + float halfScaleFloor_d = floor(depth_outline_scale * 0.5); + float halfScaleCeil_d = ceil(depth_outline_scale * 0.5); + vec2 texelSize = vec2(1.0/VIEWPORT_SIZE.x, 1.0/VIEWPORT_SIZE.y); + + vec2 bottomLeftUV_c = SCREEN_UV - vec2(texelSize.x, texelSize.y) * halfScaleFloor_c; + vec2 topRightUV_c = SCREEN_UV + vec2(texelSize.x, texelSize.y) * halfScaleCeil_c; + vec2 topUV_c = SCREEN_UV + vec2(0.0, texelSize.y * halfScaleCeil_c); + vec2 bottomUV_c = SCREEN_UV + vec2(0.0, -texelSize.y * halfScaleFloor_c); + vec2 rightUV_c = SCREEN_UV + vec2(texelSize.x * halfScaleCeil_c, 0.0); + vec2 leftUV_c = SCREEN_UV + vec2(-texelSize.x * halfScaleFloor_c, 0.0); + vec2 bottomRightUV_c = SCREEN_UV + vec2(texelSize.x * halfScaleCeil_c, -texelSize.y * halfScaleFloor_c); + vec2 topLeftUV_c = SCREEN_UV + vec2(-texelSize.x * halfScaleFloor_c, texelSize.y * halfScaleCeil_c); + vec2 centerUV_c = SCREEN_UV; + + vec2 bottomLeftUV_d = SCREEN_UV - vec2(texelSize.x, texelSize.y) * halfScaleFloor_d; + vec2 topRightUV_d = SCREEN_UV + vec2(texelSize.x, texelSize.y) * halfScaleCeil_d; + vec2 topUV_d = SCREEN_UV + vec2(0.0, texelSize.y * halfScaleCeil_d); + vec2 bottomUV_d = SCREEN_UV + vec2(0.0, -texelSize.y * halfScaleFloor_d); + vec2 rightUV_d = SCREEN_UV + vec2(texelSize.x * halfScaleCeil_d, 0.0); + vec2 leftUV_d = SCREEN_UV + vec2(-texelSize.x * halfScaleFloor_d, 0.0); + vec2 bottomRightUV_d = SCREEN_UV + vec2(texelSize.x * halfScaleCeil_d, -texelSize.y * halfScaleFloor_d); + vec2 topLeftUV_d = SCREEN_UV + vec2(-texelSize.x * halfScaleFloor_d, texelSize.y * halfScaleCeil_d); + vec2 centerUV_d = SCREEN_UV; + + float d0 = getDepthVal(DEPTH_TEXTURE, topLeftUV_d, INV_PROJECTION_MATRIX); + float d1 = getDepthVal(DEPTH_TEXTURE, topUV_d, INV_PROJECTION_MATRIX); + float d2 = getDepthVal(DEPTH_TEXTURE, topRightUV_d, INV_PROJECTION_MATRIX); + float d3 = getDepthVal(DEPTH_TEXTURE, leftUV_d, INV_PROJECTION_MATRIX); + float d4 = getDepthVal(DEPTH_TEXTURE, centerUV_d, INV_PROJECTION_MATRIX); + float d5 = getDepthVal(DEPTH_TEXTURE, rightUV_d, INV_PROJECTION_MATRIX); + float d6 = getDepthVal(DEPTH_TEXTURE, bottomLeftUV_d, INV_PROJECTION_MATRIX); + float d7 = getDepthVal(DEPTH_TEXTURE, bottomUV_d, INV_PROJECTION_MATRIX); + float d8 = getDepthVal(DEPTH_TEXTURE, bottomRightUV_d, INV_PROJECTION_MATRIX); + + float edgeDepth = 0.0; + if (depth_use_laplace) { + edgeDepth = (8.0 * d4 - (d0+d1+d2+d3+d5+d6+d7+d8)) * depth_multiplier; + } + else { + float d_sobel_edge_h = (d2 + (2.0*d5) + d8 - (d0 + (2.0*d3) + d6)) / 4.0; + float d_sobel_edge_v = (d0 + (2.0*d1) + d2 - (d6 + (2.0*d7) + d8)) / 4.0; + edgeDepth = sqrt((d_sobel_edge_h * d_sobel_edge_h) + (d_sobel_edge_v * d_sobel_edge_v)) * depth_multiplier; + } + + + float depthThreshold = depth_threshold * d0; + edgeDepth = smoothstep(depthThreshold-depthThreshold/5.0, depthThreshold, edgeDepth); + + float edgeVal = edgeDepth; + + vec4 n0 = texture(SCREEN_TEXTURE, topLeftUV_c); + vec4 n1 = texture(SCREEN_TEXTURE, topUV_c); + vec4 n2 = texture(SCREEN_TEXTURE, topRightUV_c); + vec4 n3 = texture(SCREEN_TEXTURE, leftUV_c); + vec4 n4 = texture(SCREEN_TEXTURE, centerUV_c); + vec4 n5 = texture(SCREEN_TEXTURE, rightUV_c); + vec4 n6 = texture(SCREEN_TEXTURE, bottomLeftUV_c); + vec4 n7 = texture(SCREEN_TEXTURE, bottomUV_c); + vec4 n8 = texture(SCREEN_TEXTURE, bottomRightUV_c); + + + float color_edge; + + if (color_use_laplace) { + vec4 laplace_edge = (8.0 * n4 - (n0+n1+n2+n3+n5+n6+n7+n8)); + color_edge = laplace_edge.r; + color_edge += laplace_edge.g; + color_edge += laplace_edge.b; + color_edge /= 3.0; + } + else { + vec4 sobel_edge_h = (n2 + (2.0*n5) + n8 - (n0 + (2.0*n3) + n6)) / 4.0; + vec4 sobel_edge_v = (n0 + (2.0*n1) + n2 - (n6 + (2.0*n7) + n8)) / 4.0; + vec4 sobel = sqrt((sobel_edge_h * sobel_edge_h) + (sobel_edge_v * sobel_edge_v)); + color_edge = sobel.r; + color_edge += sobel.g; + color_edge += sobel.b; + color_edge /= 3.0; + } + + edgeVal = max(edgeVal, color_edge); + + if (edgeVal > edge_threshold) { + if (use_bg_texture) { + ALBEDO = edge_color.rgb * texture(bgTex, SCREEN_UV).rgb; + } + else { + ALBEDO = edge_color.rgb; + ALPHA = min(max_edge_alpha,edgeVal * edge_alpha_multiplier); + } + + } + else { + if (use_bg_texture) { + ALBEDO = texture(bgTex, SCREEN_UV).rgb; + } + else { + ALPHA = 0.0; + } + } +} \ No newline at end of file diff --git a/utils/camera/post_process_outlines_material.tres b/utils/camera/post_process_outlines_material.tres new file mode 100644 index 0000000..2308901 --- /dev/null +++ b/utils/camera/post_process_outlines_material.tres @@ -0,0 +1,18 @@ +[gd_resource type="ShaderMaterial" load_steps=2 format=2] + +[ext_resource path="res://utils/camera/post_process_outlines.shader" type="Shader" id=1] + +[resource] +resource_local_to_scene = true +shader = ExtResource( 1 ) +shader_param/color_outline_scale = 1.0 +shader_param/depth_outline_scale = 1.0 +shader_param/depth_threshold = 1.0 +shader_param/depth_multiplier = 10000.0 +shader_param/edge_threshold = 0.1 +shader_param/max_edge_alpha = 0.8 +shader_param/edge_alpha_multiplier = 3.0 +shader_param/edge_color = Color( 0, 0, 0, 1 ) +shader_param/depth_use_laplace = true +shader_param/color_use_laplace = false +shader_param/use_bg_texture = false diff --git a/world/game.tscn b/world/game.tscn index e8a7107..a1855c0 100644 --- a/world/game.tscn +++ b/world/game.tscn @@ -38,14 +38,12 @@ environment = ExtResource( 3 ) [node name="CamBase" parent="World3d" instance=ExtResource( 5 )] [node name="Camera" parent="World3d/CamBase" index="0"] -transform = Transform( 1, 0, 0, 0, 0.910272, -0.41401, 0, 0.41401, 0.910272, 0, -1.90735e-06, 6.618 ) -movement_speed = 48.076 -min_zoom = 10.0 +transform = Transform( 1, 0, 0, 0, 0.659983, -0.75128, 0, 0.75128, 0.659983, 0, -1.90735e-06, 6.618 ) +fov = 55.0 zoom_sensibility = 1.436 -rotation_sensibility = 3.0 [node name="DirectionalLight" type="DirectionalLight" parent="World3d"] -transform = Transform( 1, 0, 0, 0, 0.512597, 0.858629, 0, -0.858629, 0.512597, 0, 1.41623, 0 ) +transform = Transform( 1, 0, 0, 0, 0.641744, 0.766919, 0, -0.766919, 0.641744, 0, 1.41623, 0 ) light_energy = 0.1 shadow_enabled = true diff --git a/world/world.material b/world/world.material index e4ba4f6..2448577 100644 Binary files a/world/world.material and b/world/world.material differ