# XPbr Shader 设计文档 日期:2026-07-15 状态:已确认 ## 目标 在 `Client/Assets/Game/shader/XShader/` 下新增一个 URP(12.1.6)PBR shader,支持两张贴图: 1. **基础贴图 `_MainTex`**:RGB = 颜色/漫反射,A = 透明或 AO(材质开关切换语义) 2. **混合贴图 `_MixTex`**(必选):RG = 球面编码压缩法线,B = 金属度,A = 粗糙度 ## 文件 - `Client/Assets/Game/shader/XShader/XPbr.shader` — Shader 名 `Test/XPbr`(与现有 `Test/XTex` 风格一致) - `Client/Assets/Game/shader/XShader/XPbr_Base.hlsl` — CBUFFER、结构体、公共函数 独立自包含,不 include `XTex_Base.hlsl`(避免 CBUFFER 与 keyword 耦合);`DecodeSphereMap`、`SampleXRuntimeAmbient`、`InitializeInputData` 等公共函数复制入本 shader 的 Base 文件,与目录内 XTex/XTerrain 各自一份的现状一致。 ## Properties | 属性 | 类型 | 说明 | |---|---|---| | `_BaseColor` | Color | 颜色叠乘,默认白 | | `_MainTex` | 2D | RGB=漫反射,A=透明或 AO | | `_MixTex` | 2D | RG=球面编码法线,B=金属度,A=粗糙度,必选 | | `[Toggle(_ALPHATEST_ON)] _AlphaTest` | Float | 勾选:A 当透明,`clip(a - _Cutoff)`,AO=1;不勾选:A 当 AO,alpha=1 | | `_Cutoff` | Range(0,1) | 透明裁剪阈值,默认 0.5 | | `_Metallic` | Range(0,2) | 金属度缩放 | | `_Roughness` | Range(0,2) | 粗糙度缩放 | | `_AO` | Range(0,1) | AO 强度:`occlusion = lerp(1, baseA, _AO)`(仅 AO 模式) | ## Fragment 逻辑 ``` albedoAlpha = SAMPLE(_MainTex, uv); mix = SAMPLE(_MixTex, uv) albedo = albedoAlpha.rgb * _BaseColor.rgb normalTS = DecodeSphereMap(mix.rg) metallic = saturate(mix.b * _Metallic) smoothness = 1 - saturate(mix.a * _Roughness) #if _ALPHATEST_ON: clip(albedoAlpha.a - _Cutoff); occlusion=1; alpha=albedoAlpha.a #else: occlusion = lerp(1, albedoAlpha.a, _AO); alpha=1 → 切线空间法线经 TBN 转世界空间 → UniversalFragmentPBR → MixFog ``` ## Pass 1. **ForwardLit**(`LightMode=UniversalForward`):multi_compile 阵容与 XTex 相同(`_MAIN_LIGHT_SHADOWS*`、`_ADDITIONAL_LIGHTS*`、`LIGHTMAP_ON`、`DYNAMICLIGHTMAP_ON`、`_ADDITIONAL_LIGHT_SHADOWS`、`_SHADOWS_SOFT*`),外加 `#pragma shader_feature_local_fragment _ALPHATEST_ON`。环境光接 `SampleXRuntimeAmbient` 全局覆盖(与 XTex 行为一致)。 2. **ShadowCaster**:支持 `_ALPHATEST_ON` 裁剪,透明模式下阴影镂空。 Tags:`RenderType=Opaque`、`RenderPipeline=UniversalPipeline`;FallBack Off。 ## 不做(YAGNI) 自发光、视差、程序化法线 fallback、半透明混合(Alpha Blend)、DepthOnly/Meta pass。 ## 验证方式 Unity 编辑器中编译无报错;创建材质赋两张贴图,检查法线/金属/粗糙响应;切换 `_AlphaTest` 开关验证 A 通道两种语义。