尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

UE5深度图与Mask图后处理实战:从原理到性能优化

发布时间:2026/9/19 5:54:39

资讯中心
01
ARTICLE

UE5深度图与Mask图后处理实战:从原理到性能优化

UE5深度图与Mask图后处理实战:从原理到性能优化
在UE5里做后处理效果绕不开两张图深度图和Mask图。前者记录每个像素到相机的距离后者标记哪些物体需要被特殊处理。听起来简单但真正上手之后你会发现深度图在移动端和PC端的精度差异、Mask图在透明材质上的失效、后处理材质里SceneTexture节点的采样时机问题每一个都能让你调半天。这篇内容面向已经能跑通UE5基础材质、想进一步做描边、景深、雾效、遮挡高亮这类效果的开发者我会把深度图和Mask图从获取到实际应用的完整链路拆开讲包括那些文档里不会写的参数陷阱和性能取舍。1. 深度图与Mask图到底在渲染管线里扮演什么角色1.1 从SceneTexture节点说起后处理材质的输入从哪来UE5的后处理材质本质上是一个全屏的Shader它在场景渲染完成之后、UI渲染之前执行。你在这个材质里能拿到的所有场景信息都通过SceneTexture节点获取。这个节点有一个Scene Texture Id参数里面列出了所有可用的输入SceneColor、SceneDepth、CustomDepth、CustomStencil、GBuffer系列等等。深度图对应的是SceneDepth它返回的是当前像素在场景中的深度值。注意这个深度值不是线性的世界空间距离而是经过投影变换后的非线性深度。在UE5的默认设置下SceneDepth输出的是以厘米为单位的距离值但这个值在近裁剪面附近精度极高在远裁剪面附近精度急剧下降。这就是为什么你用深度图做雾效时远处的过渡会显得很生硬——不是你的算法有问题是深度精度本身就不够了。Mask图在UE5里通常有两种实现方式一种是通过CustomDepth配合CustomStencil另一种是通过GBuffer里的CustomData通道。前者更常用因为CustomStencil可以存储0-255的整数值足够标记大多数场景中的不同物体类别。你只需要在需要标记的Actor上勾选Render CustomDepth Pass然后设置CustomDepth Stencil Value就能在后处理材质里通过SceneTexture:CustomStencil节点读取到这个值。1.2 深度图的精度陷阱为什么你的雾效在远处会断层UE5的深度缓冲默认使用D32_FLOAT格式也就是32位浮点深度。听起来精度很高但实际上深度值的分布是非线性的。在透视投影下深度值的精度集中在近裁剪面附近。举个例子如果近裁剪面是10cm远裁剪面是10000cm那么在前100cm的范围内深度精度可以达到毫米级但在5000cm到10000cm的范围内精度可能只有几十厘米。这个特性导致了一个常见问题当你用SceneDepth做线性雾效时远处的雾浓度会出现明显的阶梯状断层。解决办法是在后处理材质里手动做深度线性化。具体做法是先用SceneTexture:SceneDepth获取原始深度然后通过相机参数反算出线性深度。UE5提供了一个LinearEyeDepth节点但它需要你手动传入近裁剪面和远裁剪面的值。更稳妥的方式是使用CameraDepthFade节点它内部已经处理了线性化你只需要设置FadeDistance和FadeOffset两个参数。注意CameraDepthFade的FadeDistance参数单位是厘米不是米。很多人在这一步填了10以为是10米结果发现雾效只在相机前方10厘米内有效。1.3 Mask图的标记逻辑CustomStencil的0-255怎么分配CustomStencil是一个8位无符号整数取值范围是0-255。0是默认值表示没有被标记的物体。你可以把1-255分配给不同的物体类别。比如1表示敌人2表示可交互物品3表示任务目标4表示需要描边的物体。这里有一个容易忽略的细节CustomStencil的值是在每个Actor的Rendering设置里单独配置的。如果你有100个敌人你需要逐个设置它们的CustomDepth Stencil Value为1。手动做这件事很痛苦所以通常的做法是在Actor的Construction Script里根据Tag自动设置。比如给所有敌人Actor加一个Enemy标签然后在Construction Script里判断如果有这个标签就把CustomDepth Stencil Value设为1。另一个细节是CustomDepthPass的渲染顺序在Base Pass之后、Translucency之前。这意味着透明材质比如玻璃、水面默认不会写入CustomDepth。如果你需要对透明物体做Mask标记需要在材质里手动勾选Allow Custom Depth Writes并且确保材质的Blend Mode支持深度写入。2. 在材质编辑器里搭建深度与Mask的读取逻辑2.1 SceneTexture节点的参数配置与常见误用在材质编辑器里添加SceneTexture节点后你需要设置Scene Texture Id。对于深度图选择SceneDepth对于Mask图选择CustomStencil。这里有一个关键参数Post Process Input 0。这个参数决定了你读取的是哪个阶段的场景颜色。默认情况下后处理材质读取的是Post Process Input 0也就是场景渲染完成后的颜色缓冲。但如果你在材质里同时使用了SceneDepth和SceneColor需要注意它们的采样时机可能不一致。SceneDepth是在PrePass阶段写入的而SceneColor是在Base Pass之后写入的。这意味着如果你在同一个材质里同时采样这两个纹理可能会遇到深度值和颜色值不对齐的情况。解决办法是使用SceneTexture:PostProcessInput0来获取颜色同时用SceneTexture:SceneDepth获取深度并在材质里通过ScreenPosition节点确保两者的UV一致。另一个常见误用是在Translucent材质的后处理里直接采样SceneDepth。由于透明物体不写入深度缓冲你采样到的深度值可能是透明物体背后的不透明物体的深度。如果你需要对透明物体本身做深度相关的效果需要在透明材质的Material Attributes里启用Allow Custom Depth Writes然后通过CustomDepth而不是SceneDepth来获取深度。2.2 用CustomStencil做物体高亮的完整节点连线物体高亮是最常见的Mask图应用场景。基本思路是在后处理材质里采样CustomStencil判断当前像素的Stencil值是否等于目标值如果是就输出高亮颜色否则输出原始场景颜色。具体节点连线如下首先用SceneTexture:CustomStencil节点获取Stencil值然后用If节点判断是否等于目标值比如1。If节点的A输入接CustomStencil的输出B输入接一个Constant节点值设为1。If节点的A B输出接一个Lerp节点的Alpha输入。Lerp节点的A输入接SceneTexture:PostProcessInput0原始场景颜色B输入接高亮颜色比如纯红色。最后把Lerp的输出接到Emissive Color。这里有一个性能优化点If节点在Shader里会生成分支指令在移动端上分支指令的开销比较大。如果你的目标平台包括移动端建议用Step节点代替If。Step节点的逻辑是如果A B输出1否则输出0。你可以用Step(CustomStencil, 0.5)来判断Stencil是否大于0然后用这个结果去驱动Lerp。2.3 深度图与Mask图的混合使用遮挡高亮的实现遮挡高亮是指当敌人被墙壁挡住时在墙壁上显示敌人的轮廓。这个效果需要同时用到深度图和Mask图。基本思路是对于每个像素如果它的Stencil值不是敌人说明它是墙壁但它的深度值大于敌人所在位置的深度值说明敌人在这面墙壁后面就在这个像素上绘制敌人的轮廓。实现步骤稍微复杂一些。首先你需要两个后处理材质一个用于渲染敌人的Mask另一个用于最终的遮挡高亮。第一个材质把敌人的Stencil值写入一个RenderTarget同时记录敌人的深度值。第二个材质采样这个RenderTarget比较当前像素的深度和RenderTarget里记录的深度如果当前像素深度更大说明它在敌人前面需要绘制轮廓。在UE5里更简单的做法是使用CustomDepth而不是SceneDepth来做比较。因为CustomDepth只渲染被标记的物体它的深度值就是敌人的深度。你可以在后处理材质里同时采样SceneDepth和CustomDepth如果SceneDepth大于CustomDepth说明当前像素在敌人后面需要绘制轮廓。提示CustomDepth的精度和SceneDepth一样是非线性的。在做深度比较时建议先对两个深度值都做线性化否则在远距离处会出现误判。3. 高级应用从描边到体积雾的深度图实战3.1 基于深度的边缘检测描边Sobel算子的材质实现描边是深度图最经典的应用之一。基本思路是对当前像素的深度值和它周围像素的深度值做差分如果差分值超过阈值说明这个像素处于物体边缘需要绘制描边。在材质编辑器里实现Sobel算子需要采样周围8个像素的深度值。你可以用SceneTexture:SceneDepth节点配合ScreenPosition节点的偏移来采样。具体做法是先用ScreenPosition节点获取当前像素的UV然后分别加上(1,0)、(-1,0)、(0,1)、(0,-1)、(1,1)、(-1,-1)、(1,-1)、(-1,1)乘以一个偏移量比如1/屏幕分辨率得到8个周围像素的UV。然后用8个SceneTexture:SceneDepth节点分别采样这8个UV得到8个深度值。接下来计算Sobel梯度Gx (depth[2] 2*depth[4] depth[7]) - (depth[0] 2*depth[3] depth[5])Gy (depth[0] 2*depth[1] depth[2]) - (depth[5] 2*depth[6] depth[7])。最后计算梯度幅值G sqrt(Gx*Gx Gy*Gy)如果G大于阈值就输出描边颜色。这里有一个性能陷阱8次深度采样在移动端上开销很大。如果你的目标平台是移动端建议减少采样次数比如只采样上下左右4个像素用简单的差分代替Sobel算子。虽然边缘检测的精度会下降但性能会好很多。3.2 深度雾的体积感营造从线性雾到高度雾UE5自带的Exponential Height Fog已经能做出不错的高度雾效果但如果你想做更自定义的雾效比如带颜色渐变的体积雾就需要用深度图手动计算。基本思路是在后处理材质里用SceneDepth获取当前像素到相机的距离然后用这个距离去驱动一个Lerp节点在雾颜色和场景颜色之间插值。Lerp的Alpha输入可以用1 - exp(-density * distance)来计算其中density是雾的浓度distance是深度值。如果你想让雾有高度变化可以额外采样WorldPosition节点获取当前像素的世界坐标Z值然后用这个Z值去调制雾的浓度。比如density baseDensity * exp(-heightFalloff * (worldZ - fogHeight))。这样就能做出雾在低处浓、高处淡的效果。注意WorldPosition节点在后处理材质里返回的是当前像素对应的世界坐标但这个坐标是基于深度图反算出来的。如果深度图精度不够WorldPosition的Z值会有误差导致雾的高度过渡不自然。3.3 深度图在体积光中的应用Ray Marching的简化实现体积光God Rays是深度图的高级应用之一。传统的体积光需要Ray Marching也就是从相机出发沿着视线方向逐步采样计算每个采样点的光照贡献。在UE5里你可以用后处理材质做一个简化版的Ray Marching。具体做法是在后处理材质里用SceneDepth获取当前像素的深度值然后从相机位置出发沿着视线方向以固定步长前进每次前进都采样一次SceneDepth判断当前采样点是否在阴影中。如果在阴影中就累加光照贡献否则跳过。最后把累加的光照贡献叠加到场景颜色上。这个做法的性能开销取决于步长和步数。步长越小、步数越多效果越好但性能越差。在PC端上通常16-32步就能做出不错的效果在移动端上建议控制在8步以内。4. 性能优化与平台差异深度图和Mask图的实战避坑4.1 移动端与PC端的深度图精度差异移动端GPU比如Mali、Adreno的深度缓冲精度通常比PC端低。在PC端上D32_FLOAT是标配但在移动端上很多设备只支持D24_UNORM甚至D16_UNORM。这意味着在移动端上深度图的精度可能只有PC端的1/256甚至1/65536。这个差异导致了一个常见问题在PC端上跑得很好的深度雾效在移动端上会出现明显的断层。解决办法是在移动端上降低雾效的精度要求比如把线性雾改成指数雾或者把雾的浓度调低让断层不那么明显。另一个办法是使用CustomDepth代替SceneDepth。CustomDepth的精度通常比SceneDepth高因为它只渲染被标记的物体深度范围更小。但CustomDepth的缺点是它不包含未被标记的物体所以不能用于全场景的深度效果。4.2 后处理材质的性能开销哪些节点是性能杀手后处理材质的性能开销主要来自两个方面纹理采样次数和ALU指令数。纹理采样是最昂贵的操作每次SceneTexture采样都会增加开销。如果你在材质里采样了8次深度图比如Sobel算子那么每个像素就要做8次纹理采样。在1080p分辨率下这意味着每帧要做超过1600万次纹理采样。ALU指令数也很关键。If节点、Lerp节点、Sqrt节点都会增加ALU开销。在移动端上ALU指令数超过100就会明显影响性能。所以建议尽量用Step代替If用Mad代替Lerp用近似算法代替Sqrt。提示在UE5的材质编辑器里你可以用Stats面板查看当前材质的指令数。在Window菜单里打开Shader Complexity视图可以看到每个像素的Shader开销。4.3 深度图与Mask图的常见Bug排查清单在实际项目中深度图和Mask图相关的Bug通常有以下几类第一类是深度值不对齐。表现为后处理效果在屏幕边缘出现拉伸或偏移。原因是SceneDepth的UV和SceneColor的UV不一致。解决办法是使用ScreenPosition节点统一UV。第二类是Mask图失效。表现为设置了CustomStencil值但后处理材质里读不到。原因是Actor没有勾选Render CustomDepth Pass或者材质的Blend Mode不支持深度写入。解决办法是检查Actor的Rendering设置和材质的Material Attributes。第三类是性能骤降。表现为开启后处理效果后帧率从60降到30。原因是纹理采样次数过多或ALU指令数过高。解决办法是用Stats面板定位性能瓶颈减少采样次数或简化算法。第四类是移动端上效果异常。表现为PC端正常移动端上出现断层或闪烁。原因是移动端深度精度不足。解决办法是降低效果精度要求或者改用CustomDepth。5. 从项目实战中积累的深度图与Mask图使用心得5.1 什么时候该用CustomDepth什么时候该用SceneDepthCustomDepth和SceneDepth的选择取决于你的需求。如果你只需要对特定物体做效果比如描边、高亮用CustomDepth更合适因为它只渲染被标记的物体精度更高性能更好。如果你需要对全场景做效果比如雾效、景深用SceneDepth更合适因为它包含所有不透明物体。但有一个例外如果你需要对透明物体做效果SceneDepth和CustomDepth都不行因为透明物体不写入深度缓冲。这时候你需要用CustomStencil配合Allow Custom Depth Writes或者用GBuffer里的CustomData通道。5.2 深度图在后处理之外的用途从材质到Niagara深度图不仅可以用在后处理材质里还可以用在普通材质和Niagara粒子系统里。在普通材质里你可以用SceneDepth节点获取当前像素的深度然后根据深度值调整材质的颜色或透明度。比如做一个水面材质根据水深改变水的颜色。在Niagara里你可以用Depth模块获取粒子到相机的距离然后根据距离调整粒子的大小或透明度。这个功能在做体积雾或粒子光效时很有用。5.3 一个实际项目的完整配置流程从零搭建遮挡高亮系统最后分享一个我在实际项目中搭建遮挡高亮系统的完整流程。这个项目的需求是当敌人被墙壁挡住时在墙壁上显示敌人的红色轮廓。第一步给所有敌人Actor添加Enemy标签并在Construction Script里设置CustomDepth Stencil Value为1同时勾选Render CustomDepth Pass。第二步创建一个后处理材质命名为M_EnemyOcclusionHighlight。在材质里添加两个SceneTexture节点一个选择SceneDepth一个选择CustomDepth。再添加一个SceneTexture:CustomStencil节点。第三步用If节点判断CustomStencil是否等于1。如果是说明当前像素是敌人直接输出原始场景颜色。如果不是继续判断SceneDepth是否大于CustomDepth。如果是说明当前像素在敌人后面输出红色轮廓否则输出原始场景颜色。第四步把这个后处理材质添加到Post Process Volume的Post Process Materials数组里设置Blend Weight为1。第五步在移动端上测试。如果发现轮廓闪烁说明深度精度不够需要把SceneDepth和CustomDepth都做线性化或者改用CustomDepth的差值来判断遮挡关系。这个系统在PC端上跑得很稳在移动端上需要做一些精度妥协。实测下来把深度比较的阈值从0.1调到0.5可以消除大部分闪烁问题。5.4 深度图与Mask图的未来扩展方向深度图和Mask图的应用远不止描边和雾效。在UE5的Nanite和Lumen体系下深度图的获取方式可能会发生变化因为Nanite的虚拟几何体不写入传统的深度缓冲。目前UE5通过VisBuffer来存储Nanite的深度信息后处理材质里需要通过SceneTexture:SceneDepth的变体来获取。另一个方向是结合CustomStencil和GBuffer的CustomData通道做更复杂的物体分类。CustomData通道可以存储4个浮点值足够标记物体的材质类型、状态、阵营等信息。结合深度图可以实现更精细的后处理效果比如根据物体材质类型调整描边颜色或者根据物体状态调整高亮强度。我在实际项目里踩过的最大的坑是在移动端上用了D16_UNORM深度缓冲导致深度雾效在远处完全失效。后来改成指数雾并把雾的浓度调低了30%才勉强达到可接受的效果。所以如果你要做移动端项目建议在项目初期就确认目标设备的深度缓冲格式避免后期返工。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。