做场景美术这些年每次听到“这棵树的树冠跟纸片似的”心里都咯噔一下。传统游戏植被的做法大家心知肚明树冠就是几张交叉的面片加Alpha Test贴图远远近近的LOD一级比一级“扁”最后几乎只能看到一个剪影。逆光的时候更惨整棵树冠黑乎乎一坨完全没有植物该有的透光感。这其实不是美术偷懒是旧管线的瓶颈几何密度、材质通道、渲染排序都被卡死了。这两年换了思路用SpeedTree 10搭配引擎里的Nanite管线重新做了一批植被资产总算把“纸片树冠”这个问题给治了。核心变化有三点树冠从“面片贴图”变成真正有厚度的多层叶片几何叶片在逆光下有了透射响应季相变化从“手工换贴图”升级成程序化驱动的变体重构。这篇就把整条工作流拆开讲适合正在搭UE5植被管线的环境美术和TA看也适合想搞懂Nanite植被到底该怎么落地的朋友。1. “纸片树冠”的病根裁剪面片、LOD塌陷和透射缺失1.1 传统树冠的三大“假”感来源先说第一个病根建模方式。之前做树冠最省事的方法是拿三五张交叉的十字面片糊成一个大球再用一张叶片裁切贴图把边缘抠出来。这种面片树冠看起来“有形状”但经不起看它没有厚度没有内部层次风一吹整个面片一起动叶片和叶片的层叠关系完全是贴图画出来的而不是几何堆出来的。光线打上去贴图之间的遮挡关系全是假的边缘还有裁切锯齿。这套做法在PS4时代是标准答案放到次世代镜头下就成了“纸片感”的头号来源。第二个病根是LOD策略。传统流程为了保证帧率通常把树冠LOD做得非常激进LOD0还有十几片叶子几何LOD1直接把叶片合并成整块树冠MeshLOD2干脆变成一个球体或八面体。结果就是镜头一拉远原本已经见底的植被细节直接归零只剩一个光秃秃的剪影。哪怕近景做得再好远景一塌玩家体感还是“假”。第三个病根才是核心——透射缺失。真实的树冠在逆光下不是全黑的。阳光透过叶片边缘会发生内部散射从背视角看过去树冠边缘是泛黄绿色的柔和光晕中间则因为层层叶片累积而变暗。而传统管线里叶片用的是Alpha Test或者纯半透明贴片Alpha Test只能保留不透明像素半透明又有排序问题根本没有“光穿过叶片”的概念。结果逆光环境直接翻车树冠变成一片死黑。这就从生理层面暴露了“假”。1.2 为什么透射是植被有生命感的分水岭你去看电影级植被参考不管是真实照片还是影视预演树冠的生命感都来自一层东西光在叶片内部的散射。植物叶片本身是半透光的叶绿素对可见光的透射有自己的光谱响应所以逆光树冠整体会呈现一种“透亮但不刺眼”的黄绿色。这在美术上是一个极强的生命信号。旧管线做这个效果最常用的招是给叶片加半透明材质但半透明做树冠是噩梦深度排序在多层叶簇里根本排不干净远处看一片噪点。后来有人用Subsurface Profile做假透射效果不错但本质上还是只在叶片表面做了一层“透光颜色”叶片之间没有几何厚度传导。真正解决问题需要在几何层让叶片是“薄片”而非“纸片”再在材质层用厚度信息驱动透射遮罩。这就是互联网上大家常说的“告别纸片树冠”的完整解法。1.3 两代流程的直观对比维度传统面片树冠SpeedTree 10 Nanite流程树冠几何交叉面片外层单层多层叶片簇几何自带厚度叶片形态裁切贴图抠轮廓双面叶片模型边缘有圆角过渡逆光表现死黑或硬半透噪点基于厚度通道的透射光晕LOD策略手动分级远景塌成球体Nanite按像素误差自动生成层级季相变化换贴图手工维护多套资产程序化季节参数驱动变体重构这套对比做下来你会发现“纸片感”其实是旧管线几何预算不足的产物。Nanite把几何预算的天花板抬高了几个数量级树冠终于可以“用几何说话”了。2. Nanite与植被的兼容底线先把约束摆上台面2.1 Nanite怎么处理几十万片小三角Nanite的核心思路是运行时把网格切成若干Cluster再根据每个Cluster在屏幕上占的像素误差决定降级到什么密度。理论上做得好的Nanite植被可以在近处给你几十万片叶子的全精度几何远处自动退化成大片轮廓完全不用手工摆LOD。但植被在Nanite里有个天生的麻烦叶片是极小三角形。一片叶子可能就十几个三角形在屏幕上可能只占几十个像素。如果像素误差阈值设得太大这些小三角形会直接从“Cluster精度的误差预算”中被吃掉导致叶片在远处成片消失甚至近景出现闪烁。所以Nanite植被不是“导入就完事”需要针对叶片尺寸单独调误差参数这个后面聊。2.2 材质通道与动画限制先接受约束Nanite这套管线的材质限制是绕不过去的它不支持像素级的半透明混合也不支持骨骼顶点权重驱动。这意味着传统的SpeedTree风动画靠骨骼或者顶点权重驱动树枝摆动没法直接套在Nanite网格上必须退回到“世界位置偏移”或者“顶点动画纹理”来做风。对于树冠这种松散的叶片结构WPO完全够用反而能避免骨骼动画在远处大量更新算是个意外的好处。材质侧Nanite只允许不透明和遮罩类材质Subsurface Profile这类特殊光照模型在基础管线里并不通用。单棵树要做的透射、季相、风这些信息不能靠挂半透明材质解决只能全部通过顶点色、贴图通道和材质参数的组合去“压缩”进去。一开始觉得憋屈做多了就习惯了限制反而逼你把所有数据在资产侧整理干净。2.3 哪些树进Nanite哪些留在传统管线不是所有植被都适合整套流程。我按下面的原则做了分类供参考植被类型是否Nanite原因大树干、粗枝是几何量大、轮廓硬朗Nanite优势明显树冠完整叶片簇是需要多层厚度与远景轮廓正是要解决的痛点地面小灌木可选看密度稀疏小草没必要藤蔓、软花、需要精确半透的植物否保留传统管线做半透与动态草和小花这种尺寸太小的植被进Nanite反而容易踩像素误差的坑性能上也不占便宜。我现在的做法是“大树重资产进Nanite地面轻资产保持传统”两者在法线贴图、顶点色通道上保持同一个规范这样材质可以尽量共用。3. SpeedTree 10里的Nanite友好型资产重构3.1 叶片几何从单面纸片到双面薄片进Nanite之前第一件事是改SpeedTree里的枝叶生成方式。旧习惯是叶子用单面Plane配合裁切贴图面数低但没厚度。SpeedTree 10里可以直接生成带挤出厚度的双面叶片几何叶片正面和背面都是实体面边缘一圈还有圆角过渡。别小看这一圈边缘它带来的体积感和裁切贴图完全不同光线照到叶片侧面会有高光风吹时叶片翻转也不会穿帮。叶片不要做太厚厚度控制在真实叶片毫米级比例但也不能薄到渲染出闪烁。我的经验是“能看出双面轮廓但不臃肿”即可如果贴图精度高厚度可以放得更薄靠法线贴图把细微起伏补上。SpeedTree的Leaf Mesh生成器里把双面开关打开再稍微调一下叶片的随机旋转和弯曲让叶簇有“一团”的堆积感而不是一张张摊开。3.2 顶点色通道的重新分配把数据塞进可用通道Nanite材质通道卡得很严SpeedTree默认的顶点色通道又是按它自己的逻辑来的AO、密度、风化这些导入引擎后能被材质的几个引脚直接读取。为了让透射、季相、风这些逻辑顺利跑起来我在SpeedTree里重新分配了顶点色通道导入后可以直接对应到材质节点顶点色通道用途说明Red叶片厚度场边缘薄、叶脉厚用于透射强度的反向驱动Green季节掩码0为春夏季1为秋冬季过渡用SmoothstepBlue遮罩 / 土壤渐变用于树干底部到冠部的苔藓混合Alpha风权重树冠外围风大、主干风小这个分配不是固定的但一定要在资产建模阶段就定好不然导入引擎再想办法就晚了。尤其是厚度场如果没有在SpeedTree里写进顶点色的Red通道后面所有透射逻辑都会变成无源之水。3.3 导出前的法线与三角面检查Nanite会在导入时自动按像素误差生成Cluster层级所以你只需要导出最高精度的LOD0不用再像以前那样手工做LOD1、LOD2。但导出前有几项检查必须做不然导入后问题很快会暴露第一法线要在叶片和叶柄衔接处做平滑。SpeedTree默认生成的叶片法线在边缘可能比较“跳”Nanite的运行时切线重建环境对法线连续性更敏感如果法线不连续远景会出现面片闪烁。第二树干的背面不能有反转法线导致的暗面缺口尤其是树枝分叉位置要检查背面有没有洞。第三UV不要有跨叶片的超长接缝Nanite虽然不关心UV密度但季相颜色贴图需要每个叶片能正确采样到自己的颜色位置UV接缝太散会影响季节变体贴图的上色。导出设置里记得把“允许Nanite”打开但在导出前先把SpeedTree的风采样/顶点动画相关属性清掉防止烘焙出来的顶点动画通道和Nanite的WPO冲突。我在这上面栽过一次跟头导进引擎后树冠直接抖得飞起查了半天才发现是烘焙的顶点色被顶了出去。4. 叶片的透射响应不是“半透明”而是“光的穿透”4.1 先理解叶片透射的光学逻辑树叶不是半透明塑料它透光不是因为“看得穿”而是因为光线进入叶片内部后在叶肉组织里发生了大量散射一部分光又从背面逸出。这跟你在帐篷里看到阳光透过帆布是同一个原理厚的部分光被吸收得多薄的部分光逸出得多。所以透射表现的核心变量不是“透明度”而是“厚度场”——这正是我们在SpeedTree顶点色Red通道里存的东西。在材质里透射强度可以近似的表达为透射亮度 背光系数 × 厚度场的反向值背光系数用光方向和表面法线的关系来算当光从树冠背后打来时叶片法线方向和光方向基本相反这时候背光系数接近1当光从正面打来时透射几乎为0。这个计算不用精确物理视觉上对了就行。4.2 把厚度场加工成透射遮罩从SpeedTree顶点色读出来的厚度值是一张“近肉色”的渐变场叶脉处厚边缘薄。但直接用这个值做透射会显得很脏需要在材质里做几步加工。第一步saturate(厚度)把范围锁到0-1。第二步用Pow做对比度拉伸通常指数取2到4让“边缘薄”的区域更突出中间厚区快速压暗。第三步乘上一张叶片透射颜色图在SpeedTree里导出叶子纹理的亮色版透射色通常比叶片正面的绿色更亮、更偏黄。第四步全部乘上背光系数。最终输出的透射光可以叠加到BaseColor或者自发光通道让树冠在逆光时泛出一层柔和的绿色光晕而不是原本的死黑剪影。4.3 一套可落地的材质节点链路这里不贴完整蓝图只讲节点思路因为每个项目的贴图命名和通道分配不一样但逻辑是通用的读取顶点色分离出厚度(Red)和季节遮蔽(Green)。厚度做反向加Pow得到ThicknessMask。用Dot(WorldNormal, Normalize(LightDirection))取反后做Saturate得到背光Mask。叶片透射颜色贴图乘背光Mask再乘ThicknessMask得到最终透射光。透射光做一个柔和的SoftMask加进自发光避免硬边。季节遮蔽在这个节点链里做一个Lerp把夏叶的透射色和秋叶的透射色切换过去实现不同季节的透光颜色差异。这套链路跑下来逆光下的树冠可以做到“边缘泛光、内部渐暗、亮部不过曝”基本上复现了真实叶片透射的体积感。需要提醒的是自发光会被Tonemapping和Bloom放大所以透射光强度不要拉太高做到“看起来亮了但还没刺眼”的程度一般就够了。4.4 实测调参的坑第一次调透射的时候我犯了个典型错误把透射强度拉满结果整个树冠在逆光下白花花一片像塑料灯罩彻底丢了叶片本身的绿色。后来把透射倍率压到0.2到0.4再配合饱和度控制才找到“透亮但不失绿”的平衡点。另外一个细节是透射颜色不要直接取叶片Diffuse贴图的绿色那样会让透射光和叶片本体混成一片没有层次。取一个偏黄的“内部散射色”也就是把Diffuse贴图在PhotoShop里整体往黄色偏移、提亮后的版本透射效果才像真的。5. 程序化季相重构一套资产长出四季5.1 季相的本质是变体管理不是贴图切换传统季相方案是同一棵树做三四套贴图和材质季节切换时整体替换。资产数量翻几倍还容易出现“同一棵树长了一年四季但体型完全没变”的违和感。SpeedTree 10的程序化季相思路不同它把叶片数量、叶片大小、颜色曲线、形态变化全部做成参数在导出前生成多个“季节变体”而不是改贴图。这些变体本质上是多套静态网格但它们的顶点色通道和UV布局完全一致所以引擎侧可以共用一套材质。切换季节时只需要切换网格资源和少量材质参数不需要为每个季节重做一整套材质链路。这套“几何变体 材质共用”的做法才是真正的程序化季相重构。5.2 秋色与落叶的几何化处理秋色不是简单把叶子调成红而是要让叶绿素分解的过程影响透射色、叶片密度和树冠轮廓。在SpeedTree里我把夏季变体和秋季变体做成两个独立的Leaf生成器秋季变体的叶片数量减少20%到30%叶子尺寸略缩颜色从绿色Lerp到黄红同时叶片厚度场稍微降低让秋日低角度的阳光更容易透过来。落叶效果的实现我用了一个取巧的几何方案把完整的夏季树冠和仅剩稀疏叶片/裸枝的冬季树冠叠在同一棵树上通过引擎里的季节参数驱动用World Position Offset把“不合时宜”的叶片按圆滑方式隐藏。具体做法是给叶片顶点色里写入“季节落点”值当季节参数越过阈值时让叶子向内收缩成一个点视觉上就像落叶掉光了。因为Nanite对WPO的支持在较新版本引擎里已经可用只要不在运行期大规模改变拓扑性能影响可接受。5.3 引擎侧的程序化驱动与错峰过渡引擎侧我维护了一个全局季节标量范围0到10代表盛夏1代表深冬。这个值再配合每棵树的随机相位偏移驱动材质里的季节遮蔽参数和网格资源的切换。错峰很关键如果整片森林同时从绿色跳到黄色玩家会觉得“出bug了”但每棵树偏移一点时间后整片林地就能自然呈现出渐变的季相过渡。实际项目里我把季节参数同时接到透射颜色、树叶密度、风强度三处透射颜色决定逆光时树冠是绿光还是金光树叶密度决定树冠轮廓的虚实风强度决定季相变化后的枝条摆动幅度。树干的苔藓和树皮颜色也可以通过顶点色Green通道做季节性混合冬天苔藓会“退下去”开春再冒出来。整个过程不用动基础资产只动材质和资源切换维护成本从“每季一套新树”降到“每季一组参数”。5.4 后续想做的事雪、湿度与风力协同这套季相工作流目前做到了夏、秋、冬的基础切换下一步我想把“雪”和“湿度”也挂进同一套季节标量里冬天积雪通过World Position Offset的Y轴偏移叠一层雪壳春雨后用材质参数增加树干表面的湿润高光。这些都能复用已有的顶点色通道不需要新增资产。最后分享一个小经验通读这整条工作流里性价比最高的投资是先在SpeedTree阶段把顶点色通道规范定死并且为你的主力树种做一棵“测试树”专门用来在逆光、顺光、拉远、拉近四种状态下反复验证透射和季相过渡。在这棵树上把所有参数摸顺了再往整片森林推广你会发现后续每一棵树都只是重复劳动而不是新的战斗。
阅读完成 · 觉得有帮助?