主题
GameGraph Materials
Use this skill when code creates or modifies GameGraph materials, when a 3D object is invisible, or when RenderDoc/PIX suggests a technique/pass mismatch. Do not guess from screenshots alone; inspect the runtime material state when possible.
Texture Color Space And Packing
Audit every distinct color texture path actually used by the scene, including floors and props loaded directly through Texture2D.Load. Check its same-stem XML and source color-space contract, then reload and verify each texture's runtime s_rgb through material.probe or scenegraph.materials under unchanged camera, lighting and material factors. Correct settings on one imported model do not establish the settings of the other assets. Follow the per-texture acceptance steps.
When an imported model looks washed out, check Albedo/Diffuse sRGB first. If the source is typical sRGB-encoded color but the runtime texture reports
SRGB=false, first try a same-stem XML with<srgb enable="true" />, reload the texture/material and compare under unchanged lighting. Then investigate lights, environment reflections, exposure and material factors. Keep explicitly linear source color and all normal/data maps linear.For typical sRGB-encoded Albedo/Diffuse, declare
srgb enable="true"in the same-stem texture XML before loading. Normal, roughness, metallic, AO and packed data maps usefalse. Preserve an explicitly linear source color contract; do not decode gamma twice or infer color space from the file extension.For
MaterialPBRusingEditor/Techniques/PBR_PackedNormal/DefaultMetallicRoughness.xml, thenormalslot expects RG=normal XY, B=roughness, A=metallic. Ordinary RGB normal maps have B=normal Z, not roughness. Preserve the original and create a converted map; verify normal encoding and Y direction rather than flipping green based on asset origin.For that packed-normal path, factors multiply the map values. Use factors of
1when the map already stores final roughness/metallic values; explicitly configureMetalMul0or1=1in a material file needing metallic response. A nonzeroMetallicFactoralone is not proof that metallic response is enabled.MaterialPBRVertexColorinstead uses separate normal and R=roughness/G=metallic textures with additive offsets. Select the actual material/Technique contract before packing channels; do not generalize one layout to every PBR material.resource_import_model_packagegenerates color/data texture XML and compatible packing for supported sources. Direct file copies andTexture2D.Load(...)do not perform that adaptation. Check runtimematerial.probetextures_rgb, slots and parameters; after changing sidecars, reload dependencies or start a fresh session. Do not treat a post-loadSRGBsetter as proof of GPU texture recreation.For washed-out or inverted-looking surfaces, compare one object under unchanged camera, lights and color factors, then restore it. Verify actual rendering as well as metadata. Full XML examples and the channel table are in MaterialSystem.
Material Choice
| Need | Prefer | Notes |
|---|---|---|
| Normal lit object with textures, metalness, roughness, emissive | MaterialPBR | Use UseDefaultTextures() when no custom texture is available yet. |
| Runtime-generated albedo pixels | Texture2D.CreateFromImage(...) then new MaterialPBR(texture) | Set sRgb and mipLevels in the factory; set filter/addressing after upload. Dispose the runtime texture after its users. |
| Standard PBR continuous transparency or hard cutout | MaterialPBR.Create(texture, PBRAlphaMode.AlphaBlend/AlphaCutout) | Blend reads Albedo alpha and does not write depth. Cutout uses Albedo alpha at fixed 0.5 for color, depth, and shadow. |
| PBR generated mesh with vertex RGB/AO | MaterialPBRVertexColor | Requires Albedo, Normal, R=roughness/G=metalness textures and Position/Normal/UV/Color/Tangent streams. |
| Textured generated mesh with per-vertex RGB, voxel AO, or baked voxel light | MaterialVertexColor | The mesh must provide Color and UV streams. Choose one fixed VertexColorMaterialMode; do not rewrite pass defines. |
| Textured hard cutout such as leaves or fences | MaterialVertexColor(texture, LitAlphaCutout) | Albedo alpha controls the hard cutoff. Vertex alpha does not change the cutoff threshold. |
| Textured continuous transparency such as glass | MaterialVertexColor(texture, UnlitAlphaBlend) | Final alpha multiplies texture, vertex, and ColorFactor alpha. The alpha pass does not write depth. |
| No-texture solid color object, debug mesh, generated primitive | MaterialFlatLambert | Lit Lambert, affected by scene lights, shadows, and SSAO. It is not strict Unlit. |
| Transparent no-texture solid color | new MaterialFlatLambert(transparent: true) | Color alpha participates in blending. |
| Water surface | MaterialWater | Uses EngineRes/Techniques/SingleLayerWater.xml, which provides the singlelayerwater pass. |
| Existing material file or special art technique | Material.Load(...) then ToKnownMaterial() if needed | Falls back to MaterialCustom when the technique path is not a known strong type. |
| Arbitrary material parameters by name/id | MaterialCustom | Use only when a strong material type does not model the technique. |
| Runtime mesh particles | Editor/Techniques/Lambert/ParticleLambert.xml | Use with Mesh.Material(...).Technique(...) for generated mesh emitters. |
Do not replace no-texture MaterialFlatLambert with MaterialVertexColor: the latter requires an Albedo texture and a Color vertex stream. Use UnlitOpaque only for textured geometry whose brightness is intentionally baked into vertex RGB.
MaterialVertexColor uses fixed published variants for Editor, Windows, Android, and iOS. VoxelMaterialSample also contains the PBR follow-up matrix, but do not infer target-platform PBR availability from XML presence alone: verify the corresponding shadercache package and runtime logs on that environment.
Keep published texture resources on Texture2D.Load(...) so the TextureX container pipeline can select platform-specific packaged texture data, mip levels, and sampling metadata. Use CreateFromImage(...) only for client runtime Image data, and keep RenderToTexture on CreateRenderTarget(...). These are three separate resource paths. The useAlpha factory argument only changes how a single-component image is interpreted; it does not select material blending or alpha clipping.
Minimal Examples
csharp
#if CLIENT
var pbr = new MaterialPBR(useAlbedoTexture: false, useAlphaChannel: false)
{
ColorFactor = HdrColor.White,
MetallicFactor = 0f,
RoughnessFactor = 0.55f
};
var flat = new MaterialFlatLambert(transparent: false)
{
Color = new HdrColor(255, 60, 40, 255)
};
var glass = new MaterialFlatLambert(transparent: true)
{
Color = new HdrColor(60, 180, 255, 120)
};
var water = new MaterialWater
{
TintColor = new HdrColor(48, 155, 220, 255)
};
var leavesPbr = MaterialPBR.Create(leavesTexture, PBRAlphaMode.AlphaCutout);
var voxelPbr = new MaterialPBRVertexColor(
voxelAlbedo,
voxelNormal,
voxelRoughnessMetalness,
PBRVertexColorMaterialMode.Opaque);
var voxel = new MaterialVertexColor(
voxelTexture,
VertexColorMaterialMode.UnlitOpaque)
{
ColorFactor = new HdrColor(255, 255, 255, 255)
};
#endifTextured Vertex Color Modes
VertexColorMaterialMode has stable values: LitOpaque = 0, UnlitOpaque = 1, LitAlphaCutout = 2, and UnlitAlphaBlend = 3. Mode switches the whole fixed Technique; it does not mutate a shared Technique.
| Mode | Use | Required semantics |
|---|---|---|
LitOpaque | Textured vertex tint/AO plus scene lighting | Opaque pass; alpha blending is off. |
UnlitOpaque | Voxel lighting baked into vertex RGB | Ignores scene lighting; alpha blending is off. |
LitAlphaCutout | Leaves, fences, hard holes | Albedo alpha decides discard. Depth and shadow use the same cutout texture. |
UnlitAlphaBlend | Glass and continuous transparency | Alpha blend, no depth write; texture × vertex × factor alpha. |
The exact KnownTechnique and KnownTechniquePath names are:
TexturedVertexColorLitOpaque->EngineRes/Techniques/DiffVCol.xmlTexturedVertexColorUnlitOpaque->EngineRes/Techniques/DiffVColUnlit.xmlTexturedVertexColorLitAlphaCutout->EngineRes/Techniques/DiffVColAlphaMask.xmlTexturedVertexColorUnlitAlphaBlend->EngineRes/Techniques/DiffVColUnlitAlphaBlend.xml
Prefer new MaterialVertexColor(texture, mode) in gameplay code. These names are for diagnostics, path comparison, and advanced material loading. Material.Load(...) and component material reads restore these paths as MaterialVertexColor with the matching Mode.
MeshBuilder.SetColors(...) and CustomGeometryComponent.DefineColor(...) are both valid. Lit modes also need valid normals. UV and Color are required for all four textured modes; tangent is not a general requirement unless another selected shader path consumes it. Use code_sample/src/VoxelMaterialSample/ as the layout and visual comparison fixture.
PBR Alpha and Vertex Color Modes
PBRAlphaMode has stable values Opaque = 0, AlphaBlend = 1, and AlphaCutout = 2. Keep the old bool API for compatibility: useAlphaChannel: true means AlphaBlend; new code that needs hard holes must request AlphaCutout. Cutout requires an Albedo texture. Setting UseAlphaChannel = true while already in AlphaCutout preserves the explicit cutout mode.
PBRVertexColorMaterialMode has stable values Opaque = 0 and AlphaCutout = 1. This material uses the existing PBRLitSolid path, where the roughness/metalness texture is R=roughness, G=metalness and the public offsets are added to those channels. Do not reuse the opposite-channel TextureUnit.PBRMetalnessR_RoughnessG description when explaining this shader. Bind the texture through RoughnessMetalnessTexture; create Normal and roughness/metalness runtime textures with sRgb: false. The constructor initializes ColorFactor to white, SpecularFactor to mid-gray, and both offsets to zero because Technique XML does not initialize Material shader parameters. Keep those values explicit in diagnostic snapshots.
Known PBR paths are:
PhysicalBasedRenderingAlphaBlend->EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaBlend.xmlPhysicalBasedRenderingAlphaBlendSolid->EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaBlendSolid.xmlPhysicalBasedRenderingAlphaCutout->EngineRes/Techniques/PBR/DefaultMetallicRoughnessAlphaCutout.xmlPhysicalBasedRenderingVertexColor->EngineRes/Techniques/PBR/PBRMetallicRoughDiffNormalSpecVCol.xmlPhysicalBasedRenderingVertexColorAlphaCutout->EngineRes/Techniques/PBR/PBRMetallicRoughDiffNormalSpecVColMask.xml
The PBR vertex-color modes multiply full vertex RGBA. Standard MaterialPBR retains its existing vertex RGB behavior. PBR vertex-color AlphaBlend is intentionally absent; use standard PBR AlphaBlend or the classic unlit vertex-color blend path according to the desired lighting model. The older PhysicalBasedRenderingAlpha and PhysicalBasedRenderingAlphaSolid paths remain for existing loaded resources. Code-created MaterialPBR uses the explicit AlphaBlend paths above; do not select the legacy paths for new Alpha mode code.
For a mesh particle override:
csharp
meshEmitter.Mesh
.Material((GameCore.ResourceType.Material)"EngineRes/Particle/common/materials/defaultMesh.material")
.Technique("Editor/Techniques/Lambert/ParticleLambert.xml");Runtime Material Inspection
When an object is invisible, first check the material attached to the running client.
Through editor MCP:
json
{
"tool": "runtime_call_tool",
"arguments": {
"name": "material.probe",
"arguments": {
"query": "BlackHole",
"includeCurrentScenes": true,
"includeSession": true,
"includeReplicated": true,
"passNames": ["base", "alpha", "depth", "singlelayerwater"]
},
"timeout_ms": 5000
}
}Direct TCP fallback from a project or SDK ai/tools directory:
powershell
ai/tools/Invoke-SceRuntimeMcp.ps1 -Ping -Wait
ai/tools/Invoke-SceRuntimeMcp.ps1 -Tool material.probe -ArgumentsJson '{"query":"BlackHole","includeSession":true,"passNames":["base","alpha","depth","singlelayerwater"]}'Use scenegraph.materials when the node name is unknown:
powershell
ai/tools/Invoke-SceRuntimeMcp.ps1 -Tool scenegraph.materials -ArgumentsJson '{"includeCurrentScenes":true,"includeSession":true,"includeReplicated":true,"maxResults":50,"maxDiagnostics":50,"passNames":["base","alpha","depth","singlelayerwater"]}'Important result fields:
| Field | Meaning |
|---|---|
entry.graph.source | current_scene for loaded SCE scenes, session for local script graphs, or replicated; sources/scenes preserves shared identities. |
entry.node.name, entry.node.id | Use nodeId in a follow-up material.probe for an exact match. |
entry.drawable.component_type/material_index | Drawable type and material slot; historical static_mesh remains for compatibility. |
entry.geometry / entry.custom_geometry | Static Mesh LOD0 buffers/layout, or CustomGeometry vertex count and explicit layout availability. |
entry.material.type | Strong SDK wrapper such as MaterialPBR, MaterialPBRVertexColor, MaterialVertexColor, MaterialFlatLambert, MaterialWater, or MaterialCustom. |
entry.material.technique_path | Technique XML actually loaded at runtime. The engine may lowercase paths; compare case-insensitively. The historical shader_path field is retained for compatibility. |
entry.material.passes | Whether each requested RenderPath pass exists on the technique. |
entry.material.textures | Non-empty common texture slots and sampling/storage metadata; never pixel data. |
entry.material.properties | Known material parameters such as ColorFactor, AlbedoColor, WaterTint, MetallicFactor. |
entry.material.cull_mode, fill_mode, render_order, stencil_state | Common state bugs when a draw call exists but looks wrong. |
For large voxel scenes, rely on maxNodes, maxResults, and maxDiagnostics. Material/pass/texture metadata is cached by native material identity within one request. A transient invalid resource appears in bounded diagnostics or as status=unavailable; do not reinterpret it as a real false/zero value. CustomGeometry exact submitted GPU layout is not yet exported, so accept its explicit unavailable status instead of inferring a layout from authoring calls.
Camera and Lighting Evidence
For a fully dark scene or unexpected light footprint, discover scenegraph.render_snapshot through debug.list_tools and read the main camera, cluster flag, candidate Zones, fog and light configuration before changing materials. Use bounded maxNodes, maxResults and maxDiagnostics; the main viewport graph is always inspected. Older runtimes may not expose this tool.
renderer_default_zone is default configuration, not proof of the effective camera Zone. effective_camera_zone and resolved vignette mask state remain unknown. An empty vignette texture attribute can represent a directly assigned Texture. Non-finite values appear as null; inspect diagnostics and a current screenshot before drawing conclusions. See Runtime MCP guide.
RenderPath / Pass Checks
RenderPath only renders passes it requests. If the technique lacks the pass, the object will not participate in that render stage.
MaterialFlatLambertopaque usesEngineRes/Techniques/NoTextureFlatLambert.xmlwithbaseanddepth.MaterialFlatLambert(transparent: true)usesEngineRes/Techniques/NoTextureFlatLambertAlpha.xmlwithalpha.MaterialWaterusesEngineRes/Techniques/SingleLayerWater.xmlwithsinglelayerwater.MaterialVertexColor(LitOpaque)usesDiffVCol.xmlwith opaque lighting passes.MaterialVertexColor(UnlitOpaque)usesDiffVColUnlit.xmlwithbase,depth, andshadow.MaterialVertexColor(LitAlphaCutout)usesDiffVColAlphaMask.xml; includebase,depth, andshadowin probes.MaterialVertexColor(UnlitAlphaBlend)usesDiffVColUnlitAlphaBlend.xmlwithalphaand no depth write.MaterialPBR.Create(..., AlphaBlend)useslitalpha, reads Albedo alpha, and does not write depth.MaterialPBR.Create(..., AlphaCutout)uses opaque lighting passes plus matching Albedo-alphadepthandshadowcutout.MaterialPBRVertexColor(Opaque)usesPBRMetallicRoughDiffNormalSpecVCol.xml.MaterialPBRVertexColor(AlphaCutout)usesPBRMetallicRoughDiffNormalSpecVColMask.xmlwith matching Albedo-alpha color/depth/shadow cutout.ParticleLambertusesEditor/Techniques/Lambert/ParticleLambert.xmlfor generated mesh particle geometry.
For EngineRes/RenderPaths/CEMapSSAO.xml, useful probe passes are usually:
json
["base", "alpha", "depth", "singlelayerwater"]If material.probe shows the expected pass exists but the object is still invisible, check node scale, camera clipping, alpha value, depth write, render order, stencil state, and whether RenderDoc contains a draw call for the node's technique.
Local Technique Experiments
For local testing before publishing engine resources, place a trial technique under the project res/ tree using its final resource path, for example:
text
<project>/res/EngineRes/Techniques/NoTextureFlatLambert.xmlThen call Technique.Find("EngineRes/Techniques/NoTextureFlatLambert.xml"). Once verified, move the technique to the official EngineRes repository and update KnownTechniquePath only if the path should become a supported SDK entry.
Readable source examples for all current KnownTechniquePath entries, selected RenderPaths, the default Material, and light presets are under resources/rendering-reference/. Treat them as documentation copies, not as runtime resources. Prefer a unique project path for experiments instead of shadowing an installed EngineRes/... or Editor/... path.
Technique is the XML render recipe that selects passes, state, shader names, and defines. It is not shader source. Keep Shader terminology for actual shader stages, variants, shadercache, or a future runtime compiler.
Related Docs
docs/systems/MaterialSystem.mddocs/guides/RuntimeMcpDebugGuide.mddocs/guides/TransparentPictureInPicture.mddocs/ai/skills/gamegraph-transparent-pip/SKILL.mddocs/ai/skills/debug-tools/SKILL.mddocs/ai/skills/client-only-debug/SKILL.md