Perlin noise(一)
Perlin noise(一)
一、分形噪声
分形几何学的基本思想是:客观事物具有自相似的层次结构,局部与整体在形态、功能、信息、时间、空间等方面具有统计意义上的相似性,称为自相似性。客观自然界中许多事物,具有自相似的“层次”结构,在理想情况下,甚至分形分形至具有无穷层次。适当的放大或缩小事物的几何尺寸,整个结构并不改变。不少复杂的物理现象,背后就是反映着这类层次结构的分形几何学。分形思想的提出让我们了解事物的本质更进一步,同时也提供了一种研究问题的方法,那就是通过叠加来最终模拟出超乎想像的自然物体。更通俗易懂的来说,分形就是把复杂的自然物体分成一个个的简单形态,这有点像傅立叶提出的“任何连续周期信号可以由一组适当的正弦曲线组合而成”,事实证明傅立叶是对的,即便是拉格朗日也阻止不了。反过来说,可以由简单的形态通过无限次的叠加来模拟自然现象。
这是计算机图形学家利用分形理论通过迭代算法最终生成的精美图像。分形理论打开了图形学描述自然的一扇大门,影响着图形学、几何学的发展。在了解完分形概念之后,我们再来回顾一些基本知识。
波长(Wavelength):指的是两个波谷(波峰)之间的距离
振幅(amlitude):指波的高度
频率(frequency):指的是波的振动快慢,频率就是1/波长
在正弦波中,他们非常容易区分。在噪声波中,也有波长,振幅,频率之分,如下图所示。
波长(Wavelength):指的是波峰与波谷之间的距离
振幅(amlitude):指波的高大高度
频率(frequency):指的是波的振动快慢,频率就是1/波长
持续度(Persistence):这个词是由《大自然的分形几何学》[波] 伯努瓦·B. 曼德布罗特(Mandelbrot)引入的,Mandelbrot开创了分形几何先河。持续度指的是表示每个频率下的振幅,也可以看成是柔合了频率和振幅,或者说是分形中某种单一层次分形波的特征,持续度展示了叠加的每个组成部分:
下图中,Persistence值分别为 1/4, 1/2 与 3/4。可以看出不同的Persistence值对每个倍频的频率和波幅以及最后结果的影响。(注:以下若干图片来自参考文献3)
倍频 (Octaves):从字面上来理解,倍频就是加倍的频率,也是分形叠加中叠加的某种单一层次分形波的特征,倍频不一定是2倍,也可以是其他倍数,如4倍频与8倍频,倍频越高越多,最后得到的波形包含的细节越多,也越自然。
为加深理解,我们来看看在频率加倍,振幅减半的一维perlin 噪声。
可以看到,随着频率的升高,在同一尺度下提供了更高的细节,但波动(振幅)影响的范围却更小了。为更直观的演示这种效果,我们分形叠加不同的倍频,分别是1倍频,2倍频,4倍频与8倍频。
可以看到倍频数越高,Perlin噪声就越精细,但整体形状不会有很大的改变。这符合自然现象。最平常的例子是山峰轮廓,它包含着高度上的很大变化(山峰),中等变化(丘陵),小的变化(砾石),微小变化(石头)…你可以继续想象。所以在我们程序中,我们用低频率,大振幅来模拟大尺度变化,用高频率,小振幅来模拟小尺度的变化,并将之分形叠加,最终达到我们想要的效果。
二、分形布朗运动
布朗运动(Brownian movement) 指微小粒子表现出的无规则运动。1827年英国植物学家R.布朗在花粉颗粒的水溶液中观察到花粉不停顿的无规则运动。进一步实验证实,不仅花粉颗粒,其他悬浮在流体中的微粒也表现出这种无规则运动,如悬浮在空气中的尘埃。后人就把这种微粒的运动称之为布朗运动。这里我们要讲的布朗运动跟这个有点区别,要讲清分形布朗运动还得从《大自然的分形几何学》和最简单的正弦波入手,本篇开篇我们即阐明了:客观事物具有自相似的层次结构,局部与整体在形态、功能、信息、时间、空间等方面具有统计意义上的相似性,称为自相似性。这是分形学的最重要的结论。下面我们从正弦波入手来分别讲解。
正弦波是最简单的波形之一,正弦波有个非常有意思的特性,那就是波可以叠加。如下:
图上一个是频率为1的正弦波,另一个是频率为2的正弦波,通过叠加产生了一个新的波,这个波的振幅由这两个波通过简单的加减构成。不仅是正弦波,其他波也有类似的叠加特性。在音乐中,每一个音阶都对应着特定的频率,频率加倍或者减半对应着另一个八度音阶(octave),可以看到octave这个词是从音乐中引用过来的,前面我们翻译成倍频,根据我们刚说的,octave对应频率的加倍或减半而不是加1.5倍或减0.4倍。我们稍后也会对噪声作类似处理。
现在我们由正弦波来讨论Perlin噪声(下图是一维Perlin噪声图),Perlin噪声有着和正弦波一样的振幅和频率,虽然这个振幅和频率在一定的范围内波动,虽然不像正弦波那样规律,但我们还是可以看得出振幅和频率只是在一定范围内的合理偏离。由波的叠加可知,利用Perlin噪声不同倍频波的叠加可以很容易的更随机的波形。
我们通过一个步进值(lacunarity)逐渐的增大频率,同时也同过一个增益值(gain)逐渐的减小振幅,主可以得到不同的倍频(octaves),然后再将不同的倍频叠加,这种技术就叫分形布朗运动(fractal Brownian Motion(fBM) )。简单的分形布朗运动可以由下面的代码生成。
const int octaves = 2;
float lacunarity = 2.0;
float gain = 0.5;
float amplitude = 1.;
float frequency = 1.;
// 叠代 octaves,y纵轴,x为横轴
for (int i = 0; i < octaves; i++)
{
y += amplitude * noise(frequency*x);
frequency *= lacunarity;
amplitude *= gain;
}
下面是octaves为2,4,8时的一维Perlin噪声,可以看到叠加的octave越多,噪声的细节就越多,另外一个值得注意的地方是,叠加的细节与原波形具备宏观上的相似性,这就是我们说过的分形的最重要的特征。
分形布朗运动是分形几何里的重要概念,理论上叠加无限多的octave,可以得到无限细节的分形几何图形,在实际运用中,过多的叠加会削弱图形性能,根据需要取合适的值。
三、Perlin noise原理
Perlin noise原理很简单:
第一步:定义一个晶格结构,每个晶格的顶点有一个“伪随机”的梯度向量。对于二维的Perlin噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。
第二步:输入一个点(二维的话就是二维坐标,三维就是三维坐标,n维的就是n个坐标),我们找到和它相邻的那些晶格顶点(二维下有4个,三维下有8个,n维下有
第三步:使用缓和曲线(ease curves)来计算它们的权重和。在原始的Perlin噪声实现中,缓和曲线是
这就是计算Perlin噪声的逻辑和流程。下面我们以二维Perlin噪声为例加以说明:
第一步:构建一个二维平面,同时生成每个顶点的“伪随机”的梯度向量:
这里,每个顶点各自生成一个伪随机的梯度向量。梯度向量代表该顶点相对单元正方形内某点的影响是正向还是反向的(一会我们会看到梯度向里对最终效果的影响)。而伪随机是指,对于任意组相同的输入,必定得到相同的输出。虽然每个顶点生成的梯度向量看似随机,实际上并不是。这保证了在生成函数不变的情况下,每个坐标的梯度向量都是确定不变的。同时,这些梯度向量并不是完全随机的,而是由单位正方体(3维)的中心点指向各条边中点的12个向量:
(1,1,0),(-1,1,0),(1,-1,0),(-1,-1,0), (1,0,1),(-1,0,1),(1,0,-1),(-1,0,-1), (0,1,1),(0,-1,1),(0,1,-1),(0,-1,-1)
采用这些特殊梯度向量的原因在Ken Perlin’s SIGGRAPH 2002 paper: Improving Noise这篇文章里有具体说明。主要是为了避免“镜像”现象。
第二步:输入一个点,找到和它相邻的那些晶格顶点:
找到输入点所在的晶格的顶点梯度向量:
接着,求出另外4个距离向量,它们分别从各顶点指向输入点(蓝色点):
接下来,对相应的顶点梯度向量与距离向里作点积运算。从点积的特性可知:当两个向量的夹角小于90度时点积结果为正;当两个向量夹角大于90度时点积结果为负;当两个向量夹角等于90度时点积结果为0。因此点积后的结果图如下:
此图很直观的表现了梯度向量对最终效果的影响,这也是Perlin噪声最终外观表现的内在原因。
第三步:对4个顶点的影响值做插值,缓和曲线的值会用来计算插值因子,这样插值变化不再是单调的线性变化,而是这样一个过程:初始变化慢,中间变化快,结尾变化又慢下来(也就是在当数值趋近于整数时变化变慢,或者说是接近固定点时变化速率变缓)。我们用Perlin改进的缓和曲线
这就是Perlin噪声生成的原理同时也是步骤,理解起来不难。这里也可以看到,梯度值在生成噪声中影响可谓是举足轻重,这也是Perlin噪声叫作梯度噪声的来源。
四、小结
本篇文章主要关注了分形噪声,分形布朗运动,介绍了Perlin噪声原理,通过上文,我们可以看到,分形噪声跟噪声一点关系都没有,分形布朗运动跟运动一点关系都没有,不要仅仅局限于字面的理解,更要理解概念的实质,这更重要。
参考文献:
1、《大自然的分形几何学》[波] 伯努瓦·B. 曼德布罗特(Mandelbrot)
2、Perlin Noise http://freespace.virgin.net/hugo.elias/models/m_perlin.htm
3、关于噪声的一些基本定义 http://www.gamersky.com/handbook/201601/708963_2.shtml?tag=wap
4、Fractal Brownian Motion https://thebookofshaders.com/13/
5、Understanding Perlin Noise ,https://flafla2.github.io/2014/08/09/perlinnoise.html
6、谈谈噪声 http://blog.csdn.net/candycat1992/article/details/50346469
智能推荐
代码本色0章——Perlin噪声生成起伏地形
代码本色0章——Perlin噪声生成起伏地形 此博文依据代码本色第0章中的随机数与Perlin噪声运用写成,并观看了丹尼尔希夫曼关于perlin噪声的讲解,https://www.youtube.com/watch?v=D8UgRyRnvXU,大家可以看一看 参考案例 效果图 Perlin噪声 一个好的随机数生成器能产生互不关联且毫无规律的随机数。跟我们前面看到的一样,一定...
Linux信号及工作原理
什么是信号 信号可以理解为软件中断,是在软件层次上对中断机制的一种模拟,在原理上,一个进程收到一个信号与处理器收到一个中断请求可以说是差不多的。信号是异步的,一个进程不必通过任何操作来等待信号的到达。信号可以直接进行用户空间进程和内核进程之间的交互,内核进程也可以利用它来通知用户空间进程发生了哪些系统事件。 谁来产生信号 信号事件的发生有两个...
手机端图片放大,双指放大,元素的双指缩放
在做webapp时候,遇到一个需要做双指放大的功能,需求是:一张带有坐标的图片上有固定的点,需要点击这些坐标上的点进入相应的商品,并且需要对这一块进行双指可以缩放,双击缩放; 一开始是自己写监听touch事件进行处理,但是再缩放的时候,偶尔出现卡顿闪烁,用户体验不很好,后来采用插件 pinch-zoom GitHub地址: https://github.com/manuelstofer/...
猜你喜欢
redis 初步了解
1.连接redis 通过java操作 1.首先 导入redis驱动 2.连接redis通过jedis 2.创建redis连接池 连接redis通过 jedis 相当于HTTPclient 1.创建单例模式的方法 在调用的时候被创建 2.创建私有静态 jedisPool 3. 创建私有类 创建静态代码块 放入连接池的基本配置 4.有 最大连接数 最大空闲书 最小空闲连接数 5. 创建连接redis对...
第6章数据类型-基本数据类型-Boolean类型-main
防采集标记:亢少军老师的课程和资料 Dart交流群:1046954554 Flutter开源项目请关注: https://github.com/kangshaojun @作者: 亢少军 '...
使用 Infura 和 web3.js 呼叫合约
如果你希望马上开始学习以太坊DApp开发,可以访问汇智网提供的出色的在线互动教程: 以太坊DApp实战入门教程 以太坊去中心化电商应用开发实战 如果你希望了解如何部署合约,可以查看另一篇文章:在truffle中使用infura部署以太坊智能合约。 Infura 提供公开的 Ethereum 主网和测试网络节点。到 Infura 官网申请,只要输入一点基本资料和 Email,就可以收到 API-ke...
手写RPC通信框架
RPC基本介绍 服务器端构建 API包下主体编写 首先初始采用Socket进行通信利用IO进行数据交互,对客户端要提供API调用接口,使得客户端可以利用API中提供的接口,获得服务器端的数据。服务器端模块目录如下: 先编写一个接口,该接口放置在api模块下,实现类放置在provider模块下,这样做目的是让客户端仅加载API包的条件下,可以调用服务器端的实现类完成具体业务逻辑。 服务器端需要客户端...
Highcharts饼状图Ajax动态赋值的问题
这种饼状图是动态的当鼠标放上面那一部分会突出的 Highcharts下载:点击下载 Highcharts-zh_CN.js下载:点击下载 效果图: 前台js代码: 控制层代码: 其中用到两种传值方式一种JSON另一种用Map传值给Ajax,下面为取到的值。 两个饼状图并列展示前台代码: 给饼状图赋值主要就是取json拼接成 data:[[name,y],[name,y]]这样的数组 注意y后面的数...
