☰
虚幻引擎毛玻璃材质:模糊、法线扰动与光照三层实战
2026/10/27 3:47:26 网站建设 项目流程

毛玻璃这个效果,几乎每个做过室内场景或者UI面板的人都绕不开它。我最早的做法很朴素,就是把材质改成Translucent,勾上Refraction,调个IOR,然后安慰自己"这就是玻璃了"。结果实机跑起来一看,背景被拉扯了一下,但表面干干净净,一点磨砂的颗粒感都没有,近看就像一块被压扁的塑料片。后来才明白,带法线效果的毛玻璃不是"一个参数"的事,它是模糊层、扰动层、光照层三条完全不同的技术路径叠出来的结果,缺一层就露怯。这篇内容就是把我这几年在虚幻引擎里反复折腾这套材质的过程拆开讲,从为什么这么做、每层怎么搭、到实际项目里那些让人半夜爬起来改参数的坑。适合已经会连基础材质节点、但做出来的玻璃总"差点意思"的同行。看之前先记住一点:磨砂的质感来自"高频扰动 + 低频模糊",这两件事在引擎里是两套完全不同的机制,混在一起调只会越调越乱。

1. 毛玻璃在虚幻里其实是三层叠加,不是一层模糊

很多人搜"毛玻璃材质",找到的教程都是三步走:改混合模式、连个法线、调IOR。照着做完确实能出效果,但一旦换场景、换光照、换视角,效果就崩了。原因在于大家把这三步当成"步骤",而没当成"三层"。它们各自负责完全不同的视觉信息,参数之间还会互相打架。这一节先把这三层的职责边界划清楚,后面每一层再单独深挖。

1.1 拆解:模糊层、扰动层、光照层各管什么

模糊层负责的是"背景被柔化"这件事。它采样的是当前帧已经渲染好的场景颜色,用一个扩散核把周围像素平均进来。这一层的输入是屏幕空间UV,输出是一块变糊的背景。它跟法线毫无关系,哪怕你把法线关掉,模糊照样存在。

扰动层才是标题里"带法线效果"的核心。它拿一张法线贴图,把每个像素的法线方向偏转一点,然后让这个偏转去影响折射的采样方向或者屏幕UV的采样偏移。它产生的是那种"隔着毛玻璃看灯,光斑碎成一片一片"的颗粒感。注意,扰动层本身不产生模糊,它产生的是方向性的错位。

光照层决定的是这块玻璃表面本身怎么被点亮——高光形状、环境反射的内容、边缘的菲涅尔衰减。这一层如果选错光照模式,前两层做得再细,玻璃也会像贴纸。

我一般建议在材质里用三个独立的参数组去控制它们,别揉成一坨。你会发现在调的时候,往往需要"模糊很重但扰动很轻"(比如浴室玻璃门),或者"扰动很重但模糊很轻"(比如冰面),这两个维度必须能独立滑。

1.2 为什么只调 Refraction 做不出磨砂感

这是新手最容易卡住的地方。虚幻引擎的半透明材质里有两种折射模式:一种走折射率(IOR),一种走像素法线偏移(Pixel Normal Offset)。很多人一看"像素法线偏移"这个名字,觉得这就是给法线用的,直接连上法线贴图,结果发现背景是扭曲了,但扭曲得非常"整体"——像隔着水波看东西,不是磨砂。

根源在于:折射通道改变的只是采样方向,它不会增加采样次数。它把背景上某一个点的颜色搬到另一个位置,但每个像素仍然只取一次颜色。磨砂玻璃的视觉本质是"一个像素混合了背景中一整个小区域的信息",这需要多次采样,折射通道天然做不到。

所以正确的认知是:折射(或者说像素法线偏移)是扰动层的执行机构,但它只能提供"错位",提供不了"平均"。平均这件事必须靠额外采样SceneColor来做。我见过不少人把法线贴图的Tiling拉到几十倍,想靠高频扭曲模拟磨砂,结果只是让背景糊成一团彩色噪点,像信号不好的电视。

记住一句话:折射负责"往哪看",多采样负责"看多少"。两者缺一不可。

1.3 半透明光照模式的选择直接决定观感上限

材质细节面板里那个"半透明光照模式"(Translucency Lighting Mode)选项,存在感极低,但它决定了这块玻璃能不能接住环境光。

默认的体积模式(Volumetric)性能最好,但它对半透明物体的光照是近似的,高光会显得很"平",反射内容基本靠反射捕获,动态物体映不上去。表面前向着色(Surface ForwardShading)模式会为每个半透明像素跑一遍完整的光照计算,高光和反射质量明显更好,代价是像素开销翻倍——大面积玻璃幕墙用这个模式,帧率会掉得很明显。

还有一个表面体积模式,介于两者之间,适合那种"面积大但不需要精细高光"的场景,比如远景的楼宇窗玻璃。

我的经验是:近距离、玩家会盯着看的玻璃(比如手里拿的瓶子、面前的隔断)用前向着色;远景、大面积、只作为氛围的玻璃用体积模式。这个选择要在材质实例层面分两套,别用一个母材质硬扛所有场景。

2. 模糊层:SceneColor 多采样方案的取舍与实测

模糊层是整个材质里最耗性能的部分。虚幻引擎的材质编辑器不像后处理那样可以自由地做多趟渲染,你没法在半透明材质里"先降采样再升采样"。所有的模糊都得在一个着色器、一趟绘制里完成,这意味着采样次数直接等于指令数。这一节把我试过的几种方案摊开对比。

2.1 从 13 点泊松盘说起:采样数与噪点的关系

最直接的做法是用泊松盘分布取若干个点,每个点采一次SceneColor,然后平均。13个点是业内的一个常见甜点——再少噪点压不住,再多指令数顶不住。

具体操作是在材质里多次使用场景纹理节点(Scene Texture,ID选PostProcessInput0),每次给它一个不同的UV偏移。偏移量由两组向量控制:一组是分布的方向(固定的13个归一化方向),一组是分布的半径(一个标量参数,控制模糊范围)。最终UV偏移 = 方向 × 半径 × 屏幕宽高比的修正系数。

这里有个容易忽略的细节:屏幕UV是0到1的归一化坐标,X和Y方向的物理像素密度不一样。如果你的偏移直接写成(dirX, dirY) * radius,在16:9的屏幕上模糊会变成椭圆。必须乘一个(1, ScreenWidth/ScreenHeight)的修正,或者反过来,取决于你想要圆形的模糊还是各向异性的。

实测下来,13点方案在1080p、模糊半径0.01(归一化UV)时,能出比较干净的柔化。半径超过0.02之后,13个点之间的间隙就肉眼可见了,会出现"星芒"状的采样痕迹,这时候要么加到21点或29点,要么靠下一节说的抖动来救。

2.2 Mip 采样方案为什么在材质里行不通

有人会想,SceneColor肯定有Mip链,直接采样高Mip不就自动模糊了吗?思路很对,但在半透明材质的上下文里,这条路基本走不通。

原因有几个层面。第一,场景纹理节点在材质里的采样并不支持你指定LOD,那个LOD输入对PostProcessInput0这种虚拟纹理是无效的。第二,即便某些版本能通过自定义节点强行指定,拿到的Mip内容也未必是你要的——场景颜色缓冲的Mip链在渲染管线里的生成时机、降采样方式都跟"高斯模糊"不是一回事,容易出现块状伪影。

我确实见过用自定义节点调底层采样函数的写法,在本机跑出过效果,但换一个引擎小版本就失效,而且不同渲染路径下行为不一致。这种方案在演示里可以秀,进了项目就是定时炸弹。要做产品,老老实实多采样。

2.3 抖动 + TAA 累积能压多少噪点

如果采样数实在压不下来(比如移动端或者VR),有个取巧的办法:让每个像素的采样分布随机旋转一个角度,旋转量由一个屏幕空间噪声图提供,然后靠时间抗锯齿(TAA)在多帧之间累积,把噪点抹平。

这个技巧的本质是"用时间换空间"。单帧看是有噪点的,但连续几帧平均下来就干净了。实操上,把13个采样方向整体乘一个由噪声图产生的旋转矩阵,噪声图用屏幕UV采样,缩放可以给大一点让它每帧变化。

效果能压到什么程度?在我的测试里,13点加抖动,观感接近29点静态分布,指令数只多了大约十来个(旋转矩阵的计算),性价比很高。

代价也很明确:快速运动的镜头会拖影。因为TAA累积依赖前后帧的像素对应关系,一旦相机或物体快速位移,噪点就会变成糊状的拖尾。如果你的场景里有大量手持镜头或者快速转场,这个方案要慎重。另外,半透明物体在TAA里的处理本来就有历史包袱,别指望它能像不透明表面那样稳定。

2.4 采样越界的边缘修补

这个问题特别隐蔽。玻璃物体在屏幕上占据一块区域,你往外偏移UV采样的时候,很容易采到物体轮廓之外的像素。结果就是玻璃边缘出现一圈"吸"了背景颜色的光晕,看起来像描边没描干净。

修法有几种,我按推荐程度排:

最省事的是用深度衰减。在材质里算当前像素和背景场景深度的差值,边缘处差值小,就把扰动强度和模糊半径按差值做一个衰减。这样玻璃靠近轮廓的地方自动收敛回"不偏移",光晕就没了。虚幻引擎自带的深度渐变节点(Depth Fade)能直接给出这个衰减因子,虽然它的本意是做软边,但拿来做边缘收敛意外地顺手。

第二种是屏幕空间裁剪。把UV偏移后的坐标夹到0到1之间,或者干脆在偏移量过大时把偏移量按比例缩回来。这个方案简单粗暴,但对薄片状物体效果一般。

第三种是菲涅尔调制。玻璃边缘因为视角关系菲涅尔值高,本来就更不透明、反射更强,正好可以借这个因子把扰动关掉。物理上也说得通——边缘处光线穿过玻璃的路径短,本来就该更"清"。

我一般三个一起用:菲涅尔管整体的强弱分布,深度衰减管轮廓,屏幕裁剪做兜底。三层保险下来,边缘基本不会出问题。

3. 扰动层:把法线贴图真正"喂"进折射里

扰动层是这篇标题的主角,也是调参最容易失控的地方。很多人以为"连上法线贴图就完事了",实际上从贴图选型到强度映射,每一步都有讲究。这一节从数学关系讲到美术手感。

3.1 从法线到屏幕 UV 偏移的换算

先说清楚原理。法线贴图里存的是切线空间下的法线方向,取值范围大致是-1到1,用RGB编码成0到1。你要用它来偏移屏幕UV,需要做几步转换。

第一步,从贴图取出法线,乘以2减1,还原成-1到1的向量分量。第二步,只取它的XY分量——因为屏幕空间偏移是二维的,Z分量在这里没有直接用处(但可以用来做强度调制,比如法线越"歪"扰动越强)。第三步,把XY分量乘上一个强度系数,再加到原始屏幕UV上。

这里的关键在强度系数的量纲。屏幕UV是0到1的范围,如果你的强度系数给0.1,意味着最大偏移达到屏幕宽度的10%,那是极其夸张的扭曲。实际可用的范围通常在0.001到0.01之间,非常小。很多教程不写这个,新手直接给0.5,看到满屏撕裂还以为节点连错了。

如果你想让手感更直觉,可以把强度参数定义成"像素单位",然后在材质里除以屏幕分辨率换算成UV偏移。这样美术调整的时候,"扰动5个像素"比"扰动0.0039"好理解得多。

3.2 法线贴图的 Tiling 与"颗粒感"设计

磨砂玻璃的颗粒感,本质是法线扰动的空间频率。Tiling给低了,看起来像水面波纹;给高了,会闪烁(走样)。

我的经验区间是这样的:

使用场景Tiling 参考说明
大面积隔断、浴室门2 到 4颗粒大、视觉柔和,适合远观
手持玻璃杯、小摆件8 到 16颗粒细密,近距离看有质感
冰面、磨砂亚克力4 到 8介于两者之间,可叠加两层不同Tiling
屏幕保护膜类20 以上需要配合各向异性处理,否则严重走样

Tiling之外,还要注意贴图本身的选择。专用的磨砂法线贴图(那种一看就是随机噪声的)效果最好;用砖墙、布料之类的法线贴图凑合,很容易看出规律性的重复图案。如果手头没有合适的,可以用两张不同Tiling的法线相乘或相加,破坏重复感。

还有一个进阶做法:让Tiling跟物体尺寸挂钩。用物体空间坐标或者世界坐标来采样,而不是纯UV,这样不同大小的玻璃上颗粒的物理尺寸是一致的。不然一个大玻璃墙和一个小杯子如果用同样的Tiling,颗粒大小会差出几十倍,特别违和。

3.3 强度参数要跟距离绑定,否则近看全是噪点

这是我在一个室内项目里踩过的坑。远景看,玻璃质感很好;玩家走近了,屏幕上全是密密麻麻的彩色噪点,像坏掉的显示器。

原因很简单:法线扰动的屏幕空间偏移量是固定的UV值,但同样大小的UV偏移,在远处对应的世界尺寸大,在近处对应的小。当物体占满屏幕时,0.005的UV偏移换算成像素可能是好几十个,采样点之间的间隙被放大,噪点就显形了。

解法是让扰动强度跟观察距离或者物体在屏幕上的占比挂钩。简单点的做法是在材质里算相机到像素的世界距离,做一个平滑的衰减曲线,距离越近强度越低。更精细的做法是用物体的屏幕包围盒尺寸,但那需要蓝图或C++传参,成本高一些。

实测下来,用一个距离区间做映射就够用了:比如3米以内强度降到50%,1米以内降到30%,再近就基本只剩模糊没有扰动。听起来是妥协,但视觉上反而更自然——真实的毛玻璃凑近了看,颗粒确实会变得不那么明显,因为你的眼睛对焦在了玻璃表面而不是透过它看的东西。

3.4 折射通道与自定义模糊叠加时的冲突

如果你同时用了引擎自带的折射通道和自定义的SceneColor多采样,会发现两套机制在打架。

具体表现是:背景被折射拉歪了一次,然后你的模糊采样又基于这个"已经歪过"的缓冲去取点,结果就是双重扭曲,画面撕裂感很强,尤其是玻璃后面的直线物体(比如窗框)会断成好几截。

处理方式有两条路。一条是二选一:要么完全靠折射通道做扰动(配合引擎自带的模糊,如果你开了半透明的模糊选项),要么关掉折射、全部用自定义采样自己算偏移。后者可控性更强,我现在基本都走这条路。

另一条路是把折射强度调到很低,只用它做一点点微妙的扭曲,主力模糊靠自定义采样。这个方案的好处是能保留折射通道跟引擎其他系统(比如某些后处理)的兼容性,坏处是两套参数需要反复配平。

补充一句:如果决定关掉折射通道,记得把材质的折射输入断开,否则那个输入会强制引擎走折射渲染路径,白白增加开销,还可能导致排序问题。

4. 几个真正让人熬夜的坑

前面讲的是"怎么搭",这一节讲"搭完了为什么不生效"。毛玻璃这个效果有个特点:材质本身没问题,但放进场景就不对。下面这四个问题,我每一个都至少花过一整天。

4.1 半透明排序:为什么玻璃背后的物体忽隐忽现

半透明物体不写深度,它们的绘制顺序靠一个"排序优先级"参数人为指定。两片玻璃重叠的时候,如果优先级一样,引擎会按物体原点的距离去排,物体原点一动,顺序就可能翻转,于是出现"这帧A在前,下帧B在前"的闪烁。

更麻烦的是玻璃和玻璃背后的半透明粒子(比如雾气、烟)的交互。这类粒子的排序本来就脆弱,再加上一层玻璃,很容易出现"烟被玻璃吃掉"或者"烟盖在玻璃前面"的错误。

解法是给每一类半透明物体规划一个优先级区间,写进项目规范。比如背景雾效0到10,玻璃100,粒子特效200,UI用最顶层。数字之间留足空隙,方便以后插入新类型。

另外,虚幻引擎有个"分离半透明"的开关(在项目设置里),保证半透明物体在单独的通道里绘制,对排序稳定性有帮助。较新的5.x版本默认是开的,但如果你的项目是从老版本升级上来的,一定要确认一下这个设置。

4.2 Lumen、反射捕获、SSR 对毛玻璃的态度

这是虚幻5之后新增的痛点。Lumen的全局光照对半透明物体的支持是有限的,默认情况下半透明表面接收不到Lumen的间接光,看起来会比周围环境"暗一档",像是浮在场景外面的贴片。

解决办法有两个。一是把半透明光照模式改成表面前向着色,让半透明物体参与完整光照计算,Lumen的能量能传过来一部分。二是用半透明体积(Translucency Volume)模式,它会给半透明物体一个全局的间接光近似,效果不如前者但有。

反射方面,屏幕空间反射对半透明物体基本无效,你看到的反射内容其实来自反射捕获(Reflection Capture)。这意味着玻璃里映出的动态物体是不动的——一辆车开过去,玻璃上不会有倒影。这个限制短期内没法绕开,只能靠设计规避:把玻璃放在反射内容不敏感的位置,或者用高质量的天空反射 + 假的高光来掩盖。

我见过一个项目在玻璃正对面放了个动态屏幕,反射里永远是黑的,特别出戏。后来改成在玻璃材质里叠了一层贴图做的假反射,才算蒙混过去。这是我个人在实际操作中的体会——反射内容的真实性,在半透明材质上优先级可以往后放,观众注意不到的时候,不值得为它付出帧率。

4.3 移动端与前向渲染链路的限制

如果项目要出移动端,材质复杂度的天花板会低很多。

首先是折射通道本身。移动端的前向渲染路径对折射的支持是受限的,某些版本直接不支持像素法线偏移模式,你连上去也是无效的,表现就是背景完全不扭曲。

其次是SceneColor采样。移动端做屏幕空间采样需要额外的缓冲拷贝,开销比桌面端大得多,13点采样几乎不可行,得降到4到5个点,噪点靠抖动和后处理模糊去补。

还有一个容易忽略的点:移动端通常没有TAA,或者TAA质量很差。前面说的"抖动 + 时间累积"方案在移动端基本失效,你只能老老实实增加采样或者接受噪点。

我的建议是从一开始就为移动端准备一套独立材质,不要试图用一套母材质通过开关兼容。那种做法的结果是桌面端嫌参数不够用,移动端嫌功能太多,两边都不满意。

4.4 Depth Fade 与边缘硬切

半透明物体穿过不透明表面的时候,比如玻璃杯放在桌面上,杯底和桌面的交界处会出现一条生硬的分割线,像是被剪了一刀。原因是半透明不写深度,桌面遮挡的部分直接从玻璃里透出来了,但视觉上又是一个完整的物体。

深度渐变节点(Depth Fade)就是干这个的——它按当前像素深度和背景深度的差值做透明度衰减,让玻璃靠近其他物体表面的地方逐渐变透明。参数上,距离越近衰减越强,调到一个你觉得自然的过渡宽度。

这里有个度要把握:衰减距离给太大,玻璃会显得"融进"背景,失去体积感;给太小,又会出现硬边。我一般从2到5厘米开始试,看你场景的尺度。

还有一个细节:深度渐变会影响前面说的边缘光晕修复。这两个功能用同一个深度因子是没问题的,但如果你对深度因子做了非线性处理,记得两边保持一致,不然会出现"边缘收敛了但轮廓还是亮的"。

5. 把材质收敛成可复用的工程资产

做到能跑只是第一步。真正进项目的时候,一个材质要面对七八个人用、几十个实例、三四个平台。这时候"能跑"和"好维护"是两码事。这一节讲我整理材质的习惯。

5.1 参数分层:哪些进材质实例,哪些进 MPC

核心原则是:跟全局设置相关的进参数集合(Material Parameter Collection,MPC),跟单个物体手感相关的进材质实例。

比如模糊半径、扰动强度的全局倍率、平台质量档位这些,放MPC,改一次全场景生效。而这块玻璃的颗粒密度、这块玻璃的色调偏移,放材质实例。

我见过最乱的情况是一个场景里几十个材质实例,每个实例都有一份独立的模糊半径,美术改了一个忘了另一个,最后画面里玻璃的磨砂程度五花八门。这种情况用MPC加一个全局统一倍率,再让实例参数只做小幅偏移,能省掉大量返工。

另外,参数命名要成体系。前缀用组名,比如Blur_Radius、Blur_SampleCount、Normal_Tiling、Normal_Strength。材质编辑器里的参数顺序也要整理,否则实例面板里几十个参数排得乱七八糟,用的人根本找不到。

5.2 质量分级:高配和低配两套节点,共用一个母材质

比较稳妥的做法是在母材质里用静态开关(Static Switch)分叉,高配走13点采样 + 抖动,低配走4点采样 + 更重的模糊。开关用材质实例里的静态参数控制,打包的时候会被编译掉,没有运行时开销。

这里要提醒一点:静态开关的两条分支都会参与材质编译,如果你的低配分支里引用了高配分支不用的节点,编译时间会显著增加。整理节点的时候把公共部分提到开关外面,能省不少编译时间。

还有一个偷懒但有效的手段:低配直接用不同的材质。看起来不够优雅,但省掉了大量开关维护的麻烦,尤其是当两套方案的节点结构差异很大时。我现在的项目就是高配一套、移动端一套,两套共用一套参数命名规范,反而比硬塞进一个母材质清爽。

5.3 性能预算的实测数字与验收标准

给几个我自己测出来的参考值,注意这些数字跟场景复杂度强相关,只能当量级参考:

配置项高配方案精简方案备注
SceneColor 采样数134每多一个采样,像素开销增加明显
材质指令数120 到 18060 到 90超过 200 要警惕
单层全屏玻璃的耗时0.6 到 1.2 ms0.2 到 0.4 ms1080p、占屏 60% 的情况
光照模式表面前向着色体积前者质量高、开销大

验收的时候我会做两个测试。一个是"满屏玻璃"压力测试,把相机怼在玻璃上让它占满屏幕,看帧率掉多少。另一个是"多层叠加",让三片玻璃前后重叠,观察排序和性能的双重表现。这两个测试能抓出 80% 的问题。

另外提醒:性能分析要看GPU还是看帧率,别只看编辑器里的帧数。半透明材质的开销是纯像素开销,跟分辨率强相关,编辑器里视口小,数字会骗人。一定要用独立运行模式在目标分辨率下测。

6. 一个可以照着做的自检清单

写到这儿,把前面散落的东西收成一份检查顺序,我自己每次做新玻璃材质都会过一遍,能省很多来回。

第一步,先把光照模式定下来,根据这块玻璃的观看距离和面积,选前向还是体积。这一步定了再往下走,不然做完了发现光照不对,前面的参数全要重调。

第二步,把模糊层单独调出来,暂时断开法线,只看模糊效果。调到一个你觉得"背景柔化程度合适"的半径,记下这个值。

第三步,接上法线,把扰动强度从 0 慢慢往上推,推到"能看出颗粒但背景轮廓还认得出"就停。别一次给到位,很容易过头。

第四步,加菲涅尔调制,让边缘处扰动和模糊都收敛。这一步做完,玻璃的边缘应该看起来比中间"清楚"。

第五步,加深度渐变,处理和其他物体的交界面。

第六步,放进场景,找三个极端视角测试:正对、大角度斜看、贴脸近看。三个视角都过得去,这个材质基本就稳了。

最后说一个我个人的习惯。调这类材质的时候,我会把背景固定成一张有直线、有高光点、有明暗渐变的测试图,而不是用实际场景。因为直线能看出扭曲是否过度,高光点能看出颗粒感,明暗渐变能看出模糊是否均匀。用真实场景调参,很容易被场景本身的复杂度干扰判断。这个习惯是从做UI动效的时候带过来的,一直很好用。

另外补充一个后续可以扩展的方向:如果项目里有大量不同质感的玻璃,可以考虑把颗粒、划痕、水渍做成一套可叠加的细节层法线,用一张遮罩图控制各层的覆盖区域。这样一块玻璃上可以同时有磨砂区域和清透区域,接近真实的丝印玻璃效果。代价是采样数和指令数会再涨一截,得看预算够不够。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询