
1. 项目概述与核心价值VertexDirt v1.56这个在Unity社区里流传了快十年的老牌顶点烘焙工具至今仍然是我处理静态场景环境光遮蔽Ambient Occlusion, AO的首选方案之一。你可能听过很多次“顶点AO”也用过Unity自带的Lightmap烘焙但当你面对大量低多边形Low-Poly风格的资产或者需要在移动端追求极致性能、又不想完全牺牲场景立体感时VertexDirt的价值就凸显出来了。它干的活儿很简单把原本需要通过实时计算或光照贴图Lightmap来表现的环境遮蔽效果“烘焙”到模型的顶点颜色Vertex Color通道里。这样一来模型本身就携带了明暗信息运行时几乎零开销一个支持顶点颜色的Shader就能让模型立刻“站”起来细节层次感十足。为什么在有了实时光照、SSAO屏幕空间环境光遮蔽和成熟的光照烘焙管线后我们还需要它我经历过太多这样的场景一个开放世界手游项目场景里塞了成千上万的岩石、灌木、木箱。如果全用实时光照Draw Call和Overdraw直接爆炸如果用LightmapUV展开、烘焙时间、贴图内存都是噩梦而且低模物体在Lightmap上经常糊成一片细节全无。这时候给这些静态物件用VertexDirt快速烘焙一层顶点AO再配合一个简单的顶点颜色乘算Shader瞬间就能让它们摆脱“纸片感”牢牢地“粘”在地面上阴影 crevice缝隙和接触阴影Contact Shadow的效果虽然不如动态光照精确但足以骗过人眼性能开销微乎其微。v1.56作为其成熟版本修复了早期不少坑比如与Enlighten光照系统的冲突、构建时报错等稳定性已经相当可靠。接下来我就结合自己多年的使用经验带你彻底拆解这个工具从原理、实操到避坑让你能真正把它用起来。2. 核心原理顶点环境光遮蔽是如何“烙”进模型里的要玩转VertexDirt不能只停留在“点一下Bake按钮”得先明白它背后在算什么。这能帮你理解参数意义并在效果不对劲时快速定位问题。2.1 从屏幕空间到顶点空间AO计算的范式转换我们熟知的SSAO是屏幕后处理技术。它对屏幕深度图进行采样判断当前像素周围的像素是否被遮挡从而计算遮蔽因子。它的效果依赖于摄像机视角计算在像素层面。而VertexDirt的“顶点AO”是预处理和对象空间的。它的计算发生在烘焙阶段针对的是3D模型本身的顶点数据。算法核心是射线投射Ray Casting或者说半球采样。对于模型上的每一个顶点工具会模拟以该顶点的法线方向为轴在一个半球体内随机发射大量射线。如果一条射线在很短的行程内就击中了模型自身的其他三角面那么就认为这个顶点处于被遮挡的状态它的“遮蔽值”就增加。所有射线采样完毕后得到一个0到1之间的遮蔽因子0表示完全被遮蔽黑色1表示完全暴露白色这个值最终被写入该顶点对应的顶点颜色通道通常是R、G、B中的一个或全部用于灰度图。这样一来模型的几何结构所导致的自然阴影信息就被永久地“编码”进了顶点数据里。因为计算是基于模型自身的所以效果是视角无关的运行时也无需任何计算。2.2 顶点颜色作为数据载体轻量与兼容选择顶点颜色作为存储介质是VertexDirt设计上的巧妙之处。现代3D模型数据流中顶点颜色通常是一个可选通道包含R, G, B, A。在移动端或性能敏感的场景中使用顶点颜色比额外采样一张AO贴图要节省得多。它不占用额外的纹理采样指令不增加显存中的贴图内存数据随着顶点缓冲区一并传输。在Shader中调用也极其简单通常就是一句o.color v.color;或者在片元着色器里fixed4 albedo tex2D(_MainTex, i.uv) * i.vertexColor;。但这也带来了限制精度取决于顶点密度。一个大型的、顶点稀疏的平面烘焙出的AO可能会显得斑驳或不连续因为信息只在离散的顶点上有定义三角面内部是通过插值得到的。这就要求我们在建模或使用工具时对需要细节的区域如褶皱、缝隙保证足够的顶点数。2.3 VertexDirt v1.56 的算法特点根据官方历史讨论和我的实测v1.56版本的算法已经比较稳定。它并非简单的全局统一计算而是引入了两个关键参数来控制采样质量与范围这也是它比一些简单脚本工具更强大的地方采样角度Sampling Angle这个参数控制射线在法线半球体内的分布锥角。角度越小射线越集中朝向法线方向结果对比度越强主要捕捉深度的、正面的遮挡。角度越大射线分布越散能捕捉到更侧面、更微妙的遮挡关系细节更丰富但整体对比度会减弱显得更“灰”。你可以把它理解为“手电筒的聚光角度”。遮蔽距离Occlusion Distance这是射线检测的最大距离。它定义了“局部”的范围。一个顶点只会被在此距离内的其他三角面遮挡。值很小的时候只有非常紧密的几何结构如两个紧密贴合的方块之间的缝隙会产生遮蔽。值调大更大的结构比如屋檐对墙壁的影响也会被计算在内。这个参数需要根据你的模型尺度来调整太大可能导致不合理的全局变暗。理解这两个参数你就掌握了调节AO效果的钥匙。它们共同作用决定了最终顶点颜色图的对比度、细节层次和影响范围。3. 工具实战从安装到烘焙出完美顶点AO理论说再多不如上手操作一遍。我们假设你已经在Asset Store获取了VertexDirt v1.56并导入Unity项目。3.1 环境准备与界面初识导入后你通常在Window菜单下可以找到VertexDirt或类似的子菜单打开Ambient Occlusion Tool窗口。这个窗口界面保持了一贯的复古简约风格但这并不影响其功能强大。首先在Hierarchy中选中你想要烘焙的一个或多个网格物体MeshRenderer。确保这些物体是静态的或者你确定其几何结构在运行时不会改变。VertexDirt会直接修改网格的顶点颜色数据所以强烈建议先备份原始模型或者对复制出来的物体进行操作。窗口核心参数区Bake Button最大的按钮执行烘焙计算。Sampling Angle滑动条默认可能在30-90度之间根据版本略有不同。Occlusion Distance滑动条或数值输入框需要根据场景单位调整。Color Channel选择将AO信息写入顶点颜色的哪个通道R, G, B, A。通常选R通道因为灰度信息一个通道就够了这样可以留出其他通道做别的用途比如顶点着色、湿度图等。Invert反转结果将遮蔽区变亮暴露区变暗。某些特定艺术风格可能会用到。Presets可能有一些预设按钮如“Strong AO”、“Soft AO”快速应用一组参数。3.2 参数调节心法与实操步骤现在让我们一步步调出理想的AO效果。我以一个经典的“低多边形岩石”和“木箱堆叠”场景为例。步骤一设置合理的Occlusion Distance这是第一步也是最重要的一步。你需要根据场景中物体的相对尺寸来设定。在Scene视图中粗略测量一下你希望产生遮蔽效果的典型距离。比如木箱的箱板厚度大约是0.1米两个箱子紧贴时缝隙大约0.01米。初始值可以设为一个稍大于典型特征尺度的值。比如对于箱子我可能从0.2米开始。点击Bake快速预览。观察箱子木板之间的缝隙、箱角与地面接触部分是否产生了暗色。如果完全没有逐步增大距离比如到0.5米、1米。如果整个箱子都变得很暗失去了明暗变化说明距离太大需要调小。注意这个参数是场景单位敏感的。如果你的模型是从一个单位系统如厘米制的3ds Max导入到Unity默认米制而未经正确缩放可能会导致距离参数感知失常。确保你的模型在Unity中的缩放Scale是合理的比如一个角色身高约2个单位。步骤二用Sampling Angle控制对比度与细节当遮蔽距离大致正确后AO的“味道”由采样角度决定。想要强烈的、戏剧性的阴影使用较小的采样角度如30-45度。这会使射线更集中只有正法线方向的严重遮挡才会被记录结果黑白分明。适合风格化、卡通渲染或需要突出结构感的场景。想要柔和的、自然的、细节丰富的阴影使用较大的采样角度如75-90度甚至更大。射线向四周扩散能捕捉到更微妙的曲面变化和侧向遮挡结果灰度层次多对比度低更接近全局光照的柔和阴影。适合写实风格的场景。我的常用策略是先调到中间值如60度烘焙一次看效果。如果觉得缝隙够暗了但岩石曲面本身缺乏体积感就调大角度。如果觉得整体太“粉”、太“灰”缺乏力度就调小角度。步骤三烘焙与查看调节好参数后点击Bake。烘焙速度取决于模型顶点数和采样精度内部采样数通常是固定的。对于顶点数在几千到一两万的常见道具几乎是瞬间完成。烘焙后模型在Scene视图中可能看起来没什么变化这是因为默认的Standard Shader不显示顶点颜色。你需要一个支持顶点颜色的Shader来查看效果。步骤四应用顶点颜色ShaderVertexDirt包内通常会附带几个示例Shader。如果没有自己写一个也极其简单创建一个新的Unlit Shader或修改Standard Shader。在顶点着色器输出结构体v2f中添加float4 color : COLOR;语义。在顶点着色器中o.color v.color;将顶点颜色从应用阶段传递到片元。在片元着色器中将顶点颜色与主纹理颜色相乘fixed4 finalColor tex2D(_MainTex, i.uv) * i.color;。将此Shader赋给烘焙好的材质。现在你应该能在Scene和Game视图中看到模型的凹陷处、接触面变成了暗色整体立体感大幅增强。3.3 批量处理与工作流整合对于场景美术师来说一个一个物体烘焙是不可接受的。VertexDirt通常支持批量选择。你可以框选场景中所有需要相同AO参数的静态物件比如所有的岩石、所有的木桶一次性烘焙。但要注意如果物体大小差异悬殊可能需要分组进行并为不同尺度的物体组设置不同的Occlusion Distance。一个高效的工作流是资产准备阶段在DCC工具如Blender, Maya中完成建模和UV。导入Unity设置好材质和纹理。顶点AO烘焙根据资产类型小型道具、大型建筑、植被分组应用不同的VertexDirt预设。生成Prefab将烘焙好顶点颜色的模型做成Prefab。这里有一个至关重要的步骤VertexDirt修改的是MeshFilter上的Mesh数据。为了不污染原始模型文件你应该在烘焙后右键MeshFilter组件中的Mesh选择“Create Prefab”。这样会生成一个该网格的实例化副本所有修改仅保存在这个副本和Prefab中。这是保证原始资产干净、可复用的关键。场景布置使用这些带有顶点AO信息的Prefab来搭建场景。4. 深入解析参数背后的物理意义与艺术控制掌握了基本操作我们再来深挖一下参数让你从“会用”变成“精通”。4.1 Occlusion Distance定义空间的“局部性”这个参数本质上是在定义环境遮蔽的“有效半径”。在真实的物理世界中环境光来自整个半球天空遮挡可以来自无限远。但在实时渲染和风格化表现中我们往往需要控制这个范围。小距离如0.1-0.3模拟的是接触阴影Contact Shadow和缝隙阴影Crease Shadow。它只关心几何体自身非常局部的、紧密的交互。例如衣服的褶皱、砖块之间的灰浆、字母的雕刻凹陷。这种AO非常“干净”只强化最核心的轮廓不会让物体整体变脏。中等距离如0.5-2.0模拟中小型物体在局部环境下的遮蔽。例如房间内的家具之间、机器上的零件相互遮挡、树冠下的树干。这是最常用的范围能有效增强物体的体积感和在场景中的“扎根”感。大距离如5.0以上模拟大型结构或封闭空间的遮蔽。例如在峡谷中的角色、深井的底部。使用大距离要非常小心因为它很容易导致物体整体亮度不均看起来像是被“全局染色”而非自然阴影。通常需要配合较小的Sampling Angle来保持阴影的指向性。一个高级技巧是分层烘焙。对于复杂模型你可以烘焙两次第一次用很小距离捕捉尖锐缝隙写入顶点颜色的R通道第二次用中等距离捕捉整体体积写入G通道。然后在自定义Shader中混合这两个通道获得层次极其丰富的AO效果。4.2 Sampling Angle控制光线的“硬度”这个参数艺术化的成分更重它控制着遮蔽过渡的软硬程度。小角度硬阴影产生的AO边缘锐利明暗交界线清晰。这类似于直射阳光下的阴影。在风格化渲染中硬朗的AO能极大地强化图形的感觉让模型看起来像剪纸或积木轮廓分明。大角度软阴影产生的AO过渡平滑从暗到亮是渐变的。这类似于阴天或大面积漫反射光源下的阴影。写实渲染追求这种柔和感因为它更接近真实的物理光照行为能更好地表现曲面的连续变化。我发现一个规律对于硬表面Hard Surface模型如机械、建筑使用较小角度45-60度往往效果更好能突出其块面结构。对于有机体Organic模型如角色、岩石、树木使用较大角度70-85度更能体现其柔和的曲面体积。4.3 与其他光照技术的协同顶点AO不是银弹它需要与其他光照技术配合。与实时光照共存这是最常见的用法。顶点AO作为基底乘算在漫反射颜色上。实时光照方向光、点光在此基础上进行计算。这样即使在没有动态阴影或阴影质量较低的情况下物体也有基本的立体感。与光照贴图Lightmap共存这是需要特别注意的地方也是早期版本Bug的多发区。Lightmap本身已经包含了间接光照的AO信息。如果两者叠加会导致双倍变暗。通常有两种策略替代方案对性能要求极高、或物体太小导致Lightmap分辨率不足的物件直接用顶点AO替代Lightmap的间接光AO贡献。在烘焙Lightmap时可以适当降低或关闭间接光的质量。补充方案将顶点AO作为Lightmap的补充用于增强Lightmap未能很好表现的接触阴影和高频细节。这时需要将顶点AO的强度通过Shader中的一个乘数_VertexAOScale调得很低如0.3-0.5使其柔和地叠加在Lightmap结果之上。与SSAO/SSGI的关系它们是互补的。顶点AO是对象空间的、静态的、高精度的在顶点密度足够的地方。SSAO是屏幕空间的、动态的、受视角和深度图精度影响的。在移动端可能只使用顶点AO。在PC端可以同时开启顶点AO负责物体自身的细节SSAO负责处理物体之间的动态交互遮蔽效果更佳。5. 实战疑难杂症与解决方案实录用了这么多年VertexDirt踩过的坑数不胜数。下面这些是我和同事们用血泪换来的经验很多在官方文档里是找不到的。5.1 烘焙后模型在构建版本中显示异常这是最经典的问题在官方论坛的讨论中也高频出现。具体表现为在Editor里一切正常打包成PC、Android或iOS应用后模型变黑、变紫或网格错乱。问题根源Unity在构建项目时会对资源进行优化和重组。VertexDirt在Editor中运行时是直接修改了当前场景中MeshFilter引用的Mesh数据。如果这个Mesh是直接引用自原始模型文件如.fbx并且你没有将其创建为实例化副本那么构建时Unity可能会使用原始未修改的Mesh文件导致顶点颜色数据丢失。更复杂的情况是如果物体启用了静态合批Static Batching多个网格会被合并其顶点数据格式可能发生变化导致自定义的顶点颜色通道在Shader中无法正确读取。解决方案必须实例化Mesh烘焙完成后在Project视图中找到该模型导入的Mesh文件。不要直接修改它。正确做法是在Hierarchy中选中烘焙好的物体在MeshFilter组件上点击Mesh字段旁边的小圆圈在弹出的选择窗口中点击右下角的“Create New”来创建一个该Mesh的实例副本。所有修改都应在这个副本上进行。然后将这个物体保存为Prefab。检查Static Batching对于需要烘焙顶点AO的静态物体如果它们被标记为Static并参与了静态合批可能会出问题。尝试在Player Settings中关闭静态合批或者将这些物体从静态合批中排除取消Static标记或使用不同的Layer。一个更稳妥的办法是对于大量使用顶点AO的小物件使用动态合批Dynamic Batching或GPU Instancing来渲染而非静态合批。Shader兼容性确保你用于最终发布的Shader在移动端或目标平台上是兼容的并且正确声明和使用了顶点颜色语义COLOR。有些为了性能高度优化的移动端Shader可能会裁剪掉顶点颜色输入。5.2 烘焙结果全灰或全白没有变化这个问题通常让新手困惑。你点了Bake进度条一闪而过模型却没有任何明暗变化。排查步骤检查Occlusion Distance是否过小这是最常见的原因。如果你的模型尺寸很大比如一个高度为100单位的建筑而Occlusion Distance设置为默认的1.0那么射线可能根本碰不到任何其他三角面。尝试将这个值调到模型尺寸的10%-20%看看。先用一个夸张的大值如50测试如果出现效果再逐步调小。检查模型法线顶点AO计算严重依赖顶点法线。如果模型法线混乱、翻转或未平滑会导致采样射线方向错误结果不可预测。在建模软件中确保法线正确在Unity导入设置中检查“Normals”选项是“Import”还是“Calculate”。检查模型是否自相交或存在零面积面片极端扭曲或自相交的几何体可能导致射线检测失败。清理模型删除不必要的顶点确保网格是“干净”的。查看正确的顶点颜色通道你可能把AO烘焙到了R通道但Shader里却在读取G或B通道。在VertexDirt工具窗口和你的Shader中确认使用的通道一致。5.3 性能考量与最佳实践虽然顶点AO运行时开销极低但烘焙过程和大规模使用仍需注意。顶点数影响烘焙速度烘焙算法复杂度与顶点数成正比。对于超高清模型数百万顶点烘焙可能会卡住编辑器。对于这类模型建议先在建模软件中用更专业的烘焙工具如xNormal, Marmoset Toolbag烘焙出AO贴图这通常比顶点烘焙质量更高、控制更精细。VertexDirt更适合中低面数模型。Prefab化与资源管理如前所述一定要将烘焙后的Mesh创建实例并制作成Prefab。这有利于版本管理、场景迁移和团队协作。一个清晰的资源目录结构是Assets/Art/Models/Raw/存放原始FBXAssets/Art/Models/Processed/存放带有顶点AO的Mesh实例和Prefab。Shader的灵活控制不要在Shader里写死i.vertexColor的乘法。应该暴露一个强度参数_AOPower范围0-2让美术或场景师可以在材质面板微调AO的强弱以适应不同光照环境。公式可以是albedo * lerp(1.0, i.vertexColor.r, _AOPower);。与光照探头的配合在动态物体上顶点AO是静态的无法响应环境变化。但对于一个在静态场景中移动的角色其身上的顶点AO是固定的。为了更好的融合可以让角色Shader同时接收光照探头Light Probes信息顶点AO则作为其自身材质的基底细节。VertexDirt v1.56作为一个历经时间考验的工具其核心价值在于它的“直接”与“高效”。它绕开了复杂的贴图管线将关键的视觉信息压缩到顶点数据中以一种近乎“黑客”般的巧妙方式在性能与质量之间找到了一个美妙的平衡点。对于独立开发者、移动端项目或任何需要在资源限制下提升视觉质量的团队来说深入理解并掌握它无疑是工具箱里一件不可或缺的利器。它的效果可能不如高精度的贴图烘焙或实时光追但它的性价比在特定的项目语境下是无与伦比的。