祀 · 角色 Shader 实景逐层对照
从同一个庭院机位,把祀的材质由灰模受光逐步恢复到正确头骨方向输入下的完整效果。每一层都有实际模型截图、输入贴图、算法原理和制作建议。
2026-11-02 采集勘误:运行时 TAA 已有;旧文档采集另行指定 SMAA,漏掉了编辑 4×MSAA。本版沿用场景编辑预览,逐帧核对真实颜色附件,并修复重复采集将眼部 Overlay 误换成普通表面的错误。下方提供同机位抗锯齿对照和青绿色块的实渲定位。
本版已替换全部正常分析截图:在教学副本中修正被材质槽属性块遮蔽的头骨方向,重拍逐层、光角和多视角图。旧错误效果只保留在下方勘误对照的左侧。正式运行场景尚未应用此修正。
2026-11-02 可见性补充:阶段 02 法线、06 阴影 LUT、09 眼睛 Matcap、10 边缘光已改用重新渲染的局部特写。可整幅切换,也可点击“自动对比”每 0.9 秒交替查看同一部位,点击“停止对比”即可停下。原参数贡献很小的结果如实保留,辅助侧/背光另行标明。
Mask 多视角验证:9 个相机角度 × 3 种光照,原 Mask、忽略 Mask、关闭 SDF 与 Matcap 已在正确方向下重新对照。

截图勘误:已经有 TAA,为什么文档还有锯齿?
工程已实现运行时 URP TAA High。旧角色文档采用非 Play 的独立采集相机,并把环境 AA 选择硬改为 SMAA;这还绕过了场景原有的编辑多重采样分支。问题出在采集路径,旧截图不能用来判断运行时 TAA 是否有效。
| 路径 | 实际处理 | 证据与边界 |
|---|---|---|
| 庭院 Play / 独立运行 | URP TAA High | 此前庭院验证跨 64 个真实 Play 帧更新历史;见庭院抗锯齿落地说明.md。 |
| 旧文档采集 | 单样本 + SMAA High | 独立诊断实际颜色附件为 1 样本;没有 TAA 历史积累。 |
| 本次重拍最终颜色 | 4×MSAA + SMAA High | 沿用原场景编辑预览逻辑;每帧记录颜色附件实际 4 样本。 |
| 中间量 / 数据通道 | 关闭后处理 | 用于解释数值,不当作最终抗锯齿画面。 |
TAA 需要不同真实帧的子像素抖动和历史重投影。这里每次切换材质阶段都会改变当前画面,因此保留不依赖时间历史的编辑采集。连续调用两次 Camera.Render 只用于预热渲染资源,不能称为两帧 TAA 收敛。
同机位描边:旧采集 / 恢复场景编辑抗锯齿

旧采集:1 样本 + SMAA修正采集:4×MSAA + SMAA拖动画面或滑块 · 双击放大原图 · 左:旧采集:1 样本 + SMAA / 右:修正采集:4×MSAA + SMAA
两侧均为阶段 11,机位、1600×900 分辨率和描边宽度一致。观察发梢、脸轮廓及背景几何斜边;不能把全部背景叶片裁切和材质高频细节都归因于描边。MSAA 也不能自动消除所有透明裁切或着色产生的锯齿。
“屏幕宽度”只表示外扩量按像素计算。当前脸部约 0.35 像素、头发等约 0.65 像素,均小于 1 像素;单帧单样本容易把细线采成断续阶梯。OutlineMask 还使用 clip(R−0.1) 硬裁切。稳定线宽、平滑覆盖率和时间抗锯齿是三个不同环节。
眼睛青绿色平面:覆盖层误绑的实渲复现

诊断中复现旧错误:Overlay 被当成普通表面恢复正确 Overlay 类型:阶段 09 尚未启用覆盖层拖动画面或滑块 · 双击放大原图 · 左:诊断中复现旧错误:Overlay 被当成普通表面 / 右:恢复正确 Overlay 类型:阶段 09 尚未启用覆盖层
这片区域来自眼部阴影覆盖网格,正常用途是通过遮罩和模板值对已有眼部颜色作乘法调暗。它不是虹膜 Matcap,也不是 TAA 残影。旧工具重复执行时保留了内存中的 OverlaySteps,却只识别源 Shader 的 OverlayShadow 后缀,第二次切换误用了普通角色 Shader;头发阴影薄片也会受到同样影响。
本次从源材质显式恢复副本的 Shader 与属性,再同时识别源覆盖层和教学覆盖层,消除重复运行的状态残留。受控误绑复现与归档旧图逐像素一致;恢复后与正确基线的最大通道差为 0/255。正常正文中的旧色块图已经替换;这里的左图只作为错误示例。
| 核对内容 | 本次结果 |
|---|---|
| 重拍范围 | 302 张:94 张逐层/专项、153 张多视角、55 张特写 |
| 最终颜色实际 AA | 213 张逐帧核对为 4×MSAA + SMAA;其余为关闭后处理的数据通道 |
| 源文件 | 各采集报告的逐文件指纹全部保持一致 |
| 验证报告 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\capture-correction-validation.json |
| 诊断采集 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\eye-outline-inspect.json |
| 运行时 TAA 说明 | F:\UnityAITest\GameTest\Docs\庭院抗锯齿落地说明.md |
头身受光勘误:原因、修正对照与重拍范围
2026-11-02:正文的 94 张逐层/专项图及 153 张多视角图已全部在正确的头骨输入下重新采集,封面、滑块、SDF 光角、Mask、Matcap、GPU 通道及等价对照均已替换。仅本节左侧保留明确标注的旧错误效果,供解释原因。
此前脸部把正面来光判成背光,大片使用偏棕的阴影 LUT,因而比肩部明显更暗。问题出在方向参数传递:PerlicaHeadBasis 将方向写到 Renderer 级属性块;SourceShadowActor 创建材质槽级属性块写阴影索引。存在槽级块时,Renderer 级块不再生效,缺少的头骨方向回退到材质默认值。
| 输入/分支 | 旧错误输入 | 本次副本正确输入 |
|---|---|---|
| 头部前向 _HeadForward | 材质默认 (0,0,−1) | 头骨实际约 (0.0032,−0.0842,+0.9964) |
| 本次 GPU 主光方向 | (−0.1330,+0.6428,+0.7544) | 同一方向,不旋转灯光 |
| L·headForward | 约 −0.754,判为背光 | 约 +0.697,判为前方来光 |
| SDF 阈值 t | 约 0.99240 | 约 0.00931 |
| 脸 Kind=2 / 身体 Kind=1 | 脸用错误基底驱动 SDF;身体按法线受光 | 脸用正确基底驱动 SDF;身体仍按法线受光 |
脸与身体共用 T_actor_common_face_01_RD 和 T_actor_common_femaleskincolor01_lut_D,环境光强度均为 0.8、基础色乘色为白色。因此此次落差不能解释为“脸用了另一张肤色 LUT”。两者阴影强度等仍有差别,且脸部本来还有 SDF、Overlay 等艺术化处理,修正并不意味着所有部位应完全同色。
头骨世界前/右轴 → Renderer 属性块
× 被槽级属性块遮蔽 → 回退到材质默认 −Z
修正副本:读取每材质槽已有属性块
→ 保留 _TTShadowActorIndex
→ 合入真实 _HeadForward / _HeadRight
→ 渲染后逐槽核对方向仍正确
→ 在相同方向输入下比较原 Shader 与教学完整阶段三机位:旧错误效果 / 同条件同步方向后的效果
以下六张来自独立诊断采集:相同姿态、材质参数、贴图、相机及灯光,右侧只修正副本中的头骨方向传递。脸部恢复合理的正面受光;头发高光也可能变化,因为它同样读取头骨基底。此处左图是故障示例,不能用作正常 SDF 目标效果。
左斜侧 40°

旧错误:头部方向被遮蔽正确输入:副本同步头骨方向拖动画面或滑块 · 双击放大原图 · 左:旧错误:头部方向被遮蔽 / 右:正确输入:副本同步头骨方向
正面 0°

旧错误:头部方向被遮蔽正确输入:副本同步头骨方向拖动画面或滑块 · 双击放大原图 · 左:旧错误:头部方向被遮蔽 / 右:正确输入:副本同步头骨方向
右斜侧 40°

旧错误:头部方向被遮蔽正确输入:副本同步头骨方向拖动画面或滑块 · 双击放大原图 · 左:旧错误:头部方向被遮蔽 / 右:正确输入:副本同步头骨方向
同机位局部像素与验收边界
下表只采样左斜侧 40° 图中的 9×9 像素块,坐标从原图左上角计数。数值为最终 PNG 的显示 RGB,不是线性辐亮度;肩膀和背景的选定小块未变化,不能外推为整个身体都逐像素相同。
| 区域 / 中心坐标 | 旧错误 RGB 均值 | 同步方向后 RGB 均值 | 最大通道差 / 255 |
|---|---|---|---|
| 脸颊 [765, 554] | 195.00, 151.20, 125.89 | 221.65, 202.73, 180.49 | 56 |
| 肩膀 [997, 806] | 221.06, 204.06, 182.89 | 221.06, 204.06, 182.89 | 0 |
| 背景 [1423, 390] | 182.35, 156.72, 193.59 | 182.35, 156.72, 193.59 | 0 |
此前“原 Shader 与教学副本逐像素一致”只证明二者等价,两个版本可以同时继承相同的输入错误。本次额外核对每张图的槽级头骨方向、六组光角的 GPU 主光,以及正面/侧面实渲。SDF 仍保持启用,没有用提亮底色、改变曝光或永久关闭 SDF 来掩盖问题。
修改范围:截图工具、独立教学副本与本文档。正式角色脚本、原 Shader、源材质和原场景未改动;这些新图不能表示正式运行场景已完成修复。保存的教学场景把当前固定姿态方向写入复制材质,重新摆姿势后应重新采集。
| 证据/工具 | 完整路径 |
|---|---|
| 方向写入脚本 | F:\UnityAITest\GameTest\Assets\Art\Shader\Perlica\URP\PerlicaHeadBasis.cs |
| 槽级阴影索引写入 | F:\UnityAITest\GameTest\Assets\Art\Enviorment\Scripts\Runtime\SourceShadowActor.cs |
| 六张诊断截图 | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\HeadBodyDiagnosis |
| 诊断原始报告 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\headbody-diagnose.json |
| 诊断图及像素核对 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\headbody-diagnosis-validation.json |
| 247 张重拍、逐图哈希与主光检查 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\recapture-validation.json |
| 旧图归档(不用于正常分析) | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\BeforeHeadBasisCorrection-20261102\manifest.json |
先看整体,再拖动比较

00 灰模受光13 自发光与当前完整效果拖动画面或滑块 · 双击放大原图 · 左:00 灰模受光 / 右:13 自发光与当前完整效果
本篇拆解的是当前工程的 Charter_Shader URP 适配,在教学副本中统一正确的头骨方向输入。祀的原贴图与绑定提供输入证据;不能把本地适配公式称为终末地客户端完整实现。阶段开关与方向同步仅用于副本,原场景、原 Shader、源材质和导入配置均以文件指纹核对。
天空、庭院和祀的独立 VFX 材质保持原路径,未纳入本篇逐层门控;画面中的装饰特效不是 SDF、法线或自发光贴图新增的贡献。祀携带的武器若使用 Charter_Shader,也随主表面一起分层。
案例、固定条件与实际绑定
| 项目 | 本次记录 |
|---|---|
| 角色 | 祀 / chr_0036_jsspsi |
| 模型 | F:\UnityAITest\GameTest\Assets\Art\Model\Si\Si_CombatModel.prefab |
| 动作 | F:\UnityAITest\GameTest\Assets\Art\Animator\Si\Si_Combat.asset:idle + idleAdditive,固定 0.75 秒 |
| 环境 | EnvironmentArtSandbox 的独立副本;云、水、粒子、GPU 落叶固定 |
| 相机 | 三个固定机位;最终颜色实际 4×MSAA + SMAA High;关闭 dithering;两次 Camera.Render 用于预热,不是 TAA 收敛 |
| 光照 | 逐层过程保持太阳和曝光不变;SDF 专项只旋转副本太阳,每角关闭/开启成对 |
| 截图边界 | GPU 直接输出 PNG,未修图、未人工增强;通道图关闭后处理,输入图拆通道另标注 |
| 祀实例中的材质 | Shader | Kind | 实际开启输入 | 渲染队列 |
|---|---|---|---|---|
| M_wpn_claym_0010_01.mat | Charter_Shader | 0 | BumpMap, MetallicGlossMap | 2450 |
| M_eyewhiteshadow_common_01.mat | Charter_Shader/OverlayShadow | -1 | Overlay:单独的乘法材质 | 2900 |
| M_eyeshadow_common_03.mat | Charter_Shader/OverlayShadow | -1 | Overlay:单独的乘法材质 | 2900 |
| M_actor_jsspsi_body_01.mat | Charter_Shader | 1 | BumpMap, DiffRampMap, ShadowLutTex | 2000 |
| M_actor_jsspsi_cloth_02.mat | Charter_Shader | 0 | BumpMap, MetallicGlossMap, DiffRampMap, SpecRampMap, Emission, OutlineMask | 2000 |
| M_actor_jsspsi_cloth_03.mat | Charter_Shader | 0 | BumpMap, MetallicGlossMap, DiffRampMap, SpecRampMap | 3000 |
| M_actor_jsspsi_hair_01.mat | Charter_Shader | 3 | BumpMap, MetallicGlossMap, DiffRampMap, SpecRampMap, LineMap, OutlineMask | 2000 |
| M_actor_jsspsi_iris_01.mat | Charter_Shader | 4 | DiffRampMap, Matcap | 2000 |
| M_actor_jsspsi_brow_01.mat | Charter_Shader | 5 | DiffRampMap, ShadowLutTex | 2000 |
| M_actor_jsspsi_face_01.mat | Charter_Shader | 2 | BumpMap, DiffRampMap, ShadowLutTex, SDFLightmap, OutlineMask | 2000 |
| M_hairshadow_common_01.mat | Charter_Shader/OverlayShadow | -1 | Overlay:单独的乘法材质 | 2900 |
| M_actor_jsspsi_cloth_04.mat | Charter_Shader | 0 | BumpMap, MetallicGlossMap, DiffRampMap, SpecRampMap | 2000 |
| M_actor_jsspsi_cloth_01.mat | Charter_Shader | 0 | BumpMap, MetallicGlossMap, DiffRampMap, SpecRampMap, Emission, OutlineMask | 2000 |
Kind:0 衣料,1 皮肤,2 脸,3 头发,4 眼睛,5 眉;-1 表示 Overlay 无此参数。这里列的是当前模型真正引用的材质,不把目录里所有备用材质都说成已使用。
主案例的脸部 SDF 是 T_actor_common_female_face_03_SDF,Mask 是 face_03_cm_M;这里读取祀自己的绑定,没有沿用此前佩丽卡 face_01 的贴图作为案例。
骨骼姿势 / 顶点位置 / UV / 法线切线 ↓ CharacterVertex:世界坐标、TBN、BaseMap UV ↓ Base → N/HN → P → 半兰伯特或脸部 SDF → RD ↓ 阴影可见度与 P.B 上限 → LUT/备用阴影色 → 漫反射 ↓ 普通高光或头发条带 → RS / Line → Matcap / Rim / Emission ↓ 表面雾;独立反壳描边与 Overlay Pass(内部 4×MSAA) ↓ 相机曝光、色调映射、Bloom、SMAA → 实渲 PNG
上面是依赖关系和阅读顺序,不是新增 14 个运行时渲染 Pass。教学阶段在同一个原算法中开启对应分支;原 Forward、Outline、Depth、Shadow 等 Pass 结构保持。
输入贴图的彩色预览显示源文件 RGB,不把打包的 Alpha 当作网页透明度。P.A、HN.A、RD.A、SDF.A 等另用灰度通道图展示;这与模型最终透明混合是两回事。祀的独立特效材质在副本中固定到 4 秒,保留其 Shader 与原参数。
00 灰模受光
制作原因:先建立几何和受光基准
将祀的主表面 RGB 换成 18% 线性灰,保留原网格、骨骼姿势、透明度、主光、阴影和环境光。高光、法线图和艺术化明暗暂不加入。灰模已经受光,不是无光照的纯色剪影;薄衣料仍使用原 Alpha 和透明队列。

当前算法
albedo.rgb = 0.18 N = normalize(模型法线) P = (0, 0.5, 1, 0.25) lightValue = saturate(N·L × 0.5 + 0.5) 高光、SDF、Ramp、LUT、Rim、描边、Overlay、自发光 = 关闭
算法原理
灰模把颜色与纹理干扰移开,可以先观察模型体块和环境亮度。这里的 0.18 是线性数值,经曝光和显示变换后不会是 PNG 中的 18% 灰。各阶段保留同一套相机后处理。
贴图制作与导入思路(建议流程)
- 先检查低模轮廓、最终三角化、UV、顶点法线和切线。脸颊凹陷、发片穿插属于几何问题,不能用贴图掩盖。
- 固定动作、相机、分辨率、光源和曝光,再逐项恢复输入。实际 HDR 曝光、色调映射和抗锯齿设置随报告记录。
01 基础色 D
制作原因:确定角色固有色和服饰图案
恢复祀原来的 _BaseMap × _BaseColor。此时可以看到肤色、白发、衣服印花及装饰色,但还没有贴图法线、P 属性和发丝条带高光。阴影仍来自统一的基础受光。

00 灰模受光01 基础色 D拖动画面或滑块 · 双击放大原图 · 左:00 灰模受光 / 右:01 基础色 D
实际输入贴图



当前算法
uv = uv0 × _BaseMap_ST.xy + _BaseMap_ST.zw D = sample(_BaseMap, uv) albedo = D × _BaseColor 若 _AlphaClip > 0.5:clip(albedo.a - _Cutoff)
算法原理
基础色描述表面本身的颜色,而最终像素还要经过光照。颜色图开启 sRGB 后,GPU 采样会把 RGB 解码到线性空间参与计算;Alpha 仍是线性数据。源 D 中可以包含美术绘制的局部层次,但不应把固定方向的太阳投影烘死在底色里。
贴图制作与导入思路(建议流程)
- 用材质 ID、曲率等辅助分区,绘制肤色、妆容、衣料和金属饰面的固有色。为 UV 边缘扩边,避免缩小后漏出底色。
- 透明发片、薄衣料把覆盖率存入 A,先确认它们用透明混合还是 AlphaClip。本次祀实例引用的 cloth_03 使用透明分支;目录中的备用 hairt 材质未被此实例引用。
- 导出颜色 PNG,RGB 按 sRGB 导入;在固定白光及庭院环境各检查一次,不用曝光补偿错误的颜色。
02 普通法线 N 与头发 HN
制作原因:增加受光细节,并让发束明暗与高光分别可控
恢复普通部位的法线图,以及祀头发 RG/BA 打包的双法线。普通法线同时影响漫反射和高光;头发 RG 影响漫反射,BA 影响高光方向。这个阶段高光带尚未加入,因此 BA 的视觉贡献要结合后面的“高光法线单项关闭”对照判断。
上轮总览把衣料的细小法线变化缩得太小。这里分别看衣料 N 和头发 HN.RG;阶段 02 还没有头发高光,不能把尚未出现的亮带作为 HN.BA 的效果。
衣料 N:原光照下的表面细节
观察衣料的纹理、缝边和表面微小明暗;用“只看加入前/后”切换整幅,避免将画面两边不同部位互相比较。
庭院原光照;同一观察点缩窄视野至原来的 1/5.00,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

01 只有基础色和模型法线02 加入贴图法线拖动画面或滑块 · 双击放大原图 · 左:01 只有基础色和模型法线 / 右:02 加入贴图法线
本特写未增强差异:最大通道差 72/255,超过 2/255 的像素占 20.60%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 38/255,超过2/255的像素占 0.0018%,最差40×40局部平均差 0.0971/255。微弱效果需结合这项误差与通道图判断。
补充侧光:让法线方向的变化更容易辨认
此组单独把主光转到头部右侧 70°。两张使用相同侧光,只开关法线;侧光本身造成的变化不能算成 N 的贡献。
受控侧/背光:相对头骨 70°,原主光强度和曝光;同一观察点缩窄视野至原来的 1/5.00,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

01 模型法线02 模型法线 + N拖动画面或滑块 · 双击放大原图 · 左:01 模型法线 / 右:02 模型法线 + N
本特写未增强差异:最大通道差 68/255,超过 2/255 的像素占 22.97%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 49/255,超过2/255的像素占 0.0008%,最差40×40局部平均差 0.0498/255。微弱效果需结合这项误差与通道图判断。
同一表面的世界法线 N×0.5+0.5

加入前的 GPU 中间量加入后的 GPU 中间量拖动画面或滑块 · 双击放大原图 · 左:加入前的 GPU 中间量 / 右:加入后的 GPU 中间量
法线通道的色彩表示方向,不是额外涂上的颜色。细节方向已经改变,但最终亮度还会经过 N·L、环境光和后处理;因此通道清晰并不保证远景里差异强烈。
头发 HN.RG:发束近景
只比较发束上已有的暗纹和明暗起伏。HN.BA 的条带方向要到阶段 07 的高光开启后再看。
庭院原光照;同一观察点缩窄视野至原来的 1/5.00,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

01 模型法线02 HN 漫反射法线拖动画面或滑块 · 双击放大原图 · 左:01 模型法线 / 右:02 HN 漫反射法线
本特写未增强差异:最大通道差 74/255,超过 2/255 的像素占 9.90%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 16/255,超过2/255的像素占 0.0195%,最差40×40局部平均差 0.1300/255。微弱效果需结合这项误差与通道图判断。
原逐层机位总览(保留参考,细节以特写为主)

01 基础色 D02 普通法线 N 与头发 HN拖动画面或滑块 · 双击放大原图 · 左:01 基础色 D / 右:02 普通法线 N 与头发 HN
实际输入贴图



以下 HN 四通道是源图数据预览,不能把彩色原图直接当作一张 RGB 法线。




当前算法
普通图:q = (Ntex.r × Ntex.a, Ntex.g) 头发:qDiffuse = HN.rg;qSpec = HN.ba xy = q × 2 - 1 z = sqrt(max(1 - dot(xy, xy), 0.0001)) nTS = normalize(float3(xy × scale, z)) B = normalize(cross(Ngeometry, T)) × tangent.w nWS = normalize(T×nTS.x + B×nTS.y + Ngeometry×nTS.z)
算法原理
法线图改变每个像素参与 N·L 和高光计算的方向,不会改变网格外轮廓。TBN 将切线空间方向变换到世界空间。头发单独设计高光法线,可以在发束体块基本不变时调整高光带走势。当前实现先重建 Z,再缩放 XY 并归一化;不能直接换成任意 NormalMap 解码而认为结果相同。
贴图制作与导入思路(建议流程)
- 在最终三角化低模上,用匹配的切线基烘焙高模法线;检查 cage、接缝和 G 方向。
- 普通 N 按当前解码打包:RG 存 XY 时 A 必须为 1;AG 存 XY 时 R 必须为 1。使用 Default、关闭 sRGB,避免 Unity NormalMap 导入再次改写通道。
- 头发分别制作漫反射与高光的切线空间法线,取两套 XY 打包进 RG、BA。中性 HN 四通道均为 0.5,不是普通 RGB 蓝色法线。
- 转动主光检查鼻翼、衣褶、发束接缝;增加高光后再检查 BA 是否把亮带拉歪。
03 属性图 P 与普通高光
制作原因:区分金属饰件、布料与手绘受光限制
恢复祀衣料与头发的 P 图,同时开启普通部位的高光。P 是本角色 Shader 的定制数据格式,不可直接用场景 MAHS、ORM 或 RMA 替换。脸、皮肤、眼睛等类型会把金属度清零;脸和皮肤还可能使用常量而非 P 图。

02 普通法线 N 与头发 HN03 属性图 P 与普通高光拖动画面或滑块 · 双击放大原图 · 左:02 普通法线 N 与头发 HN / 右:03 属性图 P 与普通高光
实际输入贴图






当前算法
P.R = metallic;P.G = specularAmplitude P.B = paintedLitCeiling;P.A = smoothness lit = min(saturate(ramp.a × visibility), saturate(P.b)) metal = Kind == Cloth ? saturate(P.r) : 0 s = clamp(P.a, 0.02, 0.92) H = normalize(L + V) gloss = max(Nspec·H,0) ^ (2 ^ (3 + 7×s)) F0 = lerp(0.055, albedo, metal) spec = gloss × F0 × P.g 脸部 spec 再乘 0.12
算法原理
光滑度提高时,幂次变大,高光更集中;P.G 控制幅度,P.R 改变高光颜色并削弱漫反射。这里是风格化的近似 Blinn-Phong,不是场景 URP PBR 的完整 GGX。P.B 对亮面插值取上限,暗色会让局部即使正对主光也保留暗部;它不是 AO,也不是高度。
贴图制作与导入思路(建议流程)
- 分别保存金属、高光幅度、受光上限、粗糙度四个可编辑源层。金属分区按表面材质制作,不按“哪个地方亮”来涂。
- 若制作工具输出粗糙度 r,转换 P.A=1-r;本 Shader 会把有效光滑度限制到 0.02~0.92。
- P.B 默认白色,需要固定暗部时才压暗。AO 可供绘画参考,但不能无判断地复制为 P.B。
- 以 Default、线性数据导入 RGBA,保留 Alpha。分别查看四通道再合成,避免 A 在压缩或导出时丢失。
04 漫反射 Ramp RD
制作原因:把连续受光变成可设计的明暗层次
恢复各材质实际绑定的 RD。RD 的 A 决定明暗混合,RGB 只按彩色程度参与染色;仅查看 RGB 缩略图不能判断它如何分出亮面和暗面。祀的脸、头发与衣服使用各自实际绑定。

03 属性图 P 与普通高光04 漫反射 Ramp RD拖动画面或滑块 · 双击放大原图 · 左:03 属性图 P 与普通高光 / 右:04 漫反射 Ramp RD
实际输入贴图




当前算法
lightValue = saturate(N·L×0.5+0.5) ramp = sampleLOD0(RD, float2(lightValue,0.5)) visibility = lerp(1, mainShadowAttenuation, _ShadowStrength) lit = min(saturate(ramp.a × visibility), P.b) sat = max(ramp.rgb) - min(ramp.rgb) diffuse = lerp(shadowColor, albedo, lit) diffuse *= lerp(1, ramp.rgb, saturate(sat))
算法原理
Ramp 是把一个标量重新映射到颜色和权重的查找表。A 的陡坡产生分段受光,缓坡产生柔和过渡。灰度 RGB 的最大最小值相同,当前公式不会再用它重复压暗底色。主光阴影和 P.B 仍会在查表后限制结果,因此“Ramp 上白色”不代表最终像素一定亮。
贴图制作与导入思路(建议流程)
- 先独立画 A 的明暗过渡位置,再设计 RGB 的染色;不要用 RGB 黑白渐变且 A 全白来期待明暗分段。
- 建议 Clamp、Bilinear,禁止图集边框污染;当前采样显式 LOD 0。RGB 作为颜色按 sRGB,A 保持数据含义。
- 转动灯光观察脸、头发和衣料的过渡,同时检查对应的 lightValue、RD.A 和最终 lit,定位问题在哪一级。
05 脸部 SDF 与 Mask
制作原因:让脸颊和鼻侧明暗服从美术设计
仅对 Kind=Face 恢复 SDF 分支。它用相对头骨的光向查预制图,替代普通半兰伯特,再经过 RD 和阴影限制。Mask.G=0 使用 SDF,G=1 回到几何受光。原图 R/G 一起参与,不能写成“左光读 R、右光读 G”。本组已用正确头骨输入重拍;此前脸部异常变暗来自方向传递冲突,不是 SDF 本身应有的效果。

04 漫反射 Ramp RD05 脸部 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:04 漫反射 Ramp RD / 右:05 脸部 SDF 与 Mask
实际输入贴图







当前算法
q = normalize(float2(dot(L,headRight), dot(L,headForward)) + (0,0.0001)) maskUV = uv;若 q.x <= 0:uv.x = 1 - uv.x s = (SDF(uv).r + SDF(uv).g) / 2 a = q.y × 0.5 t = clamp(0.5-a, 0.001, 0.999) v = smoothstep(max(2t-1,0), min(2t,1), s) face = saturate(abs(-v - a×ceil(a))) lightValue = lerp(face, halfLambert, saturate(Mask(maskUV).g))
算法原理
几何法线会使低模鼻翼、脸颊的小面片产生不理想的阴影。SDF 受光场在 UV 上预先设计过渡,运行时由头骨和光的相对方向驱动。镜像只作用于 SDF UV,Mask 使用原 UV。这里没有独立的俯仰角维度;当前解码也不是简单 step(s,angle)。原资源叫 SDF,但不能仅凭名称认定它是单张黑白图的欧氏距离场。
贴图制作与导入思路(建议流程)
- 冻结脸部 UV 和头骨前/右轴。当前镜像 U→1-U 要求左右脸能在这个映射下对应;测试转头,防止阴影固定在世界方向。
- 建议准备一侧 0°、45°、90°、135°、180° 的目标明暗图,先烘焙初稿,再修鼻侧、脸颊和下巴;这些角度是制作建议,不是原版已证实的采样方案。
- 可用有符号距离 d=EDT(M)-EDT(1-M) 在相邻轮廓间估计切换角;再针对上面的实际解码拟合 s,使所有测试角度下的输出接近目标。不能直接把任意 SDF 工具输出塞进来。
- 新贴图可先令 R=G=s 做解码验证,但这不重建原版两通道各自语义。保留源 B/A:本项目没读不等于原版没用。
- SDF 与 Mask 按 Default、线性导入;遮罩 G 单独绘制。检查全亮/全暗、UV 接缝、左右镜像及逆光。详见下方六个光角的真实开关对照。
06 皮肤阴影 LUT
制作原因:为不同底色设计不同的阴影色
恢复祀脸部、皮肤等启用材质的阴影 LUT。它改变阴影的颜色映射,SDF/Ramp 决定哪里用这个颜色。它是角色表面着色中的查表,不是相机后处理色调映射。
原正面光下,脸中央的 lit 接近 1:lerp(shadowColor,albedo,lit) 几乎只选基础色,因此换阴影 LUT 的效果本来就很小。单纯放大这个亮区不能解决展示问题。
LUT 主对照:背侧光下的脸部阴影
观察脸颊、鼻侧和下巴的阴影色相与亮度。此处把主光设为头骨右后方 135°,让同一张皮肤进入阴影;SDF、Mask、Ramp、曝光和 LUT 贴图保持原值。
受控侧/背光:相对头骨 135°,原主光强度和曝光;同一观察点缩窄视野至原来的 1/3.57,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

05 备用亮度/饱和度阴影色06 启用原皮肤 LUT拖动画面或滑块 · 双击放大原图 · 左:05 备用亮度/饱和度阴影色 / 右:06 启用原皮肤 LUT
本特写未增强差异:最大通道差 75/255,超过 2/255 的像素占 20.97%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 30/255,超过2/255的像素占 0.0038%,最差40×40局部平均差 0.1006/255。微弱效果需结合这项误差与通道图判断。
阴影颜色本身:备用公式 / LUT

加入前的 GPU 中间量加入后的 GPU 中间量拖动画面或滑块 · 双击放大原图 · 左:加入前的 GPU 中间量 / 右:加入后的 GPU 中间量
上方通道直接输出 shadowColor,便于看清查表改变了什么;它未乘 lit,也未经过最终照明,不能当成脸部最终效果。祀的眉毛材质也启用了 LUT,因此眼睑装饰附近可能比脸颊有更明显的颜色变化;解读肤色时应单独看脸颊,不把这一大块变化都算成皮肤。
对照:原庭院正面光下为什么不明显
原光照的同部位特写
脸中央依然主要处于亮面。保留这组小差异结果,用来解释 LUT 只在阴影权重实际参与时才明显。
庭院原光照;同一观察点缩窄视野至原来的 1/3.57,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

05 备用阴影色06 原皮肤 LUT拖动画面或滑块 · 双击放大原图 · 左:05 备用阴影色 / 右:06 原皮肤 LUT
本特写未增强差异:最大通道差 84/255,超过 2/255 的像素占 2.16%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 56/255,超过2/255的像素占 0.0494%,最差40×40局部平均差 0.1994/255。微弱效果需结合这项误差与通道图判断。
原逐层机位总览(保留参考,细节以特写为主)

05 脸部 SDF 与 Mask06 皮肤阴影 LUT拖动画面或滑块 · 双击放大原图 · 左:05 脸部 SDF 与 Mask / 右:06 皮肤阴影 LUT
实际输入贴图

当前算法
c = saturate(LinearToSRGB(albedo)) z = c.b × 31;k = floor(z) uv = ((c.r×31+0.5)/1024 + k/32, (c.g×31+0.5)/32) A = sampleLOD0(LUT,uv).rgb B = sampleLOD0(LUT,uv+(1/32,0)).rgb shadowColor = lerp(A,B,frac(z)) diffuse = lerp(shadowColor,albedo,lit)
算法原理
32³ 色表把三维 RGB 输入映射为阴影 RGB。32 个蓝色切片横排成 1024×32,R/G 在切片内定位,蓝色在相邻切片间插值。因此同一张图能让肤色偏暖、灰白区域偏冷,而不只是给所有像素乘统一暗色。最终效果还取决于 lit,正面全亮时关闭 LUT 可能只有小差别。
贴图制作与导入思路(建议流程)
- 先生成中性 32³ 色表确认轴和切片布局,再对色表设计阴影色相、亮度和饱和度。尺寸必须与当前 1024×32 公式一致。
- 保持 sRGB 颜色导入、Clamp,避免额外显示色彩变换烘入两遍;当前采样 LOD 0。
- 用肤色、白发、饱和衣物和极暗颜色做测试。把 LUT 当颜色映射,不把眼眶阴影轮廓画进这张色表。
07 头发条带高光
制作原因:让发束出现连续的方向性亮带
开启头发专用高光形状;它替代普通高光。此阶段先使用默认暖色和均匀发丝强度,下一步再恢复祀自己的 RS 和 Line。头发 HN.BA 已在阶段 02 载入,实际亮带现在开始体现这套法线的作用。头发同样读取头骨基底,本节已随方向修正重拍。

06 皮肤阴影 LUT07 头发条带高光拖动画面或滑块 · 双击放大原图 · 左:06 皮肤阴影 LUT / 右:07 头发条带高光
实际输入贴图

当前算法
headUp = normalize(cross(headForward,headRight)) Tstrand = normalize(headUp - Nspec×dot(headUp,Nspec)) H = normalize(L+V) x = dot(Tstrand,H) band = sqrt(saturate(1-x²)) ^ 72 band *= smoothstep(-0.1,0.6,dot(Nspec,H)) spec = (1,0.86,0.79) × band × _HairSpecStrength
算法原理
普通表面高光围绕法线与半程向量的对齐形成;这里的头发亮带在发丝方向与 H 接近垂直时增强。投影头部上方向可得到局部发丝走向,HN.BA 调整切平面,从而塑造亮带。它是风格化各向异性近似,不是完整多重散射毛发 BSDF,也没有读取独立 Flowmap。
贴图制作与导入思路(建议流程)
- 先保证发束几何和漫反射法线成立,再调整高光法线,避免亮带在发片接缝突然中断。
- 固定光源扫一圈验证前发、侧发和后发,确认不是只在单个视角好看。
- 当前指数 72 固定,强度由 _HairSpecStrength 控制;文档保留祀原值,不为了截图夸大强度。
08 高光 Ramp RS 与发丝 Line
制作原因:给高光设计颜色变化和细碎层次
恢复祀头发和衣料的高光色表,以及头发 Line.R。头发和普通部位查表横轴不同:头发使用 band,普通部位使用 gloss;纵轴均与 N·V 有关。

07 头发条带高光08 高光 Ramp RS 与发丝 Line拖动画面或滑块 · 双击放大原图 · 左:07 头发条带高光 / 右:08 高光 Ramp RS 与发丝 Line
实际输入贴图




当前算法
lineUV = uv × _LineMap_ST.xy + _LineMap_ST.zw detail = lerp(0.65,1,Line(lineUV).r) 头发:tint = RS(saturate(band),saturate(Ndiffuse·V)).rgb specHair = tint × band × detail × _HairSpecStrength 普通部位:spec *= RS(saturate(gloss),saturate(N·V)).rgb
算法原理
RS 把强度和视角映射为高光颜色,Line 在已有高光上调制细节。Line 黑色仍保留 65% 高光,因此它不是把发片裁掉的透明遮罩。当前头发 Line 的 UV 还叠加独立缩放偏移;原参数会列在贴图绑定表。
贴图制作与导入思路(建议流程)
- 先用测试色表核对 X/Y,再绘制高光核心、过渡和掠射角的色彩;RS 按 sRGB 导入。
- 顺发束走向画或程序生成 Line,R 存强度,线性导入;避免随机噪声破坏发束方向。
- 同时检查 Line 的平铺和 UV 接缝。先单独关闭 RS、再单独关闭 Line,避免把两个输入的贡献混为一谈。
09 眼睛 Matcap
制作原因:用视空间查表补充眼睛颜色
恢复祀虹膜材质启用的 Matcap。它以视空间法线生成坐标,不跟随眼睛 UV 贴死,也不采样庭院实时反射。本材质在已测角度主要采到暗色区域,实际贡献是轻微提亮或染色,并没有明显新增的独立亮斑。下面使用单眼特写展示;白色菱形等关闭前已有的图案不能算成 Matcap。
逐层正面总览的 Matcap 贡献很小,不适合只靠小图解释。下面使用俯视 20° 和左斜侧 40° 的单眼特写,强度仍为当前算法的 0.3,没有为了截图加亮。旧特写中覆盖虹膜的青绿色平面来自采集时误绑的 Overlay,已修正并重拍;定位见“截图勘误”。
Matcap:单眼特写(俯视 20°)
重点比较虹膜暗处和色彩的轻微提亮;点击“自动对比”或“只看加入前/后”,观察同一只眼睛。白色菱形亮斑在关闭 Matcap 时已经存在,不能算成它的效果。
庭院原光照;同一观察点缩窄视野至原来的 1/12.50,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

08 Matcap 关闭09 Matcap 开启拖动画面或滑块 · 双击放大原图 · 左:08 Matcap 关闭 / 右:09 Matcap 开启
本特写未增强差异:最大通道差 100/255,超过 2/255 的像素占 7.41%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 0/255,超过2/255的像素占 0.0000%,最差40×40局部平均差 0.0000/255。微弱效果需结合这项误差与通道图判断。
第二视角:左斜侧 40° 单眼特写
这组取样主要是较暗的颜色,整体贡献轻微;眼睛已充满画面仍看不到强烈新高光,说明当前材质的 Matcap 就不是那种强效果。
庭院原光照;同一观察点缩窄视野至原来的 1/12.50,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

08 Matcap 关闭09 Matcap 开启拖动画面或滑块 · 双击放大原图 · 左:08 Matcap 关闭 / 右:09 Matcap 开启
本特写未增强差异:最大通道差 94/255,超过 2/255 的像素占 9.87%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 0/255,超过2/255的像素占 0.0000%,最差40×40局部平均差 0.0000/255。微弱效果需结合这项误差与通道图判断。
俯视 20° 同机位 Matcap 颜色项

Matcap 单项图只显示查表颜色×0.3,其他表面为黑。本例的单项图几乎是低亮度的整片虹膜,说明当前采样没有产生明显独立亮斑;它与纹理中的白色菱形不是一回事。原小图的最大差值还包含抗锯齿边缘,不能凭最大差一个数字断言高光很强。
对照:同样放大的原正面眼睛
原正面机位:相同强度下贡献很小
保留不明显的正面结果,并与上面的斜侧机位区别标注。相机改变了视空间法线和 Matcap UV;不能把两个机位整体不同的外观都归因于开关。
庭院原光照;同一观察点缩窄视野至原来的 1/10.00,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

08 Matcap 关闭09 Matcap 开启拖动画面或滑块 · 双击放大原图 · 左:08 Matcap 关闭 / 右:09 Matcap 开启
本特写未增强差异:最大通道差 6/255,超过 2/255 的像素占 0.00%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 2/255,超过2/255的像素占 0.0000%,最差40×40局部平均差 0.0031/255。微弱效果需结合这项误差与通道图判断。
原逐层机位总览(保留参考,细节以特写为主)

08 高光 Ramp RS 与发丝 Line09 眼睛 Matcap拖动画面或滑块 · 双击放大原图 · 左:08 高光 Ramp RS 与发丝 Line / 右:09 眼睛 Matcap
实际输入贴图


原逐层正面总览(非上方特写)的 08→09 对照:整图最大通道差 43/255,超过 2/255 的像素比例为 0.020347%。多视角章节另以可见虹膜区域统计;最大差不能代替对实际高光形态的观察。
当前算法
Nview = TransformWorldToViewDir(N,true) uvMatcap = Nview.xy×0.5 + 0.5 color += sample(Matcap,uvMatcap).rgb × 0.3
算法原理
Matcap 预存“某个法线朝向看起来是什么颜色”。相机变动时视空间法线改变,取样位置也改变,因此能以很低成本表现稳定的风格化亮斑。但它不包含真实场景遮挡、反射视差或动态倒影。
贴图制作与导入思路(建议流程)
- 在球面法线布局上绘制或渲染亮斑、暗部与边缘,使用彩色 sRGB 图。
- 把球面外圈处理干净,避免取样到画布边框;在眼球模型上转相机检查拉伸和亮斑方向。
- 与 D 中的虹膜和瞳孔分工:D 管固有图案,Matcap 管视空间外观。
10 边缘光 Rim
制作原因:增强轮廓附近的亮部可读性
恢复各部位原来的 _RimStrength。该项没有专用贴图,由法线、观察方向和主光方向计算。最终是否明显还取决于底色与曝光。
Rim 只加在掠射角附近,且还乘主光方向权重。当前头发强度约 0.16,多数其他材质约 0.07;原全脸图里细窄的提亮容易被底色、发丝高光与曝光掩盖。以下保持这些原强度。
Rim 主对照:最外侧发片轮廓特写
只看发片贴近背景的窄边与弧面转折。点击“自动对比”,让同一条轮廓交替显示开关前后;变化应是薄薄的提亮,不是凭空增加一圈宽白边。
庭院原光照;同一观察点缩窄视野至原来的 1/8.33,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

09 Rim 关闭10 原强度 Rim拖动画面或滑块 · 双击放大原图 · 左:09 Rim 关闭 / 右:10 原强度 Rim
本特写未增强差异:最大通道差 56/255,超过 2/255 的像素占 5.93%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 29/255,超过2/255的像素占 0.0034%,最差40×40局部平均差 0.0960/255。微弱效果需结合这项误差与通道图判断。
第二部位:发束掠射角局部
看发束边缘和弧面掠射处的细微提亮,不把阶段 07 已存在的亮带当作新增 Rim。整幅前后切换更容易定位这条窄变化。
庭院原光照;同一观察点缩窄视野至原来的 1/5.00,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

09 Rim 关闭10 原强度 Rim拖动画面或滑块 · 双击放大原图 · 左:09 Rim 关闭 / 右:10 原强度 Rim
本特写未增强差异:最大通道差 98/255,超过 2/255 的像素占 12.50%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 0/255,超过2/255的像素占 0.0000%,最差40×40局部平均差 0.0000/255。微弱效果需结合这项误差与通道图判断。
Rim:侧面轮廓局部
比较同一侧面机位的轮廓和发束转折。本轮只更换取景,不提高 Rim 强度;若原参数效果弱,就以弱效果说明,不称为强轮廓灯。
庭院原光照;同一观察点缩窄视野至原来的 1/4.17,重新渲染 1600×900。相机曝光、贴图与材质强度保持原值。

09 Rim 关闭10 原强度 Rim拖动画面或滑块 · 双击放大原图 · 左:09 Rim 关闭 / 右:10 原强度 Rim
本特写未增强差异:最大通道差 67/255,超过 2/255 的像素占 2.97%。数值只用于核对开关有无实际贡献,不能替代看图。
同状态复拍误差:最大差 18/255,超过2/255的像素占 0.0242%,最差40×40局部平均差 0.1713/255。微弱效果需结合这项误差与通道图判断。
Rim 几何/光向权重(未乘材质强度)

权重图显示 pow(1−saturate(N·V),4)×saturate(N·L×0.5+0.5)。最终还要乘基础色、主光颜色和 0.07/0.16 的强度,所以权重图的白色不等于最终出现同样亮的白边。
原逐层机位总览(保留参考,细节以特写为主)

09 眼睛 Matcap10 边缘光 Rim拖动画面或滑块 · 双击放大原图 · 左:09 眼睛 Matcap / 右:10 边缘光 Rim
当前算法
rim = (1-saturate(N·V)) ^ 4 rim *= saturate(N·L×0.5+0.5) color += albedo × mainLightColor × rim × _RimStrength
算法原理
N·V 接近 0 时处于掠射轮廓,四次幂把亮部压缩到边缘;再乘主光方向权重,防止所有背光轮廓无条件发亮。这是风格化加色项,不能称为真实轮廓灯或完整物理菲涅耳。
贴图制作与导入思路(建议流程)
- 先在原光照下检查脸颊、头发外缘和衣袖,调整每材质强度,避免纯白边圈。
- 没有额外 Rim 贴图要制作;其输入来自法线图和几何,因此法线接缝也会影响轮廓光。
11 屏幕宽度描边
制作原因:用稳定轮廓帮助角色从背景中分离
恢复原描边 Pass。反壳只渲染外扩后的背面,并按材质 _OutlineWidth 控制近似像素宽度。祀部分材质的 OutlineMask 会裁掉局部描边。

10 边缘光 Rim11 屏幕宽度描边拖动画面或滑块 · 双击放大原图 · 左:10 边缘光 Rim / 右:11 屏幕宽度描边
实际输入贴图



当前算法
Nview = TransformWorldToViewDir(Nworld,true) dir = normalize(Project2D(Nview.xy)) clipPos.xy += dir × (OutlineWidth×2 / screenSize.xy) × clipPos.w Cull Front;ZWrite On;Offset 1,1 若 UseOutlineMask:clip(OutlineMask(uv).r - 0.1) outlineColor = lerp(_OutlineColor.rgb,albedo.rgb×0.17,0.3)
算法原理
裁剪空间的偏移乘 clip.w 补偿透视除法,所以线宽近似按屏幕像素保持。反壳不是后处理边缘检测;模型法线与网格结构会影响轮廓连续性。Mask.R 在当前实现中是阈值裁切,不是连续乘到线宽上。
本节已使用 4×MSAA + SMAA 重拍。游戏运行时已有 TAA High;本篇非 Play 采集采用原场景编辑预览路径。屏幕宽度不等于抗锯齿:0.35/0.65 像素细线仍需覆盖率采样;旧图漏用多采样的原因与同机位对比见“截图勘误”。
贴图制作与导入思路(建议流程)
- 保留轮廓法线连续性,检查发片边缘与脸内面片,避免内线变成黑斑。
- OutlineMask 的 R 以白保留、黑去掉,需要稳定阈值区域;按线性数据导入。
- 以最终游戏分辨率和远近距离检查宽度。不要只在放大贴图预览中验收。
12 Overlay 艺术阴影
制作原因:用独立网格和遮罩补充发压脸、眼部阴影
恢复祀原有的 OverlayShadow 材质。它在已有颜色上做乘法调暗,并通过模板值约束接收表面。它与主光投射阴影、SDF 明暗和 LUT 颜色分别负责不同部分。

11 屏幕宽度描边12 Overlay 艺术阴影拖动画面或滑块 · 双击放大原图 · 左:11 屏幕宽度描边 / 右:12 Overlay 艺术阴影
实际输入贴图

当前算法
mask = sample(_BaseMap,uv).r factor = lerp(1,_BaseColor.rgb,mask×_Strength) Blend DstColor Zero:Cnew = factor × Cold Stencil:比较 (buffer & ReadMask) 与 (Ref & ReadMask) ZWrite Off;Cull Off;Offset -1,-1
算法原理
白色乘数 1 不改变画面,较暗乘数压低现有颜色。独立覆盖网格提供位置,贴图提供软硬形状,Stencil 避免阴影落到错误材质区域。这种艺术化阴影不会自动根据光线与发束距离计算投影。
贴图制作与导入思路(建议流程)
- 按接收区域准备覆盖网格,绘制 R 通道阴影遮罩并柔化边界。
- 配置接收材质 Stencil 和 Overlay 的 Ref/ReadMask,使发压脸与眼部各落到预期区域。
- 检查近景穿插、侧面漏影与转头表现,独立调节 Strength 和乘法颜色;不要把过黑归因于 SDF 一项。
13 自发光与当前完整效果
制作原因:恢复祀原本开启的发光,回到原材质结果
恢复衣料上原有的 Emission,并解除教学副本对湿润分支的临时门控。近景可观察头部饰件与肩部装饰的亮度变化:材质文件叫 cloth,不代表它只覆盖躯干布料。此次角色没有涉水湿润输入,因此没有新增湿润效果。至此所有教学阶段门控放开,未在原材质开启的功能仍不启用。

12 Overlay 艺术阴影13 自发光与当前完整效果拖动画面或滑块 · 双击放大原图 · 左:12 Overlay 艺术阴影 / 右:13 自发光与当前完整效果
实际输入贴图


当前算法
emission = sample(_EmissionMap,uv).rgb × _EmissionColor.rgb × _EmissionBrightness color += emission wet = saturate(WetAmount) × (1-smoothstep(waterY-0.15,waterY+max(0.02,fadeHeight),worldY)) albedo *= 1 - wet×0.22 smoothness = lerp(smoothness,0.88,wet×0.7) output = TTApplyFog(color,worldPos,era,fog)
算法原理
自发光向最终颜色额外加辐亮度。Bloom 是相机后处理对亮区的扩散,并不会自动让衣服照亮附近墙面。湿润仅改变已有表面的底色和光滑度,不会生成水膜网格。最后还有统一雾、曝光、色调映射和抗锯齿,所以截图并不等于直接显示贴图 RGB。
贴图制作与导入思路(建议流程)
- 为发光区域绘制独立 E 图,不要把发光亮度烘死在 D 里;颜色 E 按实际 sRGB 约定导入。
- 先关 Bloom 看真实图案,再开 Bloom 判断光晕;保持 HDR 强度与曝光匹配。
- 用下文“原 Shader / 教学完整阶段 / 原 Shader 复拍”验证最终结果,避免把教学重写产生的差异当成贴图作用。
SDF 专项:同一张脸,六个头部光角
为了看清 SDF 的贡献,此组只改变副本太阳方向。0° 表示光大致来自头部正面,正/负角沿头部右方向区分;每一对使用同一光向、姿态、机位和完整其他材质项。太阳略高于头部平面。这些是 Unity 中真实渲染的脸,不是 UV 平面算法示意。
本节六组光角已全部重拍,并同时核对材质槽头骨方向与渲染后的 GPU 主光。此前方向冲突下的旧光角图已撤出正文;不能用旧图解释正常正面/背面受光。
-90° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
-45° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
0° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
45° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
90° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
135° 光向

仅关闭 SDF,使用半兰伯特启用原 SDF 与 Mask拖动画面或滑块 · 双击放大原图 · 左:仅关闭 SDF,使用半兰伯特 / 右:启用原 SDF 与 Mask
读图时先比较同一角度的开关,再观察不同角度:前方 0° 下脸部大范围受光,侧向 90° 出现沿鼻侧分开的明暗,135° 背侧光下暗面增多。这组变化来自真实头骨相对光向;侧光或背光时脸与肩部仍可能因 SDF 和法线受光不同而有合理差异,不应强行调成相同颜色。
SDF 并不取代主光阴影、发压脸 Overlay 和 LUT。比如脸进入真实阴影时,即使 SDF 给出较高权重,最终 lit 仍受阴影可见度限制。原版参考中 SDF.B 还参与其他计算;当前只用 RG 的边界见后文证据。
Mask 多视角验证:相机角度与光照角度分开检查
2026-11-02 全部重拍:已同步正确头骨方向,替换本节原有 153 张截图并重新计算表格。祀固定姿态,从正面、左右 20°/40°/70°、俯视/仰视 20° 共 9 个相机角度拍摄;每角再用庭院原光照、头部左右 70° 光向拍摄 3 种状态。成对图片均来自本轮同条件的真实渲染。
“左/右相机角度”指相机位于头部前向的哪一侧,沿头骨右轴定义正角;不代表画面中鼻子朝向的左右。俯仰角相对于头部平面。每个成对对照只改变一个 Shader 开关,相机与灯光保持相同。
原 Mask:lightValue = lerp(faceSDF,halfLambert,Mask.G) 忽略 Mask:Mask.G 强制 0 → 全部使用 faceSDF 关闭 SDF:直接使用 halfLambert,Mask 此时不参与 Mask.G=0 → 使用 SDF;Mask.G=1 → 使用普通法线受光 这不是透明度 Mask,也不是轮廓宽度 Mask。
制作原因:脸中央需要保留手绘的 SDF 明暗形状,耳部及部分边缘则需要按表面法线过渡。Mask.G 为这两种结果分配权重;白色并不是“挖空”,而是选择半兰伯特结果。判断是否合适,要看这些边缘区域在斜侧光下能否与脸中央衔接。
算法原理:Mask.G 按模型原 UV 取样,当前实现不随相机角度旋转,也不跟随 SDF 的左右镜像。换相机是在查看同一遮罩的不同可见部分;换光照才会同时改变 SDF 判定和半兰伯特值。各角度的高光、Rim 等也可能随视线改变,因此应比较同一机位内的左右两张,不能把不同机位之间的所有色差都归因于 Mask。

忽略 Mask(全部 SDF)原 Mask + SDF拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:原 Mask + SDF
九个相机角度:同一庭院光照下逐个查看
下列缩略显示保留同一尺寸,点击可打开 1600×900 原图。对照可以看鼻翼、颧颊、脸缘和下巴;发束遮住的部分在当前角度不可见,不能据此判断该区域 Mask 失效。
左侧 70°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
左斜侧 40°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
左斜侧 20°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
正面 0°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
右斜侧 20°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
右斜侧 40°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
右侧 70°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
俯视 20°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
仰视 20°

忽略 Mask(全部 SDF)启用原 Mask拖动画面或滑块 · 双击放大原图 · 左:忽略 Mask(全部 SDF) / 右:启用原 Mask
Mask.G 实际落在模型哪里
以下仅为 GPU 诊断图:白色区域混回半兰伯特,黑色脸部区域保留 SDF,灰色为过渡。为了辨认覆盖范围,背景与非脸材质显示黑色;彩色效果对照仍保留实际庭院。标注为“可见脸部区域”的白色图是统计范围,不代表 Mask 本身。

可见脸材质区域Mask.G 真实采样拖动画面或滑块 · 双击放大原图 · 左:可见脸材质区域 / 右:Mask.G 真实采样






实际差异统计:只看可见脸部
统计阈值是任一 RGB 通道相差超过 2/255,分母为这个角度真正可见的脸材质像素,包含该材质的耳部;头发、眼睛、衣物与背景不进入分母。这个指标用于定位差异明显的机位,不是美术质量分数;最终仍需看相应截图。
| 相机 | 庭院原光:变化比例 / 最大差 | 左侧光:变化比例 / 最大差 | 右侧光:变化比例 / 最大差 |
|---|---|---|---|
| 左侧 70° | 13.96% / 85/255 | 10.74% / 70/255 | 25.11% / 98/255 |
| 左斜侧 40° | 4.14% / 79/255 | 3.42% / 68/255 | 9.19% / 70/255 |
| 左斜侧 20° | 2.25% / 69/255 | 1.38% / 62/255 | 4.70% / 69/255 |
| 正面 0° | 1.75% / 71/255 | 2.23% / 61/255 | 2.20% / 66/255 |
| 右斜侧 20° | 2.65% / 86/255 | 4.50% / 69/255 | 1.25% / 67/255 |
| 右斜侧 40° | 5.38% / 68/255 | 8.10% / 69/255 | 2.76% / 69/255 |
| 右侧 70° | 13.86% / 78/255 | 21.86% / 70/255 | 7.72% / 72/255 |
| 俯视 20° | 1.84% / 68/255 | 2.35% / 63/255 | 2.56% / 62/255 |
| 仰视 20° | 3.44% / 77/255 | 3.42% / 71/255 | 3.51% / 72/255 |
本次“忽略 Mask / 原 Mask”中,脸部变化比例最大的组合是 左侧 70° + 头部右侧光 +70°,约 25.11% 的可见脸部像素超过阈值。可在上方选择对应机位与光照查看。
看图结论:正面中央大部分 Mask.G 为黑,仍使用 SDF;白色主要落在耳部和少量脸缘,仰视还能看到下巴下缘的灰白过渡。忽略 Mask 后,耳内和耳廓失去部分按法线形成的明暗,侧面比正面更容易看出。下巴的影响只占很窄的一带,不能把整张脸的变化都算作这张 Mask 的贡献。
补充:眼睛 Matcap 的多视角验证
Matcap 与 SDF Mask 是不同输入:前者按视空间法线取颜色,后者按原 UV 混合脸部受光。此前仅凭正面机位观察到 Matcap 增量很小,本轮在同一组 9 个相机角度验证,保留原图、原强度与原相机后处理。

仅关闭 Matcap原完整配置拖动画面或滑块 · 双击放大原图 · 左:仅关闭 Matcap / 右:原完整配置
| 相机 | 可见虹膜像素 | 变化像素 (>2/255) | 区域平均差 / 255 | 最大差 / 255 |
|---|---|---|---|---|
| 左侧 70° | 313 | 111 | 1.543131 | 55 |
| 左斜侧 40° | 1653 | 1230 | 3.246622 | 39 |
| 左斜侧 20° | 2087 | 19 | 0.054943 | 20 |
| 正面 0° | 2243 | 11 | 0.037004 | 27 |
| 右斜侧 20° | 2088 | 22 | 0.137292 | 28 |
| 右斜侧 40° | 1622 | 19 | 0.153309 | 25 |
| 右侧 70° | 173 | 2 | 0.194605 | 11 |
| 俯视 20° | 1612 | 1362 | 4.237800 | 38 |
| 仰视 20° | 2530 | 14 | 0.108432 | 70 |
本轮 Matcap 最大差值机位为 仰视 20°,可见虹膜区域最大通道差 70/255。最大差可能只占很少的边界像素,包含抗锯齿影响,不能据此称其形成强烈的新高光。阶段 09 新增单眼特写和真实颜色项,确认主要是轻微提亮/染色;表格保留零差异,不把已有白色菱形和虹膜色归因于 Matcap。
多视角记录:正面 0° 的可见虹膜最大差为 27/255,左斜侧 40° 与俯视 20° 则分别为 39/255 和 38/255。最大差还包含少量采集边界变化;真实 Matcap 贡献需要结合单眼特写、独立颜色项和采样坐标判断,不能只凭这些最大值推断高光强度。


补拍完整性与路径
本轮重新采集并替换 153 张实渲 PNG,每张渲染后均核对材质槽的头骨方向;3868 项原资产/导入配置指纹一致,原场景脏标记未改变。9 个机位中,原 Shader 与完整教学副本在相同正确方向输入下存在稀疏边界差异,超过2/255的像素比例最高为 0.0423%,不宣称逐像素等价。原 Shader 自身复拍最大差为 107/255;完整局部/全图统计在下方验证报告。主篇 94 张逐层图也已重拍。
| 用途 | 完整路径 |
|---|---|
| 多视角 PNG | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\MaskMultiview |
| 相机/光向/材质与文件指纹 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\mask-multiview.json |
| 每对截图的脸部/虹膜像素统计 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\mask-multiview-validation.json |
| 本次补充生成器 | F:\UnityAITest\GameTest\Tools\character_mask_multiview_document.py |
完整效果中逐项关闭
以下单项开关均在正确头骨输入下重新拍摄。逐层加入会包含上游依赖,这里从完整效果中单独移除一项,查看该输入改变了什么。没有增强或后期染色;影响很小时以局部通道帮助解释。
脸部 SDF

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
SDF Mask.G(左侧全部使用 SDF)

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
独立高光法线(左侧改用漫反射法线)

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
阴影 LUT

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
发丝 Line

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
高光 RS

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
眼睛 Matcap

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
Rim

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
描边

移除 / 替换该项原完整配置拖动画面或滑块 · 双击放大原图 · 左:移除 / 替换该项 / 右:原完整配置
GPU 中间量:输入如何变成明暗
这些图在同一真实模型上直接输出中间计算量,并关闭后处理、描边和 Overlay。数据通道先进行 sRGB 反编码,使最终 PNG 的灰度近似表示 0~1 数据。颜色项保留线性到显示的正常编码。只看角色目标表面:庭院仍使用原材质。
全部中间量图已随本轮重拍。此前 SDF 后脸部大面积变暗反映的是错误方向输入,不是 SDF 的预期目标;本组使用修正输入后的真实计算结果。














材质之后:照明、阴影、雾与相机
ambient = TTScenarioProbe(position,N,era,max(0,SampleSH(N))) × AmbientStrength colorDiffuse = diffuse × (ambient + mainColor×distanceAttenuation×0.82) × (1-metal×0.65) color += spec × mainColor × visibility 附加光:albedo × otherColor × (halfLambert×distanceAttenuation×shadowAttenuation×0.35) 再加入 Matcap、Rim、Emission,最后 TTApplyFog
0.82、0.65、0.35 等是当前工程适配中的调校系数。角色通过 SH / 场景探针获取环境漫反射,本 Shader 没有在此处实现角色完整 PBR 环境镜面反射或皮肤体积次表面散射。模型没有 Lightmap UV 的采样路径,不应把庭院烘焙光照图直接说成角色材质贴图。
DepthOnly 和 DepthNormals 维持时代/Alpha 裁切;DepthNormals 当前输出几何法线,不读取 N/HN。ShadowCaster 向光空间投影,并加偏移;它与 SDF 艺术明暗不同。透明衣料的混合、ZWrite 和队列会影响遮挡与排序,不能只看片元函数判断最终结果。
证据层级、文件路径与完整性
| 层级 | 可确认内容 | 不能由此推出 |
|---|---|---|
| 当前工程源码与实渲 | 本篇所有公式、参数和逐层视觉差异 | 不等于客户端当前版本逐式完整移植 |
| 祀的源材质参数与贴图 | SourceParameters JSON、实际材质绑定、纹理通道与导入配置 | 无法唯一反推原作者的 PSD、Substance 工程或 SDF 生成工具 |
| 归档 HLSL 参考 | Perlica/Reference 中原版片元参考;皮肤 SDF 有额外 B 通道用途 | 第三方 AllShader_1.6.3.7z 不保证与本机客户端同版本 |
| 本篇制作流程 | 针对当前解码设计的可执行工作步骤 | 不是已证实的终末地内部制作流程 |
下面两侧均使用正确头骨输入。4×MSAA 采集中,原 Shader 自身复拍也存在少量边界像素变化,因此本版不宣称严格逐像素等价。表中保留最大差与局部误差;没有成片的材质变化,还需结合公式、逐帧输入和实渲判断。旧版在错误头骨输入下逐像素一致也不能证明受光正确。
全身:原 Shader 与教学完整阶段

原 Shader + 正确方向输入教学阶段 13 + 同一正确输入拖动画面或滑块 · 双击放大原图 · 左:原 Shader + 正确方向输入 / 右:教学阶段 13 + 同一正确输入
脸部:原 Shader 与教学完整阶段

原 Shader + 正确方向输入教学阶段 13 + 同一正确输入拖动画面或滑块 · 双击放大原图 · 左:原 Shader + 正确方向输入 / 右:教学阶段 13 + 同一正确输入
衣料:原 Shader 与教学完整阶段

原 Shader + 正确方向输入教学阶段 13 + 同一正确输入拖动画面或滑块 · 双击放大原图 · 左:原 Shader + 正确方向输入 / 右:教学阶段 13 + 同一正确输入
| 核对项目 | 结果 |
|---|---|
| 原文件 SHA256 | 3868 项全部一致,包含依赖资产及 .meta |
| 原场景脏标记 | False → False |
| GPU 截图 | 94 张,1600×900 |
| 源 Shader 编译 | 捕获前后无错误 |
| 比较 | 平均差 / 255 | 最大差 / 255 | 差值大于 2 的像素比例 | 最差 40×40 局部均差 / 255 |
|---|---|---|---|---|
| full_native.png / full_full.png | 0.0017655 | 59 | 0.021181% | 0.10938 |
| full_native.png / full_native_repeat.png | 0.0006012 | 57 | 0.005000% | 0.13687 |
| face_native.png / face_full.png | 0.0020306 | 72 | 0.027153% | 0.19062 |
| face_native.png / face_native_repeat.png | 0.0008586 | 34 | 0.011389% | 0.08625 |
| cloth_native.png / cloth_full.png | 0.0012685 | 60 | 0.012083% | 0.14021 |
| cloth_native.png / cloth_native_repeat.png | 0.0029560 | 60 | 0.027778% | 0.47146 |
采集稳定性门槛:全图平均差 <0.01/255,变化超过2/255的像素 <0.1%,每个40×40局部平均差 <1/255。最大单像素差不被抹除;特别弱的 Matcap/Rim 必须结合复拍误差和独立通道判断,不能把全部前后差值都当成效果贡献。
数值表按整张图片计算,含固定背景;另检查脸部、衣料、全身及光角,不以全图平均数替代视觉判断。原 Shader 复拍给出重复采集误差基准。正式运行代码未改动。
祀的源材质与当前适配入口
| 部位 | 源参数记录的 Shader | 当前 Shader | 源绑定中当前主表面无对应入口的贴图 | 源证据完整路径 |
|---|---|---|---|---|
| 脸部 | characternpr_skin | Charter_Shader | _EmotionMap, _HighlightMap | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_actor_jsspsi_face_01.json |
| 头发 | characternpr_hair | Charter_Shader | _StrokeMap | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_actor_jsspsi_hair_01.json |
| 衣料 01 | characternpr | Charter_Shader | _ClearCoatMask | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_actor_jsspsi_cloth_01.json |
| 衣料 02 | characternpr | Charter_Shader | _ParallaxTex | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_actor_jsspsi_cloth_02.json |
| 虹膜 | characternpr_eye | Charter_Shader | 本表关注的贴图入口均有对应 | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_actor_jsspsi_iris_01.json |
| 发压脸 Overlay | characternpr_overlayshadow | Charter_Shader/OverlayShadow | 本表关注的贴图入口均有对应 | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters\M_hairshadow_common_01.json |
例如脸部源数据还绑定 _EmotionMap、_HighlightMap,当前 Charter_Shader 没有对应采样入口。本表只能确认源绑定存在,不能据此断言原版在所有状态均开启这些功能;也不能把本篇 14 阶段当作已覆盖原版全部分支。Overlay 则使用自己的独立 Shader,按前述乘法公式解释。
| 用途 | 完整路径 |
|---|---|
| 交互网页 | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\index.html |
| 单文件内嵌图版 | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\祀角色Shader逐层对比-内嵌图.html |
| 完整 Markdown | F:\UnityAITest\GameTest\Docs\角色Shader祀实景逐层分析-20261030.md |
| 图片路径清单 | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\图片路径清单.csv |
| 原 Shader | F:\UnityAITest\GameTest\Assets\Art\Shader\Charter_Shader\Charter_Shader.shader |
| 原算法 | F:\UnityAITest\GameTest\Assets\Art\Shader\Charter_Shader\Charter_Shader.hlsl |
| 原 Overlay | F:\UnityAITest\GameTest\Assets\Art\Shader\Charter_Shader\Charter_OverlayShadow.shader |
| 祀材质 | F:\UnityAITest\GameTest\Assets\Art\Material\Si\URP |
| 源材质参数 | F:\UnityAITest\GameTest\Assets\Art\Material\Si\SourceParameters |
| 原版参考来源 | F:\UnityAITest\GameTest\Assets\Art\Shader\Perlica\source-provenance.json |
| 独立教学场景 | F:\UnityAITest\GameTest\Assets\Art\Shader\ShaderAnalysisCharacter\SiShaderSteps.unity |
| 独立教学 Shader | F:\UnityAITest\GameTest\Assets\Art\Shader\ShaderAnalysisCharacter\Shader\Charter_Steps.shader |
| Unity 截图工具 | F:\UnityAITest\GameTest\Assets\Art\Shader\ShaderAnalysisCharacter\Editor\CharacterShaderAnalysisCapture.cs |
| 采集报告与全部哈希 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\capture.json |
| 图像核对 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\validation.json |
| 输入来源与导入配置 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\texture-inputs.json |
| 浏览器检查 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\browser-check.json |
| 贴图制作与 SDF 长文 | F:\UnityAITest\GameTest\Docs\角色贴图制作流程与SDF详解.md |
局部特写的拍摄与核对
本次 11 组共 55 张特写由缩窄后的相机视锥重新渲染,不是把旧 PNG 数码放大。每组包含加入前、加入后、复拍和 GPU 中间量;逐帧头骨方向与实际主光均核对。材质强度保持原值,侧/背光另行标注。
| 用途 | 完整路径 |
|---|---|
| 特写 PNG | F:\UnityAITest\GameTest\Docs\ShaderAnalysisCharacter\DetailCloseups |
| 机位、取景范围、阶段与光向记录 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\detail-closeups.json |
| 逐组差异、复拍和文件核对 | F:\UnityAITest\GameTest\Logs\ShaderAnalysisCharacter\detail-closeups-validation.json |
| 特写文档工具 | F:\UnityAITest\GameTest\Tools\character_detail_document.py |
全部目标材质的贴图来源与导入
| 材质 / 槽位 | 源贴图完整路径 | 尺寸与导入 | 采样 | ST 缩放 / 偏移 |
|---|---|---|---|---|
| M_wpn_claym_0010_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Claym0010\T_wpn_claym_0010_01_D.png | 1024×1024,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_wpn_claym_0010_01.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Claym0010\T_wpn_claym_0010_01_N.png | 1024×1024,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_wpn_claym_0010_01.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Claym0010\T_wpn_claym_0010_01_P.png | 1024×1024,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_eyewhiteshadow_common_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_eyeshadow_01_M.png | 32×32,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_eyeshadow_common_03.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_eyeshadow_02_M.png | 32×32,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_body_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_body_01_D.png | 1024×1024,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_body_01.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_body_01_N.png | 1024×1024,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_body_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_face_01_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_body_01.mat / _ShadowLutTex | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_femaleskincolor01_lut_D.png | 1024×32,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_02_D.png | 512×512,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_02_N.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_02_P.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _EmissionMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_02_E.png | 512×512,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _SpecRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RS.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_02.mat / _OutlineMask | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_lizhiyan_cloth_01_ST.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_03.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_D.png | 2048×2048,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_03.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_N.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_03.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_P.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_03.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_03.mat / _SpecRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_02_RS.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_hair_01_D.png | 2048×2048,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_hair_01_P.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_hair_03_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _SpecRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_hair_01_RS.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _SplitNormalMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_hair_01_HN.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _LineMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_hairline_03_M.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 8.0, 'y': 1.0} / {'x': -0.44999998807907104, 'y': 0.0} |
| M_actor_jsspsi_hair_01.mat / _OutlineMask | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_hair_01_ST.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_iris_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_iris_01_D.png | 512×512,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_iris_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_body_01_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_iris_01.mat / _MatcapTex | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_matcap_08_D.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_brow_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_face_01_D.png | 1024×1024,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_brow_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_body_01_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_brow_01.mat / _ShadowLutTex | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_femaleskincolor03_lut_D.png | 1024×32,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_face_01_D.png | 1024×1024,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_face_01_N.png | 1024×1024,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _EmissionMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\common_deco_white.png | 68×68,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_face_01_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _ShadowLutTex | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_femaleskincolor01_lut_D.png | 1024×32,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _SDFLightmap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_female_face_03_SDF.png | 1024×1024,Default,Linear | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _SDFMask | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_female_face_03_cm_M.png | 512×512,Default,Linear | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_face_01.mat / _OutlineMask | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_face_01_ST.png | 128×128,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_hairshadow_common_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_hairshadow_01_M.png | 32×32,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_04.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_04_D.png | 512×512,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_04.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_04_N.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_04.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_04_P.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_04.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_04.mat / _SpecRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RS.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _BaseMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_D.png | 2048×2048,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _BumpMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_N.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _MetallicGlossMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_P.png | 2048×2048,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _EmissionMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_E.png | 1024×1024,Default,sRGB | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _DiffRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RD.png | 256×1,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _SpecRampMap | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_common_cloth_04_RS.png | 256×256,Default,sRGB | Clamp/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
| M_actor_jsspsi_cloth_01.mat / _OutlineMask | F:\UnityAITest\GameTest\Assets\Art\Texture\Si\T_actor_jsspsi_cloth_01_ST.png | 512×512,Default,Linear | Repeat/Bilinear, mip=True | {'x': 1.0, 'y': 1.0} / {'x': 0.0, 'y': 0.0} |
表中有绑定不等于一定参与当前分支,需同时看前面的 Use 开关及 Kind。导入设置记录实际值;正文给出制作建议时不会偷偷改写原资源。完整参数和颜色常量保存在 capture.json。
未纳入分层的祀特效材质
| 实际材质 → Shader |
|---|
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_04_01.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_04_02.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_04_03.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_06_01.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_actor_jsspsi_cloth_08_01.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_06_02.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_cloth_05.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_actor_jsspsi_cloth_05_01.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_9.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_10.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_12.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_11.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_6.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_7.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_8.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_5.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_4.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_1.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_2.mat → Game/Effect/Effect_Shader |
| Assets/Art/Material/Si/URP/M_fx_jsspsi_toppotential_01_3.mat → Game/Effect/Effect_Shader |
在 Unity 中查看与重新采集
查看独立场景 SiShaderSteps.unity,祀的复制材质里 _CAStage 为 0~13,_CADebug=0 是正常颜色。副本材质保留本次固定姿态的正确头骨方向;改变动作或旋转头骨后应重新采集,不将这个固定快照当成正式运行时修复。三机位和输入记录均在 capture.json。
需要重拍时,在 EnvironmentArtSandbox 退出 Play 后使用菜单 Tools / Time Traveler / Shader 分析 / 祀:生成庭院逐层截图。该操作重建教学副本和文档截图,不保存原场景。改写文档正文后运行 Tools/build_character_shader_document.py 可重新生成两种网页与 Markdown。