diff --git a/client/camera/Camera.gd b/client/camera/Camera.gd index edccae3..ac1e510 100644 --- a/client/camera/Camera.gd +++ b/client/camera/Camera.gd @@ -1,8 +1,6 @@ class_name Camera extends Camera3D -@export_flags_3d_physics var collision_mask := 1 - @export_group("Zoom") @export var zoom_speed := 0.5 @export var zoom_interpolation := 10.0 @@ -10,12 +8,9 @@ extends Camera3D @export var zoom_max := 8.0 var target_distance: float -var occlusion_distance: float = far -var pivot: Node3D func _ready(): target_distance = position.z - pivot = get_parent() Global.camera = self func _input(event): @@ -33,39 +28,20 @@ func on_distance_changed(): target_distance = clampf(target_distance, zoom_min, zoom_max) Global.camera_attributes.dof_blur_far_distance = target_distance + 1.0 +func is_below_terrain(): + return %CameraRays.occlusion_point.y > global_position.y + func _process(delta): var distance := target_distance - if occlusion_distance < target_distance: - distance = occlusion_distance + if %CameraRays.occlusion_distance < target_distance: + distance = %CameraRays.occlusion_distance - 0.5 + + if is_below_terrain(): + position.z = distance + return if abs(distance - position.z) < 0.01: return position.z = lerpf(position.z, distance, zoom_interpolation * delta) - -func _physics_process(_delta): - occlusion_distance = far - - var corner: Vector2 = get_viewport().get_visible_rect().size - var space_state = get_world_3d().direct_space_state - - send_ray(space_state, Vector2(0, 0)) - send_ray(space_state, Vector2(corner.x, 0)) - send_ray(space_state, Vector2(0, corner.y)) - send_ray(space_state, Vector2(corner.x, corner.y)) - send_ray(space_state, Vector2(corner.x / 2, corner.y / 2)) - -func send_ray(space_state: PhysicsDirectSpaceState3D, pos: Vector2): - var from := pivot.global_position - var to := project_position(pos, -1) - var query = PhysicsRayQueryParameters3D.create(from, to, collision_mask) - var result = space_state.intersect_ray(query) - - if result: - var hit_point: Vector3 = result.position - var diff := hit_point - pivot.global_position - var distance := diff.length() - - if distance < occlusion_distance: - occlusion_distance = distance \ No newline at end of file diff --git a/client/camera/Camera.tscn b/client/camera/Camera.tscn index 758f1cf..f8a1f15 100644 --- a/client/camera/Camera.tscn +++ b/client/camera/Camera.tscn @@ -1,9 +1,10 @@ -[gd_scene load_steps=5 format=3 uid="uid://cpdoq0oh84mfw"] +[gd_scene load_steps=6 format=3 uid="uid://cpdoq0oh84mfw"] [ext_resource type="Script" path="res://camera/FollowPlayer.gd" id="1_48rtd"] [ext_resource type="Script" path="res://camera/CameraPivot.gd" id="2_dylfm"] [ext_resource type="Script" path="res://camera/Camera.gd" id="2_pwdc2"] [ext_resource type="CameraAttributesPractical" uid="uid://b835orxyqq6w5" path="res://camera/CameraPractical.tres" id="3_olar0"] +[ext_resource type="Script" path="res://camera/CameraRays.gd" id="5_5b07p"] [node name="Follow" type="Marker3D"] script = ExtResource("1_48rtd") @@ -23,3 +24,7 @@ fov = 45.0 size = 10.0 far = 1000.0 script = ExtResource("2_pwdc2") + +[node name="CameraRays" type="Node3D" parent="Pivot"] +unique_name_in_owner = true +script = ExtResource("5_5b07p") diff --git a/client/camera/CameraPractical.tres b/client/camera/CameraPractical.tres index 068c203..58c6df7 100644 --- a/client/camera/CameraPractical.tres +++ b/client/camera/CameraPractical.tres @@ -4,3 +4,4 @@ exposure_multiplier = 0.5 dof_blur_far_transition = 50.0 dof_blur_near_enabled = true +dof_blur_near_distance = 1.8 diff --git a/client/camera/CameraRays.gd b/client/camera/CameraRays.gd new file mode 100644 index 0000000..6452f09 --- /dev/null +++ b/client/camera/CameraRays.gd @@ -0,0 +1,38 @@ +class_name CameraRays +extends Node3D + +@export_flags_3d_physics var collision_mask := 1 + +var occlusion_distance: float = 1000 +var occlusion_point: Vector3 +var pivot: Node3D + +func _ready(): + pivot = get_parent() + +func _physics_process(_delta): + occlusion_distance = Global.camera.far + + var corner: Vector2 = get_viewport().get_visible_rect().size + var space_state = get_world_3d().direct_space_state + + send_ray(space_state, Vector2(0, 0)) + send_ray(space_state, Vector2(corner.x, 0)) + send_ray(space_state, Vector2(0, corner.y)) + send_ray(space_state, Vector2(corner.x, corner.y)) + send_ray(space_state, Vector2(corner.x / 2, corner.y / 2)) + +func send_ray(space_state: PhysicsDirectSpaceState3D, pos: Vector2): + var from := pivot.global_position + var to := Global.camera.project_position(pos, -1) + var query = PhysicsRayQueryParameters3D.create(from, to, collision_mask) + var result = space_state.intersect_ray(query) + + if result: + var hit_point: Vector3 = result.position + var diff := hit_point - pivot.global_position + var distance := diff.length() + + if distance < occlusion_distance: + occlusion_distance = distance + occlusion_point = hit_point \ No newline at end of file