4、颜色与向量运算:颜色混合、线性插值、向量归一化、反射向量

好,咱们今天聊点实在的。颜色和向量运算,这俩东西在材质系统里就像水和空气一样无处不在。你写任何稍微复杂点的材质,都绕不开它们。

我个人习惯把颜色和向量放在一起讲,因为它们在底层其实是一回事——都是一组浮点数。颜色是RGBA四个通道,向量是XYZ三个分量。运算规则也几乎一样。你理解了向量的加减乘除,颜色的混合逻辑也就通了。

4.1 颜色混合:不只是“加”和“乘”

很多新手一上来就喜欢用Add节点或者Multiply节点去混合颜色。嗯,这确实能出效果,但往往不够灵活。我见过不少项目,美术同学调了半天颜色,结果在暗部区域直接死黑,或者亮部过曝——说白了就是混合模式选错了。

颜色混合的核心,其实就三个操作:

  • 线性插值(Lerp):最常用,也最可控。通过一个Alpha值在两种颜色之间平滑过渡。
  • 乘法混合:适合叠加纹理细节,但会让颜色变暗。
  • 加法混合:适合发光、火焰等自发光效果,但容易过曝。

我在项目中遇到过一个问题:用Multiply混合两张贴图,结果金属部分变得脏兮兮的。后来发现,其实应该用Overlay或者Screen模式,而不是简单的乘法。UE5的材质编辑器里没有直接提供这些混合模式节点,但你可以用几个基础节点组合出来。

核心原则:颜色混合时,先想清楚你要的是“叠加细节”还是“过渡切换”。前者用乘法或Screen,后者用Lerp。

4.2 线性插值:Lerp 节点的正确打开方式

Lerp节点,全称Linear Interpolation。它有三个输入:A、B、Alpha。输出结果就是 A * (1 - Alpha) + B * Alpha

你可能会说:“这不就是个简单的混合吗?” 对,但它能玩出的花样远超你的想象。

举个例子。你想做一个根据视角变化颜色的材质。比如从正面看是红色,侧面看是蓝色。怎么做?

// 伪代码逻辑
float3 ViewDir = normalize(CameraVector);
float3 Normal = 你的法线;
float DotProduct = dot(ViewDir, Normal);  // 范围 -1 到 1
float Alpha = saturate(DotProduct * 0.5 + 0.5);  // 映射到 0 到 1
float3 FinalColor = lerp(RedColor, BlueColor, Alpha);

你看,一个Lerp加上一个点积,就能做出视角相关的颜色变化。我曾经用这个技巧做了一套全息投影材质,效果非常棒。

小技巧:Lerp的Alpha值不一定要用常量。你可以用噪声贴图、顶点颜色、甚至时间节点来驱动它。这样颜色过渡就会变得非常生动。

4.3 向量归一化:为什么你的法线贴图总是不对?

归一化,就是把一个向量的长度变成1,但方向不变。公式很简单:Normalize(V) = V / length(V)

为什么需要归一化?因为很多运算要求输入向量是单位向量。比如光照计算中的法线方向、视角方向、光线方向。如果这些向量长度不是1,光照结果就会出错——要么太亮,要么太暗,要么出现奇怪的条纹。

我记得有一次,美术同学导入了自己做的法线贴图,结果模型上出现了大面积的黑色块。排查了半天,发现是法线贴图在压缩时精度丢失,导致向量长度偏离了1。解决办法就是在材质里加一个Normalize节点。

注意:UE5的材质编辑器里,很多节点默认不会自动归一化。比如你从Texture Sample节点读取法线贴图,它输出的是未归一化的值。一定要手动接一个Normalize节点,或者使用专门的“Normal”采样方式。

另外,归一化也常用于方向计算。比如你想计算两个点之间的方向向量,先做减法,再归一化。这样你得到的就是一个纯粹的方向,不受距离影响。

4.4 反射向量:从镜面到环境映射

反射向量,说白了就是光线打到表面后,按照“入射角等于反射角”的规律弹出去的方向。公式是:Reflect(I, N) = I - 2 * dot(I, N) * N

在UE5里,你可以直接用Reflection Vector节点来计算。这个节点输入一个视角方向和一个法线方向,输出反射方向。

反射向量最常见的用途就是环境映射。比如你做一个金属球,它应该反射周围的环境。这时候你就用反射向量去采样一个Cube Map(立方体贴图)。

// 材质蓝图中的连接方式
CameraVector -> ReflectionVector (Normal输入接法线)
ReflectionVector -> Sample Cube Map
Cube Map输出 -> Base Color

我做过一个项目,需要模拟车漆材质。车漆不仅有高光反射,还有一层清漆层的二次反射。这时候我就用了两个反射向量:一个用于金属漆层的反射,一个用于清漆层的反射,然后用Lerp混合。效果非常逼真。

避坑指南:反射向量计算时,法线必须是归一化的。我曾经因为法线没归一化,导致反射方向偏移,整个环境映射都扭曲了。排查了整整两个小时……嗯,从那以后我再也不敢省掉Normalize节点了。

知识体系总览

下面这张图,是我自己梳理的本章节核心逻辑。你可以把它当作一个快速索引:

颜色与向量运算 颜色混合 加法 / 乘法 / Overlay 避免死黑与过曝 线性插值 (Lerp) A*(1-Alpha) + B*Alpha 视角颜色 / 动态过渡 向量归一化 V / length(V) 法线 / 方向计算 反射向量 I - 2*dot(I,N)*N 环境映射 / 车漆材质

这张图把四个核心知识点串在了一起。你可以看到,它们之间其实是有逻辑关系的:颜色混合和线性插值解决的是“如何组合”的问题,向量归一化解决的是“数据正确性”的问题,反射向量则是这些运算的综合应用。

好了,这一章的内容就到这里。记住,颜色和向量运算不是死记硬背的公式,而是你手里最灵活的工具。多用、多试、多踩坑,慢慢就找到感觉了。

专注资料整理