ShaderGraph沃罗诺伊噪声:从原理到实战,打造程序化纹理与材质

1. 沃罗诺伊噪声:从数学抽象到视觉魔法的桥梁

如果你在ShaderGraph里摸爬滚打了一段时间,想从基础的柏林噪声、简单噪声里跳出来,搞点更复杂、更有“设计感”的纹理,那你迟早会撞上“沃罗诺伊噪声”(Voronoi Noise)这个节点。我第一次接触它,是在尝试模拟一些自然材质,比如龟裂的土地、昆虫翅膀的脉络,甚至是某些金属的结晶表面时,发现常规的噪声纹理怎么调都差那么点意思,要么太“软”,要么太“糊”,缺乏那种清晰的、细胞状的边界感。直到把Voronoi节点拖进画布,调了几个参数,那种瞬间成型的、充满几何美感的图案,让我一下子明白了它的价值:它不是在模拟“随机”,而是在模拟“空间划分”和“最近邻竞争”的规则。

简单来说,你可以把沃罗诺伊图理解成这样:在一张白纸上随机撒上一把点(我们称之为“特征点”或“种子点”),然后整个平面会被划分成一个个“势力范围”。每个点的势力范围,就是平面上离它最近的所有区域。最终形成的,就是一个个由直线边界分隔开来的、形状不一的多边形单元格,这些单元格看起来就像紧密排列的细胞或龟裂的纹路。ShaderGraph里的Voronoi节点,就是把这个数学过程搬到了三维(或二维)空间里,并且给了我们丰富的控制权,让我们不仅能得到这些单元格的ID、位置,还能玩出距离、边缘等各种各样的花样。

这个节点绝不只是为了生成一些好看的背景图。在游戏和实时渲染中,它的应用场景非常硬核:生成程序化地形中岩石的裂隙、模拟皮革或干燥泥地的表面细节、创建科幻场景中能量护盾或数据流的网格效果、甚至用于一些风格化渲染中的色块划分。它提供的不仅仅是颜色,更是结构信息。接下来,我们就把它彻底拆开,从原理到参数,从基础连接到高阶玩法,让你能真正把这个强大的工具收为己用。

2. 节点核心原理:空间是如何被“瓜分”的

要玩转Voronoi节点,死记硬背参数顺序没用,必须理解它底层在干什么。我们暂时忘掉ShaderGraph,回到最基本的二维沃罗诺伊图生成过程。

2.1 基础生成算法拆解

想象一个无限的二维平面。生成沃罗诺伊图的第一步,是“播种”。系统会根据你输入的UV坐标和一个“随机种子”,在这个空间里生成无数个特征点。这些点的位置并不是完全随机的乱数,而是通过一种可重复的伪随机算法确定的,这意味着相同的UV和种子,永远会生成完全相同的点分布,这对于着色器来说至关重要——保证了纹理的稳定性。

接下来,对于当前正在处理的像素点(对应一个UV坐标),算法会做一件核心事情:寻找离它最近的那个特征点。这个过程可以理解为“最近邻搜索”。找到之后,我们就得到了两个最关键的信息:

  1. 最近特征点的ID:可以理解为这个像素归属于哪个“细胞”。
  2. 到该特征点的距离:这个像素离自己所属细胞的“中心”有多远。

由所有归属于同一个特征点的像素构成的区域,就是一个沃罗诺伊单元格。单元格之间的边界,就是那些到两个不同特征点距离相等的点的集合,在理想情况下是一条直线(在更高维度是平面或超平面)。

2.2 ShaderGraph节点的抽象与输出

ShaderGraph的Voronoi节点,把这个过程封装了起来,并提供了多个维度的输出,让我们不仅能拿到最终视觉结果,还能获取中间数据,进行二次创作。

首先,节点的输入UV决定了计算发生的“空间”。你输入模型默认的UV,它就在纹理空间生成图案;你输入世界空间的XZ坐标,它就能在世界地面上生成无限延展的龟裂效果。Scale参数控制着特征点的密度,Scale值越大,单位空间内的特征点越多,生成的单元格就越小、越密集。

Angle Offset是一个容易被忽略但极其强大的参数。它并不直接移动特征点,而是影响生成特征点时所依赖的随机向量方向。稍微调整这个值,整个单元格的形态会发生平滑的、有机的变化,而不是简单的平移。这在制作动画时特别有用,可以让细胞纹理像活物一样蠕动、演变,而不是生硬地滑动。

节点的输出端口是其精华所在:

  • Cells:最常用的输出,通常直接连接到Base Color。它输出的是每个像素到其最近特征点的距离。由于距离值从中心向边缘递增,所以视觉上每个单元格中心最暗(距离为0),边缘最亮,形成了清晰的细胞状明暗对比。这本身就是一种非常实用的灰度纹理。
  • Random:输出的是最近特征点的“随机值”(通常基于其ID生成的一个固定值)。这个值在每个单元格内部是恒定的,但不同单元格之间不同。它非常适合用来给不同的单元格分配不同的颜色或材质属性,实现多彩的马赛克或分类着色效果。
  • Position:输出的是最近特征点在该像素空间中的相对位置向量。这个数据非常底层,可以用于更复杂的计算,比如自己重新计算自定义的距离度量。
  • Noise:这个输出有点特殊,它并不是传统的“噪声值”。在Unity的ShaderGraph实现中,Noise端口通常输出的是一个基于单元格的、更平滑的梯度噪声。你可以把它理解为对Cells输出的一种平滑或变形,有时能得到更柔和、更自然的有机纹理。

理解了这个流程,你就知道从UV输入到Cells输出之间,经历了一次空间播种、一次最近邻搜索和一次距离计算。这为我们后续的每一步调控都打下了基础。

3. 参数深度解析与实战调控指南

把Voronoi节点拖进画布,你会看到一堆参数。每个参数都不是孤立的,它们相互耦合,共同决定了最终的视觉形态。这里我们抛开官方文档那套简略的描述,直接讲实战中如何理解和调整它们。

3.1 核心控制参数:Scale, Angle Offset, Cell Density

1. Scale (缩放):这是最直观的参数。增大Scale,相当于把输入UV坐标缩小后再用于计算。结果就是,在同样的屏幕或模型区域里,算法认为空间“变小”了,但特征点的绝对数量(或密度)没变,因此相对密度增加,单元格变得更小、更密集。反之,减小Scale会得到更大、更稀疏的单元格。

注意:Scale对性能有直接影响。Scale值非常大(比如超过100)时,意味着需要在极小的UV区间内生成大量特征点并进行搜索,计算负荷会增大。在移动端或复杂场景中,需谨慎使用极高的Scale值。

2. Angle Offset (角度偏移):这是我个人最喜爱的参数之一。它不是一个位移,而是一个用于扰动特征点生成方向的偏移量。改变它,不会让整个图案平移,而是会让每个特征点的位置发生微妙的、非线性的变化,导致所有单元格的形状和大小同时发生平滑的形变。

  • 实战技巧:将Time节点乘以一个较小的系数(如0.1)后连接到Angle Offset,可以创造出一种细胞缓慢“呼吸”、“蠕动”的动画效果,非常适合模拟微生物培养皿、活体组织或能量场,效果比单纯平移UV要生动自然得多。

3. Cell Density (单元格密度):这个参数在有些版本或变体中可能存在,它直接控制特征点的数量。密度越高,单元格越多、越小。它和Scale的效果有时看起来相似,但底层逻辑不同:Scale是缩放整个空间坐标系,而Cell Density是直接改变空间内“撒点”的数量。在需要精确控制单元格数量而非大小的时候,这个参数更直接。

3.2 高级模式参数:开启更多可能性

很多教程只讲默认模式,但Voronoi节点下拉菜单里通常藏着“高级”模式。打开它,你会获得Euclidean(欧几里得)和Chebyshev(切比雪夫)两种距离度量的选择,以及Tile(平铺)选项。

1. 距离度量 (Distance Metric):

  • Euclidean (欧几里得):默认选项,也就是我们日常生活中理解的“直线距离”。它产生的单元格边界是直线,单元格形状更接近规则的多边形(如六边形),视觉效果最经典、最自然。
  • Chebyshev (切比雪夫):也称为“棋盘距离”。它计算的是两点在各坐标轴方向上的最大差值。这种度量下生成的单元格边界是水平的和垂直的直线,形成的图案是规整的方形网格。虽然也叫Voronoi,但视觉上更像是由大小不一的方块组成。
  • 实战选择:用Euclidean来模拟大多数自然现象(龟裂、细胞、泡沫)。用Chebyshev来创造人工感、像素感或数字感强烈的图案,比如复古游戏的地图区块、数字化面板等。

2. 平铺模式 (Tile):这是一个解决纹理接缝问题的神器。当你需要生成一张可无缝平铺的纹理时,勾选Tile选项。节点内部会采用一种特殊的算法(通常是基于周期空间的沃罗诺伊算法),确保在UV的边界(0和1处)生成的图案能够完美衔接。

  • 避坑指南:启用Tile模式后,噪声图案可能会在视觉上出现一定的重复性,尤其是Scale值较小(单元格较大)时。为了打破这种重复感,一个常见的技巧是使用多个不同Scale和Angle Offset的Voronoi节点进行混合叠加。

3.3 输出端口的创造性应用

仅仅把Cells输出当作灰度图来用,有点大材小用。我们来挖掘一下每个端口的潜力。

  • Cells (距离) 的妙用Cells输出的是距离值,范围通常在[0, 1]左右。这个线性变化的值可以直接用作高度图(连接至Height或用于视差偏移),来创造凹凸不平的细胞表面。更进阶的用法是,用一个StepSmoothStep节点处理这个距离值。例如,用SmoothStep(0.1, 0.2, Cells)可以提取出每个单元格的边缘区域,并使其平滑过渡,轻松生成描边效果,用于制作科技线框或细胞壁。
  • Random (随机值) 的妙用:这是制作“分类着色”的关键。将Random输出连接到一个基于颜色的Gradient节点,就能让每个单元格根据其ID获得一个随机但固定的颜色,瞬间生成彩色玻璃窗或马赛克地板效果。你也可以将Random值乘以一个系数后加到Base Color的某个通道上,为材质添加微妙的、按单元格变化的色相扰动。
  • Position (位置) 的深度玩法Position输出的是向量。你可以计算当前像素UV与这个Position的差值向量,然后取其长度或其他函数,这相当于在单元格内部进行二次距离计算。结合Fractional节点,你甚至可以在每个单元格内部再生成小一层的次级结构,实现分形般的复杂细节。
  • Noise (噪声) 的补充:当你觉得纯Cells输出的黑白对比太生硬时,可以尝试混合一些Noise端口的输出。它能添加一种内部的、平滑的渐变,让单元格看起来不那么“干”,更像是有体积感的凝胶或湿润的表面。

4. 核心应用场景与完整着色器案例拆解

理解了原理和参数,我们来看如何用它解决实际问题。下面通过三个从简到繁的案例,展示Voronoi节点的实战流程。

4.1 案例一:快速生成干燥地表材质

这是最直接的应用。目标是创建一个简易的、带有龟裂效果的泥土地面材质。

  1. 思路:利用Cells输出作为基础的高度和颜色变化依据。
  2. 操作步骤
    • 创建一个Voronoi节点。将UV端口连接到Tiling And Offset节点(先平铺,Offset可以连接一点基于世界位置的偏移,避免重复感),再输入。
    • 设置一个较低的Scale值(如5-10),获得较大的裂纹。
    • Cells输出连接到一个Color节点的R(红色)通道,作为基础色的一部分。同时,复制一份Cells输出,通过一个One Minus节点反转,再连接到一个Normal From Height节点,生成法线贴图。这样,裂纹的凹陷处颜色会更深,并且有正确的光影凹凸感。
    • 为了增加真实感,可以再用一个Scale值更大(如30-50)的Voronoi节点,将其Cells输出以较小的强度叠加到颜色或高度上,这相当于添加了更细小的次级裂纹细节。
  3. 参数参考与心得
    Voronoi主节点: Scale = 8, Angle Offset = 0 (或用Time*0.05做动画) 颜色混合: (Base Dirt Color) * (1 - Cells*0.3) + (Crack Dark Color) * (Cells*0.3) 法线强度: 根据场景缩放调整,通常0.1-0.3即可,过强会显得虚假。

    实操心得:单纯使用Voronoi裂纹会显得过于“完美”和“数学化”。一个关键技巧是,将生成的裂纹纹理与一张非常低频率的Simple NoisePerlin Noise进行Multiply(相乘)。低频噪声会像一张起伏的遮罩,让某些区域的裂纹变淡甚至消失,模拟出泥土湿度不均导致的裂纹断续效果,真实感大幅提升。

4.2 案例二:制作动态能量护盾网格

目标是创建一个科幻感十足的、带有脉冲光效的蜂窝状能量护盾。

  1. 思路:利用Random输出区分单元格,利用Cells输出制作发光边缘,并加入时间动态。
  2. 操作步骤
    • 创建Voronoi节点,使用Euclidean模式,Scale调高至20-30,获得密集的小单元格。
    • Random输出通过Fractional节点取小数部分后,连接至一个Pulse波形发生器(可以用Sine节点加Time,再通过AbsoluteRemap制作)。这样,每个单元格会根据其ID,以不同的相位进行明暗脉冲,形成此起彼伏的发光效果。
    • 处理Cells输出:使用SmoothStep(0.05, 0.1, Cells)来提取出非常细的单元格边界。将这个边界输出与上一步的脉冲颜色进行Add(相加)或Multiply(相乘),让边界也随脉冲发光或保持常亮。
    • 将最终的颜色输出连接到Emission(自发光)通道,并赋予一个蓝绿色系的色彩。
    • 高级动态:将摄像机或对象的世界位置作为UV偏移量输入,可以创造出护盾随着观察者或物体移动而“流动”的视觉效果。
  3. 节点网络逻辑梳理: 这个案例的关键在于信号的分离与重组。Random用于控制“谁在发光”(单元格身份),Cells用于控制“哪里更亮”(单元格边缘),Time用于控制“何时发光”(动态节奏)。将它们用MultiplyAdd节点有机组合,而非简单串联,是做出复杂效果的核心。

4.3 案例三:混合噪声生成复杂生物组织纹理

单一噪声节点总有局限。将Voronoi与其他噪声混合,能产生质变。

  1. 目标:模拟皮肤、黏膜或某些器官表面那种既有较大褶皱,又有细微颗粒和血管纹理的复杂质感。
  2. 混合策略
    • 基底纹理(大结构):使用一个低Scale(如3-5)的Voronoi节点的Cells输出,经过Power节点(例如0.5)使其对比度柔和化,作为皮肤下大块脂肪或肌肉组织的起伏基底。
    • 次级纹理(中细节):使用一个Perlin Noise节点,中等Scale(如15),叠加到基底上,模拟皮肤本身的细腻纹理和毛孔感。混合模式建议用OverlaySoft Light,以保留基底明暗关系的同时添加细节。
    • 血管/裂纹细节(高细节):使用一个高Scale(如50)的Voronoi节点,但只取其经过Step函数处理后的、非常细的边界线(Step(0.02, Cells))。将这个细线纹理以Screen(滤色)模式叠加在最上层,并染上暗红色,模拟皮下的毛细血管。
    • 颜色变化:使用第一个低Scale的Voronoi节点的Random输出,轻微地扰动表面基础色的色相(Hue),让不同“区域”的皮肤有微妙的颜色差异,避免单调。
  3. 性能与质量权衡:这个材质使用了三个噪声节点,对于移动端可能负担较重。一个优化方法是,将中、高细节的噪声采样频率降低(例如,在UV输入前除以2或4),牺牲一些远处细节来换取性能。或者,考虑将最终混合好的纹理烘焙成一张贴图,用于静态或中距离物体。

5. 常见问题、性能陷阱与调试技巧

即使理解了原理,在实际连接节点时还是会遇到各种奇怪的现象。这里整理了一些高频问题和我的排查经验。

5.1 视觉问题排查表

问题现象可能原因解决方案
纹理出现明显重复/棋盘格Scale值过低,单元格过大,平铺时特征点分布规律被肉眼识别;或者使用了Chebyshev模式且Scale为整数值。1. 增加Scale值,使单元格变小变密。
2. 给Scale输入一个非整数值(如7.3)。
3. 使用Tile模式并叠加多层不同Scale的噪声进行混合。
动画时纹理“滑动”而非“形变”直接将Time节点乘以一个向量后连接到UVOffset上。改为将Time乘以一个小系数(如0.1)后连接到Angle Offset参数,实现有机形变动画。
单元格边缘过于锐利/模糊Cells输出的距离值范围或对比度不理想。Cells输出后连接Power节点(小于1变柔和,大于1变锐利)或Contrast节点进行调整。需要清晰边界时,可用StepSmoothStep
“Random”输出看起来不随机误解了Random端口的含义。它在一个单元格内是恒定值,不同单元格间才变化。这是正常现象。要验证其随机性,可以将其直接连接到Base Color,你会看到均匀的色块,每个色块代表一个单元格的固定随机值。
启用Tile后边缘有接缝可能是UV本身有接缝,或者Scale值与平铺算法不匹配导致。1. 检查输入UV是否来自UV节点,确保是0-1的连续空间。
2. 轻微调整Scale值,有时能避开平铺算法的周期边界问题。
3. 尝试使用Triplanar节点采样世界坐标来彻底避免UV接缝。

5.2 性能优化要点

Voronoi噪声的计算复杂度高于Simple Noise。在ShaderGraph中,以下几点对性能影响显著:

  1. Scale值是性能杀手Scale值越大,计算越密集。在移动端或VR项目中,尽量避免使用超过50的Scale值。如果需要高细节,考虑使用纹理采样代替,或者将高频细节通过烘焙到贴图的方式实现。
  2. 节点实例化数量:在同一个着色器中,每多使用一个Voronoi节点,就多一份计算开销。尽可能复用输出。例如,如果需要不同Scale的Voronoi进行混合,可以尝试用一个Voronoi节点,将其输出通过Fractional和数学运算衍生出不同频率的细节,而不是直接创建两个节点。
  3. 高级模式与平铺:启用Tile模式通常会引入额外的计算,以确保边界连续性。如果不需要无缝平铺,请关闭它。
  4. 预览与调试:在ShaderGraph编辑器中,频繁修改Voronoi参数并实时预览可能会造成卡顿,尤其是连接了复杂后续节点时。如果感到卡顿,可以临时将节点输出直接连接到Master StackColor进行独立预览,或者降低预览分辨率。

5.3 调试与可视化技巧

当效果不符合预期时,不要盲目调整参数。学会“可视化”中间数据是调试的关键。

  • 隔离观察:将CellsRandomPosition等输出端口分别直接连接到Base Color,单独观察它们各自生成的原始图案是什么样子。这能帮你快速定位问题是出在Voronoi节点本身,还是出在后续的颜色处理或混合逻辑上。
  • 范围重映射:Voronoi各端口的输出范围可能不是理想的[0,1]。在连接到颜色或高度之前,习惯性地加一个Remap节点,将实际观察到的值域(例如Cells可能是[0, 0.5])重新映射到[0,1],可以确保你后续的SmoothStepPower等操作是在一个可控的、全范围内进行的。
  • 使用HDR Color节点:对于Position这类向量输出,直接连到颜色上可能显示为灰色。使用HDR Color节点,并勾选Exposure选项,可以更好地观察向量各个分量的正负变化。

沃罗诺伊噪声节点是一个典型的“易学难精”的工具。它的基础输出很容易上手,能立刻产生吸引人的图案。但真正让它发挥威力的,在于你能否理解其数学本质,并将它输出的结构化数据(距离、ID、位置)视为创作的原材料,而非最终结果。通过与其他节点(尤其是数学节点和混合节点)的创造性组合,你可以将它从简单的纹理生成器,变成构建复杂材质、动态效果甚至视觉逻辑的基石。我自己的习惯是,每当需要一个有“区域感”、“归属感”或“结构化随机”的效果时,第一个想到的就是它,而不是更常见的柏林噪声。多实验,多拆解,把它的每个输出端口都接到颜色上看一看,你会不断发现新的可能性。