Godot 4 GDScript 教程 / 光照与环境
光照与环境
概述
Godot 4 的光照系统基于 Vulkan 渲染器,支持实时光照和多种全局光照(GI)方案。环境系统(Environment)统一管理天空、雾、色调映射和后处理效果。
| 光照节点 | 说明 |
|---|---|
DirectionalLight3D | 方向光(太阳光) |
OmniLight3D | 点光源(灯泡) |
SpotLight3D | 聚光灯(手电筒) |
| GI 节点 | 说明 |
|---|---|
VoxelGI | 体素全局光照 |
LightmapGI | 光照贴图烘焙 |
LightmapProbe | 光照探针 |
ReflectionProbe | 反射探针 |
DirectionalLight3D(方向光)
方向光模拟无限远处的光源(如太阳),所有光线平行。
extends DirectionalLight3D
func _ready():
# 基本设置
light_color = Color(1.0, 0.95, 0.9) # 暖白色
light_energy = 1.0
shadow_enabled = true
# 方向光特有属性
# 光照角度(通过旋转设置)
rotation_degrees = Vector3(-45, 30, 0)
# 阴影模式
directional_shadow_mode = DirectionalLight3D.SHADOW_PARALLEL_4_SPLITS
# 阴影参数
directional_shadow_max_distance = 100.0
directional_shadow_split_1 = 0.1
directional_shadow_split_2 = 0.2
directional_shadow_split_3 = 0.5
# 阴影模糊
directional_shadow_blur = 1.0
# 光源范围
# 方向光影响整个场景
阴影分片模式
| 模式 | 说明 | 适用场景 |
|---|---|---|
SHADOW_ORTHOGONAL | 正交阴影 | 大型场景 |
SHADOW_PARALLEL_2_SPLITS | 2 分区级联 | 中型场景 |
SHADOW_PARALLEL_4_SPLITS | 4 分区级联 | 大型场景精度高 |
OmniLight3D(点光源)
点光源从一个点向所有方向发射光线。
extends OmniLight3D
func _ready():
# 基本参数
light_color = Color(1, 0.8, 0.5) # 暖色光
light_energy = 2.0
shadow_enabled = true
# 点光源特有
omni_range = 10.0 # 影响范围
omni_attenuation = 1.0 # 衰减系数
# 衰减公式:attenuation = 1 - (distance / range) ^ attenuation_exp
# omni_attenuation 越大,光线衰减越快
衰减参数对比
| attenuation | 效果 |
|---|---|
| 0.0 | 无衰减(不推荐) |
| 1.0 | 线性衰减 |
| 2.0 | 二次衰减(最接近物理) |
SpotLight3D(聚光灯)
聚光灯从一个点向特定方向发射锥形光线。
extends SpotLight3D
func _ready():
light_color = Color(1, 1, 0.8)
light_energy = 3.0
shadow_enabled = true
# 聚光灯特有
spot_range = 15.0 # 照射距离
spot_attenuation = 1.0 # 衰减
spot_angle = 30.0 # 锥角(度)
spot_angle_attenuation = 1.0 # 边缘衰减
# spot_angle_attenuation 越大,边缘越硬
💡 提示:spot_angle 控制锥角大小,spot_angle_attenuation 控制边缘柔和度。值越大边缘越锐利。
GI 全局光照
VoxelGI(体素全局光照)
实时计算间接光照,适合室内场景和动态光源。
extends Node3D
func setup_voxel_gi():
var voxel_gi = VoxelGI.new()
# 设置覆盖范围
voxel_gi.size = Vector3(20, 10, 20)
# 体素细分(越大精度越高,性能越差)
voxel_gi.subdiv = VoxelGI.SUBDIV_128
add_child(voxel_gi)
# 需要在编辑器中烘焙
| 细分级别 | 体素数 | 内存 | 精度 |
|---|---|---|---|
SUBDIV_16 | 16³ | 低 | 低 |
SUBDIV_32 | 32³ | 中低 | 中低 |
SUBDIV_64 | 64³ | 中 | 中 |
SUBDIV_128 | 128³ | 高 | 高 |
SUBDIV_256 | 256³ | 很高 | 很高 |
SUBDIV_512 | 512³ | 极高 | 极高 |
VoxelGI 烘焙流程
- 在场景中添加
VoxelGI节点 - 设置
size覆盖需要 GI 的区域 - 确保 MeshInstance3D 启用
Use In Baked Light(全局光照属性) - 选中 VoxelGI 节点 → 点击编辑器中的 “Bake VoxelGI” 按钮
⚠️ 注意:VoxelGI 仅对启用 global_transform 的静态网格生效。动态物体(RigidBody)可接收 GI,但不贡献 GI。
LightmapGI(光照贴图)
预烘焙光照到纹理,运行时零计算开销,适合室外大型场景。
extends Node3D
func setup_lightmap():
var lightmap = LightmapGI.new()
# 烘焙质量
lightmap.quality = LightmapGI.QUALITY_HIGH
# 光线弹射次数
lightmap.bounces = 3
# 生成探针
lightmap.generate_probes = LightmapGI.GENERATE_PROBES_SUBDIV_8
# 分辨率
lightmap.environment_custom_sky = preload("res://sky.tres")
add_child(lightmap)
LightmapGI 烘焙流程
- 场景中添加
LightmapGI节点 - MeshInstance3D 导入时启用 “Generate Lightmap UV”
- 确保所有静态网格启用
Use In Baked Light - 选中 LightmapGI → “Bake Lightmaps”
- 烘焙完成后保存
.lmbake文件
| 质量设置 | 说明 |
|---|---|
QUALITY_LOW | 快速烘焙,低质量 |
QUALITY_MEDIUM | 平衡 |
QUALITY_HIGH | 高质量 |
QUALITY_ULTRA | 最高质量,烘焙慢 |
SDFGI(SDF 全局光照)
Godot 4 的 SDFGI 是一种无需烘焙的全局光照方案,适合大型开放世界。
extends WorldEnvironment
func _ready():
var env = Environment.new()
# 启用 SDFGI
env.sdfgi_enabled = true
# SDFGI 参数
env.sdfgi_use_occlusion = true # 遮挡剔除
env.sdfgi_cascade0_distance = 12.8 # 近处精度
env.sdfgi_num_cascades = 8 # 级联数量(2~8)
env.sdfgi_energy = 1.0
env.sdfgi_normal_bias = 1.0
env.sdfgi_probe_bias = 1.0
environment = env
💡 提示:SDFGI 无需烘焙,但 GPU 开销较大。适合室外开放世界,室内效果不如 VoxelGI/LightmapGI。
ReflectionProbe(反射探针)
extends ReflectionProbe
func _ready():
# 反射探针覆盖区域
size = Vector3(10, 6, 10)
# 反射更新模式
update_mode = ReflectionProbe.UPDATE_ONCE # 静态环境
# update_mode = ReflectionProbe.UPDATE_ALWAYS # 动态环境(性能高)
# 混合距离(边缘过渡)
blend_distance = 1.0
# 环境模式
ambient_mode = ReflectionProbe.AMBIENT_ENVIRONMENT
ambient_color = Color(0.1, 0.1, 0.1)
ambient_color_energy = 0.5
# 是否覆盖天空
box_projection = true # 适合室内
interior = true # 室内模式,忽略天空
Environment 环境设置
天空设置
extends WorldEnvironment
func _ready():
var env = Environment.new()
# 程序化天空
var sky = Sky.new()
var sky_mat = ProceduralSkyMaterial.new()
sky_mat.sky_top_color = Color(0.3, 0.5, 0.8)
sky_mat.sky_horizon_color = Color(0.6, 0.7, 0.9)
sky_mat.ground_bottom_color = Color(0.1, 0.07, 0.05)
sky_mat.ground_horizon_color = Color(0.6, 0.7, 0.9)
sky_mat.sun_angle_max = 30.0
sky_mat.sun_longitude = 120.0
sky.sky_material = sky_mat
env.sky = sky
env.background_mode = Environment.BG_SKY
environment = env
雾效
func setup_fog(env: Environment):
env.fog_enabled = true
env.fog_light_color = Color(0.7, 0.8, 0.9)
env.fog_light_energy = 1.0
env.fog_density = 0.01
env.fog_aerial_perspective = 0.5 # 空气透视
env.fog_height = -10.0 # 雾高度
env.fog_height_density = 0.2 # 高度雾密度
# 体积雾(Volumetric Fog)
env.volumetric_fog_enabled = true
env.volumetric_fog_density = 0.03
env.volumetric_fog_albedo = Color(0.9, 0.9, 0.9)
env.volumetric_fog_emission = Color(0, 0, 0)
env.volumetric_fog_gi_inject = 0.5
env.volumetric_fog_anisotropy = 0.8
env.volumetric_fog_length = 128.0
色调映射
func setup_tonemap(env: Environment):
# 色调映射模式
env.tonemap_mode = Environment.TONE_MAP_ACES
env.tonemap_exposure = 1.0
env.tonemap_white = 6.0
# 对比度和饱和度
env.adjustment_enabled = true
env.adjustment_brightness = 1.0
env.adjustment_contrast = 1.0
env.adjustment_saturation = 1.1 # 轻微增加饱和度
色调映射模式
| 模式 | 特点 | 适用场景 |
|---|---|---|
TONE_MAP_LINEAR | 线性映射 | 无特殊需求 |
TONE_MAP_REINHARD | 经典算法 | 通用 |
TONE_MAP_FILMIC | 电影风格 | 电影感 |
TONE_MAP_ACES | ACES 标准 | 推荐默认 |
TONE_MAP_AGX | AgX 新算法 | 高保真 |
SSAO(屏幕空间环境光遮蔽)
func setup_ssao(env: Environment):
env.ssao_enabled = true
env.ssao_radius = 1.0 # 采样半径
env.ssao_intensity = 2.0 # 强度
env.ssao_power = 1.5 # 对比度
env.ssao_detail = 0.5 # 细节
env.ssao_horizon = 0.06 # 地平线剔除
env.ssao_sharpness = 0.98 # 锐度
env.ssao_light_affect = 0.0 # 光照影响
SSR(屏幕空间反射)
func setup_ssr(env: Environment):
env.ssr_enabled = true
env.ssr_max_steps = 64 # 追踪步数
env.ssr_fade_in = 0.15 # 淡入
env.ssr_fade_out = 2.0 # 淡出
env.ssr_depth_tolerance = 0.2 # 深度容差
env.ssr_roughness = true # 粗糙反射
发光(Glow)
func setup_glow(env: Environment):
env.glow_enabled = true
env.glow_intensity = 0.4
env.glow_strength = 1.0
env.glow_bloom = 0.1
env.glow_blend_mode = Environment.GLOW_BLEND_MODE_SOFTLIGHT
env.glow_hdr_threshold = 1.0 # HDR 阈值
env.glow_hdr_luminance_cap = 12.0
env.glow_map_strength = 1.0
BOKEH(景深)
func setup_dof(env: Environment):
env.dof_blur_far_enabled = true
env.dof_blur_far_distance = 10.0 # 焦点距离
env.dof_blur_far_transition = 5.0 # 过渡范围
env.dof_blur_far_amount = 0.1 # 模糊量
env.dof_blur_near_enabled = true
env.dof_blur_near_distance = 2.0
env.dof_blur_near_transition = 1.0
env.dof_blur_near_amount = 0.1
完整环境设置示例
extends Node3D
func _ready():
var env = Environment.new()
# 天空
var sky = Sky.new()
var sky_mat = PhysicalSkyMaterial.new()
sky_mat.rayleigh_coefficient = 2.0
sky_mat.mie_coefficient = 0.005
sky_mat.turbidity = 3.0
sky.sky_material = sky_mat
env.sky = sky
env.background_mode = Environment.BG_SKY
# 环境光
env.ambient_light_source = Environment.AMBIENT_SOURCE_SKY
env.ambient_light_energy = 0.3
# 色调映射
env.tonemap_mode = Environment.TONE_MAP_ACES
env.tonemap_exposure = 1.2
# SSAO
env.ssao_enabled = true
# 发光
env.glow_enabled = true
env.glow_intensity = 0.2
# 雾
env.fog_enabled = true
env.fog_density = 0.005
var world_env = WorldEnvironment.new()
world_env.environment = env
add_child(world_env)
光照性能优化策略
| 策略 | 说明 |
|---|---|
| 使用 LightmapGI 替代实时光照 | 烘焙后零 GPU 开销 |
| 减少阴影光源数量 | 每个阴影光源增加 Draw Call |
| 降低阴影分辨率 | Project Settings → Rendering → Lights |
| 禁用远处阴影 | directional_shadow_max_distance |
| 限制 OmniLight 范围 | 小范围减少着色器计算 |
| 使用 LOD | 远处物体降低材质精度 |
| 合理选择 GI 方案 | 室内用 VoxelGI,室外用 SDFGI/LightmapGI |
实时光照 vs 烘焙选择
| 方案 | 实时 | GPU 开销 | 内存 | 适用场景 |
|---|---|---|---|---|
| 实时光照 | ✅ | 中 | 低 | 动态光源 |
| VoxelGI | ✅ | 中 | 中 | 室内动态 |
| LightmapGI | ❌ | 极低 | 中 | 室外静态 |
| SDFGI | ✅ | 高 | 高 | 开放世界 |
💡 提示:大型项目常混合使用——室内使用 LightmapGI,室外使用 SDFGI,动态物体使用实时光。
游戏开发场景
| 场景 | 推荐方案 |
|---|---|
| 室外白天 | DirectionalLight + SDFGI + 雾 |
| 室内暗室 | OmniLight + VoxelGI + SSAO |
| 夜景手电筒 | SpotLight + 体积雾 |
| 恐怖氛围 | 低光 + 高 SSAO + 体积雾 |
| 赛博朋克 | 发光材质 + Glow + 高对比度 |
| 怀旧风格 | 低环境光 + 线性色调映射 |
⚠️ 常见陷阱
- 阴影光源越多性能越差,建议同时不超过 3~5 个阴影光源
- VoxelGI 需要烘焙,烘焙前确保场景网格启用
Use In Baked Light - SDFGI 在室内效果不佳,容易漏光
- LightmapGI 的 UV 重叠会导致光照错误,导入时启用 Generate Lightmap UV
- 体积雾对性能影响大,低端设备慎用