Bläddra i källkod

Add doors as an example of dynamic occluders in the Occlusion culling demo (#807)

The occluders don't actually move, but are toggled when the door starts
opening and finishes closing to avoid unnecessary BVH rebuilds.
Hugo Locurcio 1 år sedan
förälder
incheckning
4f866f2a9a

+ 30 - 0
3d/occlusion_culling_mesh_lod/door.gd

@@ -0,0 +1,30 @@
+extends Node3D
+
+
+var open := false
+
+
+func _input(event: InputEvent):
+	if event.is_action_pressed("toggle_doors"):
+		if open:
+			# Close the door.
+			# The occluder will be re-enabled when the animation ends
+			# using `_on_animation_player_animation_finished()`.
+			$AnimationPlayer.play_backwards("open")
+			open = false
+		else:
+			# Open the door.
+			$AnimationPlayer.play("open")
+			open = true
+			# Disable the occluder as soon as the door starts opening.
+			# The occluder is not part of the pivot to prevent it from having its
+			# position changed every frame, which causes the occlusion culling BVH
+			# to be rebuilt each frame. This causes a CPU performance penalty.
+			$OccluderInstance3D.visible = false
+
+
+func _on_animation_player_animation_finished(_anim_name):
+	if not open:
+		# Re-enable the occluder when the door is done closing.
+		# To prevent overocclusion, the door must be fully closed before the occluder can be re-enabled.
+		$OccluderInstance3D.visible = true

+ 77 - 0
3d/occlusion_culling_mesh_lod/door.tscn

@@ -0,0 +1,77 @@
+[gd_scene load_steps=9 format=3 uid="uid://b72b3llm3ks25"]
+
+[ext_resource type="Script" path="res://door.gd" id="1_cd56o"]
+
+[sub_resource type="BoxMesh" id="BoxMesh_uwx0y"]
+size = Vector3(0.05, 3.25, 2.5)
+
+[sub_resource type="BoxMesh" id="BoxMesh_uj7hy"]
+size = Vector3(0.2, 0.2, 0.6)
+
+[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_yypcp"]
+
+[sub_resource type="BoxOccluder3D" id="BoxOccluder3D_gavni"]
+size = Vector3(0.05, 3.3, 2.5)
+
+[sub_resource type="Animation" id="Animation_4cjd4"]
+length = 0.001
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Pivot:rotation")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0),
+"transitions": PackedFloat32Array(1),
+"update": 0,
+"values": [Vector3(0, 0, 0)]
+}
+
+[sub_resource type="Animation" id="Animation_6r4px"]
+resource_name = "open"
+tracks/0/type = "value"
+tracks/0/imported = false
+tracks/0/enabled = true
+tracks/0/path = NodePath("Pivot:rotation")
+tracks/0/interp = 1
+tracks/0/loop_wrap = true
+tracks/0/keys = {
+"times": PackedFloat32Array(0, 1),
+"transitions": PackedFloat32Array(-2, -2),
+"update": 0,
+"values": [Vector3(0, 0, 0), Vector3(0, 1.5708, 0)]
+}
+
+[sub_resource type="AnimationLibrary" id="AnimationLibrary_5gp0p"]
+_data = {
+"RESET": SubResource("Animation_4cjd4"),
+"open": SubResource("Animation_6r4px")
+}
+
+[node name="Door" type="Node3D"]
+script = ExtResource("1_cd56o")
+
+[node name="Pivot" type="Node3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 1.2)
+
+[node name="MeshInstance3D" type="MeshInstance3D" parent="Pivot"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.005, -1.2)
+mesh = SubResource("BoxMesh_uwx0y")
+skeleton = NodePath("../..")
+
+[node name="MeshInstance3D" type="MeshInstance3D" parent="Pivot/MeshInstance3D"]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, -0.2, -0.8)
+mesh = SubResource("BoxMesh_uj7hy")
+surface_material_override/0 = SubResource("StandardMaterial3D_yypcp")
+
+[node name="OccluderInstance3D" type="OccluderInstance3D" parent="."]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1.7, 0)
+occluder = SubResource("BoxOccluder3D_gavni")
+
+[node name="AnimationPlayer" type="AnimationPlayer" parent="."]
+libraries = {
+"": SubResource("AnimationLibrary_5gp0p")
+}
+
+[connection signal="animation_finished" from="AnimationPlayer" to="." method="_on_animation_player_animation_finished"]

+ 6 - 1
3d/occlusion_culling_mesh_lod/node_3d.gd

@@ -11,9 +11,14 @@ func _input(event):
 	if event.is_action_pressed("cycle_draw_mode"):
 		get_viewport().debug_draw = wrapi(get_viewport().debug_draw + 1, 0, 5)
 		update_labels()
+	if event.is_action_pressed("toggle_vsync"):
+		if DisplayServer.window_get_vsync_mode() == DisplayServer.VSYNC_DISABLED:
+			DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_ENABLED)
+		else:
+			DisplayServer.window_set_vsync_mode(DisplayServer.VSYNC_DISABLED)
 
 
-func _process(delta):
+func _process(_delta):
 	$Performance.text = """%d FPS (%.2f mspf)
 
 Currently rendering:

+ 20 - 3
3d/occlusion_culling_mesh_lod/node_3d.tscn

@@ -1,9 +1,10 @@
-[gd_scene load_steps=12 format=3 uid="uid://dp872nvjdbsc2"]
+[gd_scene load_steps=13 format=3 uid="uid://dp872nvjdbsc2"]
 
 [ext_resource type="ArrayOccluder3D" uid="uid://cop123efet6j2" path="res://node_3d.occ" id="1_clbmh"]
 [ext_resource type="Script" path="res://node_3d.gd" id="1_x3hdm"]
 [ext_resource type="Script" path="res://camera.gd" id="2_6krsy"]
 [ext_resource type="PackedScene" uid="uid://ck4wa4vxhhk1v" path="res://room.glb" id="2_fu476"]
+[ext_resource type="PackedScene" uid="uid://b72b3llm3ks25" path="res://door.tscn" id="5_cprsk"]
 
 [sub_resource type="PhysicalSkyMaterial" id="PhysicalSkyMaterial_gmnym"]
 energy_multiplier = 2.63
@@ -77,9 +78,9 @@ surface_material_override/0 = SubResource("StandardMaterial3D_4es5y")
 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 3.4, 0)
 light_color = Color(1, 0.909804, 0.537255, 1)
 shadow_enabled = true
-shadow_bias = 0.1
+shadow_bias = 0.07
 shadow_blur = 3.0
-omni_range = 7.0
+omni_range = 8.0
 
 [node name="Room2" parent="Rooms" instance=ExtResource("2_fu476")]
 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 10)
@@ -3150,6 +3151,20 @@ transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 110, 0, 190)
 [node name="Room1024" parent="Rooms" instance=ExtResource("2_fu476")]
 transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, 110, 0, 180)
 
+[node name="Doors" type="Node3D" parent="."]
+
+[node name="DoorNegX" parent="Doors" instance=ExtResource("5_cprsk")]
+transform = Transform3D(1, 0, 0, 0, 1, 0, 0, 0, 1, -15, 0, 0)
+
+[node name="DoorPosX" parent="Doors" instance=ExtResource("5_cprsk")]
+transform = Transform3D(-1, 0, -8.74228e-08, 0, 1, 0, 8.74228e-08, 0, -1, 15, 0, 0)
+
+[node name="DoorNegZ" parent="Doors" instance=ExtResource("5_cprsk")]
+transform = Transform3D(-4.37114e-08, 0, -1, 0, 1, 0, 1, 0, -4.37114e-08, 6.55671e-07, 0, -15)
+
+[node name="DoorPosZ" parent="Doors" instance=ExtResource("5_cprsk")]
+transform = Transform3D(-4.37114e-08, 0, 1, 0, 1, 0, -1, 0, -4.37114e-08, -6.55671e-07, 0, 15)
+
 [node name="OcclusionCulling" type="Label" parent="."]
 offset_left = 16.0
 offset_top = 16.0
@@ -3190,6 +3205,8 @@ theme_override_colors/font_outline_color = Color(0, 0, 0, 1)
 theme_override_constants/outline_size = 4
 text = "O: Toggle occlusion culling
 L: Toggle mesh LOD
+F: Open/close doors
+V: Toggle V-Sync
 Space: Cycle between draw modes
 Escape or F10: Toggle mouse capture"
 

+ 15 - 5
3d/occlusion_culling_mesh_lod/project.godot

@@ -54,13 +54,13 @@ move_left={
 ]
 }
 toggle_occlusion_culling={
-"deadzone": 0.2,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":79,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":79,"key_label":0,"unicode":0,"echo":false,"script":null)
 ]
 }
 toggle_mesh_lod={
-"deadzone": 0.2,
-"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":76,"physical_keycode":0,"key_label":0,"unicode":0,"echo":false,"script":null)
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":76,"key_label":0,"unicode":0,"echo":false,"script":null)
 ]
 }
 cycle_draw_mode={
@@ -74,9 +74,19 @@ toggle_mouse_capture={
 , Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":4194341,"key_label":0,"unicode":0,"echo":false,"script":null)
 ]
 }
+toggle_doors={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":70,"key_label":0,"unicode":0,"echo":false,"script":null)
+]
+}
+toggle_vsync={
+"deadzone": 0.5,
+"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":86,"key_label":0,"unicode":0,"echo":false,"script":null)
+]
+}
 
 [rendering]
 
-anti_aliasing/quality/screen_space_aa=1
+anti_aliasing/quality/msaa_3d=2
 anti_aliasing/quality/use_debanding=true
 occlusion_culling/use_occlusion_culling=true