主题
材质系统(Material System)
管理 GameGraph 3D 与 Urho2D 渲染材质的创建、属性设置、着色器配置。仅客户端可用(#if CLIENT)。
定义位置:GameGraph.MaterialSystem
材质类型
| 类型 | 用途 | 关键属性 |
|---|---|---|
MaterialPBR | PBR 金属度/粗糙度材质 | ColorFactor, MetallicFactor, RoughnessFactor |
MaterialVertexColor | 贴图乘顶点颜色,提供固定的受光、无光、裁剪与混合模式 | Mode, AlbedoTexture, ColorFactor |
MaterialFlatLambert | 无贴图 Lambert 纯色材质 | Color, Transparent |
MaterialWater | 水面材质 | TintColor |
MaterialUrho2D | Urho2D 无光照精灵材质 | Texture, Color, BlendMode, DepthTestMode, DepthWrite |
MaterialCustom | 通用参数访问 | SetFloat/SetColor/SetVector |
选型建议
| 需求 | 推荐做法 | 说明 |
|---|---|---|
| 常规模型、带贴图或金属度/粗糙度 | MaterialPBR | SDK 当前最完整的通用材质入口 |
| 程序网格、体素 AO、逐顶点烘焙亮度 | MaterialVertexColor | Albedo、ColorFactor 和顶点 RGBA 相乘;透明语义由固定模式决定 |
| 树叶、栅栏等硬边透明表面 | MaterialVertexColor(..., LitAlphaCutout) | 按 Albedo Alpha 裁剪,并保留不透明深度与裁剪阴影 |
| 玻璃等半透明表面 | MaterialVertexColor(..., UnlitAlphaBlend) | Alpha 混合且不写深度;按透明对象规则分组和排序 |
| 程序生成几何体、调试几何体、无贴图纯色对象 | MaterialFlatLambert | 受场景光照、阴影和 SSAO 影响,不是严格 Unlit |
| 无贴图半透明纯色对象 | new MaterialFlatLambert(transparent: true) | Color.A 参与 alpha 混合 |
| 单层水面 | MaterialWater | 对应 singlelayerwater pass |
| 运行时 Mesh 粒子 | Editor/Techniques/Lambert/ParticleLambert.xml | 用 Mesh.Material(...).Technique(...) 覆盖 mesh emitter technique |
| 特殊美术材质或项目自定义 technique | MaterialCustom | 直接用属性名或 Technique.PropertyToID(...) 读写参数 |
MaterialVertexColor 是有贴图且要求网格提供 Color 顶点流的专用入口。无贴图纯色仍使用 MaterialFlatLambert;它不会因为新增顶点颜色材质而变成 Unlit。
对应变体已发布到 Editor、Windows、Android 和 iOS shadercache overlay。真实 Editor 已覆盖四档场景画质、HDR 开关、投影与两种程序网格路径。
MaterialVertexColor
MaterialVertexColor 将 AlbedoTexture × ColorFactor × 顶点颜色 组合为最终表面颜色。它适合方块网格、顶点 AO、天光/方块光烘焙和需要同一贴图在不同顶点显示不同亮度的程序生成几何体。该类型仅客户端可用,不改变 MaterialPBR 的顶点色或透明行为。
csharp
#if CLIENT
using System.Drawing;
using GameCore.Drawing;
using GameGraph.MaterialSystem;
using GameGraph.ResourceSystem;
var texture = Texture2D.Load("texture/voxel/stone.tga")
?? throw new InvalidOperationException("Voxel texture was not found.");
var material = new MaterialVertexColor(
texture,
VertexColorMaterialMode.UnlitOpaque)
{
ColorFactor = new HdrColor(255, 255, 255, 255)
};
var mesh = new MeshBuilder()
.SetPositions(positions)
.SetNormals(normals)
.SetTexCoords(uvs)
.SetColors(vertexColors)
.SetIndices(indices)
.Build();
#endifVertexColorMaterialMode 使用显式稳定编号,便于配置、触发器和序列化保持一致:
| 模式 | 数值 | 光照与 Alpha 语义 |
|---|---|---|
LitOpaque | 0 | 受场景光照影响;按不透明对象绘制,不启用 Alpha 混合 |
UnlitOpaque | 1 | 不受场景光照影响;适合把 AO 或体素亮度烘焙到顶点 RGB |
LitAlphaCutout | 2 | 受场景光照影响;按 Albedo Alpha 做硬裁剪,并让深度/阴影 pass 使用同一裁剪贴图 |
UnlitAlphaBlend | 3 | 不受场景光照影响;最终 Alpha 为贴图、顶点色与 ColorFactor Alpha 的乘积,使用 Alpha 混合且不写深度 |
这些模式的 Alpha 语义是固定契约:LitAlphaCutout 的去留由 Albedo Alpha 决定,顶点 Alpha 不改变裁剪阈值;UnlitAlphaBlend 才使用连续顶点 Alpha。需要硬边洞口时不要改用 Alpha 混合,需要连续半透明时也不要用裁剪模式。切换 Mode 会整体切换到对应的固定 Technique,不会运行时改写共享 pass defines。
MeshBuilder.SetColors(...) 与 CustomGeometryComponent.DefineColor(...) 都可提交顶点颜色。受光模式应提供有效 Normal;UV 与 Color 是四种模式的必要数据。Tangent 仅在所选 shader 确实需要切线空间数据时提供,不应把它作为顶点色材质的通用前置条件。
四个固定 Technique 入口如下;KnownTechnique 与 KnownTechniquePath 使用相同属性名:
| 公开名称 | Technique XML |
|---|---|
TexturedVertexColorLitOpaque | EngineRes/Techniques/DiffVCol.xml |
TexturedVertexColorUnlitOpaque | EngineRes/Techniques/DiffVColUnlit.xml |
TexturedVertexColorLitAlphaCutout | EngineRes/Techniques/DiffVColAlphaMask.xml |
TexturedVertexColorUnlitAlphaBlend | EngineRes/Techniques/DiffVColUnlitAlphaBlend.xml |
一般代码直接构造 MaterialVertexColor 即可。只有诊断或需要读取路径时才使用上述 KnownTechnique / KnownTechniquePath。通过 Material.Load(...) 或组件读取已加载材质时,这四条路径会恢复为 MaterialVertexColor,Mode 与路径保持对应。
纹理来源边界
- 项目发布的普通纹理继续使用
Texture2D.Load(...)。资源系统会经由 TextureX 容器链路选择当前平台的压缩格式、mip 和采样数据;不要把发布资源改成启动时从原图重新上传。 - 客户端运行时生成或修改的
Image使用Texture2D.CreateFromImage(...),并由创建者管理纹理生命周期。 - RenderToTexture 使用
Texture2D.CreateRenderTarget(...)。它与发布纹理和运行时静态上传是三条不同路径。
VoxelMaterialSample 使用运行时 16×16 图片,只是为了生成确定性的视觉夹具。正式方块贴图仍应优先走 Texture2D.Load(...) 与 TextureX 发布链。样例同时对照经典顶点色四模式、PBR 顶点色不透明/裁剪,以及标准 PBR 混合/裁剪;每种路径都覆盖 MeshBuilder + StaticMeshComponent 与 CustomGeometryComponent。project.voxel_material_snapshot 返回逐格材质与纹理状态,project.voxel_render_profile 可查询或切换场景画质、HDR 和动态灯光。
MaterialPBR
csharp
var mat = new MaterialPBR(useAlbedoTexture: true, useAlphaChannel: false);
mat.ColorFactor = HdrColor.White;
mat.MetallicFactor = 0.5f;
mat.RoughnessFactor = 0.3f;
mat.EmissiveColor = new HdrColor(1f, 0.5f, 0f);
mat.EmissiveIntensity = 2.0f;
mat.UseDefaultTextures(); // 设置默认的 Albedo 和 MetalnessRoughness 贴图已有自定义 Albedo 纹理时可直接传入构造函数,避免先创建无贴图材质再切换状态:
csharp
var texture = Texture2D.CreateFromImage(image, sRgb: true, mipLevels: 1)
?? throw new InvalidOperationException("Texture upload failed.");
var mat = new MaterialPBR(texture, useAlphaChannel: false);需要明确区分连续透明与硬裁剪时,使用 PBRAlphaMode:
csharp
var glass = MaterialPBR.Create(glassTexture, PBRAlphaMode.AlphaBlend);
var leaves = MaterialPBR.Create(leavesTexture, PBRAlphaMode.AlphaCutout);AlphaBlend 使用 Albedo Alpha 混合且不写深度;AlphaCutout 以固定阈值 0.5 裁剪颜色、深度和阴影。旧构造器的 useAlphaChannel: true 继续表示 AlphaBlend。UseAlphaChannel 也继续保留:从不透明模式设为 true 会进入混合模式,设为 false 会回到不透明;已经明确选择裁剪模式时,再设为 true 不会把它降级为混合。
代码创建的混合材质使用 PhysicalBasedRenderingAlphaBlend / PhysicalBasedRenderingAlphaBlendSolid。旧的 PhysicalBasedRenderingAlpha / PhysicalBasedRenderingAlphaSolid 路径继续保留给既有资源文件和路径比较;新代码不要用旧路径代替明确的 PBRAlphaMode。
程序化图片的生成、上传参数和资源释放见运行时程序化纹理指南。
属性
| 属性 | 类型 | 说明 |
|---|---|---|
UseAlbedoTexture | bool | 是否使用 Albedo 贴图(影响 Shader 选择) |
UseAlphaChannel | bool | 兼容入口;true 默认选择 Alpha 混合,false 选择不透明 |
AlphaMode | PBRAlphaMode | Opaque、AlphaBlend 或 AlphaCutout;裁剪要求 Albedo 纹理 |
ColorFactor | HdrColor | 颜色系数 |
EmissiveColor | HdrColor | 自发光颜色 |
MetallicFactor | float | 金属度(0-1) |
RoughnessFactor | float | 粗糙度(0-1) |
EmissiveIntensity | float | 自发光强度 |
贴图颜色空间与通道契约
贴图的颜色空间由内容和用途决定,不能根据 .png、.tga 等后缀或是否使用 PBR 推断。常见 Albedo / Diffuse 是 sRGB 编码的颜色;法线、粗糙度、金属度和 AO 是线性数据。源素材明确使用线性颜色时,保留其约定,不再做 sRGB 解码。
| 输入 | 颜色空间 | 使用规则 |
|---|---|---|
| 常见 sRGB 编码的 Albedo / Diffuse | sRGB=true | 保留原始颜色字节,加载时解码;不要再手工做一次 gamma 转换 |
| 普通 RGB 法线 | sRGB=false | 先核对目标材质的法线编码、通道与 Y 方向约定 |
| 粗糙度、金属度、AO、混合数据图 | sRGB=false | 通道值是数据,sRGB 解码会改变这些值 |
项目贴图在首次加载前添加同名 XML。例如 res/props/crate.tga 的参数文件为 res/props/crate.xml:
xml
<texture><srgb enable="true" /></texture>混合贴图 res/props/crate_mix.png 对应 res/props/crate_mix.xml:
xml
<texture><srgb enable="false" /></texture>Texture2D.Load("props/crate.tga") 不会因绑定到颜色槽就自动补齐该声明。运行时创建纹理时,在 Texture2D.CreateFromImage(...) 的 sRgb 参数中明确指定颜色空间,见运行时程序化纹理指南。
混合贴图没有跨材质通用的通道布局。 当前两条 PBR 路线应分别处理:
| 材质 / Technique | 法线与数据图布局 | 参数作用 |
|---|---|---|
MaterialPBR 的 Editor/Techniques/PBR_PackedNormal/DefaultMetallicRoughness.xml | normal 槽(TextureUnit.Normal):R/G=法线 X/Y,B=粗糙度,A=金属度 | RoughnessFactor、MetallicFactor 是乘数;金属度还受 MetalMul0or1 控制 |
MaterialPBRVertexColor | 独立 NormalTexture;RoughnessMetalnessTexture 的 R=粗糙度、G=金属度 | RoughnessOffset、MetallicOffset 是加法偏移 |
普通 RGB 法线中的 B 是法线 Z,不能原样用作第一条路线的粗糙度。适配时保留原图,生成新的 RGBA 混合图:在源法线编码兼容的前提下保留 R/G,将实际粗糙度填入 B、金属度填入 A。法线 Y 方向不根据 Maker 来源或文件名自动翻转,应依据源约定并在固定光照下检查凹凸方向。glTF ORM 等打包图也应按其源通道定义重新组合。
对于上述 packed-normal Technique,混合图已保存最终粗糙度和金属度时,将两个 Factor 设为 1;例如 B=0.85 再乘 RoughnessFactor=0.85 会得到约 0.72,并非 0.85。材质文件需要金属效果时显式配置 <parameter name="MetalMul0or1" value="1" />。不要仅凭 MetallicFactor 非零就认定金属效果已经启用,仍需检查材质参数与实际反光。没有混合图时先保留网格法线,用材质系数控制表面;不要给其它 Technique 套用这张表。
resource_import_model_package 会为支持的源材质生成上述颜色空间声明;有普通法线时生成 RGBA 混合图,并将已写入通道的 Factor 设为 1。直接复制资源或用 GameGraph 引用裸贴图时,需要自行完成这些适配。详见项目模型资源包导入。
发白与法线异常的验证
导入模型发白时,优先检查颜色贴图的 sRGB 设置。 若源 Albedo / Diffuse 是常见 sRGB 编码的颜色图,而实际纹理 SRGB=false,先在同名 XML 中设置 <srgb enable="true" />,重载贴图及材质,在相同镜头和光照下比较。确认颜色空间后,再排查灯光、环境反射、曝光与材质系数。源颜色明确为线性时保留 false;法线和混合数据图也保持 false。
先用 Runtime MCP material.probe 检查实际 Technique、贴图槽、纹理 s_rgb 和材质系数;也可读取纹理的 SRGB 属性。颜色纹理被按线性值使用时可能发白,数据图误用 sRGB 则可能改变凹凸与表面反光。亮度还受灯光、环境反射和曝光影响,单凭截图不能确定原因。
修改 XML 后重载贴图及引用它的材质;仍有缓存疑点时重新进入项目或调试。不要把对已加载纹理修改 SRGB 属性当作 GPU 资源已按新格式重建的证明。同一资源路径的纹理可能共享,需要不同颜色空间时使用不同资源路径和各自的 XML。
固定模型、镜头、光照和颜色系数,每次只改一个设置,拍摄修改前后与恢复后的画面,并检查未修改对象。贴图加载成功或已绑定到槽位,也不能代替实际法线、反光和颜色的验收。
逐张贴图验收
导入验收覆盖场景实际使用的每个独立颜色贴图路径,包括角色、武器、地板和道具。某个模型的配置正确,不能代替其他资源的检查;手动复制或通过 Texture2D.Load 加载的贴图也需要检查。
- 从实际材质的颜色槽收集资源路径,逐张核对源颜色空间和同名 XML。常见 sRGB 编码颜色图设为
true,明确线性颜色图保留源约定;法线及混合数据图保持false。 - 重载贴图和材质,或重新进入调试。在
scenegraph.materials返回的贴图列表中按资源路径定位材质,再用material.probe的nodeId精确查询,确认每张贴图的实际s_rgb,不能只检查磁盘上的 XML。 - 固定镜头、光照和材质系数比较前后画面,并检查未修改对象。资源加载成功不代表颜色空间已验收;补齐声明后也不要同时调亮灯光来抵消颜色变化。
MaterialPBRVertexColor
MaterialPBRVertexColor 用于需要法线、粗糙度/金属度和顶点 RGBA 的程序网格。它独立于 MaterialPBR,不会改变既有 PBR 对顶点 RGB 的处理。
csharp
var material = new MaterialPBRVertexColor(
albedoTexture,
normalTexture,
roughnessMetalnessTexture,
PBRVertexColorMaterialMode.Opaque);
material.ColorFactor = HdrColor.White;
material.RoughnessOffset = 0f;
material.MetallicOffset = 0f;首版提供 Opaque 与 AlphaCutout 两种固定模式。裁剪始终读取 Albedo Alpha,并让颜色、深度和阴影使用同一个 0.5 阈值;不提供 PBR 顶点色 Alpha 混合,连续透明仍使用 MaterialPBR.Create(..., PBRAlphaMode.AlphaBlend) 或经典 MaterialVertexColor(UnlitAlphaBlend)。
网格必须提交 Position、Normal、UV、Color 和 Tangent。法线贴图以及粗糙度/金属度贴图是线性数据,运行时创建时应设置 sRgb: false。这条 PBR 路径读取混合贴图的 R=粗糙度、G=金属度,并分别加上 RoughnessOffset、MetallicOffset;它与 MaterialPBR 的 ShaderLab 参数契约不同。
| 属性 | 类型 | 说明 |
|---|---|---|
Mode | PBRVertexColorMaterialMode | Opaque 或 AlphaCutout |
AlbedoTexture | Texture2D? | sRGB Albedo,与材质乘色和顶点 RGBA 相乘 |
NormalTexture | Texture2D? | 线性法线贴图 |
RoughnessMetalnessTexture | Texture2D? | 线性混合贴图,R=粗糙度、G=金属度 |
ColorFactor | HdrColor | MatDiffColor 材质乘色 |
SpecularFactor | HdrColor | MatSpecColor 非金属高光颜色因子 |
RoughnessOffset | float | 加到混合贴图 R 通道的偏移 |
MetallicOffset | float | 加到混合贴图 G 通道的偏移 |
MaterialFlatLambert
csharp
var mat = new MaterialFlatLambert(transparent: true);
mat.Color = new HdrColor(1f, 0f, 0f, 0.5f); // 半透明红色| 属性 | 类型 | 说明 |
|---|---|---|
Transparent | bool | 是否透明(影响 Shader 选择) |
Color | HdrColor | 主颜色。透明模式下 Alpha 通道参与混合 |
MaterialFlatLambert 使用已缓存的 Lambert 渲染路径,适合程序生成 Mesh、调试几何体和无贴图纯色对象。它会受场景光照、阴影和 SSAO 影响,不是严格意义的 Unlit。需要“贴图 × 顶点色”的无光照路径时使用 MaterialVertexColor(UnlitOpaque);无贴图 Unlit 仍没有独立强类型入口。
MaterialUrho2D
MaterialUrho2D 使用已有的 Urho2D 顶点/像素 shader,为 StaticSprite2D.CustomMaterial 提供可独立配置的材质。输出颜色为主纹理、精灵顶点颜色和材质 Color 的乘积;精灵自身的 Color / Alpha 已包含在顶点颜色中。它不受场景光照影响。
csharp
#if CLIENT
using EngineInterface.Urho3DInterface.Graphics;
using GameCore.Drawing;
using GameGraph.MaterialSystem;
// staticSprite 是已设置 Sprite 的 StaticSprite2D。
var material = new MaterialUrho2D
{
Texture = staticSprite.Sprite!.Texture,
Color = new HdrColor(255, 255, 255, 255),
BlendMode = staticSprite.BlendMode,
DepthTestMode = CompareMode.Always
};
staticSprite.CustomMaterial = material;
#endif| 配置项 | 默认值 | 行为 |
|---|---|---|
Texture | null | 主纹理,必须自行绑定;不自动跟随精灵换图 |
Color | 白色 | 材质乘色,含 Alpha;可通过 KnownColorProperty.Urho2DColor 访问 MatDiffColor |
BlendMode | Alpha | 材质的混合方式,接管后不跟随精灵的 BlendMode |
DepthTestMode | LessEqual | Always 忽略已有深度遮挡,但仍可能被后续透明对象或 UI 覆盖 |
DepthWrite | false | 开启后透明纹素也可能写深度,不会自动做 Alpha 裁剪 |
继承的 CullMode | None | 默认双面绘制 |
每个 MaterialUrho2D 拥有独立 Technique,修改混合和深度状态不会修改其他材质。也可使用 KnownTechnique.Urho2D:它是按需创建的共享方案,修改 pass 前必须 Clone()。例如:
csharp
var technique = KnownTechnique.Urho2D.Clone();
technique.GetPass("alpha")!.DepthTestMode = CompareMode.Always;
var custom = new MaterialCustom(technique);
custom.CullMode = CullMode.None;
custom.Textures[TextureUnit.Diffuse] = staticSprite.Sprite!.Texture;
custom.Colors[KnownColorProperty.Urho2DColor] = new HdrColor(255, 255, 255, 255);KnownTechnique / KnownColorProperty 位于 GameGraph.MaterialSystem.Enum。Urho2D 在内存中创建,不依赖新增 XML 文件,也没有 KnownTechniquePath.Urho2D;不要通过空 Technique.Path 判断材质类型。通过 MaterialCustom.ToKnownMaterial() 按路径识别时,不会自动转换为 MaterialUrho2D。
使用边界:
AnimatedSprite2D会把同一个CustomMaterial用到所有批次。仅在明确共享同一纹理和混合方式时使用;此入口不自动适配多图集或混合方式不同的动画部件。PremulAlpha只改变混合状态,不自动预乘纹理或颜色;资源和颜色参数需要匹配对应混合约定。- 默认 shader 不读取通用 UV 平铺、滚动、旋转参数,也不提供灰度、描边、溶解、扭曲。
- 需要客户端已经提供 Technique/Pass 接口及 Urho2D shadercache;新增依赖 API 不会给缺少底层接口的旧客户端补出能力。
MaterialWater
csharp
var mat = new MaterialWater();
mat.TintColor = new HdrColor(0f, 0.3f, 0.6f);MaterialWater 使用 EngineRes/Techniques/SingleLayerWater.xml,其 pass 名为 singlelayerwater,可匹配 CEMapSSAO.xml 等 RenderPath 中的水体 pass。
MaterialCustom
通用材质,通过名称或预定义属性 ID 访问参数。
csharp
var technique = Technique.Find("path/to/technique.xml")
?? throw new InvalidOperationException("Technique not found.");
var mat = new MaterialCustom(technique);
// 按名称设置
mat.SetFloat("CustomParam", 1.0f);
mat.SetVector("UVScale", new Vector4(1, 1, 0, 0));
mat.SetColor("TintColor", someHdrColor);
// 按名称读取
float val = mat.GetFloat("CustomParam");
Vector4 vec = mat.GetVector("UVScale");
HdrColor col = mat.GetColor("TintColor");
// 按属性 ID(更高效)
uint id = Technique.PropertyToID("CustomParam");
mat.SetFloat(id, 1.0f);
float v = mat.GetFloat(id);预定义属性访问器
csharp
mat.Colors[KnownColorProperty.PBRColorFactor] = color;
mat.Floats[KnownFloatProperty.PBRMetallicFactor] = 0.5f;
mat.Vectors[KnownVectorProperty.SomeProperty] = vec4;KnownColorProperty
PBRColorFactor, PBREmissiveColor, FlatLambertColor, VertexColorColorFactor, OverrideColor, WaterTintColor
KnownFloatProperty
PBRMetallicFactor, PBRRoughnessFactor, PBREmissiveIntensity
ToKnownMaterial
将 MaterialCustom 转换为具体类型(如果 Shader 匹配):
csharp
Material? typed = customMat.ToKnownMaterial();
if (typed is MaterialPBR pbr)
{
pbr.MetallicFactor = 0.8f;
}基类 Material
所有材质类型的共有成员。
属性
| 属性 | 类型 | 说明 |
|---|---|---|
Technique | Technique? | 材质绑定的 Technique XML 渲染方案 |
Textures | MaterialTextureAccessor | 贴图访问器 |
StencilState | StencilState | 模板测试配置 |
CullMode | CullMode | 背面剔除(None, CCW, CW) |
FillMode | FillMode | 填充模式(Solid, Wireframe, Point) |
RenderOrder | uint | 渲染顺序(值越大越晚渲染) |
方法
csharp
// 加载材质文件
static Material? Load(GameCore.ResourceType.Material materialPath);
// Technique Pass 控制
void SetPassEnabled(string passName, bool enabled);
void SetPassDepthWrite(string passName, bool depthWrite);
void SetPassColorWrite(string passName, bool colorWrite);
// 运行时诊断
bool HasPass(string passName, uint techniqueIndex = 0);
MaterialDebugInfo GetDebugInfo(IEnumerable<string>? passNames = null);
string DebugDescribe(IEnumerable<string>? passNames = null);运行时诊断
当材质在代码里已经赋给 StaticMeshComponent,但画面里看不到或和 RenderDoc 抓帧不一致时,先读取运行时材质快照,不要只猜 shader 或 C# 逻辑。
csharp
Game.Logger.LogInformation("black hole material: {Material}", material.DebugDescribe());
bool hasBase = material.HasPass("base");
bool hasAlpha = material.HasPass("alpha");
bool hasDepth = material.HasPass("depth");
var info = material.GetDebugInfo(["base", "alpha", "depth"]);MaterialDebugInfo 常用字段:
| 字段 | 说明 |
|---|---|
TechniquePath | 当前绑定的 technique XML 路径 |
TechniqueCount | 当前材质 technique 数量 |
Passes | 指定 pass 在各 technique 上是否存在 |
Properties | 已知材质类型的关键参数,例如 MatDiffColor、ColorFactor、Emissive_Mul |
CullMode / FillMode / RenderOrder | 常见渲染状态 |
StencilState | 模板测试状态 |
VertexShaderDefines / PixelShaderDefines | 材质级 shader defines |
也可以通过 Runtime MCP 在运行中的客户端里直接探测 SceneGraph 材质:
json
{
"name": "material.probe",
"arguments": {
"query": "BlackHole",
"passNames": ["base", "alpha", "depth"]
}
}json
{
"name": "scenegraph.materials",
"arguments": {
"query": "Unlit",
"includeCurrentScenes": true,
"includeSession": true,
"includeReplicated": true,
"maxResults": 20,
"passNames": ["base", "alpha", "depth"]
}
}scenegraph.materials 会遍历已加载 SCE 场景、脚本 session SceneGraph 和 replicated SceneGraph,覆盖 StaticMeshComponent 与 CustomGeometryComponent。StaticMesh 还返回 Mesh/LOD0 Geometry/VertexBuffer/IndexBuffer 元数据;CustomGeometry 返回 material slot 和顶点数,当前无法读取的精确 GPU layout 会明确标为 unavailable。材质条目同时包含常用纹理槽与实际 pass 状态。
material.probe / scenegraph.materials 参数说明:
| 参数 | 类型 | 说明 |
|---|---|---|
query | string | 可选。按节点名、材质类型名或 technique path 子串过滤 |
nodeId | integer | material.probe 可选。精确匹配 SceneGraph 节点 ID |
materialIndex | integer | 可选。指定 StaticMesh 或 CustomGeometry 的几何体/材质槽索引 |
includeCurrentScenes | bool | 是否包含已加载 SCE 场景,默认 true |
includeSession | bool | 是否包含客户端脚本本地创建的 session SceneGraph,默认 true |
includeReplicated | bool | 是否包含客户端订阅到的 replicated SceneGraph,默认 true |
maxNodes | integer | 最多遍历节点数,默认 1000 |
maxResults | integer | scenegraph.materials 返回的最大材质条目数,默认 200 |
maxDiagnostics | integer | 局部资源不可读诊断上限;列表默认跟随 maxResults,单点探测默认 50 |
passNames | string[] | 需要检查的 pass 名。对 CEMapSSAO.xml 常用 ["base","alpha","depth","singlelayerwater"] |
返回值里优先看 entry.graph、entry.drawable、entry.geometry / entry.custom_geometry、entry.material.technique_path、entry.material.passes、entry.material.textures 与渲染状态。瞬态失效只生成有界 diagnostics,不会让其他条目一起失败。static_mesh、shader_path、has_shader 等旧字段继续保留。
RenderPath 与 pass 排查
RenderPath 只会执行它声明的 pass。若 technique 没有对应 pass,该对象不会参与那一轮渲染。MaterialFlatLambert 默认使用 EngineRes/Techniques/NoTextureFlatLambert.xml,它包含 base 和 depth pass;在 EngineRes/RenderPaths/CEMapSSAO.xml 这类先执行 pass="depth" 生成 SSAO 深度缓冲的 RenderPath 下,opaque FlatLambert 会参与 depth prepass。
EngineRes/Techniques/NoTextureFlatLambertAlpha.xml 提供 alpha pass;CEMapSSAO.xml 也会执行 alpha pass,所以透明 FlatLambert 从 pass 名匹配上看是成立的。MaterialWater 使用 EngineRes/Techniques/SingleLayerWater.xml,提供 singlelayerwater pass。若对象仍不可见,优先检查材质 alpha、RenderOrder、深度/混合状态、节点 scale、相机裁剪和 RenderDoc 中是否存在对应 draw call。
贴图
csharp
material.Textures[TextureUnit.PBRAlbedo] = albedoTexture;
material.Textures[TextureUnit.PBRMetalnessR_RoughnessG] = specularTexture;常用 TextureUnit:PBRAlbedo(0), Normal(1), PBRMetalnessR_RoughnessG(2), Emissive(3), PBRAmbientOcclusionMap(14), LightMap(16)
模板测试(Stencil)
csharp
material.StencilState = new StencilState
{
StencilTest = true,
StencilCompare = CompareMode.Equal,
StencilRef = 1,
StencilWriteMask = 0xFF,
StencilReadMask = 0xFF,
PassOp = StencilOp.Keep,
};StencilState 字段
| 字段 | 类型 | 默认值 | 说明 |
|---|---|---|---|
StencilTest | bool | false | 是否启用 |
StencilCompare | CompareMode | Always | 比较方式 |
StencilRef | int | 0 | 参考值 |
PassOp | StencilOp | Keep | 通过时操作 |
StencilReadMask | uint | 0 | 读取掩码 |
StencilWriteMask | uint | 0 | 写入掩码 |
CompareMode:Always, Equal, NotEqual, Less, LessEqual, Greater, GreaterEqual
StencilOp:Keep, Zero, Ref, Incr, Decr
SceneGraph 遮罩示例
Stencil 只依赖材质渲染状态。SceneGraph 中使用遮罩时,先让写入模板的物体渲染,再让读取模板的物体渲染;用 RenderOrder 显式固定顺序,避免默认排序影响结果。
csharp
const int stencilRef = 1;
// 写入模板:先渲染,把覆盖区域写成 stencilRef
var maskMat = new MaterialPBR { RenderOrder = 10 };
maskMat.StencilState = new StencilState
{
StencilTest = true,
StencilCompare = CompareMode.Always,
StencilRef = stencilRef,
StencilReadMask = 0xFF,
StencilWriteMask = 0xFF,
PassOp = StencilOp.Ref,
};
// 读取模板:只在写入区域内渲染
var insideMat = new MaterialPBR { RenderOrder = 20 };
insideMat.StencilState = new StencilState
{
StencilTest = true,
StencilCompare = CompareMode.Equal,
StencilRef = stencilRef,
StencilReadMask = 0xFF,
StencilWriteMask = 0,
PassOp = StencilOp.Keep,
};
insideMat.SetPassDepthWrite("base", false);
// 读取模板:只在写入区域外渲染
var outsideMat = new MaterialPBR { RenderOrder = 30 };
outsideMat.StencilState = new StencilState
{
StencilTest = true,
StencilCompare = CompareMode.NotEqual,
StencilRef = stencilRef,
StencilReadMask = 0xFF,
StencilWriteMask = 0,
PassOp = StencilOp.Keep,
};
outsideMat.SetPassDepthWrite("base", false);当读取物体的几何范围大于写入物体时,insideMat 只会显示在写入区域内,outsideMat 只会显示在写入区域外。若结果看起来只是普通叠色,优先检查 RenderOrder、StencilRef、StencilReadMask/StencilWriteMask 是否匹配,以及 Viewport 是否设置了预期的 RenderPath。
应用材质
csharp
// 设置整体材质
meshComponent.Material = material;
// 按几何体索引设置
meshComponent.SetMaterial(0, material);
// 批量设置
meshComponent.Materials = new[] { mat1, mat2 };Technique 与 Shader 的边界
Technique 表示材质的渲染方案,可以从 XML 加载,也可以在内存中创建。它负责组织 pass、混合/深度状态、shader 名称与 defines,但不是真正的 HLSL/GLSL shader 源文件。未来如果开放运行时 shader 编译,将使用独立的 ShaderSource、ShaderStage、ShaderVariant、ShaderCompiler 等概念,不复用 Technique 名称。
csharp
// 查找 Technique XML
Technique? technique = Technique.Find("path/to/technique.xml");
// 参数名转 ID(用于 MaterialCustom 高效访问)
uint id = Technique.PropertyToID("MetallicFactor");内置 Technique 路径(KnownTechniquePath)
| 常量 | 路径 |
|---|---|
PhysicalBasedRendering | Editor/Techniques/PBR_PackedNormal/DefaultMetallicRoughness.xml |
PhysicalBasedRenderingAlpha | 兼容旧资源:Editor/Techniques/PBR_PackedNormal/DefaultMetallicRoughnessTransparent.xml;新代码使用 PhysicalBasedRenderingAlphaBlend |
PhysicalBasedRenderingSolid | Editor/Techniques/PBR_PackedNormal/DefaultMetallicRoughnessSolid.xml |
PhysicalBasedRenderingAlphaSolid | 兼容旧资源:Editor/Techniques/PBR_PackedNormal/DefaultMetallicRoughnessTransparentSolid.xml;新代码使用 PhysicalBasedRenderingAlphaBlendSolid |
PhysicalBasedRenderingAlphaCutout | EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaCutout.xml |
PhysicalBasedRenderingAlphaBlend | EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaBlend.xml |
PhysicalBasedRenderingAlphaBlendSolid | EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaBlendSolid.xml |
DefaultLambert | Editor/Techniques/Lambert/DefaultLambert.xml |
ParticleLambert | Editor/Techniques/Lambert/ParticleLambert.xml |
UnlitStealth | Editor/Techniques/Lambert/UnlitStealth.xml |
GrayLevelFive | Editor/Techniques/PBR_PackedNormal/GrayLevelFive.xml |
GrayLevelTwo | Editor/Techniques/PBR_PackedNormal/GrayLevelTwo.xml |
HairSimulation | Editor/Techniques/PBR_PackedNormal/HairSimulation.xml |
StaticObject | Editor/Techniques/PBR_PackedNormal/StaticObject.xml |
FlatLambert | EngineRes/Techniques/NoTextureFlatLambert.xml |
FlatLambertAlpha | EngineRes/Techniques/NoTextureFlatLambertAlpha.xml |
Water | EngineRes/Techniques/SingleLayerWater.xml |
TexturedVertexColorLitOpaque | EngineRes/Techniques/DiffVCol.xml |
TexturedVertexColorUnlitOpaque | EngineRes/Techniques/DiffVColUnlit.xml |
TexturedVertexColorLitAlphaCutout | EngineRes/Techniques/DiffVColAlphaMask.xml |
TexturedVertexColorUnlitAlphaBlend | EngineRes/Techniques/DiffVColUnlitAlphaBlend.xml |
PhysicalBasedRenderingVertexColor | EngineRes/Techniques/PBR/PBRMetallicRoughDiffNormalSpecVCol.xml |
PhysicalBasedRenderingVertexColorAlphaCutout | EngineRes/Techniques/PBR/PBRMetallicRoughDiffNormalSpecVColMask.xml |
部分 KnownTechniquePath 对应的 Technique XML 可在 resources/rendering-reference/ 中直接阅读。参考目录还包含常用 RenderPath、默认 Material 和 Day/Dusk/Night 光照预设。它们是文档副本,不会自动成为项目运行时资源;Technique 中引用的真正 shader/define 组合由已发布 shadercache 提供。
相关文档
- GameGraph 概览 — 节点和组件系统
- GameGraph 透明背景画中画 —
GameOverlay.xml、多 Viewport 与透明 RTT - Actor 系统 — GameDataActorMaterial 和 MaterialPriority
- Runtime MCP 调试指南 —
debug.capture_screenshot、scenegraph.materials、material.probe - GameGraph 材质 AI Skill — AI 排查材质与 RenderPath 的操作清单