godot-3d-lighting
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinese3D Lighting
3D灯光
Expert guidance for realistic 3D lighting with shadows and global illumination.
关于带阴影和全局光照的写实3D灯光的专家指导。
NEVER Do
绝对不要做
- NEVER use VoxelGI without setting a proper extents — Unbound VoxelGI tanks performance. Always set to tightly fit your scene.
size - NEVER enable shadows on every light — Each shadow-casting light is expensive. Use shadows sparingly: 1-2 DirectionalLights, ~3-5 OmniLights max.
- NEVER forget directional_shadow_mode — Default is ORTHOGONAL. For large outdoor scenes, use PARALLEL_4_SPLITS for better shadow quality at distance.
- NEVER use LightmapGI for fully dynamic scenes — Lightmaps are baked. Moving geometry won't receive updated lighting. Use VoxelGI or SDFGI instead.
- NEVER set omni_range too large — Light attenuation is quadratic. A range of 500 affects 785,000 sq units. Keep range as small as visually acceptable.
- 绝对不要在未设置合适范围的情况下使用VoxelGI —— 无边界的VoxelGI会严重拖垮性能。务必将设置为紧密贴合你的场景。
size - 绝对不要给每盏灯都启用阴影 —— 每盏投射阴影的灯光都会消耗大量性能。谨慎使用阴影:最多1-2盏DirectionalLight,3-5盏OmniLight。
- 绝对不要忘记设置directional_shadow_mode —— 默认值是ORTHOGONAL。对于大型户外场景,使用PARALLEL_4_SPLITS可提升远距离阴影质量。
- 绝对不要在全动态场景中使用LightmapGI —— 光照贴图是烘焙好的。移动的几何体无法获得更新后的光照。请改用VoxelGI或SDFGI。
- 绝对不要将omni_range设置得过大 —— 灯光衰减是二次方的。范围设为500会影响785000平方单位。请将范围保持在视觉可接受的最小程度。
Available Scripts
可用脚本
MANDATORY: Read the appropriate script before implementing the corresponding pattern.
强制要求:在实现对应模式前,请阅读相应的脚本。
day_night_cycle.gd
day_night_cycle.gd
Dynamic sun position and color based on time-of-day. Handles DirectionalLight3D rotation, color temperature, and intensity curves. Use for outdoor day/night systems.
基于时间的动态太阳位置与颜色。处理DirectionalLight3D的旋转、色温以及强度曲线。适用于户外昼夜系统。
light_probe_manager.gd
light_probe_manager.gd
VoxelGI and SDFGI management for global illumination setup.
用于全局光照设置的VoxelGI与SDFGI管理工具。
lighting_manager.gd
lighting_manager.gd
Dynamic light pooling and LOD. Manages light culling and shadow toggling based on camera distance. Use for performance optimization with many lights.
动态灯光池与LOD(细节层次)。基于相机距离管理灯光剔除与阴影开关。适用于多灯光场景的性能优化。
volumetric_fx.gd
volumetric_fx.gd
Volumetric fog and god ray configuration. Runtime fog density/color adjustments and light shaft setup. Use for atmospheric effects.
体积雾与上帝光线配置。运行时雾密度/颜色调整以及光轴设置。适用于大气效果。
DirectionalLight3D (Sun/Moon)
DirectionalLight3D(太阳/月亮)
Shadow Cascades
阴影级联
gdscript
undefinedgdscript
undefinedFor outdoor scenes with camera moving from near to far
适用于相机在近远区间移动的户外场景
extends DirectionalLight3D
func _ready() -> void:
shadow_enabled = true
directional_shadow_mode = SHADOW_PARALLEL_4_SPLITS
# Split distances (in meters from camera)
directional_shadow_split_1 = 10.0 # First cascade: 0-10m
directional_shadow_split_2 = 50.0 # Second: 10-50m
directional_shadow_split_3 = 200.0 # Third: 50-200m
# Fourth cascade: 200m - max shadow distance
directional_shadow_max_distance = 500.0
# Quality vs performance
directional_shadow_blend_splits = true # Smooth transitionsundefinedextends DirectionalLight3D
func _ready() -> void:
shadow_enabled = true
directional_shadow_mode = SHADOW_PARALLEL_4_SPLITS
# 分割距离(以相机为基准的米数)
directional_shadow_split_1 = 10.0 # 第一级级联:0-10米
directional_shadow_split_2 = 50.0 # 第二级:10-50米
directional_shadow_split_3 = 200.0 # 第三级:50-200米
# 第四级级联:200米 - 最大阴影距离
directional_shadow_max_distance = 500.0
# 质量与性能平衡
directional_shadow_blend_splits = true # 平滑过渡undefinedDay/Night Cycle
昼夜循环
gdscript
undefinedgdscript
undefinedsun_controller.gd
sun_controller.gd
extends DirectionalLight3D
@export var time_of_day := 12.0 # 0-24 hours
@export var rotation_speed := 0.1 # Hours per second
func _process(delta: float) -> void:
time_of_day += rotation_speed * delta
if time_of_day >= 24.0:
time_of_day -= 24.0
# Rotate sun (0° = noon, 180° = midnight)
var angle := (time_of_day - 12.0) * 15.0 # 15° per hour
rotation_degrees.x = -angle
# Adjust intensity
if time_of_day < 6.0 or time_of_day > 18.0:
light_energy = 0.0 # Night
elif time_of_day < 7.0:
light_energy = remap(time_of_day, 6.0, 7.0, 0.0, 1.0) # Sunrise
elif time_of_day > 17.0:
light_energy = remap(time_of_day, 17.0, 18.0, 1.0, 0.0) # Sunset
else:
light_energy = 1.0 # Day
# Color shift
if time_of_day < 8.0 or time_of_day > 16.0:
light_color = Color(1.0, 0.7, 0.4) # Orange (dawn/dusk)
else:
light_color = Color(1.0, 1.0, 0.9) # Neutral white
---extends DirectionalLight3D
@export var time_of_day := 12.0 # 0-24小时
@export var rotation_speed := 0.1 # 每秒小时数
func _process(delta: float) -> void:
time_of_day += rotation_speed * delta
if time_of_day >= 24.0:
time_of_day -= 24.0
# 旋转太阳(0°=正午,180°=午夜)
var angle := (time_of_day - 12.0) * 15.0 # 每小时15°
rotation_degrees.x = -angle
# 调整强度
if time_of_day < 6.0 or time_of_day > 18.0:
light_energy = 0.0 # 夜晚
elif time_of_day < 7.0:
light_energy = remap(time_of_day, 6.0, 7.0, 0.0, 1.0) # 日出
elif time_of_day > 17.0:
light_energy = remap(time_of_day, 17.0, 18.0, 1.0, 0.0) # 日落
else:
light_energy = 1.0 # 白天
# 颜色偏移
if time_of_day < 8.0 or time_of_day > 16.0:
light_color = Color(1.0, 0.7, 0.4) # 橙色(黎明/黄昏)
else:
light_color = Color(1.0, 1.0, 0.9) # 中性白色
---OmniLight3D (Point Light)
OmniLight3D(点光源)
Attenuation Tuning
衰减调优
gdscript
undefinedgdscript
undefinedtorch.gd
torch.gd
extends OmniLight3D
func _ready() -> void:
omni_range = 10.0 # Maximum reach
omni_attenuation = 2.0 # Falloff curve (1.0 = linear, 2.0 = quadratic/realistic)
# For "magical" lights, reduce attenuation
omni_attenuation = 0.5 # Flatter falloff, reaches fartherundefinedextends OmniLight3D
func _ready() -> void:
omni_range = 10.0 # 最大照射范围
omni_attenuation = 2.0 # 衰减曲线(1.0=线性,2.0=二次方/写实)
# 对于“魔法”灯光,降低衰减值
omni_attenuation = 0.5 # 更平缓的衰减,照射更远undefinedFlickering Effect
闪烁效果
gdscript
undefinedgdscript
undefinedcampfire.gd
campfire.gd
extends OmniLight3D
@export var base_energy := 1.0
@export var flicker_strength := 0.3
@export var flicker_speed := 5.0
func _process(delta: float) -> void:
var flicker := sin(Time.get_ticks_msec() * 0.001 * flicker_speed) * flicker_strength
light_energy = base_energy + flicker
---extends OmniLight3D
@export var base_energy := 1.0
@export var flicker_strength := 0.3
@export var flicker_speed := 5.0
func _process(delta: float) -> void:
var flicker := sin(Time.get_ticks_msec() * 0.001 * flicker_speed) * flicker_strength
light_energy = base_energy + flicker
---SpotLight3D (Flashlight/Headlights)
SpotLight3D(手电筒/车头灯)
Setup
设置
gdscript
undefinedgdscript
undefinedflashlight.gd
flashlight.gd
extends SpotLight3D
func _ready() -> void:
spot_range = 20.0
spot_angle = 45.0 # Cone angle (degrees)
spot_angle_attenuation = 2.0 # Edge softness
shadow_enabled = true
# Projector texture (optional - cookie/gobo)
light_projector = load("res://textures/flashlight_mask.png")undefinedextends SpotLight3D
func _ready() -> void:
spot_range = 20.0
spot_angle = 45.0 # 圆锥角度(度)
spot_angle_attenuation = 2.0 # 边缘柔化
shadow_enabled = true
# 投影纹理(可选 - 遮罩图案)
light_projector = load("res://textures/flashlight_mask.png")undefinedFollow Camera
跟随相机
gdscript
undefinedgdscript
undefinedplayer_flashlight.gd
player_flashlight.gd
extends SpotLight3D
@onready var camera: Camera3D = get_viewport().get_camera_3d()
func _process(delta: float) -> void:
if camera:
global_transform = camera.global_transform
---extends SpotLight3D
@onready var camera: Camera3D = get_viewport().get_camera_3d()
func _process(delta: float) -> void:
if camera:
global_transform = camera.global_transform
---Global Illumination: VoxelGI vs SDFGI
全局光照:VoxelGI与SDFGI对比
Decision Matrix
决策矩阵
| Feature | VoxelGI | SDFGI |
|---|---|---|
| Setup | Manual bounds per room | Automatic, scene-wide |
| Dynamic objects | Fully supported | Partially supported |
| Performance | Moderate | Higher cost |
| Use case | Indoor, small-medium scenes | Large outdoor scenes |
| Godot version | 4.0+ | 4.0+ |
| 特性 | VoxelGI | SDFGI |
|---|---|---|
| 设置 | 每个房间手动设置边界 | 自动,全场景 |
| 动态物体 | 完全支持 | 部分支持 |
| 性能 | 中等 | 较高消耗 |
| 使用场景 | 室内、中小型场景 | 大型户外场景 |
| Godot版本 | 4.0+ | 4.0+ |
VoxelGI Setup
VoxelGI设置
gdscript
undefinedgdscript
undefinedroom_gi.gd - Place one VoxelGI per room/area
room_gi.gd - 每个房间/区域放置一个VoxelGI节点
extends VoxelGI
func _ready() -> void:
# Tightly fit the room
size = Vector3(20, 10, 20)
# Quality settings
subdiv = VoxelGI.SUBDIV_128 # Higher = better quality, slower
# Bake GI data
bake()undefinedextends VoxelGI
func _ready() -> void:
# 紧密贴合房间
size = Vector3(20, 10, 20)
# 质量设置
subdiv = VoxelGI.SUBDIV_128 # 数值越高质量越好,速度越慢
# 烘焙GI数据
bake()undefinedSDFGI Setup
SDFGI设置
gdscript
undefinedgdscript
undefinedworld_environment.gd
world_environment.gd
extends WorldEnvironment
func _ready() -> void:
var env := environment
# Enable SDFGI
env.sdfgi_enabled = true
env.sdfgi_use_occlusion = true
env.sdfgi_read_sky_light = true
# Cascades (auto-scale based on camera)
env.sdfgi_min_cell_size = 0.2 # Detail level
env.sdfgi_max_distance = 200.0
---extends WorldEnvironment
func _ready() -> void:
var env := environment
# 启用SDFGI
env.sdfgi_enabled = true
env.sdfgi_use_occlusion = true
env.sdfgi_read_sky_light = true
# 级联(基于相机自动缩放)
env.sdfgi_min_cell_size = 0.2 # 细节级别
env.sdfgi_max_distance = 200.0
---LightmapGI (Baked Static Lighting)
LightmapGI(烘焙静态光照)
When to Use
适用场景
- Static architecture (buildings, dungeons)
- Mobile/low-end targets
- No dynamic geometry
- 静态建筑(房屋、地牢)
- 移动端/低端设备目标平台
- 无动态几何体
Setup
设置
gdscript
undefinedgdscript
undefinedScene structure:
场景结构:
- LightmapGI node
- LightmapGI节点
- StaticBody3D meshes with GeometryInstance3D.gi_mode = STATIC
- StaticBody3D网格,且GeometryInstance3D.gi_mode = STATIC
lightmap_baker.gd
lightmap_baker.gd
extends LightmapGI
func _ready() -> void:
# Quality settings
quality = LightmapGI.BAKE_QUALITY_HIGH
bounces = 3 # Indirect light bounces
# Bake (editor only, not runtime)
# Click "Bake Lightmaps" button in editor
---extends LightmapGI
func _ready() -> void:
# 质量设置
quality = LightmapGI.BAKE_QUALITY_HIGH
bounces = 3 # 间接光反弹次数
# 烘焙(仅编辑器中可用,运行时不可用)
# 点击编辑器中的“烘焙光照贴图”按钮
---Environment & Sky
环境与天空
HDR Skybox
HDR天空盒
gdscript
undefinedgdscript
undefinedworld_env.gd
world_env.gd
extends WorldEnvironment
func _ready() -> void:
var env := environment
env.background_mode = Environment.BG_SKY
var sky := Sky.new()
var sky_material := PanoramaSkyMaterial.new()
sky_material.panorama = load("res://hdri/sky.hdr")
sky.sky_material = sky_material
env.sky = sky
# Sky contribution to GI
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
env.ambient_light_sky_contribution = 1.0undefinedextends WorldEnvironment
func _ready() -> void:
var env := environment
env.background_mode = Environment.BG_SKY
var sky := Sky.new()
var sky_material := PanoramaSkyMaterial.new()
sky_material.panorama = load("res://hdri/sky.hdr")
sky.sky_material = sky_material
env.sky = sky
# 天空对GI的贡献
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
env.ambient_light_sky_contribution = 1.0undefinedVolumetric Fog
体积雾
gdscript
extends WorldEnvironment
func _ready() -> void:
var env := environment
env.volumetric_fog_enabled = true
env.volumetric_fog_density = 0.01
env.volumetric_fog_albedo = Color(0.9, 0.9, 1.0) # Blueish
env.volumetric_fog_emission = Color.BLACKgdscript
extends WorldEnvironment
func _ready() -> void:
var env := environment
env.volumetric_fog_enabled = true
env.volumetric_fog_density = 0.01
env.volumetric_fog_albedo = Color(0.9, 0.9, 1.0) # 偏蓝
env.volumetric_fog_emission = Color.BLACKReflectionProbe
ReflectionProbe(反射探针)
For localized reflections (mirrors, shiny floors):
gdscript
undefined用于局部反射(镜子、光滑地面):
gdscript
undefinedreflection_probe.gd
reflection_probe.gd
extends ReflectionProbe
func _ready() -> void:
# Capture area
size = Vector3(10, 5, 10)
# Quality
resolution = ReflectionProbe.RESOLUTION_512
# Update mode
update_mode = ReflectionProbe.UPDATE_ONCE # Bake once
# or UPDATE_ALWAYS for dynamic reflections (expensive)
---extends ReflectionProbe
func _ready() -> void:
# 捕获区域
size = Vector3(10, 5, 10)
# 质量
resolution = ReflectionProbe.RESOLUTION_512
# 更新模式
update_mode = ReflectionProbe.UPDATE_ONCE # 烘焙一次
# 或使用UPDATE_ALWAYS实现动态反射(性能消耗大)
---Performance Optimization
性能优化
Light Budgets
灯光预算
gdscript
undefinedgdscript
undefinedRecommended limits:
推荐限制:
- DirectionalLight3D with shadows: 1-2
- 带阴影的DirectionalLight3D:1-2盏
- OmniLight3D with shadows: 3-5
- 带阴影的OmniLight3D:3-5盏
- SpotLight3D with shadows: 2-4
- 带阴影的SpotLight3D:2-4盏
- OmniLight3D without shadows: 20-30
- 无阴影的OmniLight3D:20-30盏
- SpotLight3D without shadows: 15-20
- 无阴影的SpotLight3D:15-20盏
Disable shadows on minor lights
禁用次要灯光的阴影
@onready var candle_lights: Array = [$Candle1, $Candle2, $Candle3]
func _ready() -> void:
for light in candle_lights:
light.shadow_enabled = false # Save performance
undefined@onready var candle_lights: Array = [$Candle1, $Candle2, $Candle3]
func _ready() -> void:
for light in candle_lights:
light.shadow_enabled = false # 节省性能
undefinedPer-Light Shadow Distance
单灯光阴影距离
gdscript
undefinedgdscript
undefinedDisable shadows for distant lights
禁用远距离灯光的阴影
extends OmniLight3D
@export var shadow_max_distance := 50.0
func _process(delta: float) -> void:
var camera := get_viewport().get_camera_3d()
if camera:
var dist := global_position.distance_to(camera.global_position)
shadow_enabled = (dist < shadow_max_distance)
---extends OmniLight3D
@export var shadow_max_distance := 50.0
func _process(delta: float) -> void:
var camera := get_viewport().get_camera_3d()
if camera:
var dist := global_position.distance_to(camera.global_position)
shadow_enabled = (dist < shadow_max_distance)
---Edge Cases
边缘情况
Shadows Through Floors
阴影穿透地板
gdscript
undefinedgdscript
undefinedProblem: Thin floors let shadows through
问题:薄地板导致阴影穿透
Solution: Increase shadow bias
解决方案:增加阴影偏移
extends DirectionalLight3D
func _ready() -> void:
shadow_enabled = true
shadow_bias = 0.1 # Increase if shadows bleed through
shadow_normal_bias = 2.0
undefinedextends DirectionalLight3D
func _ready() -> void:
shadow_enabled = true
shadow_bias = 0.1 # 若阴影穿透则增大该值
shadow_normal_bias = 2.0
undefinedLight Leaking in Indoor Scenes
室内场景灯光泄漏
gdscript
undefinedgdscript
undefinedProblem: VoxelGI light bleeds through walls
问题:VoxelGI灯光穿墙泄漏
Solution: Place VoxelGI nodes per-room, don't overlap
解决方案:每个房间放置独立的VoxelGI节点,避免重叠
Also: Ensure walls have proper thickness (not paper-thin)
另外:确保墙壁有足够厚度(不要像纸一样薄)
undefinedundefinedReference
参考资料
- Master Skill: godot-master
- 核心技能:godot-master