关于 godot-3d-materials
面向 Godot 开发者的 3D 材质技能,提供 StandardMaterial3D 与 PBR 材质的设置和优化指导。内容涵盖 ORM 贴图、透明模式、材质复用、实例化参数及运行时效果。
主要功能
- 01PBR 与 ORM 通道打包
- 02透明模式与排序处理
- 03共享材质和实例参数
- 04三平面投影与风摆动
- 05运行时闪烁和溶解效果
适用场景
- 01为场景材质整理 AO、粗糙度与金属度贴图
- 02为树叶和栅栏配置透明裁切
- 03在多个网格间复用材质以减少批次开销
- 04为角色或植被制作次表面散射效果
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-3d-materials安装后在 Claude Code 中输入/godot-3d-materials确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/migration-notes.mdpbr-workflows.mdscripts/decal_placer_expert.gddepth_precision_fix.gdinstance_uniform_batching.gdshadermaterial_batcher.gdmaterial_fx.gdorganic_material.gdpbr_material_builder.gdpbr_orm_packer.gdshader_state_manager.gdsubsurface_scattering_setup.gdtransparency_sorting_fix.gdtriplanar_world_projection.gdshadertriplanar_world.gdshadervertex_wind_sway.gdshadershaders/triplanar_smooth.gdshader详细介绍
3D 材质
Godot 中 PBR 材质和 StandardMaterial3D 的专业指南。
切勿
- 切勿使用分开的金属度/粗糙度/AO 纹理 — 使用 ORM 打包(1 张 RGB 纹理,分别存储 Occlusion、Roughness 和 Metallic 通道),以节省纹理槽和内存。
- 切勿忘记启用 normal_enabled — 除非设置
normal_enabled = true,否则法线贴图不会生效。静默失效很常见。 - 切勿将 TRANSPARENCY_ALPHA 用于镂空材质 — 请改用 TRANSPARENCY_ALPHA_SCISSOR 或 TRANSPARENCY_ALPHA_HASH。完全 Alpha 混合开销很大,还会导致排序问题。
- 切勿将 metallic 设为 0.5 — 材质要么是金属(1.0),要么是电介质(0.0)。除锈蚀/污垢过渡外,中间值不符合物理规律。
- 切勿在未启用 HDR 的情况下使用 emission — emission 值 > 1.0 仅在“项目设置”中启用 HDR 渲染后才有效。
- 切勿为大型环境表面使用透明材质 — 透明对象无法依靠 Z 缓冲进行早期片段剔除,导致大量过度绘制。如果网格只有很小一部分透明,请将其拆分成两个表面:一个不透明表面,一个透明表面。
- 切勿在性能下降时仍创建数百个只有细微差别的 StandardMaterial3D 资源 — Godot 会自动复用底层着色器,以尽量减少 GPU 状态更改,前提是材质的配置标志(复选框)完全相同。请尝试将材质配置分组。
- 切勿只靠拉远对象来解决 Z-fighting — 浮点精度会随距离增加而下降。要修复纹理闪烁,请增大 Camera3D 的
Near平面属性,并减小Far属性,以压缩精度范围。 - 切勿为每个 MeshInstance3D 使用独立的 Material 资源 — 这会破坏绘制调用批处理。请使用“实例 Uniform”,在保持单个共享材质的同时调整参数。
- 切勿在运行时修改共享的 Material
.tres/表面材质 — 调用duplicate(true)或启用 Local To Scene,然后先分配唯一实例再调整参数。用于闪光/溶解时,必须使用material_fx.gd中的ensure_unique_override()/叠加辅助方法。 - 切勿在没有 Cull Mask 的情况下对动态移动角色使用 Decal — 子弹孔不应该在玩家走动时粘在玩家脸上。请屏蔽角色图层。
可用脚本
必须:实现相应模式前,请先阅读对应脚本。
工作流路由器(必须/不要加载)
| 任务 | 加载 | 不要加载 |
|---|---|---|
| StandardMaterial3D/ORM/透明度 | pbr_orm_packer.gd、transparency_sorting_fix.gd、material_batcher.gd、material_fx.gd | triplanar_world*.gdshader、vertex_wind_sway.gdshader |
| 无 UV 地形/峭壁 | triplanar_world.gdshader 或 triplanar_world_projection.gdshader + pbr_material_builder.gd | 除非处理植被,否则不要加载风摆动脚本 |
| 植被风动 | vertex_wind_sway.gdshader | 除非还需要岩石/地形处理,否则不要加载 Triplanar |
| 运行时伤害/溶解 | 必须 material_fx.gd | 编辑共享的导入材质 |
| 实例颜色/生命值/纹理数组变体 | 必须 instance_uniform_batching.gdshader | 每个网格各自使用 StandardMaterial3D 副本;身体纹理数组采样 |
| HLOD/远距离材质简化 | material_batcher.gd(setup_lod_materials) | Alpha 混合距离淡出(请使用 Pixel Dither) |
| 有机材质 SSS/边缘光/清漆层 | organic_material.gd、subsurface_scattering_setup.gd | Mobile/Compatibility 上的 SSS 配置方案 |
纯 StandardMaterial3D 反照率/ORM/透明度处理:不要加载 Triplanar、风动或纹理数组着色器。
material_fx.gd
运行时特效必须使用。使用 ensure_unique_override()/叠加闪光/剪裁溶解 — 切勿对共享的 .tres 材质执行 Tween。
pbr_material_builder.gd
运行时创建 PBR 材质,支持 ORM 纹理和三平面映射。
organic_material.gd
为有机表面(皮肤、树叶)设置次表面散射和边缘光照。用于制作逼真的角色或植被材质。
triplanar_world.gdshader
适用于无 UV 映射地形的三平面投影着色器。根据表面法线混合纹理。适用于悬崖、洞穴或程序化生成的地形。
pbr_orm_packer.gd
专业 PBR 资源工具。将环境光遮蔽、粗糙度和金属度打包到单张 ORM 纹理中,以优化显存占用和绘制调用。
vertex_wind_sway.gdshader
高性能、由 GPU 驱动的植被动画。使用顶点世界坐标和顶点颜色权重绘制,在无需骨架的情况下模拟风吹效果。
triplanar_world_projection.gdshader
无需 UV 的环境映射。沿 X/Y/Z 轴投影纹理,使其在复杂岩石和地形表面自然融合。
subsurface_scattering_setup.gd
配置逼真的有机材质。介绍 Forward+ 渲染的皮肤模式、透射和深度散射设置。
instance_uniform_batching.gdshader
高速批处理的架构模式。允许 10,000 个网格共用一种材质,同时通过实例 uniform 保持各自的颜色或生命值状态。
decal_placer_expert.gd
动态 3D 贴花系统,支持剔除掩码和生命周期管理,可用于冲击效果。
transparency_sorting_fix.gd
使用 Alpha Hash 和 Depth Prepass 策略解决视觉伪影。
shader_state_manager.gd
用于在多个实体上切换基于着色器的视觉状态(冻结、烧伤)的简洁模式。
depth_precision_fix.gd
从摄像机端修复大规模世界中的 Z-fighting 和纹理闪烁问题。
material_batcher.gd
全局覆盖系统,确保环境网格以优化且状态锁定的批次进行绘制。
StandardMaterial3D 清单(脚本优先)
- 打包 AO/粗糙度/金属度 → 必需
pbr_orm_packer.gd;设置orm_texture(切勿使用三张独立贴图)。 - 在指定
normal_texture之前启用normal_enabled(否则会静默无效)。 - 从下方矩阵中选择透明度模式——镂空材质不要使用文档默认的 ALPHA。
- 有机皮肤/树叶 →
organic_material.gd+subsurface_scattering_setup.gd(仅 Forward+ 支持真正的 SSS)。 - 运行时闪烁/溶解 → 必需,先调用
material_fx.gdensure_unique_override()。 - 共享网格的色调/变体 →
instance_uniform_batching.gdshader;切勿为每个实例创建独有的.tres。 - 简化远距离 LOD / 像素抖动淡出 →
material_batcher.gdsetup_lod_materials()。 - 启用 SSS/透明涂层/各向异性之前,请检查 Forward+ 与 Mobile 的功能矩阵。
Forward+ 与 Mobile(材质功能)
| 功能 | Forward+ | Mobile / Compatibility | 原因 |
|---|---|---|---|
| 次表面散射 / Skin Mode | 完整支持 | 有限支持 / 通常不可用 | SSS 需要 Forward+ 光照路径;在 Mobile 上可通过边缘光 + 透射烘焙来模拟 |
| Clearcoat | 支持 | 通常会被剥离 / 近似处理 | 额外高光波瓣会产生开销;远距离 LOD 和 Mobile 上应移除 |
| Anisotropy | 支持 | 建议关闭 | 流动贴图 + 各向异性 BRDF 会占用大量移动设备片元预算 |
| Alpha Hash / Pixel Dither 淡出 | 支持 | 建议使用 Alpha Scissor 或不透明抖动 | 哈希噪声 + 过度绘制会影响瓦片式 GPU |
| 实例化 uniform(批处理) | 支持 | 支持(建议使用) | 保持使用同一种材质;避免因资源各不相同而中断绘制 |
透明模式
决策矩阵
| 模式 | 使用场景 | 性能 | 排序问题 |
|---|---|---|---|
| ALPHA_SCISSOR | 植被、铁丝网 | 快 | 无 |
| ALPHA_HASH | 抖动淡出、LOD 过渡 | 快 | 有噪点 |
| ALPHA | 玻璃、水、godot-particles | 慢 | 有(渲染顺序) |
Alpha Scissor(镂空)
# For leaves, grass, fences
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA_SCISSOR
mat.alpha_scissor_threshold = 0.5 # Pixels < 0.5 alpha = discarded
mat.albedo_texture = load("res://leaf.png") # Must have alpha channel
# Enable backface culling for performance
mat.cull_mode = BaseMaterial3D.CULL_BACK
Alpha Hash(抖动)
# For smooth fade-outs without sorting issues
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA_HASH
mat.alpha_hash_scale = 1.0 # Dither pattern scale
# Animate fade
var tween := create_tween()
tween.tween_property(mat, "albedo_color:a", 0.0, 1.0)
Alpha Blend(完全透明)
# For glass, water (expensive)
mat.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
mat.blend_mode = BaseMaterial3D.BLEND_MODE_MIX
# Disable depth writing for correct blending
mat.depth_draw_mode = BaseMaterial3D.DEPTH_DRAW_DISABLED
mat.cull_mode = BaseMaterial3D.CULL_DISABLED # Show both sides
纹理通道打包
必需使用 pbr_orm_packer.gd 处理 R=AO / G=Roughness / B=Metallic。不要在此处内联打包方案。仅当导入的图集与 ORM 布局不一致时,才自定义通道映射。
着色器转换
何时转换为 ShaderMaterial
- 需要自定义效果(溶解、顶点位移)
- 遇到 StandardMaterial3D 的功能限制
- 着色器优化(移除未使用的功能)
转换工作流
# 1. Create StandardMaterial3D with all settings
var std_mat := StandardMaterial3D.new()
std_mat.albedo_color = Color.RED
std_mat.metallic = 1.0
std_mat.roughness = 0.2
# 2. Convert to ShaderMaterial
var shader_mat := ShaderMaterial.new()
shader_mat.shader = load("res://custom_shader.gdshader")
# 3. Transfer parameters manually
shader_mat.set_shader_parameter("albedo", std_mat.albedo_color)
shader_mat.set_shader_parameter("metallic", std_mat.metallic)
shader_mat.set_shader_parameter("roughness", std_mat.roughness)
材质变体(Godot 4.0+)
高效复用材质
# Base material (shared)
var base_red_metal := StandardMaterial3D.new()
base_red_metal.albedo_color = Color.RED
base_red_metal.metallic = 1.0
# Variant 1: Rough
var rough_variant := base_red_metal.duplicate()
rough_variant.roughness = 0.8
# Variant 2: Smooth
var smooth_variant := base_red_metal.duplicate()
smooth_variant.roughness = 0.1
# Note: Use resource_local_to_scene for per-instance tweaks
性能优化
材质批处理
# ✅ GOOD: Reuse materials across meshes
const SHARED_STONE := preload("res://materials/stone.tres")
func _ready() -> void:
for wall in get_tree().get_nodes_in_group("stone_walls"):
wall.material_override = SHARED_STONE
# All walls batched in single draw call
# ❌ BAD: Unique material per mesh
func _ready() -> void:
for wall in get_tree().get_nodes_in_group("stone_walls"):
var mat := StandardMaterial3D.new() # New material!
mat.albedo_color = Color(0.5, 0.5, 0.5)
wall.material_override = mat
# Each wall is separate draw call
纹理图集
# Combine multiple materials into one texture atlas
# Then use UV offsets to select regions
# material_atlas.gd
extends StandardMaterial3D
func set_atlas_region(tile_x: int, tile_y: int, tiles_per_row: int) -> void:
var tile_size := 1.0 / tiles_per_row
uv1_offset = Vector3(tile_x * tile_size, tile_y * tile_size, 0)
uv1_scale = Vector3(tile_size, tile_size, 1)
边缘情况
法线贴图不起作用
# Problem: Forgot to enable
mat.normal_enabled = true # REQUIRED
# Problem: Wrong texture import settings
# In Import tab: Texture → Normal Map = true
模型上出现纹理接缝
# Problem: Mipmaps causing seams
# Solution: Disable mipmaps for tightly-packed UVs
# Import → Mipmaps → Generate = false
材质看起来很平
# Problem: Missing normal map or roughness variation
# Solution: Add normal map + roughness texture
mat.normal_enabled = true
mat.normal_texture = load("res://normal.png")
mat.roughness_texture = load("res://roughness.png")
专家技巧与优化
1. 使用 Pixel Dither 进行 LOD 过渡
使用分层细节级别(HLOD)或可见性范围在远距离淡出物体时,标准 Alpha 混合会因透明边界重叠而造成严重的性能损耗。请将材质的 Distance Fade 模式设为 Pixel Dither。这样既能实现视觉上平滑的淡出,又能完全使用高性能的不透明渲染管线。
2. 模板缓冲区(Godot 4.5+)
直接在 StandardMaterial3D 中使用模板缓冲区。这样无需为基本效果编写自定义着色器,即可轻松为被墙壁遮挡的物体渲染轮廓或 X 射线效果。
3. AR 阴影叠加着色器
如果你正在开发 AR 游戏,可能希望虚拟阴影显示在现实世界的摄像头画面上。不要使用标准混合,而应在空间着色器中使用 Godot 内置的 shadow_to_opacity 渲染模式。
shader_type spatial;
// shadow_to_opacity makes the material invisible when lit,
// but opaque (dark) when it receives a shadow from another 3D object.
render_mode blend_mix, depth_draw_opaque, cull_back, shadow_to_opacity;
void fragment() {
// The surface color is black; opacity will be driven by incoming shadows
ALBEDO = vec3(0.0, 0.0, 0.0);
}
专家模式:材质-纹理数组(实例化变体)
对于每个实例的颜色/生命值以及纹理数组索引变体,必须使用 instance_uniform_batching.gdshader。通过 GeometryInstance3D.set_instance_shader_parameter 设置 texture_index——切勿为每种树木/人群变体创建独立材质。
专家模式:溶解着色器集成(Alpha Scissor)
使用 Alpha Scissor 实现高性能溶解效果(保留阴影,避免 Alpha 排序)。必须使用 material_fx.gd 中的 dissolve_scissor()——该函数会先复制材质覆盖项。
专家模式:材质 LOD 系统(HLOD)
网格 LOD 会自动处理;材质着色则不会。对于可见性范围切换、远距离材质功能剥离,以及 Pixel Dither 距离淡出(而非 Alpha 混合),必须使用 material_batcher.gd 中的 setup_lod_materials()。
专家见解(WHY — 保留在正文中)
- ORM 打包 — WHY:三张独立贴图会让采样器槽位增加到三倍,并破坏批处理。将 AO、粗糙度和金属度打包到一张 RGB 贴图中(pbr_orm_packer.gd)。
- 金属度设为 0.5 — WHY:PBR 金属的金属度为 0 或 1;中间值仅用于污垢/锈蚀过渡,不应用作默认涂装。
- 共享材质修改 — WHY:调整共享的
.tres会影响每个实例。在运行时应用 FX 前,使用duplicate(true)或 Local To Scene(material_fx.gd)。 - 像素抖动 LOD 淡出 — WHY:Alpha 混合距离淡出会使片段留在透明渲染管线中;抖动则保持不透明(material_batcher.gd)。
深入方案(按需查阅)
| 主题 | 参考资料/脚本 |
|---|---|
| 金属/电介质预设/SSS/清漆层 | pbr-workflows.md |
参考资料
渐进式披露:仅在研究特定 API 时打开官方文档链接; 将工作分派给相关领域时再加载相关技能,不要预加载整个技能网络。
官方文档
- Standard Material 3D 和 ORM Material 3D — 关于反照率/金属度/粗糙度、ORM 打包、透明模式,以及 StandardMaterial3D 功能标志的主要 PBR 教程。
- BaseMaterial3D — 提供透明度枚举、纹理通道、剔除/深度绘制、距离淡出和次表面散射控制的通用 API。
- StandardMaterial3D — 本技能的构建器、FX 助手和预设中使用的具体材质类。
- ORMMaterial3D — 当遮蔽/粗糙度/金属度已位于同一张 RGB 纹理中时,使用专用的 ORM 打包材质路径。
- 使用 Decal — 投影 Decal、剔除掩码,以及用于弹孔和细节表现且无需唯一材质的性能限制。
- 导入图像 — 正确的法线贴图和通道导入设置,确保 PBR 贴图不会被当作颜色数据处理。
- 可见性范围(HLOD) — 距离切换/淡出模式,可与简化的远景材质和像素抖动距离淡出配合使用。
- Spatial 着色器 — 当 StandardMaterial3D 无法满足需求时,用于三平面映射、风吹摆动、
instance uniform和shadow_to_opacity的内置功能。 - 第一个 3D 着色器 — 将 StandardMaterial3D 设置转换为可编辑 Spatial ShaderMaterial 的方法。
- GeometryInstance3D — 用于共享材质批处理的
set_instance_shader_parameter、材质叠加/覆盖和可见性范围属性。 - GPU 优化 — 过度绘制、透明度开销和批处理方面的指导,说明了 ORM 打包及避免使用唯一材质的原因。
相关技能
前置条件
- godot-project-foundations — 在编写可复用的
.tres材质和纹理集之前,必须掌握节点、资源和导入基础知识。 - godot-resource-data-patterns — 材质/纹理资源、复制与共享,以及可保持绘制调用批处理完整的数据驱动预设。
- godot-shaders-basics — 转换 StandardMaterial3D 或编写三平面/实例 uniform 着色器之前,需掌握着色语言和 ShaderMaterial 基础知识。
补充
- godot-3d-lighting — 发射能量、HDR、GI 和 AreaLight3D 的交互,这些因素决定了 PBR 材质和发光材质在场景中的实际观感。
- godot-3d-world-building — 在大型关卡几何体上应用共享环境材质、贴花和三平面投影。
- godot-camera-systems — Camera3D 的近远裁剪面和取景设置,可解决单靠材质无法处理的 Z-fighting / 深度精度问题。
- godot-particles — 粒子绘制模式和 Alpha 管线必须与材质透明度选项(scissor/hash 与 blend)保持一致。
- godot-performance-optimization — 扩展使用独特材质与共享材质时的绘制调用批处理、MultiMesh 和 GPU 预算。
- godot-debugging-profiling — 使用 GPU/过度绘制分析器,验证材质变更后透明度和材质状态是否出现回归。
下游 / 使用方
- godot-genre-open-world — 大型世界会用到此技能中的 HLOD 可见范围、抖动式距离淡出和共享材质批处理模式。
- godot-procedural-generation — 缺少 UV 或 UV 不稳定时,程序化网格和地形通常需要三平面/世界投影材质。
- godot-adapt-2d-to-3d — 将平面美术素材转入 3D 时,需要设置 PBR 贴图、法线导入和透明度模式;这些内容均在此介绍。
主入口
- godot-master — 用于跨技能发现的库路由器和镜像模块入口。