mcpField
S
scenario-unity-shaders

scenario-unity-shaders

github.com/scenario-labs开发1.2k263 次安装1 天前更新
代码仓库

关于 scenario-unity-shaders

scenario-unity-shaders 面向使用 Unity 6.3 的技术美术和着色工程师,指导着色器编写与验证。重点包括目标平台编译、渲染通道一致性、变体预算、首次使用表现和 GPU 成本测量。

主要功能

  1. 01手写 URP HLSL 工作流
  2. 02基于模板编辑 Shader Graph
  3. 03目标 API 着色器编译检查
  4. 04变体剥离与预算审计
  5. 05PSO 预热与首次使用检查
  6. 06GPU 成本测量

适用场景

  1. 01编写卡通、水面或溶解着色器
  2. 02检查各渲染阶段的着色器通道
  3. 03减少发布的着色器变体
  4. 04测量全屏效果成本和预热情况

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/scenario-labs/skills --skill scenario-unity-shaders

安装后在 Claude Code 中输入/scenario-unity-shaders确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
critique.md
expert-notes.md
gui-paths.md
procedures.md
sources.md
scripts/
ut_shaders.py
scripts/AgentKit/Shaders/
ComputeJobs.cs
GpuCostJobs.cs
PsoJobs.cs
RendererFeatureJobs.cs
ShaderGraphJobs.cs
ShaderJobs.cs
ShaderLab.cs
VariantJobs.cs
scripts/Runtime/
AgentFullscreenFeature.cs
AgentPsoProbe.cs
scripts/Shaders/
AgentCompute.compute
AgentCustomLighting.hlsl
AgentDissolve.shader
AgentEdgeOutline.shader
AgentGrayscale.shader
AgentLit.shader
AgentNoise.hlsl
AgentPasses.hlsl
AgentToon.shader
AgentWater.shader

详细介绍

Unity 着色器(技术美术、着色)

在 Unity 6.3 中,专业着色效果必须经得起验证:能为目标图形 API 编译、所有通道结果一致、剥离后统计变体数量、展示首次使用时的预热效果、以 GPU 毫秒为单位测量开销,并通过带数值的捕获画面检查外观。没有鼠标的 Agent 要通过文本实现这些目标:手写 URP HLSL 是主要路径;Shader Graph 则通过现有图表和公开属性驱动,并在 Custom Function 节点后使用由 Agent 编写的 .hlsl;新建图表连线需要 GUI 操作(references/gui-paths.md)。目标环境:6000.3.21f1、URP 17.3、Shader Graph 17.3、Apple Silicon 上的 Metal。如果此处提到的同级技能不在可用技能中,请让用户安装(npx skills add scenario-labs/skills --skill <name>);若无人值守,请根据工具架构继续操作并标明这一缺口。

必需背景: scenario-unity-expert(通道、审查流程、6.3 陷阱)。其工具包(ut_env、ut_run、ut_review、AgentKit)仅导入,不复制。

状态(2026-09-24,盲评重构后): 此处所有流程均已在 Unity 6000.3.21f1 中运行:tests/code/unity-shaders/run_all.sh --live(73 项实时检查,包括开发播放器 PSO 验证、32 项离线检查,全部通过;证据见 archive/tests/unity-shaders/)。

立场(专家增量)

  1. 优先使用文本,图形按模板制作。 Shader Graph 没有循环,照明节点也几乎没有,因此灯光和循环都写在 HLSL 中(Daniel Ilett,F8bAI6dIrto [00:07:13]);它唯一的优势是能生成深度和阴影通道(bH--RU6qyTw [00:38:24]),而 AgentPasses.hlsl 也让手写着色器具备了这一能力。使用图形时,复制一个图形,设置其公开引用,并将变化逻辑放进 File 模式的 .hlsl 文件中。Graph Settings 会绑定每个通道:启用 Alpha Clipping 且不启用 Allow Material Override,会将 #define _ALPHATEST_ON 1 写入全部 8 个生成的通道,而且没有布尔关键字能将其移除(已观察已安装的 UniversalTarget.cs)。
  2. 每个通道都必须保持一致。 位移和 clip() 也会在 ShadowCaster、DepthOnly 和 DepthNormals 中运行(6.3 Manual;Ilett [00:37:52])。缺少 DepthOnly 通道会导致不透明着色器在 Depth Priming 下不可见(已观察)。DepthNormals 会写入原始世界空间法线:Manual 中的 normal * 0.5 + 0.5 示例在 SSAO 和轮廓线中读取结果有误(已观察)。
  3. 阅读已安装的渲染管线,而不是教程。 从已安装的 Lit.shader 复制关键字(Ilett [00:14:51];ut_shaders.urp_lit_keywords()):6.3 有 _CLUSTER_LIGHT_LOOP 和 4 个软阴影变体。LIGHT_LOOP_BEGIN 会跳过方向光,因此自定义循环在 Forward+ 下需要一个方向光预循环;Unity 自带的 Custom Lighting 示例缺少这一环节(已观察)。
  4. 变体预算要在剥离之后计算。 材质切换使用 shader_feature,仅运行时 C# 切换使用 multi_compile,dynamic_branch 要配合 if 测试,绝不能用 #if(6.3 Manual)。先启用 Strict Shader Variant Matching,再查看构建日志中的漏斗统计(Carotenuto,Unity 博客,2024 年)。只有构建中某个材质启用了 shader_feature(或 _local)变体,该变体才会随包发布(已观察到 0 与 6 的差异):绝不要在运行时 C# 中切换这类变体。Unity 6 Shader Build Settings 可以排除或重新设置没有代码的关键字类型,但对于用 #if 测试的关键字,dynamic_branch 覆盖设置会被静默忽略,URP 的软阴影和 SSAO 集也包括在内(已观察)。
  5. 证明首次使用时已完成预热。 在开发版播放器中,针对每种图形 API 和平台各采集一份 GraphicsStateCollection,在加载画面期间预热,并展示游戏帧中 Shader.CreateGPUProgram 采样数为 0、日志上传数为 0(6.3 Manual;已观察到 Metal 上从 14 降至 0)。
  6. 成本看 GPU 时间,而不是指令数。 循环按最大迭代次数计,float4 的成本约为 float 的 4 倍,超越函数会消耗很多周期(Ben Cloward,E82XxlXMJs4 [00:15:44])。此处测得:对 float4 执行 64 次 sin 的成本约为 float 的 3 倍,是乘加循环的 10 倍或更多。只有设备分析器显示受 ALU 限制时,half 才有优势(Freya Holmér,kfM-yu0iQBk [01:20:26]):桌面端 PlatformDefault 会将 half 编译为 float。
  7. Render Graph 结构。 RecordRenderGraph 只声明内容,不记录内容;先 blit 一次到新纹理,再设置 resourceData.cameraColor = destination;在 AddRenderPasses 中进行条件判断;拒绝使用后备缓冲区(6.3 文档;Unity 抖动示例,U8PygjYAF7A [00:09:06] [00:10:10])。
  8. 一个标量场,一个阈值,两种颜色;先观察,再测量。 卡通着色、水、溶解、轮廓线和抖动都会对 0..1 值进行阈值处理(视觉摘要);水的深度遮罩也能让岸边法线更平缓(gRq-IdShxpU [00:06:12])。让发光边缘与裁剪测试错开(Brackeys,taMp1g1pBeE [00:05:31])。将中间结果输出为颜色(Freya [01:57:25]),然后断言投影探针处的像素。

首先明确

  • 平台和图形 API:Metal、Vulkan、DX12、GLES 3.x、WebGL 2 或 WebGPU。计算功能运行于 Metal、Vulkan、DX11/12 和 GLES 3.1+(GLES 3.1 保证支持 4 个缓冲区),不支持 GLES 3.0 或 WebGL 2;Web 端通过 WebGPU 使用该功能(6.3 中为实验性功能)。GPU Resident Drawer 和 STP 完全不支持 GLES。
  • 各渲染器的渲染路径(Forward、Forward+、Deferred+):决定光照循环代码; Shader Graph 自定义光照仅适用于 Forward 和 Forward+。
  • 各质量级别的 URP 资源:Depth 和 Opaque Texture、软阴影、SSAO。模板中的 Mobile_RPAsset 默认关闭了 Depth Texture:渐隐水面需要开启此选项,或使用烘焙的岸边遮罩。
  • 风格和作者:卡通渲染或 PBR;由美术人员编辑图形(保留图形文件,由 Agent 维护 .hlsl), 或仅编写代码。
  • 每个对象的值:材质实例、MeshRenderer/SkinnedMeshRenderer.SetShaderUserValue (6.3,兼容 SRP Batcher),或 MaterialPropertyBlock(会破坏 SRP Batcher)。
  • 预算:效果的 GPU 毫秒数、每个着色器的变体数、过度绘制、首次使用时的卡顿。未明确说明时的默认值: URP 17.3 Forward+、模板中的 PC 和移动设备级别、HLSL,着色器位于 Assets/AgentShaders/。

工作流

  1. 安装并盘点。 ut_shaders.install(P);RendererFeatureJobs.ListFeatures(检查每个 质量级别、资源、渲染器和功能);lint_shader_file、shadergraph_summary(目标、属性、Graph Settings 检查结果)、 lint_project_keywords。GATE:计划中列出管线信息;列出 lint 错误。
  2. 编写。 从 scripts/Shaders/ 开始:AgentLit、AgentToon、 AgentWater、AgentDissolve、AgentEdgeOutline、AgentGrayscale、AgentCompute、共享文件 AgentPasses.hlsl(AGENT_CLIP/AGENT_DISPLACE)和 AgentNoise.hlsl。图形路线: ShaderGraphJobs.ImportPackageSample、DuplicateGraph、shadergraph_set_target_settings、 GeneratedCode、AgentCustomLighting.hlsl。GATE:lint 错误为零。
  3. 针对目标编译。 ShaderJobs.ValidateShaders(ShaderUtil.GetShaderMessages,并在 Metal 上对每个通道执行 CompileVariant)。GATE:错误为零,且四个不透明通道均存在。
  4. 进行基准测试并检查效果。 SetupMaterials、ShaderLab.BuildScene、ShaderLab.Shots(每次 启动进行多次拍摄:材质、渲染器、功能和 URP 更改;将探针投影到像素)。GATE:ut_review 标记无异常,已打开联系表,探针数值符合预期(阴影比开阔地面暗,溶解值为 1 时阴影消失,额外光源会改变受光侧)。
  5. 全屏效果。 使用 RendererFeatureJobs.AddFeature 和 AgentFullscreenFeature,或零代码的 FullScreenPassRendererFeature。GATE:开启和关闭时的捕获结果差异符合预期;无后备缓冲区错误。
  6. 变体。 VariantJobs.StrippingSettings(开启严格匹配)、针对发货材质执行 BuildShaderBundle、parse_variant_funnel、variant_budget_check、剥离规则或 KeywordOverrides(Shader Build Settings)、PostProcessingAudit(保留 Assets/ 下每个 VolumeProfile 的后处理变体)。 GATE:每个着色器的发货变体数量低于预算;记录器总数与 Unity 的“After scriptable stripping”一致; 覆盖项已清除,或已明确选择提交。
  7. 首次使用卡顿。 PsoJobs.BuildPsoScene、ut_run.build(development=True)、 ut_shaders.run_pso_player 追踪,分别执行冷启动和热启动;PsoJobs.InspectCollection;将 StreamingAssets/PSO/<platform>_<api>.graphicsstate 随产品一起发布,由 AgentPsoProbe 读取。GATE: pso_gate 无异常(冷启动按标记和日志均显示有上传,热启动则均不显示)。
  8. 成本。 使用 GpuCostJobs.MeasureFullscreenCost 执行 A/B 测试、交错测试,关闭异步编译 (半精度测试使用 precision_model)。GATE:耗时改善超过噪声范围;设备数据取自开发版播放器(scenario-unity-performance)。
  9. 交付。 着色器、材质、功能资源、每种 API 对应的 .graphicsstate,以及证据包(Handoffs)。

数值

数值对应情境来源
7,688 个完整变体;每个阶段 4,046 个;设置后 62 个;实际发布 13 个在 macOS AssetBundle 构建中,使用模板的 URP 资源时的 AgentKit/Lit实测
13 个降至 11 个在 Shader Build Settings 中排除软阴影组后,实际发布的 AgentLit 变体数量实测
433 个升至 577 个当 Assets/ 下有一个未使用的 Bloom HQ + dirt 配置文件时的 UberPost 变体数量实测
14 个降至 0 个;1.8 ms 升至 2.4 ms游戏过程中首次使用时 GPU 程序的上传次数,冷启动与预热后对比;macOS 播放器中一帧内预热 26 至 27 个 PSO实测
0.007 至 0.033 / 0.29 至 0.42 / 0.89 至 1.66 ms单次 1080p 全屏绘制:64 次乘加运算 / 64 次 sin / 64 次 float4 sin,M5 Max;在同一次运行中对比实测
0.92 至 1.00 / 0.77 至 0.89half4 与 float4 sin 耗时之比,PlatformDefault / Unified 精度模型,M5 Max(噪声约 10%)实测
超过 128 个关键字,预留 4 个每个着色器:编译速度会变慢6.3 手册
2000 / 2450 / 3000Geometry / AlphaTest / Transparent 队列Cyanilux
64x1x1、8x8x1计算着色器线程组;向上取整分块调度,并进行边界检查6.3 手册,[新增]
(1.2, 0.35, 0.03) 与 (4, 1.1, 0.15)HDR 溶解边缘在 Neutral 色调映射下保持橙色与褪成奶油色的对比实测
0.2126、0.7152、0.0722线性颜色上的 Rec. 709 亮度6.3 手册

质量门槛

  • 可测量: lint 和 lint_project_keywords 均无错误;目标 API 的 ValidateShaders 无错误;兼容 SRP Batcher(渲染后读取);探针(阴影亮度低于开放地面亮度的 0.75 倍;溶解阴影在 1 时恢复;Forward 和 Forward+ 中额外光源会改变受光侧;水面法线在岸边比深水处更平缓);功能开关前后的差异;实际发布的变体数在预算内且保持稳定;没有多余的 VolumeProfile;每个 API 的 pso_gate 均通过;GPU 毫秒数 A/B 对比;计算着色器 GPU 结果与 CPU 一致(最大误差低于 1e-5)。
  • 视觉: 已打开对照图集;卡通明暗色带清晰;水面色调变化、平静的岸边、泡沫、运动效果;溶解边缘保持色调;描边仅出现在轮廓上;没有洋红色。

常见错误

错误表现修复
没有 DepthOnly 通道强制使用 Depth Priming 时物体消失AgentDepthOnlyVertex/Fragment
只在前向通道中裁剪溶解后的物体仍投下完整阴影所有通道共用 AGENT_CLIP
DepthNormals 返回 n * 0.5 + 0.5SSAO 和轮廓错误返回原始法线
LIGHT_LOOP_BEGIN 前没有定向光预循环在 Forward+ 下,第二盏定向光无法照亮任何物体先循环 URP_FP_DIRECTIONAL_LIGHTS_COUNT
_FORWARD_PLUS、SHADOWS_SCREEN、ComputeScreenPos(自 URP 11 起已弃用)编译警告,阴影分支无效_CLUSTER_LIGHT_LOOP、GetMainLight(shadowCoord)、GetNormalizedScreenSpaceUV(positionCS)
通过运行时 C# 切换 shader_feature_local(溶解“命中时”)玩家版本中缺少变体:显示粉色或使用最接近的匹配项替换材质,或使用 multi_compile_local;lint_project_keywords
用布尔关键字跳过 Shader Graph Alpha Clipping所有通道中的整个物体始终进行 Alpha 测试允许材质覆盖(_ALPHATEST_ON 关键字)或使用第二个不透明材质
对通过 #if 测试的关键字使用 dynamic_branch 类型覆盖变体数量不变使用 if() 测试,不带阶段后缀声明关键字
在带有 _fragment 后缀的关键字上使用 if (KW)“已知关键字,但未在此通道中声明”为所有阶段声明该关键字
多余的 VolumeProfile 资源(示例、测试)为场景未使用的效果生成后处理变体将它们移出 Assets/;使用 PostProcessingAudit
每个 API 共用一个 PSO 集合,或没有经过验证的集合设备上首次使用时出现卡顿按 API 跟踪,对比冷启动与热启动运行
URP 资源上关闭了 Depth Texture水变成不透明泡沫;SSAO 仍请求深度时画面被隐藏在每个渲染它的 URP 资源上启用;关闭 SSAO 进行测试
某个 Renderer 缺少此功能某个质量级别下“效果不起作用”在各质量级别运行 ListFeatures
在渲染后注入没有绘制内容,出现后备缓冲区错误渲染后处理之后
HDR 边缘颜色为 4 或更高自发光边缘褪成乳白色设为 1 到 1.5,让 Bloom 承载辉光
根据指令数判断成本,或只在桌面端减半“优化过的”着色器速度并未提升使用 MeasureFullscreenCost;在设备上减半
属性位于 UnityPerMaterial 之外SRP Batcher 关闭,数值串扰在 HLSLINCLUDE 中使用一个 CBUFFER

交接

  • 接收:来自 scenario-unity-rendering-lighting:各质量级别的 URP 资源、渲染路径、Depth/Opaque Texture、后处理堆栈、色调映射、Default Volume Profile。来自 scenario-unity-vfx:粒子着色器需求(混合模式、软粒子、翻页书);scenario-unity-vfx 负责 VFX Graph、Particle System 和特效预算。来自 scenario-unity-world-building:水面和地形表面。来自 scenario-unity-architecture:驱动材质的游戏玩法代码。
  • 交付:向 scenario-unity-vfx 和 scenario-unity-world-building 提供着色器、附有说明文档的材质引用、功能资源。向 scenario-unity-performance 提供 GPU 毫秒数表、变体筛选漏斗、包含设备捕获冷/热证明的 .graphicsstate 文件。向 scenario-unity-pipeline-automation 提供变体预算和 CI 的 PSO 门禁。向 scenario-unity-mobile 和 scenario-unity-web 提供 API 限制(GLES 3.1 支持计算着色器,GLES 3.0 和 WebGL 2 均不支持)、需在设备上分析的半精度、移动端 Depth Texture 开销、平铺式 GPU 上的 Alpha 测试开销。
  • **资料包:**路径、ValidateShaders JSON、联系表、探针、筛选漏斗、PSO 运行记录、开销表、已验证和假设。

Unity 6.3 说明

  • 仅支持 Render Graph:已移除 Compatibility Mode(仅为移植保留 URP_COMPATIBILITY_MODE,并将在 6.4 中移除);AddBlitPass 返回一个 builder(returnBuilder: true);After Rendering 始终位于最终 blit 之后(6.2+)。
  • _CLUSTER_LIGHT_LOOP 取代 _FORWARD_PLUS(6.1);软阴影有 _LOW/_MEDIUM/_HIGH 变体;URP 的 Fog.hlsl 中,雾声明为 dynamic_branch。
  • Shader Build Settings:EditorGraphicsSettings.Get/SetShaderBuildSettings(当前生效的设置;构建配置文件可以覆盖)。GraphicsStateCollection 仍处于实验阶段;追踪需要开发版播放器;在 Metal 上,CreateGraphicsGraphicsPipelineImpl 不存在。Log Shader Compilation 会打印 Uploaded shader variant to the GPU driver: ...。
  • URP 会在每次构建前将所有覆盖项重新添加到 Default Volume Profile,因此大多数后处理变体族都会始终随构建发布。
  • SetShaderUserValue(uint) 存在于 MeshRenderer 和 SkinnedMeshRenderer 上,而非 Renderer 上;着色器读取 unity_RendererUserValue。
  • Shader Graph 17.3:模板、通过 Unlit 加 Keep Lighting Variants 实现自定义光照;反射 HLSL 节点需要 17.5,Preprocessor Directives 将在 6.6 中推出。WebGPU 从 6.6 起受支持;Built-in RP 从 6.5 起弃用。

参考资料

评论

支持 Markdown