mirror of
https://github.com/godotengine/godot-demo-projects.git
synced 2025-12-16 05:20:06 +01:00
265 lines
9.4 KiB
GDScript
265 lines
9.4 KiB
GDScript
extends Node3D
|
||
|
||
enum GIMode {
|
||
NONE,
|
||
LIGHTMAP_GI_ALL,
|
||
LIGHTMAP_GI_INDIRECT,
|
||
VOXEL_GI,
|
||
SDFGI,
|
||
MAX, # Maximum value of the enum, used internally.
|
||
}
|
||
|
||
enum ReflectionProbeMode {
|
||
NONE,
|
||
ONCE,
|
||
ALWAYS,
|
||
MAX,
|
||
}
|
||
|
||
enum SSILMode {
|
||
NONE,
|
||
SSAO,
|
||
SSIL,
|
||
SSAO_AND_SSIL,
|
||
MAX, # Maximum value of the enum, used internally.
|
||
}
|
||
|
||
# Keep this in sync with the SSILMode enum (except for MAX).
|
||
const SSIL_MODE_TEXTS = [
|
||
"Disabled (Fastest)",
|
||
"Screen-space ambient occlusion (Fast)",
|
||
"Screen-space indirect lighting (Average)",
|
||
"SSAO + SSIL (Slow)",
|
||
]
|
||
|
||
# Keep this in sync with the ReflectionProbeMode enum (except for MAX).
|
||
var reflection_probe_mode_texts: Array[String] = [
|
||
"Disabled - Using environment, VoxelGI or SDFGI reflections (Fast)",
|
||
"Enabled - \"Once\" Update Mode (Average)",
|
||
"Enabled - \"Always\" Update Mode (Slow)",
|
||
]
|
||
|
||
# Keep this in sync with the GIMode enum (except for MAX).
|
||
var gi_mode_texts: Array[String] = [
|
||
"Environment Lighting (Fastest)",
|
||
"Baked Lightmap All (Fast)",
|
||
"Baked Lightmap Indirect (Average)",
|
||
"VoxelGI (Slow)",
|
||
"SDFGI (Slow)",
|
||
]
|
||
|
||
var gi_mode := GIMode.NONE
|
||
var reflection_probe_mode := ReflectionProbeMode.NONE
|
||
var ssil_mode := SSILMode.NONE
|
||
var is_compatibility: bool = false
|
||
|
||
# This is replaced further below if using Compatibility to point to a newly created DirectionalLight3D
|
||
# (which does not affect sky rendering).
|
||
@onready var sun: DirectionalLight3D = $Sun
|
||
@onready var lightmap_gi_all_data: LightmapGIData = $LightmapGIAll.light_data
|
||
@onready var environment: Environment = $WorldEnvironment.environment
|
||
@onready var gi_mode_label: Label = $GIMode
|
||
@onready var reflection_probe_mode_label: Label = $ReflectionProbeMode
|
||
@onready var reflection_probe: ReflectionProbe = $Camera/ReflectiveSphere/ReflectionProbe
|
||
@onready var ssil_mode_label: Label = $SSILMode
|
||
|
||
# Several copies of the level mesh are required to cycle between different GI modes.
|
||
@onready var zdm2_lightmap_all: Node3D = $Zdm2LightmapAll
|
||
@onready var zdm2_lightmap_indirect: Node3D = $Zdm2LightmapIndirect
|
||
|
||
|
||
func _ready() -> void:
|
||
if RenderingServer.get_current_rendering_method() == "gl_compatibility":
|
||
is_compatibility = true
|
||
# Remove unsupported VoxelGI/SDFGI references from the label.
|
||
reflection_probe_mode_texts[0] = "Disabled - Using environment reflections (Fast)"
|
||
set_gi_mode(GIMode.NONE)
|
||
# Darken lights' energy to compensate for sRGB blending (without affecting sky rendering).
|
||
# This only applies to lights with shadows enabled.
|
||
$GrateOmniLight.light_energy = 0.25
|
||
$GarageOmniLight.light_energy = 0.5
|
||
sun.sky_mode = DirectionalLight3D.SKY_MODE_SKY_ONLY
|
||
sun = sun.duplicate()
|
||
sun.light_energy = 0.15
|
||
sun.sky_mode = DirectionalLight3D.SKY_MODE_LIGHT_ONLY
|
||
add_child(sun)
|
||
$Help.text = """Space: Cycle between GI modes
|
||
R: Cycle between reflection probe modes
|
||
Escape or F10: Toggle mouse capture"""
|
||
else:
|
||
set_gi_mode(gi_mode)
|
||
|
||
set_reflection_probe_mode(reflection_probe_mode)
|
||
set_ssil_mode(ssil_mode)
|
||
|
||
|
||
func _input(input_event: InputEvent) -> void:
|
||
if input_event.is_action_pressed(&"cycle_gi_mode"):
|
||
if is_compatibility:
|
||
# Only LightmapGI is supported in Compatibility.
|
||
# Note that the actual GI mode is the opposite of what's being set here, due to a bug
|
||
# in the Compatibility rendering method.
|
||
set_gi_mode(wrapi(gi_mode + 1, 0, GIMode.VOXEL_GI))
|
||
else:
|
||
set_gi_mode(wrapi(gi_mode + 1, 0, GIMode.MAX))
|
||
|
||
if input_event.is_action_pressed(&"cycle_reflection_probe_mode"):
|
||
set_reflection_probe_mode(wrapi(reflection_probe_mode + 1, 0, ReflectionProbeMode.MAX))
|
||
|
||
if input_event.is_action_pressed(&"cycle_ssil_mode"):
|
||
set_ssil_mode(wrapi(ssil_mode + 1, 0, SSILMode.MAX))
|
||
|
||
|
||
func set_gi_mode(p_gi_mode: GIMode) -> void:
|
||
gi_mode = p_gi_mode
|
||
gi_mode_label.text = "Global illumination: %s " % gi_mode_texts[gi_mode]
|
||
|
||
match p_gi_mode:
|
||
GIMode.NONE:
|
||
if is_compatibility:
|
||
# Work around Compatibility bug where lightmaps are still visible if the LightmapGI node is hidden.
|
||
$LightmapGIAll.light_data = null
|
||
|
||
$Zdm2LightmapAll.visible = true
|
||
$Zdm2LightmapIndirect.visible = false
|
||
|
||
# Halve sky contribution to prevent shaded areas from looking too bright and blue.
|
||
environment.ambient_light_sky_contribution = 0.5
|
||
$LightmapGIIndirect.visible = false
|
||
$LightmapGIAll.visible = false
|
||
$VoxelGI.visible = false
|
||
environment.sdfgi_enabled = false
|
||
|
||
# There is no difference between Indirect and Disabled when no GI is used.
|
||
# Pick the default value (which is Indirect).
|
||
sun.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GrateOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GarageOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$CornerSpotLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$Camera/Box.gi_mode = GeometryInstance3D.GI_MODE_DISABLED
|
||
|
||
GIMode.LIGHTMAP_GI_ALL:
|
||
$Zdm2LightmapAll.visible = true
|
||
$Zdm2LightmapIndirect.visible = false
|
||
$LightmapGIAll.light_data = lightmap_gi_all_data
|
||
|
||
# Halve sky contribution to prevent dynamic objects from looking too bright and blue.
|
||
# (When using lightmaps, this property doesn't affect lightmapped surfaces.)
|
||
environment.ambient_light_sky_contribution = 0.5
|
||
$LightmapGIIndirect.visible = false
|
||
$LightmapGIAll.visible = true
|
||
$VoxelGI.visible = false
|
||
environment.sdfgi_enabled = false
|
||
|
||
# Make lights not affect baked surfaces by setting their bake mode to All.
|
||
|
||
sun.light_bake_mode = Light3D.BAKE_STATIC
|
||
$GrateOmniLight.light_bake_mode = Light3D.BAKE_STATIC
|
||
$GarageOmniLight.light_bake_mode = Light3D.BAKE_STATIC
|
||
$CornerSpotLight.light_bake_mode = Light3D.BAKE_STATIC
|
||
$Camera/Box.gi_mode = GeometryInstance3D.GI_MODE_DYNAMIC
|
||
|
||
GIMode.LIGHTMAP_GI_INDIRECT:
|
||
$LightmapGIAll.light_data = lightmap_gi_all_data
|
||
$Zdm2LightmapAll.visible = false
|
||
$Zdm2LightmapIndirect.visible = true
|
||
|
||
# Halve sky contribution to prevent dynamic objects from looking too bright and blue.
|
||
# (When using lightmaps, this property doesn't affect lightmapped surfaces.)
|
||
environment.ambient_light_sky_contribution = 0.5
|
||
$LightmapGIIndirect.visible = true
|
||
$LightmapGIAll.visible = false
|
||
$VoxelGI.visible = false
|
||
environment.sdfgi_enabled = false
|
||
|
||
sun.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GrateOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GarageOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$CornerSpotLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
# Mark box as dynamic so it benefits from lightmap probes.
|
||
# Don't do this in other GI modes to avoid the heavy performance impact that
|
||
# happens with VoxelGI for dynamic objects.
|
||
$Camera/Box.gi_mode = GeometryInstance3D.GI_MODE_DYNAMIC
|
||
|
||
GIMode.VOXEL_GI:
|
||
# Work around bug where VoxelGI is not visible if the LightmapGI node is hidden (with LightmapGIData still present).
|
||
$LightmapGIAll.light_data = null
|
||
|
||
$Zdm2LightmapAll.visible = true
|
||
$Zdm2LightmapIndirect.visible = false
|
||
|
||
environment.ambient_light_sky_contribution = 1.0
|
||
$LightmapGIIndirect.visible = false
|
||
$LightmapGIAll.visible = false
|
||
$VoxelGI.visible = true
|
||
environment.sdfgi_enabled = false
|
||
|
||
# Bake mode must be Indirect, not Disabled. Otherwise, GI will
|
||
# not be visible for those lights.
|
||
sun.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GrateOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GarageOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$CornerSpotLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$Camera/Box.gi_mode = GeometryInstance3D.GI_MODE_DISABLED
|
||
|
||
GIMode.SDFGI:
|
||
# Work around bug where SDFGI is not visible if the LightmapGI node is hidden (with LightmapGIData still present).
|
||
$LightmapGIAll.light_data = null
|
||
|
||
$Zdm2LightmapAll.visible = true
|
||
$Zdm2LightmapIndirect.visible = false
|
||
|
||
environment.ambient_light_sky_contribution = 1.0
|
||
$LightmapGIIndirect.visible = false
|
||
$LightmapGIAll.visible = false
|
||
$VoxelGI.visible = false
|
||
environment.sdfgi_enabled = true
|
||
|
||
# Bake mode must be Indirect, not Disabled. Otherwise, GI will
|
||
# not be visible for those lights.
|
||
sun.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GrateOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$GarageOmniLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$CornerSpotLight.light_bake_mode = Light3D.BAKE_DYNAMIC
|
||
$Camera/Box.gi_mode = GeometryInstance3D.GI_MODE_DISABLED
|
||
|
||
|
||
func set_reflection_probe_mode(p_reflection_probe_mode: ReflectionProbeMode) -> void:
|
||
reflection_probe_mode = p_reflection_probe_mode
|
||
reflection_probe_mode_label.text = "Reflection probe: %s " % reflection_probe_mode_texts[reflection_probe_mode]
|
||
|
||
match p_reflection_probe_mode:
|
||
ReflectionProbeMode.NONE:
|
||
reflection_probe.visible = false
|
||
reflection_probe.update_mode = ReflectionProbe.UPDATE_ONCE
|
||
ReflectionProbeMode.ONCE:
|
||
reflection_probe.visible = true
|
||
reflection_probe.update_mode = ReflectionProbe.UPDATE_ONCE
|
||
ReflectionProbeMode.ALWAYS:
|
||
reflection_probe.visible = true
|
||
reflection_probe.update_mode = ReflectionProbe.UPDATE_ALWAYS
|
||
|
||
|
||
func set_ssil_mode(p_ssil_mode: SSILMode) -> void:
|
||
ssil_mode = p_ssil_mode
|
||
if is_compatibility:
|
||
ssil_mode_label.text = "Screen-space lighting effects: Not supported on Compatibility"
|
||
ssil_mode_label.self_modulate.a = 0.6
|
||
return
|
||
else:
|
||
ssil_mode_label.text = "Screen-space lighting effects: %s " % SSIL_MODE_TEXTS[ssil_mode]
|
||
|
||
match p_ssil_mode:
|
||
SSILMode.NONE:
|
||
environment.ssao_enabled = false
|
||
environment.ssil_enabled = false
|
||
SSILMode.SSAO:
|
||
environment.ssao_enabled = true
|
||
environment.ssil_enabled = false
|
||
SSILMode.SSIL:
|
||
environment.ssao_enabled = false
|
||
environment.ssil_enabled = true
|
||
SSILMode.SSAO_AND_SSIL:
|
||
environment.ssao_enabled = true
|
||
environment.ssil_enabled = true
|