Add an occlusion culling and mesh LOD demo (#801)

This commit is contained in:
Hugo Locurcio
2022-12-19 16:58:12 +01:00
committed by GitHub
parent 4eb852ac78
commit d3cc6be62c
14 changed files with 3532 additions and 0 deletions

View File

@@ -0,0 +1,43 @@
# Occlusion Culling and Mesh LOD
This demo showcases the use of occlusion culling and mesh level of detail in a 3D scene.
The demo contains 1,024 identical rooms in a 64×64 grid. The room geometry is
used as a basis for a baked OccluderInstance3D, which allows each room to be
culled if it is hidden by another room's walls.
Occlusion culling can provide a performance benefit in draw call-bound
scenarios. However, since the Forward Plus backend uses a depth prepass, the
shading cost is already reduced by the depth prepass. As a result, occlusion
culling will not always result in a tangible performance increase, especially in
outdoor scenes that have fewer occlusion culling opportunities. Indoor scenes
with no DirectionalLight3D casting shadows are a best-case scenario for
occlusion culling.
The blue spheres make use of automatically generated LODs, which reduce the
number of triangles that need to be rendered each frame by the GPU. This
provides a significant performance increase in scenes with complex geometry. In
most scenes, this provides a greater performance benefit compared to occlusion
culling.
While running the demo, you can toggle the use of mesh LOD and occlusion culling
to view the performance difference these features make in this project. Results
will vary depending on your CPU and GPU model.
> **Warning**
>
> If you are using a engine build that is not fully optimized, you may notice
> that enabling occlusion culling decreases performance. This is because
> occlusion culling is a demanding process on the CPU, which needs all the
> build-time optimization it can get.
>
> Official builds are fully optimized, but self-compiled builds are not fully
> optimized by default (use the `optimize=speed use_lto=yes` SCons options).
Language: GDScript
Renderer: Forward Plus
## Screenshot
![Screenshot](screenshots/occlusion_culling_mesh_lod.webp)

View File

@@ -0,0 +1,43 @@
extends Camera3D
const MOUSE_SENSITIVITY = 0.002
const MOVE_SPEED = 1.5
var rot = Vector3()
var velocity = Vector3()
func _ready():
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _input(event):
# Mouse look (only if the mouse is captured).
if event is InputEventMouseMotion and Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
# Horizontal mouse look.
rot.y -= event.relative.x * MOUSE_SENSITIVITY
# Vertical mouse look.
rot.x = clamp(rot.x - event.relative.y * MOUSE_SENSITIVITY, -1.57, 1.57)
transform.basis = Basis.from_euler(rot)
if event.is_action_pressed("toggle_mouse_capture"):
if Input.get_mouse_mode() == Input.MOUSE_MODE_CAPTURED:
Input.set_mouse_mode(Input.MOUSE_MODE_VISIBLE)
else:
Input.set_mouse_mode(Input.MOUSE_MODE_CAPTURED)
func _process(delta):
var motion = Vector3(
Input.get_axis(&"move_left", &"move_right"),
0,
Input.get_axis(&"move_forward", &"move_back")
)
# Normalize motion to prevent diagonal movement from being
# `sqrt(2)` times faster than straight movement.
motion = motion.normalized()
velocity += MOVE_SPEED * delta * (transform.basis * motion)
velocity *= 0.85
position += velocity

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,34 @@
[remap]
importer="texture"
type="CompressedTexture2D"
uid="uid://d1a87sh6t6ncl"
path="res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"
metadata={
"vram_texture": false
}
[deps]
source_file="res://icon.png"
dest_files=["res://.godot/imported/icon.png-487276ed1e3a0c39cad0279d744ee560.ctex"]
[params]
compress/mode=0
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/bptc_ldr=0
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1

View File

@@ -0,0 +1,49 @@
extends Node3D
func _input(event):
if event.is_action_pressed("toggle_occlusion_culling"):
get_viewport().use_occlusion_culling = not get_viewport().use_occlusion_culling
update_labels()
if event.is_action_pressed("toggle_mesh_lod"):
get_viewport().mesh_lod_threshold = 1.0 if is_zero_approx(get_viewport().mesh_lod_threshold) else 0.0
update_labels()
if event.is_action_pressed("cycle_draw_mode"):
get_viewport().debug_draw = wrapi(get_viewport().debug_draw + 1, 0, 5)
update_labels()
func _process(delta):
$Performance.text = """%d FPS (%.2f mspf)
Currently rendering:
%d objects
%dK primitive indices
%d draw calls
""" % [
Engine.get_frames_per_second(),
1000.0 / Engine.get_frames_per_second(),
RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_OBJECTS_IN_FRAME),
RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_PRIMITIVES_IN_FRAME) * 0.001,
RenderingServer.get_rendering_info(RenderingServer.RENDERING_INFO_TOTAL_DRAW_CALLS_IN_FRAME),
]
func update_labels():
$OcclusionCulling.text = "Occlusion culling: %s" % ("Enabled" if get_viewport().use_occlusion_culling else "Disabled")
$MeshLOD.text = "Mesh LOD: %s" % ("Enabled" if not is_zero_approx(get_viewport().mesh_lod_threshold) else "Disabled")
$DrawMode.text = "Draw mode: %s" % get_draw_mode_string(get_viewport().debug_draw)
func get_draw_mode_string(draw_mode):
match draw_mode:
0:
return "Normal"
1:
return "Unshaded"
2:
return "Lighting"
3:
return "Overdraw"
4:
return "Wireframe"

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,81 @@
; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
; [section] ; section goes between []
; param=value ; assign values to parameters
config_version=5
[application]
config/name="Occlusion Culling and Mesh LOD"
config/description="This demo showcases the use of occlusion culling and mesh level of detail in a 3D scene."
run/main_scene="res://node_3d.tscn"
config/features=PackedStringArray("4.0")
config/icon="res://icon.png"
[display]
window/vsync/vsync_mode=0
window/stretch/mode="canvas_items"
window/stretch/aspect="expand"
[filesystem]
import/blender/enabled=false
[input]
move_forward={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"unicode":0,"echo":false,"script":null)
, 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":4194320,"unicode":0,"echo":false,"script":null)
]
}
move_back={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"unicode":0,"echo":false,"script":null)
, 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":4194322,"unicode":0,"echo":false,"script":null)
]
}
move_right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"unicode":0,"echo":false,"script":null)
, 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":4194321,"unicode":0,"echo":false,"script":null)
]
}
move_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":0,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"unicode":0,"echo":false,"script":null)
, 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":4194319,"unicode":0,"echo":false,"script":null)
]
}
toggle_occlusion_culling={
"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":79,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
]
}
toggle_mesh_lod={
"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":76,"physical_keycode":0,"unicode":0,"echo":false,"script":null)
]
}
cycle_draw_mode={
"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":32,"unicode":0,"echo":false,"script":null)
]
}
toggle_mouse_capture={
"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":4194305,"unicode":0,"echo":false,"script":null)
, 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,"unicode":0,"echo":false,"script":null)
]
}
[rendering]
anti_aliasing/quality/screen_space_aa=1
anti_aliasing/quality/use_debanding=true
occlusion_culling/use_occlusion_culling=true

Binary file not shown.

View File

@@ -0,0 +1,45 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://cynp2w1tdntud"
path="res://.godot/imported/room.blend-36213b70cb5ffa4e1f840d45a32b9acb.scn"
[deps]
source_file="res://room.blend"
dest_files=["res://.godot/imported/room.blend-36213b70cb5ffa4e1f840d45a32b9acb.scn"]
[params]
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
import_script/path=""
_subresources={}
blender/nodes/visible=2
blender/nodes/punctual_lights=true
blender/nodes/cameras=true
blender/nodes/custom_properties=true
blender/nodes/modifiers=1
blender/meshes/colors=false
blender/meshes/uvs=true
blender/meshes/normals=true
blender/meshes/tangents=true
blender/meshes/skins=2
blender/meshes/export_bones_deforming_mesh_only=false
blender/materials/unpack_enabled=true
blender/materials/export_materials=1
blender/animation/limit_playback=true
blender/animation/always_sample=true
blender/animation/group_tracks=true

Binary file not shown.

View File

@@ -0,0 +1,29 @@
[remap]
importer="scene"
importer_version=1
type="PackedScene"
uid="uid://ck4wa4vxhhk1v"
path="res://.godot/imported/room.glb-80432416ed16d717e78c80d413b8774e.scn"
[deps]
source_file="res://room.glb"
dest_files=["res://.godot/imported/room.glb-80432416ed16d717e78c80d413b8774e.scn"]
[params]
nodes/root_type="Node3D"
nodes/root_name="Scene Root"
nodes/apply_root_scale=true
nodes/root_scale=1.0
meshes/ensure_tangents=true
meshes/generate_lods=true
meshes/create_shadow_meshes=true
meshes/light_baking=1
meshes/lightmap_texel_size=0.2
skins/use_named_skins=true
animation/import=true
animation/fps=30
import_script/path=""
_subresources={}

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB