资讯动态

深入理解 Perlin 噪声:p5.js 中的 noise() 原理、历史与创意编程应用

发布时间:2026/10/15 20:13:57 来源:尧图企业网站定制
教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载本篇技术指南源自 Coding Train 网站存档中 Perlin Noise 系列课程_learning/noise/的 Introduction 章节_learning/noise/0.2-inroduction.md系统讲解 Perlin 噪声是什么、它是如何被发明与构造的、它与普通random()的本质区别以及在 p5.js 中noise()的具体用法。读者读完本文将掌握如何用一维噪声驱动平滑运动、如何绘制一维噪声曲线、如何用二维/三维噪声生成地形、粒子流场与动画纹理并理解noiseDetail()、noiseSeed()等底层参数的真实作用。系列课程定位这是什么、讲给谁_learning/noise/目录是一个多集 Perlin Noise 教程系列playlist_idPLRqwX-V7Uu6bgPNQAdxQZpJuJCjeOr7VD从index.md的描述可以看出它是一组“关于 p5.jsJavaScript与 ProcessingJava中噪声算法的视频集合”。本系列各章节依次为章节文件核心主题I.2 Introduction0.2-inroduction.mdPerlin 噪声是什么、如何产生及其历史I.3 noise() vs random()0.3-noise-vs-random.md对比noise()与random()两种随机数函数I.4 Graphing 1D0.4-graphing-1d.md绘制一维 Perlin 噪声曲线并与随机性对比I.5 2D Noise0.5-2d-noise.md在 p5.js 中使用二维 Perlin 噪声本篇文章以 IntroductionI.2为主体同时结合仓库中 I.3I.5 的配套示例源码与 p5.js 库实现把“噪声是什么、从哪来、怎么用”讲透。Perlin 噪声是什么平滑的“类随机”信号Perlin 噪声是一种由 Ken Perlin 于 1980 年代发明的随机序列生成器它产生的数字序列相比普通的random()更具“自然的秩序感与和谐感”。在 p5.js 的官方文档描述中它被用来生成程序化纹理、自然运动、形状与地形等效果。理解它的关键在于对比两种随机random()每次调用都返回一个独立、互不相关的随机数前后两次取值之间没有任何连续性。你无法预测前一步与后一步的差异表现上是“杂乱无章”的抖动。noise()返回值介于0.01.0之间且相邻输入坐标对应的输出值高度平滑连续。输入坐标变化得越小输出变化得越平缓输入坐标之间的距离决定了噪声的“频率”与平滑程度。在仓库配套示例learning/noise/0.3-noise-vs-random/P5/sketch.js中两种方式的效果被直接对照let xoff 0; function setup() { createCanvas(400, 400); } function draw() { background(51); // let x random(width); // 随机小球位置每帧跳变 let x map(noise(xoff), 0, 1, 0, width); // 噪声小球平滑移动 xoff 0.01; ellipse(x, 200, 24, 24); }把注释行取消即可看到对比使用random(width)时小球在水平方向随机跳动位置毫无规律使用map(noise(xoff), 0, 1, 0, width)时小球会沿着一条平滑的路径来回摆动。这正是噪声的核心价值——在保持“不可预测的随机感”的同时输出相邻取值连续、像一个自然信号。为什么叫“噪声”从 p5.js 源码仓库中的CodingChallenges/CC_166_Ascii_Image/ascii-text/p5.js可以看出noise()的实现结构与“音频信号”非常相似The actual noise is structured similar to an audio signal, in respect to the functions use of frequencies... perlin noise is computed over several octaves which are added together for the final result.也就是说Perlin 噪声像音频一样由若干**倍频程octave**叠加而成低倍频程决定信号的整体轮廓高倍频程补充精细细节——这直接对应到下文要讲的noiseDetail()参数。历史Ken Perlin 与《电子世界争霸战》本系列 Introduction 视频video_idQf4dIN99e2w明确交代了噪声的起源Ken Perlin 于 1980 年代发明了该算法当时他在为电影《Tron》《电子世界争霸战》开发特效需要一种能生成“自然、有机纹理”的数学方法以替代当时人工手绘纹理的繁琐工作。Perlin 噪声随后被广泛应用于图形学领域用于生成程序化纹理、自然运动、地形、云层、火焰等效果。p5.js 官方文档中也有印证“It was invented by Ken Perlin in the 1980s and been used since in graphical applications to produce procedural textures, natural motion, shapes, terrains etc.”见ascii-text/p5.js。关键的历史性贡献在于Perlin 噪声定义在一个无限维的噪声空间中空间中每一组坐标都对应一个固定的半随机值在程序生命周期内固定。这带来了两个推论输入坐标本身决定输出同一个坐标永远返回同一个值除非重新播种可以在噪声空间里“漫游”通过不断改变输入坐标例如每帧xoff 0.01就能让输出值沿平滑路径随时间演化——这就是noise()动画化的基本原理。p5.js 中 noise() 的调用规则p5.js 的noise()支持 1D、2D、3D 三种用法取决于传入的坐标个数源码签名见ascii-text/p5.jsnoise(x); // 一维噪声返回 0.0~1.0 noise(x, y); // 二维噪声 noise(x, y, z); // 三维噪声第三维常被当作“时间轴”几个核心使用要点返回值恒在 [0, 1]因此通常配合map()把噪声值映射到画布坐标、颜色或角度范围。坐标增量决定平滑度p5.js 文档给出的经验范围是0.0050.03的效果最佳——增量越小曲线越平滑增量越大抖动越剧烈。上文示例中xoff 0.01即落在推荐区间。可动画化在draw()中让输入坐标持续递增或把 z 维当作时间轴噪声输出就会随时间平滑变化产生“流动”的效果。坐标可以是负值源码中会对负数坐标取绝对值if (x 0) { x -x; }见ascii-text/p5.js因此不必担心传入负坐标。噪声空间是“无限”的起点的绝对值不重要重要的是连续两次采样之间的距离。这也是为什么教程中习惯用一个持续累加的xoff而不是直接用像素坐标。底层实现梯度、余弦插值与倍频程叠加从仓库中 p5.js 的源码可以看到noise()的真实计算流程ascii-text/p5.js将输入坐标拆分为整数部分xi, yi, zi与小数部分xf, yf, zf整数部分用于索引预生成的随机值表perlin[]大小为PERLIN_SIZE 4095对小数部分使用scaled_cosine()做余弦缓动插值0.5 * (1.0 - cos(i * PI))见ascii-text/p5.js这样插值在端点处斜率趋零曲线更平滑在 X/Y/Z 三个方向上逐级做线性插值得到该八度octave的贡献将各倍频程按ampl初始 0.5累加每过一个倍频程幅值乘以perlin_amp_falloff默认 0.5并把坐标翻倍xi 1; xf * 2;进入更高频的下一层循环perlin_octaves默认 4次后返回累加结果。这段实现直接解释了为什么噪声既平滑又有细节——低倍频程提供大尺度轮廓高倍频程叠加微小起伏这就是 Perlin 噪声“自然感”的数学来源。noise() 与 random() 的深度对比I.3 章节0.3-noise-vs-random.md专门对比了这两个“返回随机数”的函数核心差异总结如下维度random()noise()返回值范围取决于参数如random(width)返回 0width恒为 0.01.0连续性每次调用彼此独立前后无关联相邻输入坐标的输出连续平滑一维空间一维随机数流无空间概念定义在无限维噪声空间中坐标决定取值动画效果逐帧跳变、闪烁、抖动平滑运动、流动、有机演化可控性只能控制范围可通过坐标增量、noiseDetail()调节平滑度与细节典型用途随机位置、随机选择地形、流场、运动轨迹、程序化纹理实践中的选择标准很简单如果希望效果“抖”、完全无规律用random()如果希望效果“自然流动、平滑变化”用noise()。例如粒子系统里用random()做随机初速度、用noise()做随时间演化的风力两者互补使用是创意编程的常见组合。绘制一维噪声曲线可视化随机与噪声的差异I.4 章节0.4-graphing-1d.md通过把噪声值画成曲线来直观展示其性质。仓库提供了三个可运行变体learning/noise/0.4-graphing-1d/下的noise-graph、y-axis、noisy-sin三个子目录。基础版噪声曲线 vs 随机曲线核心代码learning/noise/0.4-graphing-1d/noise-graph/sketch.jslet inc 0.01; let start 0; function setup() { createCanvas(400, 400); } function draw() { background(51); stroke(255); noFill(); beginShape(); let xoff start; for (let x 0; x width; x) { // let y random(height); // 换成这行曲线变成杂乱毛刺 let y noise(xoff) * height; vertex(x, y); xoff inc; } endShape(); start inc; // 每帧整体平移曲线随时间“流动” }这个示例同时演示了三个概念逐像素采样从左到右每个 x 采样一个noise(xoff)值并乘以画布高度xoff以inc 0.01步进流动动画start inc让整条曲线在每帧沿 x 方向平滑滚动这是“在噪声空间中移动”的直接体现与随机的对照把noise(xoff) * height换成random(height)曲线立即变成布满毛刺的乱线——一帧内像素间毫无连续性。尝试修改inc如 0.001、0.05可以直观感受到inc越小曲线越平滑越大越粗糙这印证了“坐标增量决定噪声频率”的规则。变体一加 Y 轴——独立噪声驱动的二维漫游learning/noise/0.4-graphing-1d/y-axis/sketch.js用两个独立的噪声游标分别控制 x 与 ylet xoff1 0; let xoff2 10000; // 拉开两个游标的起点避免二者相关 function setup() { createCanvas(400, 400); } function draw() { background(51); let x map(noise(xoff1), 0, 1, 0, width); let y map(noise(xoff2), 0, 1, 0, height); xoff1 0.01; xoff2 0.01; ellipse(x, y, 24, 24); }这里有一个关键技巧两个噪声游标必须从相距很远的坐标起步xoff1 0、xoff2 10000。因为噪声空间中相邻区域的取值是相关的若两者都从 0 开始且以相同步长递增x 与 y 会产生相似的运动轨迹拉开距离后两个方向就各自独立、互不相关。这种“为每个运动自由度分配独立的噪声游标”的手法在后面的粒子系统中会被反复使用。变体二Noisy Sin——正弦波加噪声扰动learning/noise/0.4-graphing-1d/noisy-sin/sketch.js演示了噪声与确定性波形叠加的经典组合let n map(noise(xoff), 0, 1, -50, 50); // 噪声作为扰动映射到 -50~50 let s map(sin(xoff), -1, 1, 0, height); // 基础正弦波 let y s n; // 叠加正弦波提供规律起伏的骨架噪声在其上叠加小幅随机扰动得到“规律但不呆板”的自然波形。文件注释中还保留了其他实验写法如height / 2 sin(xoff) * height / 2与noise(xoff) * 100 ...展示了从纯正弦到纯噪声的过渡区间适合读者逐个尝试感受组合效果。这种“确定性波形 噪声扰动”的思路广泛用于模拟水面、呼吸、旗帜飘动等自然运动。二维噪声逐像素生成程序化纹理I.5 章节0.5-2d-noise.md把噪声扩展到二维对画布上每一个像素以该像素对应的(xoff, yoff)采样noise(xoff, yoff)得到一张平滑连续的灰度纹理。仓库示例learning/noise/0.5-2d-noise/P5/sketch.jslet inc 0.01; function setup() { createCanvas(200, 200); pixelDensity(1); // 关闭高分屏缩放保证像素数组尺寸与画布一致 } function draw() { let yoff 0; loadPixels(); for (let y 0; y height; y) { let xoff 0; for (let x 0; x width; x) { let index (x y * width) * 4; let r noise(xoff, yoff) * 255; // 换成 random(255) 则变成静态噪点 pixels[index 0] r; pixels[index 1] r; pixels[index 2] r; pixels[index 3] 255; xoff inc; } yoff inc; } updatePixels(); }实现要点与底层含义双重循环 双游标每行y一个yoff行内每个像素x一个递增的xoff。这样(xoff, yoff)就像在二维噪声平面上做“蛇形扫描”采样点之间保持恒定间距inc确保纹理各方向平滑一致。pixel 数组四通道p5.js 像素数组中每个像素占 4 个连续索引R、G、B、A因此index (x y * width) * 4同灰度纹理即 RGB噪声值。pixelDensity(1)的必要性在高 DPI 屏幕上像素密度大于 1 时pixels数组的实际尺寸会放大二维纹理的索引映射会出错因此示例显式关闭了像素密度。换掉噪声试试把noise(xoff, yoff) * 255换成random(255)得到的将是一屏静态颗粒噪点雪花屏——这就是“随机 vs 噪声”在二维上的终极对比。去掉noLoop()注释试试当前每帧重算纹理会有轻微“呼吸”感取消注释后只绘制一帧纹理静止适合作为背景。二维噪声是所有“有机纹理类”效果的基础云朵、水面、火焰、地形高度图均由此演化而来。三维噪声把第三维当作时间轴noise(x, y, z)的三维形式在本系列之后被大量使用核心技巧是把 z 当作时间轴固定(x, y)采样点随时间递增 z该点噪声值就沿平滑路径演化从而让整幅二维噪声图“流动”起来。仓库中有多个成熟用例流场Flow FieldCodingChallenges/CC_024_PerlinNoiseFlowField/P5/sketch.js中每个网格单元计算noise(xoff, yoff, zoff) * TWO_PI * 4作为向量角度zoff 0.0003让整个向量场随时间缓慢演化300 个粒子跟随场运动形成有机漂流的轨迹。这里第三维的增量0.0003远小于前两维0.1因为时间轴的变化应该比空间轴更缓慢、更平滑。地形TerrainCodingChallenges/CC_011_PerlinNoiseTerrain/P5/sketch.js用noise(xoff, yoff)生成高度值存入地形网格flying - 0.1作为全局偏移让整片地形在 WEBGL 画布上持续起伏飞行map(noise(...), 0, 1, -100, 100)把噪声映射为顶点高度。雪景风力CodingChallenges/CC_088_snowfall/P5/sketch.js中每片雪花以其归一化位置采样noise(xOff, yOff, zOff) * TWO_PI得到风向角度zOff 0.1使风场随时间漂移雪花随之摇曳下落。火焰冷却图案CodingChallenges/CC_103_Flames/P5/sketch.js用pow(noise(xoff, yoff), 3) * 255生成冷却图pow(..., 3)压缩噪声分布让暗区更多模拟火焰的明暗形态。可以看到“坐标增量”与“采样范围”决定了噪声的尺度与流动速度——这是三维噪声使用中最值得反复调参的两个旋钮。调节噪声性格noiseDetail() 与 noiseSeed()noiseDetail(lod, falloff)控制细节层次noiseDetail()调整噪声的“性格”两个参数p5.js 文档见ascii-text/p5.jslodoctaves 数量默认4。低倍频程低频决定整体轮廓高倍频程高频补充细碎细节。lod越大细节越丰富但计算量线性增加。falloff每倍频程衰减因子默认0.5即每个倍频程的贡献是前一个的 50%。取值 0.01.0 有效注意大于 0.5 时noise()返回值可能超过 1.0超出 [0, 1] 的约定范围。源码中的默认值与叠加逻辑ascii-text/p5.js与ascii-text/p5.jsvar perlin_octaves 4; // 默认 4 个倍频程 var perlin_amp_falloff 0.5; // 默认每层衰减 50% // 每层循环中r n1 * ampl; ampl * perlin_amp_falloff;直观体验noiseDetail(2, 0.2)得到大尺度、平滑的轮廓noiseDetail(8, 0.65)得到细节更丰富、起伏更尖锐的曲线p5.js 文档示例即用这两种设置对比绘制了两幅纹理。在同一 sketch 中反复调用noiseDetail()会影响后续所有noise()的取值因此要么在setup()中一次性设置要么在调用前明确切换。noiseSeed(seed)固定随机序列默认情况下noise()每次运行程序都产生不同的序列因为底层随机值表用Math.random()初始化见ascii-text/p5.js。若想让每次运行生成相同的噪声结果例如复现某个地形、或让多人看到同一纹理调用noiseSeed(seed)即可。源码实现采用线性同余生成器LCGascii-text/p5.js// Linear Congruential Generator源码注释Variant of a Lehmer Generator var m 4294967296; // 模数决定周期上限 var a 1664525; // 乘数a-1 应被 m 的质因数整除 var c 1013904223; // 增量与 m 互质 // z (a * z c) % m; 返回 z / m落在 [0, 1)noiseSeed(seed)用该生成器以固定种子重新填充噪声值表perlin[]PERLIN_SIZE 4095项从而让noise()的整个空间确定性可复现。注意noiseSeed()与randomSeed()是两套独立的随机体系分别只影响noise()和random()。应用案例把噪声放进真实项目除了本系列教程整个仓库中 Perlin 噪声几乎无处不在可作为延伸阅读与实战参照粒子流场CC_024_PerlinNoiseFlowField——三维噪声驱动 300 粒子沿平滑场漂移是最经典的噪声创意案例3D 地形CC_011_PerlinNoiseTerrain——map(noise(xoff, yoff), 0, 1, -100, 100)生成地形高度网格配合 WEBGL 实时渲染火焰效果CC_103_Flames——pow(noise(xoff, yoff), 3)生成流动的冷却图案控制火焰形态雪景CC_088_snowfall——用三维噪声生成随时间漂移的风场让雪花自然摇曳极坐标噪声环CC_136_Polar_Noise_Loop_1与CC_136_Polar_Noise_Loop_2内含noiseLoop.js工具——把噪声映射到极坐标并做成无缝循环动画Perlin 噪声地形挑战_CodingChallenges/011-perlinnoiseterrain.md配套的完整文档。在这些项目里反复出现的模式是先为每个自由度准备独立的噪声游标xoff/yoff/zoff再以恒定的微小增量在draw()中推进游标最后用map()把 [0,1] 噪声值映射到坐标、角度或颜色。掌握这一模式就能把本系列的入门知识直接移植到任何需要“自然演化”的创意编程场景中。学习路径与运行方式文档索引本系列总览见_learning/noise/index.md按 I.2 → I.3 → I.4 → I.5 的顺序学习即可由浅入深。示例源码I.3 的对比示例在learning/noise/0.3-noise-vs-random/P5/sketch.jsI.4 的三个绘图变体在learning/noise/0.4-graphing-1d/I.5 的二维纹理在learning/noise/0.5-2d-noise/P5/sketch.js。运行方式各示例的index.html通过 CDN 引入 p5.js仓库示例固定为p51.4.1见learning/noise/0.3-noise-vs-random/P5/index.html直接用浏览器打开 HTML 文件即可运行无需构建工具修改sketch.js中的inc、xoff增量或noiseDetail()参数即可观察噪声性格的变化。延伸资料p5.js 的noise()、noiseDetail()、noiseSeed()的完整参考文档内嵌于仓库自带的 p5.js 库文件CodingChallenges/CC_166_Ascii_Image/ascii-text/p5.js中查阅该文件的源码注释可获取最权威的参数说明本教程的理论背景与 Daniel Shiffman 的著作《The Nature of Code》一脉相承仓库中的_learning/nature-of-code/目录是其配套学习资料。结语Perlin 噪声之所以能成为创意编程的基石在于它用简单的一维随机值表 余弦插值 倍频程叠加就构造出了一个“处处连续、无限可漫游、性格可调、种子可复现”的数学空间。从本系列 I.2 的历史与原理出发配合 I.3I.5 的对比示例你已经掌握了noise()的全部核心用法一维驱动平滑运动、二维生成程序化纹理、三维制造随时间流动的场再用noiseDetail()与noiseSeed()精细调控输出性格。接下来不妨在流场、地形、火焰等仓库案例中动手调整参数感受噪声从“随机数”到“自然信号”的质变。赞分享教程文档示例工程【免费下载链接】website-archiveArchive of the Coding Train website (first version)项目地址https://gitcode.com/gh_mirrors/we/website-archive点击查看免费下载相关推荐p5.js 二维 Perlin 噪声2D Noise实战指南从一维到二维的逐像素生成原理p5.js 二维 Perlin 噪声2D Noise实战指南从一维到二维的逐像素生成原理 Perlin 噪声Perlin Noise是创意编程中生成平教程文档示例工程推荐项目Python中的高性能Perlin噪声库——noise推荐项目Python中的高性能Perlin噪声库—— noise 1、项目介绍 在Python编程中寻找一种简单且快速的方法来生成Perlin噪声吗那么 n图形学游戏开发Python中的Perlin噪声库——noise安装与配置完全指南Python中的Perlin噪声库——noise安装与配置完全指南 项目基础介绍 noise是一个专为Python设计的Perlin噪声库由Casey D图形学游戏开发创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑