想象一下,你是一名面包师,今天要烤一款“大理石面包”:深色面团的纹路要在浅色面团里蜿蜒成河流。如果你只是抓起一把芝麻盐撒进面团——那是“随机”:每一粒芝麻的位置和前一粒毫无关系,切开一看,像电视雪花屏一样支离破碎。真正的花纹需要“连贯”:你用手指在面团里反复揉压墨汁,墨汁沿着力场慢慢扩散,形成连绵的丘陵与河谷。游戏地形生成所依赖的噪声函数,就是那位藏在面团里的“墨汁艺术家”。Perlin 噪声像方格模具,Simplex 噪声像三角模具,fBm 则像一层层叠加压出来的大理石纹路。本文用揉面的语言,拆解噪声函数如何从网格、梯度与插值开始,最终揉出山川、云海和可复现的程序化世界。

岗位关联

对 AI 从业者来说,噪声是程序化内容生成(PCG)的地基:用一行伪随机场替代手工雕刻几千小时的地形、云层和洞穴,还能为强化学习智能体无限铺设训练场地并保证结果可复现。

目录
  1. 可视化演示
  2. 噪声基础概念
  3. 梯度噪声原理
  4. Simplex 演进
  5. fBm 分形叠加
  6. 地形应用实践
  7. 工程实现要点
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

展示Perlin噪声梯度插值生成伪随机场、fBm分形布朗运动多倍频叠加、以及地形高度图与等高线生成过程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

Perlin噪声场 网格角点梯度向量插值生成连续伪随机场 高值区域红色发光,低值区域深色,梯度箭头标示方向 n=lerp(g1,g2,fade(t)) 梯度插值确保噪声连续平滑,无方块伪影

噪声基础概念

面包师的案板上有一碗芝麻盐和一管墨汁。芝麻盐撒下去,每粒都在“独立行动”:你完全没法从第一粒猜出第二粒在哪,这就是随机;墨汁则不同,指尖一压,它沿着力场缓缓晕开,邻近位置的颜色总归相近。自然界的山峦、云层、木纹,全是这种“带着记忆的随机”。程序里,前者叫白噪声——每个采样点独立随机,像坏电视机的雪花屏;后者才配叫噪声——它保证相邻坐标输出值接近,这个性质叫连贯性。

噪声本质上是一个函数:输入坐标 (x, y),输出一个数。输入连续变化时,输出也连续起伏,像一块会呼吸的地毯,每根毛线都和邻居颜色相近。它和普通随机函数最大的区别在于“有结构的随机”:随机只是散点,噪声是地形。游戏引擎里的随机函数 random() 给不了你山,而半信半疑的 noise(x, y) 却可以。

值得强调:噪声函数大多由“伪随机”构造。伪随机不是假随机,而是“可复现的随机”——给它一个编号(种子 seed),它永远返回同一套地形。面包师把配方编号写在小黑板上:编号 42 的面团烤出来的纹路,明天重做一模一样。这对 AI 游戏开发至关重要:同一个种子 = 同一张地图,测试、复盘、多人联机才有一致的世界。

所以第一步的直觉是:芝麻盐代表无序,墨汁代表连贯,而配方编号代表可复现。噪声,就是用一颗“可控的随机种子”揉出来的天然花纹。

梯度噪声原理

墨汁为什么知道该往哪爬?因为面团里埋着什么?答案是“风向标”。1985 年,Ken Perlin 发明了梯度噪声:先把平面切成方方正正的棋盘格,在每一个格子的四个角上,各插一个随机方向的风向标——专业说法叫梯度向量。当墨汁(采样点)飘到网格内部时,四个角的风向标同时“吹风”,把墨汁往各自的方向推。

怎样衡量一个角的风向标对点的“推力”?用点积:风向标向量 g_i 点乘“从角指向采样点”的偏移向量 v_i。点积越大,说明风的方向和墨汁的走向越一致。四个角各算一次,得到四个贡献值。

接下来是“怎么把四个方向的拉力拧成一股绳”。直接用线性插值会在网格边界留下“折痕”,所以 Perlin 引入缓动函数 fade,让权重变化先慢后快再慢,像面团被反复折叠时受力均匀。

一句话:风向标决定“墨汁往哪个方向流”,点积决定“每个风标推多大力”,fade 决定“换格子时如何不露馅”。Perlin 噪声的美妙之处在于:每个格子独立设计风向,但相邻格子的风在边界上自然吻合,墨痕就连绵不绝了。棋盘格越多,面团纹理越细腻——这就是最朴素的“网格化随机”。

ni=g⃗i⋅v⃗i=gix⋅vix+giy⋅viy\displaystyle n_i = \vec{g}_i \cdot \vec{v}_i = g_{ix} \cdot v_{ix} + g_{iy} \cdot v_{iy}
\displaystyle f(t) = 6t^5 - 15t^4 + 10t^3,\quadN(x,y) = \sum_{i=0}^{3} w_i(u, v) \cdot n_i
  1. 梯度向量g_i 是网格角的随机单位向量,相当于风向标,每个角独立生成
    gi=(cos⁡θi,sin⁡θi)g_i = (\cos\theta_i, \sin\theta_i)
  2. 偏移向量v_i 是从角指向采样点的向量,表示“风从角吹向哪里”
    vi=(x−xi,y−yi)v_i = (x - x_i, y - y_i)
  3. 点积贡献把风向标投影到偏移方向,值越大说明该角对当前点推力越强
    ni=gixvix+giyviyn_i = g_{ix} v_{ix} + g_{iy} v_{iy}
  4. 缓动函数f(t) 在 0 和 1 端点处斜率为 0,保证跨网格时值变化平滑无折痕
    f(t)=6t5−15t4+10t3f(t) = 6t^5 - 15t^4 + 10t^3
  5. 加权求和w_i 是由缓动后的 u、v 计算的双线性权重,把四个推力的贡献融合成一个高度值
    N=w00n00+w10n10+w01n01+w11n11N = w_{00}n_{00} + w_{10}n_{10} + w_{01}n_{01} + w_{11}n_{11}

Simplex 演进

方形的千层糕有个毛病:接缝太“方正”。当你用方格模具切大理石纹路时,对角线方向总会出现肉眼可辨的直线伪影;更麻烦的是,方格在 n 维空间里需要 2 的幂次个角点参与计算——二维算 4 个角,三维算 8 个,四维算 16 个,指数爆炸让高维噪声寸步难行。Perlin 本人后来也意识到:方形网格并不是最优的“揉面模具”。

2001 年,Simplex 噪声登场。它把方格换成“单形”:二维是三角形,三维是四面体。三角形是二维里边数最少的形状,没有对角线,天然没有方形网格的轴对齐伪影;每个采样点最多落在 3 个角之间,计算量从 4 个点积降到 3 个,维度越高节省越夸张。但三角形需要先做一次坐标变换,把斜格子变回直角印象。

把方格模具换成蜂巢一样的三方模具,同样一坨面团,纹路少了一半“直棱直角”,细节更圆润自然。Simplex 在数学上更优雅:计算量接近线性增长,方向性伪影几乎消失,于是它成为许多引擎做 3D/4D 噪声时的首选。对小白而言,记住一句话就够了:Perlin 是在方格里插值,Simplex 是在三角形里插值——后者更快,也更像大自然。

x′=x−x+y2,y′=y−x+y2\displaystyle x' = x - \frac{x + y}{2}, \qquad y' = y - \frac{x + y}{2}
  1. 坐标切变先把正方形平面沿对角线“斜切”,使平铺单元变为三角形网眼
    (x,y)↦(x′,y′)(x, y) \mapsto (x', y')
  2. 单形判定根据 x 与 y 的大小关系,确定点落在哪个三角形内,只需取 3 个角点
    if x>y: (1,0),(1,1),(0,1)→3 个角\text{if } x > y:\ (1,0),(1,1),(0,1) \to \text{3 个角}
  3. 反向映射算出三角形内的局部坐标 u, v 后,再对 3 个角做梯度点积与插值,流程与 Perlin 相同但少一个角
    N=∑i=02wi′⋅ni′N = \sum_{i=0}^{2} w_i' \cdot n_i'

fBm 分形叠加

单一频率的噪声是什么样?它像一条均匀起伏的波浪线:要么全是大缓坡,要么全是小碎纹。可真正的山体同时拥有“大骨架”和“小细节”:远处是连绵的山脉走向,近处是嶙峋的岩壁裂纹。面包师的秘诀是分层揉压——先用大擀面杖压出墨汁的宏观河流,再用小模子刻出微观波纹,一层叠一层。

分形布朗运动(fBm)就是这个“多擀几杖”的数学版本。它把同一个噪声函数反复调用多次,每次调用叫一个倍频层(octave):频率按 lacunarity 倍数递增(波纹变密),振幅按 persistence 倍数递减(波纹变轻)。把各层叠加起来,就同时拥有低频的起伏骨架和高频的岩石肌理。

fBm 是地形生成的灵魂配方:octaves 决定揉几杖(层数),lacunarity 决定每次换多密的模子(频率),persistence 决定后几杖力度多轻(振幅)。大波浪提供山骨架,小波纹补充河床碎石;两者一叠,大理石面包立刻有了可攀爬的层次。这个“多层叠加”思想也广泛用于云层、木纹、水面波纹——凡是“大形中有小形”的自然物,都能用 fBm 揉出来。

fBm(x,y)=∑i=0n−1pi⋅noise(Li⋅x, Li⋅y)\displaystyle \text{fBm}(x, y) = \sum_{i=0}^{n-1} p^{i} \cdot \text{noise}\left(L^{i} \cdot x,\ L^{i} \cdot y\right)
  1. 层序号i 是当前倍频层的编号,从第 0 层(最粗)到第 n-1 层(最细)
    i=0,1,2,…,n−1i = 0, 1, 2, \dots, n-1
  2. 频率倍增L 是 lacunarity,通常取 2,每层频率翻倍,波纹越来越密
    fi=Li=2if_i = L^{i} = 2^{i}
  3. 振幅衰减p 是 persistence,通常取 0.5,每层振幅减半,细节不会盖过骨架
    ai=pi=0.5ia_i = p^{i} = 0.5^{i}
  4. 加权求和把每一层“频率不同、音量不同”的噪声累加
    fBm=a0n(f0x)+a1n(f1x)+⋯+an−1n(fn−1x)\text{fBm} = a_0 n(f_0 x) + a_1 n(f_1 x) + \dots + a_{n-1} n(f_{n-1} x)
  5. 归一化因为叠加会让数值范围膨胀,最后除以权重总和,让输出仍保持在约 -1 到 1 之间
    out=fBm∑iai\text{out} = \frac{\text{fBm}}{\sum_i a_i}

地形应用实践

同样的面团,换不同手法能揉出不同的花样。地形高度图是最直白的用法:把 fBm 的输出值当成海拔——值为 -1 是深海,0 是海岸线,1 是雪峰。每个像素一行代码,几百万格的地形就生成了。但想让山更有“棱角”,还得加点小技巧。

第一个技巧叫山脊噪声。自然界山脉不是圆润的土丘,而是锋利的刃脊。面包师把面团对折再对折,让波谷变成波峰。数学上只需对噪声取绝对值再取反:1 - |noise(x, y)|。原本平滑过渡的波谷会被“折叠”成 V 字形刻痕,溪流和悬崖瞬间有了。

第二个技巧叫域扭曲,专门用来做云。云朵边缘不是光滑的椭圆,而是絮状的、被风撕裂的。诀窍是:在采样地形之前,先用另一层噪声“搅乱”采样坐标——把 (x, y) 换成 (x + 2*fBm(x,y), y + 2*fBm(x,y)),就像面团还没擀开时先横竖搅了几圈,花纹立刻变得缠绕翻卷。

参数调优也顺手记下:想揉出温润丘陵,persistence 调低到 0.4;想要险峻的 Alpine 山脉,把山脊技巧叠两层并用 lacunarity=2.5;想制造大片层云,octaves 降到 3 并加大域扭曲系数。地面、云海、熔岩、木纹,本质是同一坨面团、不同手法——噪声函数是原料,fBm 是配方,而山脊与扭曲是你的揉面手法。

R(x,y)=1−∣fBm(x,y)∣\displaystyle R(x, y) = 1 - \left| \text{fBm}(x, y) \right|
terrain(x,y)=fBm(x+2⋅fBm(x,y), y+2⋅fBm(x,y))\displaystyle \text{terrain}(x, y) = \text{fBm}\left(x + 2 \cdot \text{fBm}(x, y),\ y + 2 \cdot \text{fBm}(x, y)\right)
  1. 绝对值取反把噪声的负值区域“折叠”到正侧,形成尖锐刻痕
    1−∣t∣1 - |t|
  2. 山脊映射fBm 输出越接近 0,山脊越高,形成刀刃般的棱线
    R=1−∣fBm∣R = 1 - |\text{fBm}|
  3. 偏移采样坐标把坐标本身交给另一个噪声函数扭曲,产生缠绕效果
    x′=x+k⋅fBm(x,y)x' = x + k \cdot \text{fBm}(x, y)
  4. 复合采样用扭曲后的坐标再采样一层 fBm,得到絮状云或风蚀地形
    out=fBm(x′,y′)\text{out} = \text{fBm}(x', y')

工程实现要点

面包店的生意越做越大,师傅开始写配方卡:编号 42 的面团,温度、湿度、揉压次数全部记录在案。工程上也一样,不能每次生成地形都“靠感觉”。把噪声函数封装成一个可复用的 API,是程序化内容生成的第一课——一个 Noise 类接收种子、倍频数、频率和振幅,内部藏好哈希表与梯度表,外部只暴露 fbm(x, y) 一个方法。

核心的工程细节是“哈希表梯度”。Perlin 噪声需要“同一网格角永远返回同一梯度”,否则画面会闪。做法是准备一张 256 长度的排列表(permutation table),用坐标哈希索引出梯度编号:gradient = GRAD[perm[perm[xi & 255] + yi & 255]]。这张表就是面包师的“号码牌”,保证每次路过同一个角,风向标都指向同一个方向。种子不同,号码牌的洗牌方式不同,地形自然不同;种子相同,一切复现。

最后是归一化与性能。fBm 叠加后数值范围可能超出 -1 到 1,需要把所有输出映射回统一区间,否则不同参数生成的地形高度不可比。

性能上,噪声函数是高频调用者:一帧渲染几百万像素,每一像素都要跑多层 fBm。常见优化有几种:降低 octaves 上限、用预生成的高度图纹理替代实时计算、把噪声计算搬进 GPU shader、按瓦片分块缓存。AI 游戏做地图生成时,宁可先离线烘焙好高度图,也不在运行时逐帧重算。

工程小结:封装 API 控制复杂度,哈希表保证梯度稳定,固定种子保证世界可复现,归一化保证参数可比,缓存策略保证帧率不崩。面包师有了配方卡,AI 游戏则有了“无限地图工厂”——每张新地图都是一次可复现的烘焙。

h(x,y)=fBm(x,y)−mM−m\displaystyle h(x, y) = \frac{\text{fBm}(x, y) - m}{M - m}
  1. 求极值m 和 M 分别是当前噪声场的最小值与最大值
    m=min⁡x,yfBm(x,y),M=max⁡x,yfBm(x,y)m = \min_{x,y} \text{fBm}(x,y),\quad M = \max_{x,y} \text{fBm}(x,y)
  2. 平移缩放减去最小值让最低点归 0,再除以范围让最高点归 1
    t−mM−m∈[0,1]\frac{t - m}{M - m} \in [0, 1]
  3. 映射高度将归一化值映射到实际海拔区间,供引擎直接建 mesh
    h=hmin⁡+t′⋅(hmax⁡−hmin⁡)h = h_{\min} + t' \cdot (h_{\max} - h_{\min})

AI 应用场景

开放世界地形的高度图生产

阶段:程序化内容生成(PCG)素材生产

解决的问题:手工雕刻一张 4096×4096 的开放世界地图需要美术团队数周,且难以快速尝试“多山”或“多水”的不同风格。用 fBm 噪声生成高度图,改几个参数就能秒出一条新地形。

具体案例:某游戏技术美术团队用 octaves=6, lacunarity=2, persistence=0.5 生成大陆骨架,再叠加山脊噪声制造山脉棱线,最后用域扭曲生成河谷与冲积平原,把整个出生点区域的地形打磨时间从 3 周压缩到 2 小时。

云层与天气系统的动态纹理

阶段:渲染/纹理合成

解决的问题:静态贴图云层在镜头拉近时会出现“纸片感”。域扭曲噪声可以为云层提供絮状、翻卷的动态轮廓,让云朵边缘随时间连续变形。

具体案例:飞行模拟游戏用两层 fBm——上层低频控制云团整体分布,下层高频加域扭曲让边缘产生毛絮;再叠加时间偏移量让云层缓慢流动,玩家飞入云中时视线模糊过渡自然。

强化学习智能体的无限训练场地

阶段:AI 训练环境生成

解决的问题:强化学习智能体在单一地图上训练容易过拟合,需要不断更换地形;但完全随机地图又会导致训练不稳定。噪声 + 固定种子可以批量生成“风格一致但细节不同”的训练场。

具体案例:机器人足球 AI 团队用 seed 枚举 1000 个由 fBm 生成的随机球场——斜坡、坑洼、障碍物分布都由同一套噪声参数派生,保证难度曲线一致,同时测试智能体的环境泛化能力。

Python 演示

python65 行
import mathimport random  class PerlinNoise2D:    """Compact 2D Perlin noise with a fixed seed."""    GRAD = ((1, 0), (-1, 0), (0, 1), (0, -1),            (1, 1), (-1, 1), (1, -1), (-1, -1))     def __init__(self, seed=42):        rng = random.Random(seed)        p = list(range(256))        rng.shuffle(p)        self.perm = p * 2     @staticmethod    def _fade(t):        return t * t * t * (t * (t * 6 - 15) + 10)     @staticmethod    def _grad(h, x, y):        gx, gy = PerlinNoise2D.GRAD[h & 7]        return gx * x + gy * y     def noise(self, x, y):        xi, yi = math.floor(x), math.floor(y)        xf, yf = x - xi, y - yi        u, v = self._fade(xf), self._fade(yf)        X, Y = xi & 255, yi & 255        n00 = self._grad(self.perm[self.perm[X] + Y], xf, yf)        n10 = self._grad(self.perm[self.perm[X + 1] + Y], xf - 1, yf)        n01 = self._grad(self.perm[self.perm[X] + Y + 1], xf, yf - 1)        n11 = self._grad(self.perm[self.perm[X + 1] + Y + 1], xf - 1, yf - 1)        return (n00 + u * (n10 - n00) + v * (n01 - n00)                + u * v * (n11 - n10 - n01 + n00))     def fbm(self, x, y, octaves=5, lacunarity=2.0, persistence=0.5):        total = 0.0        amplitude = 1.0        freq = 1.0        max_amplitude = 0.0        for _ in range(octaves):            total += amplitude * self.noise(x * freq, y * freq)            max_amplitude += amplitude            amplitude *= persistence            freq *= lacunarity        return total / max_amplitude  def render_terrain(seed=42, width=48, height=20, octaves=5):    noise = PerlinNoise2D(seed)    chars = " .,:*?#"    for row in range(height):        line = []        for col in range(width):            x = col / width * 8            y = row / height * 5            h = noise.fbm(x, y, octaves)            idx = min(len(chars) - 1, int((h + 1) * 0.5 * len(chars)))            line.append(chars[idx])        print("".join(line))  if __name__ == "__main__":    render_terrain(seed=2024)
目的:完整实现 Perlin 噪声与 fBm 分形叠加,并输出一段 ASCII 可视化地形,帮助理解噪声如何生成高度图。
  1. self.perm = p * 2排列表复制一份,避免索引越界,同时保证哈希查找速度
  2. _grad(h, x, y)从 8 个预定义方向中取一个梯度向量,与偏移量做点积
  3. X, Y = xi & 255, yi & 255对网格坐标取模,映射到排列表长度内
  4. n00 + u * (n10 - n00) + v * (n01 - n00)双线性插值主体,合并四个角点贡献
  5. amplitude *= persistence振幅逐层衰减,让高频细节不掩盖低频骨架
  6. freq *= lacunarity频率逐层倍增,让每层噪声的波纹越来越密
  7. idx = int((h + 1) * 0.5 * len(chars))把归一化高度映射到字符表下标,实现可视化

常见误区

误区噪声不就是 `random()` 吗?我写个随机数数组,把每个格子的高度随机赋一个值,不也能当地形吗?为什么大家不用?

正解普通随机函数生成的“白噪声”每个点独立,相邻点之间没有关联,看起来像一屏雪花,完全没有山体轮廓。噪声函数的核心价值是连贯性:相邻坐标输出相近,中间值平滑过渡。地形要的是“随机中有秩序,无序中有连绵”,这正是噪声区别于随机数的地方。

为何常见:两者都叫“随机”,且底层都用伪随机数生成器,初学者很容易混淆“随机取值”和“随机场”的差别。

误区只要有一个噪声函数,我把参数随便填一填,就能自动生成完美的山谷、河流、雪线分布,完全不需要人工调整。

正解噪声生成的只是“连续随机场”,要变出具体地形还得靠工程配方:高度图需要归一化映射,山脊需要绝对值取反,河流需要按高度阈值二次处理。参数调优同样关键——没有正确设置 octaves 与 persistence,出来的可能是“一马平川”或“毫无章法的碎渣”。

为何常见:看过几个华丽演示后,容易把“底层工具”当成“完整方案”,忽略了 PCG 中大量后处理步骤。

误区既然 Simplex 更快又没有伪影,所有项目都该用 Simplex,Perlin 是过时的老古董,学了没用。

正解Simplex 在计算复杂度和方向性伪影上确实更优,尤其适合 3D 以上噪声;但 Perlin 在 2D 教学中更直观,代码实现更短,数学结构更清晰,很多成熟引擎和教材仍以它为基础。先吃透 Perlin 的“网格-梯度-插值”思想,再看 Simplex 的坐标变换,理解成本反而更低。

为何常见:性能对比数字看起来“一边倒”,新手容易陷入“谁强用谁”的二元思维,忽略教学价值与适用场景差异。

误区fBm 的 octaves 加到 8 层、10 层,细节肯定更丰富,地形一定更漂亮;反正计算量不是问题。

正解超过 5-6 层后,细节增量急剧减小——每层振幅按 persistence 衰减,后面几层贡献接近零,却要付出成倍的采样成本。高 octaves 还会引入高频噪点,让山体显得“脏”。工程上要按视距和分辨率平衡:远景 3 层足够,近景 5 层封顶。

为何常见:“叠加越多越精细”符合日常直觉,但没意识到振幅衰减让高层贡献趋近于零,属于非线性收益递减。

误区种子参数随便填,反正每次生成的随机地图都不一样,也很有趣。

正解AI 训练和 QA 测试最怕“每次都不一样”:智能体跑第五万回合时地形突变,bug 无法复现,排行榜无法对比。固定种子是 PCG 的第一工程纪律——同一种子必须产生同一地形,这样才能复现问题、对比算法、做跨团队协作。

为何常见:演示阶段“每次不同”很惊艳,但进入工业化管线后,可复现性远比新鲜感重要;新手往往在踩了“无法定位 bug”的坑后才意识到种子值的意义。

面试题

Q1. 关于“白噪声”和“噪声”的关键区别是?

单选题 · easy

  • A.前者靠随机数函数实现
  • B.后者要求相邻点连贯← 正确答案
  • C.前者不可用于游戏开发
  • D.后者完全不含随机性

答案:B。白噪声每个点独立,像雪花屏;噪声强调连贯性,相邻坐标输出相近。A 是错误因果,C 和 D 都过于绝对。噪声既依赖随机数,又通过插值建立空间连贯,选 B。

Q2. Perlin 噪声最核心的思路是?

单选题 · easy

  • A.网格角点放梯度向量← 正确答案
  • B.直接把随机数相乘
  • C.对每个像素查全表
  • D.用正弦函数无限叠加

答案:A。Perlin 噪声把平面切成网格,在每个角点放置随机梯度向量,再通过点积与插值得到连续值。B 无法产生连贯性,C 不是噪声的思路,D 是无根据的猜测。

Q3. fade 缓动函数在噪声中的作用是?

单选题 · easy

  • A.让插值更平滑自然← 正确答案
  • B.让梯度变成矢量
  • C.加快采样循环速度
  • D.让噪声值变为整数

答案:A。fade 函数在 0 和 1 两端斜率为 0,使网格边界的导数连续,避免线性插值的折痕感。梯度向量由随机方向生成,与 fade 无关,C 和 D 也不符合 fade 的职责。

Q4. Simplex 噪声相比 Perlin 的核心改进是?

单选题 · mid

  • A.使用三角单形节省预算← 正确答案
  • B.完全不需要梯度向量
  • C.只适合三维空间使用
  • D.输出永远是固定常数

答案:A。Simplex 用三角形(单形)代替方格,每个点只需 3 个角点贡献,计算更少、伪影更少。它仍需要梯度向量,可用于任意维度,输出也非线性,故选 A。

Q5. fBm 合成中常用的三个参数是?

多选题 · mid

  • A.倍频叠加层数 octaves← 正确答案
  • B.频率倍增系数 lacunarity← 正确答案
  • C.振幅衰减系数 persistence← 正确答案
  • D.光照明暗调节参数

答案:ABC。fBm 的三个核心旋钮是 octaves(层数)、lacunarity(频率倍增)、persistence(振幅衰减)。光照参数属于渲染阶段,不在噪声合成流程中。

Q6. 当 lacunarity 增大时,下一层噪声会?

单选题 · mid

  • A.频率更高细节更细← 正确答案
  • B.频率更低整体更平
  • C.振幅持续变大
  • D.输出值全部翻倍

答案:A。lacunarity 是层间频率的倍增系数,取 2 表示频率翻倍、波纹更密、细节更细。振幅由 persistence 控制,与 lacunarity 无关,C 和 D 是干扰项。

Q7. 生成“山脊噪声”的常用技巧是?

单选题 · mid

  • A.对噪声绝对值取反← 正确答案
  • B.把噪声值整体乘二
  • C.改用白噪声求和均值
  • D.交换噪声的通道

答案:A。1 - |noise| 能把波谷折叠成 V 形刻痕,制造刀刃般的山脊。整体乘二只会拉伸高度,白噪声无连贯性,交换通道不改变地形结构。

Q8. 一个完整 Perlin 噪声实现需要包含?

多选题 · hard

  • A.随机排列哈希表← 正确答案
  • B.顶点梯度向量点积← 正确答案
  • C.缓动函数与插值← 正确答案
  • D.学习率反向传播

答案:ABC。Perlin 的三块基石:permutation 表提供确定性哈希,梯度向量做点积贡献,fade 与双线性插值合成连续场。反向传播属于深度学习,与噪声生成无关。

Q9. 固定随机种子最重要的工程意义是?

单选题 · hard

  • A.保证地形可复现测试← 正确答案
  • B.让噪声运行得更快
  • C.让噪声没有规律统计
  • D.替代所有纹理缓存

答案:A。同一种子生成同一地形,是复现 bug、对比算法、团队协作的前提。种子不参与性能,也不消除统计规律,更不能替代纹理缓存,故选 A。

Q10. 关于域扭曲(domain warping)的正确说法是?

多选题 · extreme

  • A.用噪声偏移采样坐标← 正确答案
  • B.适合生成絮状云层← 正确答案
  • C.会破坏低频连续性
  • D.需要双倍噪声调用← 正确答案

答案:ABD。域扭曲先算一层噪声,用它偏移原始坐标后再采样第二层噪声,因此需要双倍调用,能产生云絮和卷曲纹理。它不破坏低频连续性——恰恰相反,它是在已有噪声场上施加连续变形,故选 ABD。