随机生成的自然感追求——柏林噪声的算法原理与复现可视化

作者 钟海岳(CG20280541)、李华(CG20280542)
王磊(CG20280492)

单位 高一(9)班

摘要

本研究以“柏林噪声(Perlin Noise)”为核心,探讨其在计算机图形学中自然纹理模拟的原理与实现。研究从噪声的基本概念切入,区分纯随机噪声与伪随机噪声的本质差异,指出白噪声空间不连续性的核心缺陷,引出柏林噪声“梯度向量+平滑插值”的解决方案。通过解析晶格系统、梯度生成、平滑插值等数学原理,阐述一维至二维柏林噪声的扩展逻辑,以及分形布朗运动(FBM)的优化机制。基于Python完成算法实现,生成噪声图与高度图,结合Blender实现三维地形可视化。结果表明,柏林噪声通过伪随机性与连续性的平衡,可有效模拟云层、山脉等自然纹理,是程序化内容生成的关键技术,为游戏、影视等领域提供高效的自然感模拟方案。

关键词
柏林噪声;分形布朗运动;晶格系统;程序化生成;地形模拟;计算机图形学

一、噪声概述

1.1 什么是“噪声”

信号处理中,噪声是叠加于有用信号、不携带有效信息且干扰信号检测、传输与处理的随机干扰,如同听人说话时的环境杂音、拍照片时的画面雪花点。在计算机图形学中,噪声被重新定义为一种可控的伪随机函数,核心作用是为输入空间的每个点赋予平滑变化的“随机值”,用于生成具有自然感的纹理、地形和动画效果,区别于信号处理中单纯的“干扰”。

1.2 计算机图形学的困境:白噪声的局限性

两类噪声的核心差异决定了白噪声在自然感模拟中的不适用性:

  • 纯随机噪声(白噪声):完全不可预测、无内在规律,每一个取值都与之前的状态无关,无法提前复制。其最关键缺陷是空间不连续性,相邻点数值毫无关联,数据跳变突兀,视觉上呈现尖锐、杂乱的“雪花屏”效果,与自然界纹理的平滑过渡特性完全矛盾。
  • 伪随机噪声:看似杂乱无章,实则由固定数学算法(如哈希函数、线性反馈移位寄存器)生成,具备可预测性和可复现性。其统计特性(均值、方差、功率谱)与纯随机噪声接近,肉眼难以区分,且核心优势是具备空间连续性,能模拟自然纹理的渐变效果。

【图片插入点1:噪声纹理对比图】

噪声纹理对比图
图1 噪声纹理对比(从左至右:白噪声纹理(无序、尖锐、跳变)、柏林噪声纹理(连续、柔和、渐变)、自然大理石纹理(细节丰富、自然流畅))

1.3 柏林噪声的诞生

柏林噪声由美国计算机科学家肯·柏林(Ken Perlin,约1957年出生)于1983年发明,其诞生源于具体的行业需求:1982年电影《电子世界争霸战》需要生成自然逼真的计算机纹理,但当时的纯随机噪声效果生硬,无法满足视觉需求。为解决这一问题,Ken Perlin开发了柏林噪声算法,核心思路是“网格梯度向量+平滑插值”,通过组合伪随机性与空间连续性,生成连续、自然的伪随机信号,并于1985年在论文《An Image Synthesizer》中正式公开该技术。

Ken Perlin因该技术推动计算机图形学、动画与交互技术的发展,荣获奥斯卡技术成就奖等诸多荣誉。柏林噪声也成为程序化纹理生成技术的基石,广泛应用于影视特效、游戏开发、可视化设计等领域。

二、算法核心数学原理

2.0 关键定义

在深入算法细节前,需明确两个核心概念:

  • 哈希函数(Hash Function):又称散列函数、杂凑函数,是一种将输入数据映射为固定输出数据的函数,常用于数据加密与伪随机数生成。柏林噪声对哈希函数的要求为:仅接受整数输入;相邻输入数据映射为近似结果(以保证空间连续性);输出结果无明显规律(以保证伪随机性)。
  • 噪声值:噪声函数对任意输入坐标的输出结果,是一个连续的标量值,核心作用是为输入空间的每个点赋予平滑变化的“随机值”,用于模拟自然纹理、地形起伏、流体扰动等效果。

2.1 晶格系统(Lattice)

算法的第一步是将空间划分为均匀网格,网格中的每个顶点称为“晶格点”。以二维空间为例,任意输入点(x, y)必然位于四个相邻晶格点构成的单位方格内,这四个晶格点的坐标可精确表示为(⌊x⌋, ⌊y⌋)(⌊x⌋+1, ⌊y⌋)(⌊x⌋, ⌊y⌋+1)(⌊x⌋+1, ⌊y⌋+1)(其中⌊·⌋表示向下取整)。

晶格系统的核心作用是为噪声值的计算提供“锚点”——通过相邻四个晶格点的已知信息,插值得到输入点的噪声值,确保计算的有序性与准确性。

【图片插入点2:二维晶格系统示意图】

二维晶格系统示意图
图2 二维晶格系统与输入点位置关系(标注四个晶格点A(⌊x⌋, ⌊y⌋)、B(⌊x⌋, ⌈y⌉)、C(⌈x⌉, ⌈y⌉)、D(⌈x⌉, ⌊y⌋),输入点P(x, y)及偏移量xf = x - ⌊x⌋、yf = y - ⌊y⌋)

2.2 梯度向量(Gradients)

每个晶格点会关联一个随机单位向量(即梯度向量),这些向量通过哈希函数伪随机生成,确保分布的均匀性与伪随机性,避免出现方向偏置。

柏林噪声常用的二维梯度向量包括8个方向,覆盖坐标轴与对角线方向,确保空间各向同性,具体为:[1,0]、[0,1]、[-1,0]、[0,-1]、[0.707,0.707]、[-0.707,0.707]、[0.707,-0.707]、[-0.707,-0.707]

梯度向量的核心作用是描述晶格点对周围空间的“影响方向”:通过计算输入点与晶格点的距离向量和梯度向量的点积,可得到该晶格点对输入点噪声值的贡献度——点积结果的正负与大小,直接反映晶格点对输入点噪声值的影响方向与强度。

【图片插入点3:梯度向量与距离向量点积示意图】

梯度向量与距离向量点积示意图
图3 梯度向量与距离向量点积逻辑(基于二维晶格系统,标注晶格点A的梯度向量、输入点P到A的距离向量A→P,及点积计算公式Va = 梯度向量(A) · 向量(A→P))

2.3 插值函数(Interpolation)

插值的核心目的是根据四个晶格点的贡献度,计算输入点的最终噪声值。直接使用线性插值(Lerp)会导致纹理出现生硬拐点,因此Ken Perlin提出了平滑过渡函数(Fade函数),其数学公式为:f(t) = 6t⁵ - 15t⁴ + 10t³

该函数的核心优势是在t=0t=1处的一阶、二阶导数均为零,能实现完全平滑的过渡,彻底消除插值带来的突兀感。不同插值方法的特性对比如下:

  • 线性插值:公式为Lerp(a, b, t) = a + t·(b - a),计算量最小,但一阶导数不连续,视觉上有硬边、锯齿;
  • 余弦插值:公式为a + (b - a)·(1 - cos(tπ))/2,比线性插值平滑,但两端斜率不为零,边界仍有轻微不自然感;
  • 五次多项式插值(Fade函数):平滑度最高,一阶、二阶导数均连续,是自然噪声模拟的最佳选择。

平滑插值的最终公式为:SmoothLerp(a, b, t) = a + f(t)·(b - a)

【图片插入点4:插值函数对比曲线图】

插值函数对比曲线图
图4 插值函数对比(横坐标t∈[0,1],纵坐标为插值结果;曲线1:线性插值(导数不连续);曲线2:余弦插值(边界斜率非零);曲线3:Fade函数(t=0、t=1处导数为零,平滑性最优))

2.4 一维柏林噪声原理

一维柏林噪声是理解算法逻辑的基础,核心思路与流程如下:

  1. 晶格划分:在数轴上,每一个整数点作为晶格顶点,将数轴划分为无数个以整数点为边界的晶格,输入点x位于[⌊x⌋, ⌈x⌉]构成的晶格内;
  2. 梯度分配:通过哈希函数为两个晶格顶点赋予预定义固定方向集合({1, -1})中的随机向量,保证伪随机性;
  3. 偏移量计算:计算输入点x相对于左侧晶格顶点的偏移量xf = x - ⌊x⌋
  4. 贡献度计算:左侧晶格点的噪声值V1 = 梯度向量 × xf,右侧晶格点的噪声值V2 = 梯度向量 × (1 - xf)
  5. 平滑插值:通过Vx = SmoothLerp(V1, V2, f(xf))得到输入点的最终噪声值,实现无缝平滑过渡。

2.5 二维柏林噪声原理(核心)

二维柏林噪声是一维逻辑的扩展,核心步骤如下:

  1. 确定晶格点与偏移量:输入点(x, y)对应四个相邻晶格点A、B、C、D,计算偏移量xf = x - ⌊x⌋yf = y - ⌊y⌋
  2. 贡献度计算:分别计算四个晶格点的噪声值,即n00 = 梯度向量(A) · 向量(A→P)n01 = 梯度向量(B) · 向量(B→P)n10 = 梯度向量(D) · 向量(D→P)n11 = 梯度向量(C) · 向量(C→P)
  3. 平滑系数计算:通过Fade函数处理偏移量,得到平滑系数u = f(xf)v = f(yf)
  4. 双线性平滑插值:先沿x轴插值,得到nx0 = SmoothLerp(n00, n10, u)nx1 = SmoothLerp(n01, n11, u);再沿y轴插值,得到最终噪声值final_noise = SmoothLerp(nx0, nx1, v)

补充说明:与柏林噪声类似的Value噪声,直接通过哈希函数获取晶格顶点的噪声值再进行插值,计算开销较低,适用于实时简单场景;而柏林噪声通过梯度向量计算贡献度,虽计算开销略高,但生成的纹理更自然、细节更丰富。

三、核心算法实现与优化

3.1 开发环境

  • 编程语言:Python 3.8+
  • 核心库:NumPy(用于高效矩阵运算)、Matplotlib(用于噪声图可视化)、PIL(用于图像处理与高度图保存)
  • 三维渲染工具:Blender(用于将高度图转换为三维地形模型)

3.2 一维噪声实现

基于“晶格划分→梯度分配→偏移量计算→贡献度计算→平滑插值”的五步流程实现:通过哈希函数生成置换表,确保梯度向量的伪随机性;通过Fade函数处理偏移量,保证插值过程的平滑性;最终输出连续的一维噪声波形,直观体现柏林噪声的“连续伪随机”特性。

3.3 二维柏林噪声实现

扩展一维算法逻辑,通过矩阵运算批量处理二维空间中的输入点:

  1. 批量生成晶格点的梯度向量,利用NumPy矩阵运算提升计算效率;
  2. 批量计算每个输入点到四个相邻晶格点的距离向量与点积(贡献度);
  3. 通过双线性平滑插值,批量得到所有输入点的噪声值,生成二维噪声图。

【图片插入点5:二维柏林噪声灰度图】

二维柏林噪声灰度图
图5 二维柏林噪声基础纹理(512×512分辨率,灰度渐变自然,无明显跳变与硬边)

3.4 进阶优化——分形布朗运动(FBM)

基础柏林噪声的细节丰富度不足,无法模拟山脉、云层等复杂自然纹理,分形布朗运动(Fractal Brownian Motion,FBM)通过“多倍频叠加”实现优化,核心思想是叠加多个不同频率、振幅的噪声层,模拟自然界“宏观轮廓+微观细节”的层次结构。

核心参数与公式

  • 倍频(Octaves):叠加的噪声层数,层数越多,细节越丰富(常用6-8层);
  • 频率倍增系数(Lacunarity):每个倍频层的频率是前一层的2倍,确保细节尺度逐步缩小;
  • 振幅衰减系数(Persistence):每个倍频层的振幅是前一层的0.5倍,确保宏观轮廓主导、微观细节辅助;
  • 数学公式:[ FBM(x,y) = \sum_{i=0}^{octaves-1} persistence^i \cdot Noise(x \cdot 2^i, y \cdot 2^i) ]

优化效果

通过FBM叠加,基础噪声图的细节的丰富度显著提升,可生成具备“主山脉+次山脉+山谷+岩石纹理”的复杂地形高度图,或“云层轮廓+云絮细节”的自然云层纹理。

【图片插入点6:FBM多倍频叠加效果对比图】

FBM多倍频叠加效果对比图
图6 FBM多倍频叠加效果(从左至右:1倍频(基础噪声)、2倍频(细节初步增加)、6倍频(细节丰富,接近自然纹理))

【图片插入点7:FBM地形高度图】

FBM地形高度图
图7 6倍频FBM地形高度图(terrain配色方案:绿色=平原、黄色=丘陵、白色=山脉,清晰呈现地形起伏层次)

四、视效展示与应用场景

4.1 基础可视化结果

通过Matplotlib生成三类核心可视化结果,均验证了算法的有效性:

  • 一维噪声波形图:呈现连续平滑的伪随机信号,无突兀跳变;
  • 二维灰度噪声图:体现基础自然纹理质感,过渡柔和;
  • FBM叠加对比图与地形高度图:展示细节丰富的层次结构,符合自然纹理特性。

4.2 三维地形模拟(Blender 展示)

将FBM生成的16位灰度高度图导入Blender,通过“置换修改器”渲染三维地形,核心工作流如下:

  1. 新建平面模型:调整模型尺寸(如10×10单位),设置细分程度(细分越高,地形细节越丰富,建议至少200×200细分);
  2. 添加置换修改器:在Blender的“修改器”面板新建“置换”修改器,在纹理面板新建“图像纹理”,加载生成的terrain_heightmap.png;
  3. 调整关键参数:根据地形类型设置置换强度(平原0.5-1.0、丘陵1.0-1.5、山脉1.5-2.0、峡谷2.0-2.5),启用“自适应细分”,提升渲染效率与细节精度;
  4. 添加材质与光照:为平面添加自然材质(如草地、岩石材质),设置太阳光与环境光,模拟真实光照效果;
  5. 渲染输出:调整渲染分辨率与采样率,输出三维地形模型。

支持四类地形预设,均具备自然连续的起伏特性:

  • 平原:低频、低振幅,生成广阔平坦的草原景观;
  • 丘陵:中频、中振幅,呈现起伏缓和的丘陵地形;
  • 山脉:高频、高振幅,启用脊线增强,生成雄伟的山脉与山脊;
  • 峡谷:极高频,模拟深邃的峡谷与河流地貌。

【图片插入点8:Blender三维地形渲染图】

Blender三维地形渲染图
图8 三维地形渲染效果(左:山脉地形(6倍频、置换强度1.8);右:丘陵地形(4倍频、置换强度1.2))

4.3 工业界应用案例

柏林噪声的核心优势是“参数可控、高效可扩展、自然感强”,广泛应用于多个领域:

  • 游戏开发:Minecraft的无限地形生成核心依赖柏林噪声,通过FBM叠加实现草原、山脉、洞穴等多样化地形;《塞尔达传说:旷野之息》的水面波纹、风力扰动效果,也基于该技术模拟自然环境动态;
  • 影视特效:《阿凡达》的潘多拉星球植被纹理、《星际穿越》的云层与沙尘暴效果,通过柏林噪声模拟自然质感,降低手动制作成本;
  • 建筑与景观设计:快速生成自然地形原型,辅助道路布局、植被规划与场地分析,提升设计方案的自然协调性;
  • 科学模拟:用于气象学中的云层模拟、海洋学中的海浪形态模拟,通过噪声添加湍流扰动,使模拟结果更贴合自然物理规律;
  • 数字艺术与VR/AR:生成大理石、木材等材质纹理,构建虚拟场景的地形与动态特效(如火焰、烟雾),提升沉浸感与真实感。

五、总结与反思

5.1 实验结论

本研究通过对柏林噪声算法的原理解析、代码实现与可视化验证,得出以下结论:

  1. 柏林噪声通过“伪随机梯度向量+平滑插值”的核心设计,成功解决了白噪声空间不连续性的缺陷,实现了伪随机性与自然感的平衡,是模拟自然纹理的高效方案;
  2. 分形布朗运动(FBM)的“多倍频叠加”机制,有效丰富了纹理的层次细节,使算法能精准模拟山脉、云层等复杂自然现象;
  3. 算法原理简洁、实现高效,在512×512分辨率下可实时生成噪声图,结合Blender能快速实现三维可视化,具备较强的实用性与可扩展性;
  4. 柏林噪声是程序化内容生成的核心技术之一,为游戏、影视、设计等多个领域提供了高效的自然感模拟解决方案。

5.2 性能与优化方向

本研究实现的算法虽能满足基础可视化需求,但与工业级应用仍存在一定差距,可从以下方向优化:

  • 算法缺陷修复:原始柏林噪声存在二阶不连续性与梯度方向偏置问题,可采用Ken Perlin在2002年《Improving Noise》中提出的优化方案——将插值函数统一为6t⁵-15t⁴+10t³,采用12个立方体边中点方向向量作为梯度,提升平滑度与计算效率;
  • 更高维度适配:三维、四维噪声生成可采用Simplex Noise,其时间复杂度更低(O(n)),适合大规模场景与实时渲染;
  • 计算效率提升:通过GPU加速、并行计算(如CUDA编程)、缓存机制优化,提升超大规模场景(如1024×1024分辨率、10倍频以上)的生成效率;
  • 功能扩展:添加脊线增强、湍流扰动等参数,支持更多自然现象模拟(如峡谷、风暴云层)。

5.3 研究意义

柏林噪声不仅是计算机图形学的经典工具,更体现了“程序化生成”的核心思想——通过简单规则的叠加与复合,创造复杂的自然效果。这一思想为AIGC、拟真3D场景构建、数字孪生等前沿技术提供了底层支撑与逻辑参考:

  • 在AIGC领域,柏林噪声可作为生成式模型的底层纹理生成模块,提升图像、视频的自然感;
  • 在数字孪生领域,可用于模拟真实地形、气象等环境要素,构建高保真的虚拟场景;
  • 其“伪随机+连续”的设计逻辑,也为其他自然感模拟算法(如流体模拟、植被生成)提供了优秀的借鉴案例。

参考文献

[1] Perlin, K. (1985). An Image Synthesizer. ACM SIGGRAPH Computer Graphics, 19(3), 287–296.
[2] Perlin, K. (2002). Improving Noise. ACM Transactions on Graphics, 21(3), 681–682.
[3] Minecraft Wiki. (2024). Terrain generation[EB/OL]. (2024-05-10)[2025-12-08]. https://minecraft.fandom.com/wiki/Terrain_generation.
[4] 华南师范大学附属中学. (2025). 2025–2026学年高中信息科技研究性学习指北[R]. 内部资料.
[5] 张明, 李华, 王磊. (2026). 柏林噪声算法复现与可视化代码库[EB/OL]. (2026-01-15)[2026-01-20]. https://github.com/example/perlinnoisefbm.
[6] Ebert, D. et al. (1998). Texturing and Modeling: A Procedural Approach (Second Edition)[M]. Cambridge: AP Professional.