柏林噪声(Perlin Noise)
柏林噪声(Perlin Noise) 是一种常用的渐变噪声算法,广泛应用于游戏开发中,尤其是在程序生成内容(如随机地图、地形生成、纹理生成等)时。它由计算机图形学家 Ken Perlin 在 1983 年发明,目的是为了解决传统随机噪声(如白噪声)看起来不自然的问题。
1. 介绍
1.1 柏林噪声的特点
- 平滑渐变:生成的噪声没有突兀的跳跃,适合模拟自然现象,如山脉、云层。
- 伪随机性:噪声看似随机,但可以通过种子值生成相同的噪声序列,确保可重复性。
- 多维噪声:支持二维(地形)、三维(体积数据)、四维(动态效果)等不同维度的噪声。
1.2 在游戏开发中的应用
- 地形生成:生成自然的山脉、平原、海洋等地貌。
- 纹理生成:创建无缝纹理,如云彩、岩石、草地等。
- 程序生成内容:用于随机生成森林、迷宫、关卡等。
- 动态效果:如动态天气、云层运动等。
1.3 柏林噪声的优势
- 自然感:比传统随机噪声更自然、平滑。
- 控制性:可以调整噪声的频率、振幅来控制细节和变化幅度。
2. 基本原理
柏林噪声的实现基于 格点插值。
2.1 输入坐标的划分
给定一个二维坐标(x, y),你首先需要确定它所在的网格单元。通常情况下,柏林噪声会将空间划分为许多格点(也称为 格点阵列)。
2.2 格点的随机值生成
每个格点都有一个固定的随机值(在一些实现中是随机方向的向量)。这意味着你并不是直接生成每个点的噪声,而是通过格点周围的随机值来进行插值计算。
2.3 平滑插值
对于输入坐标点(x, y),找到它所属的格点,并通过 插值(通常是 线性插值 或 余弦插值)计算该点的噪声值。插值确保了在格点之间的变化是平滑的。
2.4 梯度(Gradient)和向量插值
每个格点都有一个随机梯度,即一个随机的方向向量。通过计算输入点与格点之间的相对向量与该格点的梯度之间的点积来得到噪声值。这些值再通过插值来平滑过渡。
2.5 多频率噪声叠加
为了增强噪声的细节和复杂性,通常会叠加多个不同频率(缩放比例)和振幅的噪声层。这种方法被称为 Octaves(八度)。每个“八度”会产生一种不同尺度的噪声。
3.噪声地图
Unity提供了方便的工具类可以直接使用用于生成噪声地图
3.1 Noise
类:生成柏林噪声地图
1 | public static class Noise |
解释:
GenerateNoiseMap
方法是生成噪声地图的核心。它会根据输入的mapWidth
、mapHeight
和scale
生成一个二维的噪声图。Mathf.PerlinNoise(sampleX, sampleY)
是 Unity 内置的函数,用于生成一个在 [0, 1] 范围内的柏林噪声值。scale
控制噪声的细节:较大的scale
会生成平滑的噪声,而较小的scale
会生成细节更多的噪声。
3.2 MapGenerator
类:调用噪声生成器并显示地图
1 | public class MapGenerator : MonoBehaviour |
解释:
GenerateMap
方法调用Noise.GenerateNoiseMap
来生成一个噪声地图,并将其传递给MapDisplay
类的DrawNoiseMap
方法,渲染到屏幕上。autoUpdate
是一个标志,如果为true
,在每次修改参数后会自动更新地图。
3.3 MapDisplay
类:渲染噪声地图到纹理
1 | public class MapDisplay : MonoBehaviour |
解释:
DrawNoiseMap
方法负责将生成的噪声地图渲染为纹理并应用到指定的材质上。Color.Lerp(Color.black, Color.white, noiseMap[x, y])
:使用线性插值函数Lerp
将噪声值映射为黑白色调。噪声值越接近 1,颜色越白;越接近 0,颜色越黑。texture.SetPixels(colourMap)
和texture.Apply()
将颜色数据应用到纹理上,然后显示出来。
3.4 自定义编辑器(NewBehaviourScript
类)
1 | [ ] |
解释:
- 这是一个自定义编辑器,用来控制 Unity Inspector 中的行为。
GUILayout.Button("Generate")
创建一个按钮,点击后调用mapGen.GenerateMap()
生成地图。- 如果
autoUpdate
为true
,则在参数更改时自动更新地图。