精华内容
下载资源
问答
  • 本文主要简单介绍了滤波电容容值与所滤噪声频率的关系
  • 摘要:本文介绍了一个简单...但这类放大器有一个缺点:在自动归零频率及其倍频上存在明显的噪声。自动归零频率位于 典型仪表放大器的有效带宽以外。有些应用中,仪表放大器的输出直接连接到模/数转换器(ADC),这些噪声
  • 摘要:本文介绍了一个简单...但这类放大器有一个缺点:在自动归零频率及其倍频上存在明显的噪声。自动归零频率位于 典型仪表放大器的有效带宽以外。有些应用中,仪表放大器的输出直接连接到模/数转换器(ADC),这些噪声
  • 摘要:本文介绍了一个简单的降低...但这类放大器 有一个缺点:在自动归零频率及其倍频上存在明显的噪声。自动归零频率位于典型仪表 放大器的有效带宽以外。有些应用中,仪表放大器的输出直接连接到模/数转换器(ADC),
  • 注释标题文档提供了多个使用示例,并与应用笔记、网站、Excel 工作和专用相位噪声实验室测量设备中提供的其他相位噪声抖动计算器进行比较。 例子: >> f = [10^0 10^1 10^3 10^4 10^6]; Lf = [-39 -73 -122 -131...
  • 也许你也会跟我一样认为典型数据中的某些规格难以理解,这是因为其中...参考路径中生成的噪声受控于回路中对系统输出的低通频率响应,而压控振荡器(VCO)中生成的噪声受控于回路中对系统输出的高通频率响应。参见图
  • 噪声系数

    2021-04-13 14:47:51
    噪声系数噪声分类噪声系数的定义电阻(无源器件)的输出噪声功率半导体器件放大器噪声因子噪声系数NF无源器件的噪声系数噪声系数的级联...热噪声的功率谱密度不随频率变化,称为白噪声,又因服从Gauss概率密度分布,所

    噪声分类

    • 热噪声(Thermal Noise):最基本的一种噪声,就像冬日里北方的霾一样,可以说是无处不在的。热噪声又称为Johanson或Nyquist噪声,是由电子的热运动产生的。在绝对零度(0 K)以上,就会存在自由电子的热运动。因此,几乎所有的器件/设备,都会产生热噪声。热噪声的功率谱密度不随频率变化,称为白噪声,又因服从Gauss概率密度分布,所以又称为高斯白噪声
    • 散粒噪声(Shot Noise):由电子管或半导体固态设备中载流子的随机波动产生的,比如PN结二极管,当级间存在电压差时,就会发生电子和空穴的移动,此过程中就会产生散粒噪声。其功率谱密度也不随频率变化,也是一种白噪声。散粒噪声是半导体器件所特有的,无源器件(比如衰减器)是不产生散粒噪声的。
    • 闪烁噪声(Flicker Noise):产生于真空管(阴极氧化涂层)或半导体(半导体晶体表面缺陷)固态设备。噪声功率主要集中在低频段,其功率谱密度与频率成反比,所以又称为1/f 噪声。高于一定频率时,其噪声功率谱非常微弱,但是平坦的。因此,有时也称为pink noise.
    • 等离子体噪声(Plasma Noise):因电离化气体中电荷的随机运动产生,如电离层中或电火花接触时,就会产生等离子体噪声。
    • 量子噪声(Quantum Noise):因载流子或光子的量子化特性所产生。
      对于电子器件而言,相对其它三种噪声,最后两种噪声是可以忽略的。

    噪声系数的定义

    电阻(无源器件)的输出噪声功率

    将一个电阻置于温度为T (开尔文温度)的环境中,电阻中的自由电子随机运动,动能与温度T成正比。电子的随机运动会产生小的随机电压波动,此时电阻相当于一个噪声源,输出波形如图1所示,该噪声在足够长时间内的算术平均值为0,但RMS平均值值不为零。
    在这里插入图片描述图1. 电阻产生的随机噪声
    噪声电压的有效值可以简化为: V n = 4 k T B R V_{n} =\sqrt{4kTBR} Vn=4kTBR
    上式可以看出,噪声电压有效值与频率无关,且为常数,是一种白噪声。

    可将电阻等效为一个内阻为R的噪声源,当构成图2所示的共轭匹配电路时,其可输出最大噪声功率为:
    P n , m a x = ( V n 2 R ) 2 R = K T B P_{n,max} =(\frac{V_{n} }{2R} )^2R=KTB Pn,max=(2RVn)2R=KTB
    在这里插入图片描述
    由上式可知,电阻输出的最大噪声功率只与当前温度及系统带宽有关,与电阻值无关。
    对于衰减器等无源器件而言,因其内部只有电子热运动,只产生热噪声,所以情况与电阻类似。

    半导体器件

    基于半导体的器件,虽然产生的噪声种类相对多一些,但是可以将所有的噪声等效为热噪声,其输出最大噪声功率的能力,使用等效噪声温度Te表征。
    在这里插入图片描述图3. 将有源器件等效为热噪声源
    共轭匹配时,器件输出的最大噪声功率为: N o = K T e B N_{o} =KT_{e}B No=KTeB
    式中, T e T_{e} Te为器件的等效噪声温度。

    放大器

    对于放大器,等效噪声电路如图4所示,放大器本身可以产生噪声,为了引入等效噪声温度,假设输入端连接了一个电阻R,但是在绝对温度0K时,该电阻并不产生噪声功率,放大器的输出噪声功率只源自于自身。等效之后,放大器只有增益G而不会产生噪声功率,而输入端提供一个 K T e B KT_{e}B KTeB的等效噪声输入功率,此时放大器输出噪声功率为: N o = K T e B G N_{o} =KT_{e}BG No=KTeBG
    在这里插入图片描述
    图4. 放大器的等效噪声电路

    噪声因子

    IEEE给出的噪声因子定义为:在290K温度下,器件输出的总噪声功率与仅仅输入噪声功率引起的输出噪声功率的比值。
    通常情况下,工程师们更习惯于朗朗上口的定义:噪声因子为器件或系统的输入与输出信噪比之比。很显然,噪声因子表征了信号经过器件后信噪比的恶化程度。
    F = S i / N i S o / N o = N i ⋅ G + N a N i ⋅ G F=\frac{S_{i} /N_{i} }{S_{o} /N_{o} } =\frac{N_{i} \cdot G+N_{a} }{N_{i} \cdot G} F=So/NoSi/Ni=NiGNiG+Na
    式中 N i N_{i} Ni为290K温度下对应的噪声输入功率, N o N_{o} No为总输出噪声功率, N a N_{a} Na为器件本身引入的输出噪声功率, G G G为器件增益。
    在这里插入图片描述
    图5. 放大器的等效噪声电路
    IEEE对噪声因子的定义基于两个条件:290K开尔文温度下,且端口阻抗匹配。通常所说的噪声因子或噪声系数都是在这两个条件下定义的。后续篇章涉及到的数学公式推导及噪声系数的测试都是基于这两个条件。
    T 0 T_{0} T0=290K温度下,放大器的输入噪声功率为 K B T 0 KBT_{0} KBT0,假设其等效噪声温度为 T e T_{e} Te,则噪声因子F为:
    F = N i ⋅ G + N a N i ⋅ G = K B T 0 G + K B T e G K B T 0 G F=\frac{N_{i} \cdot G+N_{a} }{N_{i} \cdot G} =\frac{KBT_{0} G+KBT_{e} G}{KBT_{0} G} F=NiGNiG+Na=KBT0GKBT0G+KBTeG
    进一步化简得: F = 1 + T e T 0 F=1+\frac{T_{e} }{T_{0} } F=1+T0Te

    噪声系数NF

    N F = 10 l g F NF=10lgF NF=10lgF

    无源器件的噪声系数

    但凡从事RF/µW相关职业的工程师,对于无源器件的噪声系数都有一个共识:噪声系数与插入损耗相同。比如6dB的衰减器,其噪声系数就是6dB。其实这个共识也有一个非常重要的前提——290K( T 0 T_{0} T0)温度下。
    在这里插入图片描述
    图6. 无源器件的等效噪声电路

    图6给出了无源器件的等效噪声电路,假设输入、输出都是匹配的,当前温度为T,无源器件的增益和等效噪声温度分别为G和 T e T_{e} Te(290K下计算出的值),因为整个系统处于热平衡状态,所以其输出的噪声功率为 K B T KBT_{} KBT,且满足如下关系式: N o = K B T G + K B T e G = K B T N_{o} =KBTG+KBT_{e} G=KBT No=KBTG+KBTeG=KBT
    化简得到: T e = ( 1 G − 1 ) ⋅ T T_{e} =(\frac{1}{G}-1 )\cdot T Te=(G11)T
    依据等效噪声温度与噪声因子的关系可以得到: F = 1 + T e T 0 = 1 + ( 1 G − 1 ) ⋅ T T 0 F=1+\frac{T_{e} }{T_{0} }=1+(\frac{1}{G}-1 )\cdot \frac{T}{T_{0}} F=1+T0Te=1+(G11)T0T
    T = T 0 T=T_{0} T=T0时,上式可化简为: F = 1 G F=\frac{1}{G} F=G1 N F = 10 l g ( 1 G ) = − 10 l g ( G ) NF=10lg(\frac{1}{G})=-10lg(G) NF=10lg(G1)=10lg(G)
    也就是说,只有在T0=290K温度下,无源器件的噪声系数才等于其插入损耗。

    值得一提的是,无源混频器的噪声系数并不等于变频损耗,因为除了产生热噪声外,还会产生散粒噪声和闪烁噪声,不满足上面提到的热平衡状态,只有仅仅产生热噪声的器件才会达到热平衡态。

    噪声系数的级联

    在这里插入图片描述
    图7. 两级器件级联及噪声输出示意图
    图7给出了两级放大器级联示意图,级联后输出的总噪声功率为: N o = K T B G 1 G 2 + N a 1 G 2 + N a 2 = K T B G 1 G 2 + K T e 1 B G 1 G 2 + K B T e 2 G 2 N_{o} =KTBG_{1} G_{2} +N_{a1} G_{2} +N_{a2} =KTBG_{1} G_{2} +KT_{e1} BG_{1} G_{2} +KBT_{e2} G_{2} No=KTBG1G2+Na1G2+Na2=KTBG1G2+KTe1BG1G2+KBTe2G2式中,Te1、Te2分别为两个放大器的等效噪声温度。当然,处于同一个链路中,也认为两个器件的带宽B是相同的。

    如果将两个级联DUT的总等效噪声温度设为Te,则总输出噪声功率为: N o = K T B G 1 G 2 + K T e B G 1 G 2 N_{o} =KTBG_{1} G_{2} +KT_{e} BG_{1} G_{2} No=KTBG1G2+KTeBG1G2从而得到两级联后的总等效噪声温度和噪声因子: T e = T e 1 + T e 2 G 1 ⇒ F = F 1 + F 2 − 1 G 1 T_{e}=T_{e1}+\frac{T_{e2}}{G_{1}} \Rightarrow F=F_{1} +\frac{F_{2} -1}{G_{1} } Te=Te1+G1Te2F=F1+G1F21以此类推,对于N级器件级联后,则满足如下关系: T e = T e 1 + T e 2 G 1 + ⋯ + T e N G 1 G 2 ⋯ G N T_{e}=T_{e1}+\frac{T_{e2}}{G_{1} } +\cdots +\frac{T_{eN}}{G_{1}G_{2}\cdots G_{N} } Te=Te1+G1Te2++G1G2GNTeN F = F 1 + F 2 − 1 G 1 + ⋯ + F N − 1 G 1 G 2 ⋯ G N F=F_{1} +\frac{F_{2} -1}{G_{1} } +\cdots +\frac{F_{N} -1}{G_{1}G_{2}\cdots G_{N} } F=F1+G1F21++G1G2GNFN1公式表明,第一级器件的选择对于整个链路的NF有比较大的影响,这也是为什么在接收机链路中第一级采用LNA的原因。

    噪声系数对系统的影响

    绝大多数情况下,器件或系统产生的噪声都是有害的,当然也有例外,比如噪声源就是专门产生宽带噪声的设备,用于NF测试,或者验证系统的抗噪声性能。

    在绝对零度以上,任何器件均会产生噪声,那么当信号经过器件时,必然会导致信噪比SNR的降低,就好比一张清晰的图片,引入噪声后却变得模糊。
    在这里插入图片描述图8. 噪声系数导致SNR恶化

    射频收发链路中,通常接收机链路更加关注噪声系数,因为这决定了接收机的灵敏度,噪声系数越低,接收灵敏度越高,二者存在如下关系。
    在这里插入图片描述
    从应用的角度讲,接收机噪声系数对雷达和通信系统性能至关重要。较高的噪声系数直接限制了雷达最远探测距离,类似地,对于目前广泛应用的宽带通信系统,往往采用高阶、复杂的数字调制,这类调制信号对于SNR要求更高,如果接收机灵敏度不够高,会导致误码的产生,从而影响数据的有效传输。
    在这里插入图片描述

    展开全文
  • 更现代的“噪声系数分析仪”的关键属性之一是能够绘制噪声系数与频率和增益与频率的关系图,而不是 8970a 的简单 LED 读数。 以比现代NFM所需的少得多的成本,人们可以具有这种基本的绘图功能,并将数据导入MATLAB...
  • 目前最好的运算放大器(比如超低噪声AD797)可以实现低于1nV/ Hz的噪声性能(1 kHz),但低频率噪声限制了可以实现的噪声性能为大约50 nV p-p(0.1 Hz至10 Hz频段内)。过采样和平均可以降低宽带噪声的rms贡献,但代价...
  • 噪声学习

    千次阅读 2018-07-31 18:27:20
    关于噪声 噪声在图形学中的使用非常普遍,这里的噪声是通过程序生成一系列的随机值,通过特定的噪声算法,在给定一个输入,生成对应输出,输入和输出可以是不同维数的组合。  噪声在图形学中常用来模拟火焰、地形...

    关于噪声

    噪声在图形学中的使用非常普遍,这里的噪声是通过程序生成一系列的随机值,通过特定的噪声算法,在给定一个输入,生成对应输出,输入和输出可以是不同维数的组合。 
    噪声在图形学中常用来模拟火焰、地形、云朵等包含随机变化的对象。既然是获得随机值,为何不直接使用类似 random 这样的随机函数呢?原因是随机函数所得到的值在既定范围内分布过于均匀,这样的随机值被称为"白噪声",二维白噪声的纹理为: 
     
    实际在自然界中,充满随机变化的对象,如地形,云朵等,分布不会像白噪声这样,对于地形,既有高度变化很大的山脉和峡谷,也有起伏变化很小的山丘,这些不同程度的随机变化叠加在一起形成自然的地形走向。因此才会有特定的噪声函数,来模拟不同的自然界中的噪声(随机变化)。比如,Perlin噪声用于云朵,火焰的模拟,Simplex噪声在此基础上进行优化,提高计算的效率。

    噪声分类

    由wiki的分类,程序噪声算法分类如下: 

    以上为单噪声,与之对应的叫做 分形噪声(也可以叫做FBM噪声),分形噪声是在将这些单噪声以不同的频率和振幅进行叠加组合,从而产生不同程度的随机细节。这里的频率指的是计算噪声时的采样距离,例如对于基于晶格的噪声们,频率越高,单位面积(特指二维)内的晶格数目越多,看起来噪声纹理“越密集”;而振幅指的就是噪声的值域。下图显示了一些基础噪声和它们fbm后的效果: 

    左侧为单噪声,右侧为不同频率叠加后的效果 
    【图片来自https://blog.csdn.net/candycat1992/article/details/50346469

    噪声算法的实现

    主要包括常用噪声 Perlin噪声、Value噪声、Simplex噪声及简单的FBM实现。

    Perlin噪声

    Perlin噪声的实现有三个步骤:

    1. 定义一个晶格结构,每个晶格的顶点有一个“伪随机”的梯度向量(其实就是个随机向量)。对于二维的Perlin噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。
    2. 输入一个点(二维的话就是二维坐标,三维就是三维坐标,n维的就是n个坐标),我们找到和它相邻的那些晶格顶点(二维下有4个,三维下有8个,n维下有2^n个),计算该点到各个晶格顶点的距离向量,再分别与顶点上的梯度向量做点乘,得到2n个点乘结果。
    3. 使用缓和曲线来计算它们的权重和。在原始的Perlin噪声实现中,缓和曲线是s(t)=3t^2−2t^3,在2002年,Perlin改进为s(t)=6t^5−15t^4+10t^3。这里简单解释一下,为什么不直接使用s(t)=t,即线性插值。直接使用的线性插值的话,它的一阶导在晶格顶点处(即t = 0或t = 1)不为0,会造成明显的不连续性。s(t)=3t^2−2t^3在一阶导满足连续性,s(t)=6t^5−15t^4+10t^3在二阶导上仍然满足连续性。

    对应的图例说明: 

    左侧为各个晶格顶点的随机向量,右侧为位于某一晶格内的输入点与晶格顶点的距离向量。

    Unity下的实现效果: 

    单Perlin噪声(左下角)主要代码:

    float PNoise(float2 p){
    float2 i=floor(p);
    float2 f=frac(p);
    
    //缓和曲线,计算权重
    float2 w=f*f*(3.0-2.0*f);
    
    //使用权重值计算插值
    return lerp( lerp(dot(Hash22(i+float2(0.0,0.0)),f-float2(0.0,0.0)),
                      dot(Hash22(i+float2(1.0,0.0)),f-float2(1.0,0.0)),w.x),
                 lerp(dot(Hash22(i+float2(0.0,1.0)),f-float2(0.0,1.0)),
                      dot(Hash22(i+float2(1.0,1.0)),f-float2(1.0,1.0)),w.x),w.y);
    }
    

    其中Hash22是用来生成随机向量的函数。 单Perlin噪声为左下角部分,右下角,左上角和右上角为Perlin单噪声的分形叠加效果。 
    右下角部分分形叠加公式:

    noise(p)+1/2noise(2p)+1/4noise(4p)+...       
    

    实现代码:

    //叠加5层,初始化采样距离设置为7,可以自定义。这种噪声可以用来模拟石头、山脉这类物体。
    float Noise_Sum(float2 p){
    float f=0.0;
    p=p*7.0;
    f+=1.0000*Noise(p);p=2.0*p;
    f+=0.5000*Noise(p);p=2.0*p;
    f+=0.2500*Noise(p);p=2.0*p;
    f+=0.1250*Noise(p);p=2.0*p;
    f+=0.0625*Noise(p);p=2.0*p;
    return f;
    }
    

    左上角部分分形叠加公式:

    |noise(p)|+1/2|noise(2p)|+1/4|noise(4p)|+...    
    

    实现代码:

    //由于进行了绝对值操作,因此会在0值变化处出现不连续性,形成一些尖锐的效果。
    //通过合适的颜色叠加,可以用这种噪声来模拟火焰、云朵这些物体。float Noise_Sum_Abs(float2 p){
    float f=0.0;
    p=p*7.0;
    f+=1.0000*abs(Noise(p));p=2.0*p;
    f+=0.5000*abs(Noise(p));p=2.0*p;
    f+=0.2500*abs(Noise(p));p=2.0*p;
    f+=0.1250*abs(Noise(p));p=2.0*p;
    f+=0.0625*abs(Noise(p));p=2.0*p;
    return f;
    }
    

    右上角部分分形叠加公式:

    sin(x+|noise(p)|+1/2|noise(2p)|+1/4|noise(4p)|+...) 
    

    实现代码:

    //这个公式可以让表面沿着x方向形成一个条纹状的结构。Perlin使用这个公式模拟了一些大理石材质。
    float Noise_Sum_Abs_Sin(float2 p){
    float f=0.0;
    p=p*7.0;
    f+=1.0000*abs(Noise(p));p=2.0*p;
    f+=0.5000*abs(Noise(p));p=2.0*p;
    f+=0.2500*abs(Noise(p));p=2.0*p;
    f+=0.1250*abs(Noise(p));p=2.0*p;
    f+=0.0625*abs(Noise(p));p=2.0*p;
    
    f=sin(f+p.x/32.0);
    
    return f;   
    }  
    

    Value噪声

    Value噪声的实现和Perlin噪声唯一的区别在于将原来的梯度向量替换成简单的伪随机值,同时不需要做点乘操作,直接在晶格点处按照缓和曲线的权重值进行叠加。 
    Value噪声是一种基于晶格的操作,也需要三个步骤:

    1.定义一个晶格结构,每个晶格的顶点有一个“伪随机”的值(Value)。对于二维的Value噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。 
    2.输入一个点(二维的话就是二维坐标,三维就是三维坐标,n维的就是n个坐标),我们找到和它相邻的那些晶格顶点(二维下有4个,三维下有8个,n维下有2^n个),得到这些顶点的伪随机值。 
    3.使用缓和曲线来计算它们的权重和。同样,缓和曲线可以是s(t)=3t^2−2t^3,也可以是s(t)=6t^5−15t^4+10t^3(如果二阶导不连续对效果影响较大时)。

    Value噪声比 Perlin噪声实现过程更加简单,需要进行的计算也比较少。 
    Unity下的实现效果: 

    单Value噪声(左下角)主要代码:

    float VNoise(float2 p){
    float2 i=floor(p);
    float2 f=frac(p);
    //缓和曲线,计算插值点
    float2 w=f*f*(3.0-2.0*f);
    
    return lerp(lerp(Hash21(i+float2(0.0,0.0)),Hash21(i+float2(1.0,0.0)),w.x),
                lerp(Hash21(i+float2(0.0,1.0)),Hash21(i+float2(1.0,1.0)),w.x),w.y);
    }
    

    单Value噪声像素化明显,不过其对应的分形噪声效果可以接受。

    Simplex噪声

    Simplex噪声理解上相对不太友好,但其效率上要比Perlin噪声要高。 
    Simplex噪声也是一种基于晶格的梯度噪声,它和Perlin噪声在实现上唯一不同的地方在于,它的晶格并不是方形(在2D下是正方形,在3D下是立方体,在更高纬度上我们称为超立方体,hypercube),而是单形。

    单形可以认为是在N维空间里,选出一个最简单最紧凑的多边形,让它可以平铺整个N维空间。比如一维空间下的单形是等长的线段(1-单形),把这些线段收尾相连即可铺满整个一维空间。在二维空间下,单形是三角形(2-单形),可以把等腰三角形连接起来铺满整个平面。三维空间下的单形,即3-单形就是四面体。更高维空间的单形也是存在的。

    使用单行的好处在于——它的顶点数很少,要远小于超立方体(hypercube)的顶点个数。总结起来,在N维空间下,超立方体的顶点数目是2n,而单形的顶点数目是n+1,这样在计算梯度噪声时可以大大减少需要计算的顶点权重数目。

    在理解了单形后,Simplex噪声的计算过程其实和Perlin噪声基本一样。以二维空间下的为例。二维空间下的单形即是等边三角形,如下图所示。这些单形组成了一个单形网格结构,和Perlin噪声类似,这些网格顶点处也存储了伪随机梯度向量。 

    【图片来自https://blog.csdn.net/candycat1992/article/details/50346469

    当输入一点后,找到该点所在的三角形(图中红色三角形),再找到该三角形三个顶点的梯度向量和每个顶点到输入点的差值向量,把每个顶点的梯度向量和插值向量做点乘,得到三个点乘结果。最后,把它们按权重进行叠加混合,这个权重与输入点到每个顶点的有关,即每个顶点的噪声贡献度为:

    (r^2−|dist|^2)^4×dot(dist,grad)
    

    其中,dist是输入点到该顶点的距离向量,grad是该点存储的伪随机梯度向量,r^2的取值是0.5或0.6。取0.5时可以保证没有不连续的间断点,在连续性并不那么明显时可以取0.6得到更好的视觉效果。在Perlin原始的论文中,r的取值是0.6(后面会讲到0.5的值是如何得到的)。当得到单形每个顶点的噪声贡献度后,就可以把它们相加起来。为了把结果归一到-1到1的范围,还需要在最后乘以一个系数。

    目前需要解决的是如何找到输入点所在的单形?在计算Perlin噪声时,判断输入点所在的正方形是非常容易的,只需要对输入点下取整即可找到,这里可以把单形进行坐标偏斜(skewing),把平铺空间的单形变成一个新的网格结构,这个网格结构是由超立方体组成的,而每个超立方体又由一定数量的单形构成。对应的图解: 

    【图片来自https://blog.csdn.net/candycat1992/article/details/50346469

    之前讲到的单形网格如上图中的红色网格所示,它们有一些等边三角形组成(注意到这些等边三角形是沿空间对角线排列的)。经过坐标倾斜后,它们变成了后面的黑色网格,这些网格由正方形组成,每个正方形是由之前两个等边三角形变形而来的三角形组成。这个把N维空间下的单形网格变形成新网格的公式如下:

    在二维空间下,取n为2即可。这样变换之后,可以按照之前方法判断该点所在的超立方体,在二维下即为正方形。这样可以得到Simplex噪声的第一步:

    1.坐标偏斜:把输入点坐标进行坐标偏斜,对坐标下取整得到输入点所在的超立方体xi=floor(x′),yi=floor(y′),...,同时可以得到小数部分xf=x′−xi,yf=y′−yi,...,这些小数部分可以进一步判断输入点所在的单形以及计算权重。

    最终是要得到输入点所在的单形,而不是超立方体。因此需要继续做判断。还是如之前的图所示,经过坐标偏斜后,一个正方形由两个三角形组成,可以判断xf和yf之间的关系来判断输入点位于哪个三角形内,并得到该三角形的三个顶点。由此,Simplex噪声的第二步:

    2 单形分割:将之前得到的(xf,yf,...)中的数值按降序排序,来决定输入点位于变形后的哪个单形内。这个单形的顶点是由按序排列的(0, 0, …, 0)到(1, 1, …, 1)中的n+1个顶点组成,共有n!种可能性。可以按下面的过程来得到这n+1个顶点:从零坐标(0, 0, …, 0)开始,找到当前最大的分量,在该分量位置加1,直至添加了所有分量。例如,对于二维空间来说,如果xf,yf满足xf>yf,那么对应的3个单形坐标为:首先找到(0, 0),由于x分量比较大,因此下一个坐标是(1, 0),接下来是y分量,坐标为(1, 1);对于三维空间来说,如果xf,yf,zf满足xf>zf>yf,那么对应的4个单形坐标位:首先从(0, 0, 0)开始,接下来在x分量上加1得(1, 0, 0),再在z分量上加1得(1, 0, 1),最后在y分量上加1得(1, 1, 1)。这一步的算法复杂度即为排序复杂度O(n^2)。

    找到了对应的单形后,后面的工作就比较简单了。首先找到该单形各个顶点上的伪随机梯度向量,这就是第三步:

    3 梯度选取:在偏斜后的超立方体网格上获取该单形的各个顶点的伪随机梯度向量。

    现在需要的东西基本都准备好了,最后一步就是计算所有单形顶点对输出的噪声贡献度。

    4 贡献度取和:首先需要把单形顶点变回到之前由单形组成的单形网格。这一步需要使用第一步公式的逆函数来求得: 

    我们由此可以得到输入点到这些单形顶点的位移向量。这些向量有两个用途,一个是为了和顶点梯度向量点乘,另一个是为了得到之前提到的距离值dist,来据此求得每个顶点对结果的贡献度:

    (r^2−|dist|^2)^4×dot(dist,grad)
    

    这里r^2为什么取0.5,由于要求经过第一步坐标偏斜后得到的网格宽度为1,因此可以倒推出在变形前单形网格中每个单形边的边长为sqrt(2/3),这样一来单形每个顶点到对面边的距离(即高)的长度为sqrt(2)/2,它的平方即为0.5。不仅是二维,在其他维度下,每个单形顶点到对面边/面的距离都是0.5。

    在把它们相加并返回最终结果前,需要保证返回值的范围在-1到1,这就需要计算n每个分量相加后的最大值。这个最大值可以在输入点在某一边中点时取得,此时|a|=sqrt(2)/2,|b|=|c|=1/sqrt(6),得h=(0,1/3,1/3)。取最大值时,梯度和距离向量的点乘结果可以认为是两者模的乘积,而梯度模的最大值为sqrt(2),因此最后和的最大值为:

    (1/3)^4(1/sqrt(6))sqrt(2)*2≈1/70

    因此,最后把结果乘以70。那么,如果r2取0.6,大约乘24.51。利用这个想法,可以在任意维度下计算最后的伸缩值,例如在三维下,单形,即正四面体的边长为sqrt(3)/2,当r^2取0.5时,最后大概需要乘以31.32。

    虽然理解上Simplex噪声相比于Perlin噪声更难理解,但由于它的效果更好、速度更优,因此很多情况下会替代Perlin噪声。

    Unity下的实现效果: 

    单Simplex噪声(左下角)主要代码:

    float SNoise(float2 p){
    const float K1=0.366025404;  //(sqrt(3)-1)/2
    const float K2=0.211324685; //(3-sqrt(3))/6
    
    //将输入点进行坐标偏移,向下取整得到原点,转换到超立方体空间
    float2 i=floor(p+(p.x+p.y)*K1);
    //得到转换前输入点到原点距离(单形空间下)
    float2 a=p-(i-(i.x+i.y)*K2);
    //确定顶点在哪个三角形内
    float2 o=(a.x<a.y)?float2(0.0,1.0):float2(1.0,0.0);
    //得到转换前输入点到第二个顶点的距离
    float2 b=a-o+K2;
    //得到转换前输入点到第三个顶点的距离
    float2 c=a-1+2*K2;  
    
    //根据权重计算每个顶点的贡献度
    float3 h=max((0.5-float3(dot(a,a),dot(b,b),dot(c,c))),0.0);
    float3 n=h*h*h*h*float3(dot(a,Hash22(i)),dot(b,Hash22(i+o)),dot(c,Hash22(i+1.0)));
    
    //乘以系数,做归一化处理
    return dot(float3(70.0,70.0,70.0),n);
    } 
    

    参考: 
    https://blog.csdn.net/candycat1992/article/details/50346469

    展开全文
  • 谈谈噪声

    千次阅读 2017-05-01 09:37:28
    写在前面很早就想学习和整理下噪声,稍微接触过图形学的人大概都听到过噪声,然后就会发现有各种噪声,Perlin噪声,Worley噪声,分形(fractal)噪声等等。尤其是Perlin噪声,一搜资料发现大家说的各不相同,更加...

    文章转自http://m.blog.csdn.net/article/details?id=50346469


    写在前面

    很早就想学习和整理下噪声,稍微接触过图形学的人大概都听到过噪声,然后就会发现有各种噪声,Perlin噪声,Worley噪声,分形(fractal)噪声等等。尤其是Perlin噪声,一搜资料发现大家说的各不相同,更加不明所以。我也总是困惑,后来发现还是要相信wiki和paper。

    这篇文章在于总结上面这些常见的噪声(即图形学中常见的程序噪声),它们是什么,怎么算出来的,以及一些应用。文章里的所有代码可以在我的Shadertoy上找到:

    2D版:

    width="500" height="320" src="https://www.shadertoy.com/embed/ldc3RB?gui=true&t=10&paused=true&muted=false" allowfullscreen="">

    3D版:

    width="500" height="320" src="https://www.shadertoy.com/embed/4sc3z2?gui=true&t=10&paused=false&muted=false" allowfullscreen="">


    什么是噪声

    在图形学中,我们使用噪声就是为了把一些随机变量来引入到程序中。从程序角度来说,噪声很好理解,我们希望给定一个输入,程序可以给出一个输出:

    value_type noise(value_type p) {
        ...
    }
       
    • 1
    • 2
    • 3

    它的输入和输出类型的维数可以是不同的组合,例如输入二维输出一维,输入二维输出二维等。我们今天就是想讨论一下上面函数中的实现部分是长什么样的。


    为什么我们需要这么多噪声

    我对噪声的学习还没有很深,在此只想谈一点自己的想法。噪声其实就是为了把一些随机变量引入到程序中。在我们写一些C++这样的程序时,也经常会使用random这样的函数。这些函数通常会产生一些伪随机数,但很多情况下也足够满足我们的需要。同样,在图形学中我们也经常会需要使用随机变量,例如火焰、地形、云朵的模拟等等。相信你肯定听过大名鼎鼎的Minecraft游戏,这个游戏里面的地形生成也大量使用了随机变量。那么我们直接使用random这种函数不就好了吗?为什么要引入这么多名字的噪声呢?

    这种直接使用随机生成器生成的随机值固然有它的好处,但它的问题在于生成的随机值太“随机”了。在图形学中,我们可以认为这种噪声就是白噪声(White noise)。wiki上说白噪声是功率谱密度在整个频域内均匀分布的噪声,听不懂对不对?通俗来讲,之所以称它为“白”噪声,是因为它类似于光学中包括全部可见光频率在内的白光。我相信你肯定听过白噪声,小时候电视机收音机没信号时,发出的那个沙沙声就是一种声音上的白噪声。我们这里只需要把白噪声理解为最简单的随机值,例如二维的白噪声纹理可以是下面这个样子:

    这里写图片描述

    可以看出白噪声非常不自然,听起来很刺耳,看起来也不好看。不光你这么想,图形学领域的前辈们也早发现了。如果你观察现实生活中的自然噪声,它们不会长成上面这个样子。例如木头纹理、山脉起伏,它们的形状大多是趋于分形状(fractal)的,即包含了不同程度的细节。比如地形,它有起伏很大的山脉,也有起伏稍小的山丘,也有细节非常多的石子等,这些不同程度的细节共同组成了一个自然的地形表面。那么,我们如何用程序来生成类似这样的自然的随机数(可以想象对应了地形不同的高度)呢?学者们根据效率、用途、自然程度(即效果好坏)等方面的衡量,提出了许多希望用程序模拟自然噪声的方法。例如,Perlin噪声被大量用于云朵、火焰和地形等自然环境的模拟;Simplex噪声在其基础上进行了改进,提到了效率和效果;而Worley噪声被提出用于模拟一些多孔结构,例如纸张、木纹等。

    因此,学习和理解这些噪声在图形学中是十分必要的,因为它们的应用实在是太广泛了!


    噪声的分类

    根据wiki,由程序产生噪声的方法大致可以分为两类:

    类别名称
    基于晶格的方法(Lattice based)又可细分为两种:
    第一种是梯度噪声(Gradient noise),包括Perlin噪声Simplex噪声Wavelet噪声等;
    第二种是Value噪声(Value noise)
    基于点的方法(Point based)Worley噪声



    需要注意的是,一些文章经常会把Perlin噪声、Value噪声与分形噪声(Fractal noise)弄混,这实际在概念上是有些不一样的。分形噪声会把多个不同振幅、不同频率的octave相叠加,得到一个更加自然的噪声。而这些octave则对应了不同的来源,它可以是Gradient噪声(例如Perlin噪声)或Value噪声,也可以是一个简单的白噪声(White noise)。

    一些非常出色的文章也错误把这种分形噪声声称为Perlin噪声,例如:

    如果读者常逛shadertoy的话,会发现很多shader使用了类似名为fbm的噪声函数。fbm实际就是分型布朗运动(Fractal Brownian Motion)的缩写,读者可以把它等同于我们上面所说的分形噪声(Fractal noise),我们以下均使用fbm来表示这种噪声的计算方法。如果要通俗地说fbm和之前提及的Perlin噪声、Simplex噪声、Value噪声、白噪声之间的联系,我们可以认为是很多个不同频率、不同振幅的基础噪声(指之前提到的Perlin噪声、Simplex噪声、Value噪声、白噪声等之一)之间相互叠加,最后形成了最终的分形噪声。这里的频率指的是计算噪声时的采样距离,例如对于基于晶格的噪声们,频率越高,单位面积(特指二维)内的晶格数目越多,看起来噪声纹理“越密集”;而振幅指的就是噪声的值域。下图显示了一些基础噪声和它们fbm后的效果:

    这里写图片描述

    说明:分割线左侧表示单层的基础噪声,右侧表示通过叠加不同频率噪声后的fbm效果。上面效果来源于shadertoy:Perlin噪声Simplex噪声Value噪声Worley噪声

    由于Worley噪声的生成和其他噪声有明显不同,因此不是本文的重点。它主要用于产生孔状的噪声,有兴趣的读者可以参见偶像iq的文章:

    Perlin噪声、Simplex噪声和Value噪声在性能上大致满足:Perlin噪声 > Value噪声 > Simplex噪声,Simplex噪声性能最好。Perlin噪声和Value噪声的复杂度是O(2n),在高纬度上优化明显。

    下面的内容就是重点解释Perlin噪声、Perlin噪声和Simplex噪声这三种常见的噪声,最后再介绍fbm。

    Perlin噪声

    先介绍大名鼎鼎的Perlin噪声。很多人都知道,Perlin噪声的名字来源于它的创始人Ken Perlin。Ken Perlin早在1983年就提出了Perlin noise,当时他正在参与制作迪士尼的动画电影《电子世界争霸战》(英语:TRON),但是他不满足于当时计算机产生的那种非常不自然的纹理效果,因此提出了Perlin噪声。随后,他在1984年的SIGGRAPH Course上做了名为Advanced Image Synthesis1的课程演讲,并在SIGGRAPH 1985上发表了他的论文2。由于Perlin噪声的算法简单,被迅速应用到各种商业软件中。我们这位善良的Perlin先生却并没有对Perlin噪声算法申请专利(他说他的祖母曾叫他这么做过……),如果他这么做了那会是多大一笔费用啊!(不过在2001年的时候,旁人看不下去了,把三维以上的Simplex噪声的专利主动授予了Perlin。对,Simplex噪声也是人家提出的……)再后来Perlin继续研究程序纹理的生成,并和他的一名学生又在SIGGRAPH 1989上发表了一篇文章3,提出了超级纹理(hypertexture)。他们使用噪声+fbm+ray marching实现了各种有趣的效果。到1990年,已经有大量公司在他们的产品中使用了Perlin噪声。在1999年的GDCHardCore大会上,Ken Perlin做了名为Making Noise的演讲4,系统地介绍了Perlin噪声的发展、实现细节和应用。如果读者不想读论文的话,强烈建议你看一下Perlin演讲的PPT。

    后来在2002年,Perlin又发表了一篇论文5来改进原始的Perlin噪声中的一些问题,例如原来的缓和曲线s(t)=3t22t3;此外还改进了晶格顶点处随机梯度向量的选取。有兴趣的读者可以参考:

    后面只介绍原始Perlin噪声的实现。


    实现

    Perlin噪声还是比较简单的,在1983年的计算机上实现的算法也不允许对计算量、内存有多大的要求。概括来说,Perlin噪声的实现需要三个步骤:

    1. 定义一个晶格结构,每个晶格的顶点有一个“伪随机”的梯度向量(其实就是个向量啦)。对于二维的Perlin噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。
    2. 输入一个点(二维的话就是二维坐标,三维就是三维坐标,n维的就是n个坐标),我们找到和它相邻的那些晶格顶点(二维下有4个,三维下有8个,n维下有2n个点乘结果。
    3. 使用缓和曲线(ease curves)来计算它们的权重和。在原始的Perlin噪声实现中,缓和曲线是s(t)=3t22t3在二阶导上仍然满足连续性。

    我们下面以二维的为例,再详细解释一下。我们可以用下面的图来表示上面的第一步和第二步:

    这里写图片描述

    一个问题是晶格顶点处的伪随机梯度向量是如何得到的,当然我们可以通过random这样的函数来计算单位正方形(二维)内的x和y分量值,但我们更愿意要那些在单位圆内的梯度向量。Perlin在他的实现中选择使用蒙特卡洛模拟方法来选取这些随机梯度向量。具体方法是(我把描述适应到了二维):首先按之前的方法生成在单位正方形内随机梯度向量,然后剔除那些不在单位圆内的向量,直到找到了需要数目的随机梯度向量。Perlin把这些预计算得到的向量存储在一个查找表G[n]中,n是纹理大小,例如256 x 256大小的纹理对应n为256。虽然我们实际上需要n x n个梯度向量,这样会造成有些顶点的梯度是重复的。Perlin认为,重复是可以允许的,只要它们的间距够大就不会被察觉。因此,Perlin还预计算了一个随机排列数组P[n],P[n]里面存储的是打乱后的0~n-1的排列值。这样一来,当我们想要得到(i, j)处晶格的梯度向量时,可以使用:

    G=G[(i+P[j])mod n]

    得到了梯度后,我们就可以进行点乘,得到4个点乘结果,然后使用缓和曲线对它们进行插值即可。这里使用的权重就是输入点到4个顶点的横纵距离。

    在原始的Perlin噪声实现中,Perlin对梯度向量的选择一般是取单位圆(三维就是单位球)内一些不同方向的向量。在他后面的改进算法7中,Perlin建议把三维的梯度向量初始化为到立方体12条边的向量值,来保证各个方向之间的不关联性。


    可以看出,Perlin噪声算法的时间复杂度为O(2n),在高纬度上时间优化明显,我们后面会讲到这种噪声。


    效果

    Shadertoy上有很多关于Perlin噪声的实现,我也山寨了一个:

    这里写图片描述

    它的主要代码如下:

    vec2 hash22(vec2 p)
    {
        p = vec2( dot(p,vec2(127.1,311.7)),
                  dot(p,vec2(269.5,183.3)));
    
        return -1.0 + 2.0 * fract(sin(p)*43758.5453123);
    }
    float perlin_noise(vec2 p)
    {
        vec2 pi = floor(p);
        vec2 pf = p - pi;
    
        vec2 w = pf * pf * (3.0 - 2.0 * pf);
    
        return mix(mix(dot(hash22(pi + vec2(0.0, 0.0)), pf - vec2(0.0, 0.0)), 
                       dot(hash22(pi + vec2(1.0, 0.0)), pf - vec2(1.0, 0.0)), w.x), 
                   mix(dot(hash22(pi + vec2(0.0, 1.0)), pf - vec2(0.0, 1.0)), 
                       dot(hash22(pi + vec2(1.0, 1.0)), pf - vec2(1.0, 1.0)), w.x),
                   w.y);
    }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    这里的实现实际是简化版的,我们在算梯度的时候直接取随机值,而没有归一化到单位圆内。

    上图包含了四种噪声组合,这也是Perlin在1999年的GDC上做演讲时采用的一个示例,不过Perlin的例子是三维的,而且添加了光照等计算。

    • 左上角的部分。这是最简单的单独的Perlin噪声,它的噪声模拟如下:

      float noise_itself(vec2 p)
      {
          return noise(p * 8.0);
      }
           
      • 1
      • 2
      • 3
      • 4

      上面的代码在整个屏幕上模拟了一个8 x 8的网格结构。在绘制时,我们只需要将一个深蓝色乘以噪声即可得到类似的效果。

      单独一个Perlin噪声虽然也有一定用处,但是效果往往很无趣。因此,Perlin指出可以使用不同的函数组合来得到更有意思的结果,这些函数组合通常就是指通过分形叠加(fractal sum),也就是我们之前说的fbm。

    • 左下角的部分。这个部分使用了fbm进行叠加来形成一个分形噪声。公式如下:

      noise(p)+12noise(2p)+14noise(4p)+...

      即每一次噪声的采样频率翻倍,而振幅减少一倍。很多文章错误地把这种计算认为是Perlin噪声,这是不对的。Perlin噪声只是对应了其中每一个octave。代码是:

      float noise_sum(vec2 p)
      {
          float f = 0.0;
          p = p * 4.0;
          f += 1.0000 * noise(p); p = 2.0 * p;
          f += 0.5000 * noise(p); p = 2.0 * p;
          f += 0.2500 * noise(p); p = 2.0 * p;
          f += 0.1250 * noise(p); p = 2.0 * p;
          f += 0.0625 * noise(p); p = 2.0 * p;
      
         return f;
      }
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      上面叠加了5层,并把初始化采样距离设置为4,这都是可以自定义的。这种噪声可以用来模拟石头、山脉这类物体。

    • 右下角的部分。这一部分只是在上一部分进行了一点修改,对噪声返回值进行了取绝对值操作。它使用的公式如下:

      |noise(p)|+12|noise(2p)|+14|noise(4p)|+...

      它对应的代码如下:

      float noise_sum_abs(vec2 p)
      {
          float f = 0.0;
          p = p * 7.0;
          f += 1.0000 * abs(noise(p)); p = 2.0 * p;
          f += 0.5000 * abs(noise(p)); p = 2.0 * p;
          f += 0.2500 * abs(noise(p)); p = 2.0 * p;
          f += 0.1250 * abs(noise(p)); p = 2.0 * p;
          f += 0.0625 * abs(noise(p)); p = 2.0 * p;
      
          return f;
      }
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      由于进行了绝对值操作,因此会在0值变化处出现不连续性,形成一些尖锐的效果。通过合适的颜色叠加,我们可以用这种噪声来模拟火焰、云朵这些物体。Perlin把这个公式称为turbulence(湍流?),因为它看起来挺像的。

    • 右上角的部分。这个部分是在之前turbulence公式的基础上使用了一个关于表面x分量的正弦函数:

      sin(x+|noise(p)|+12|noise(2p)|+14|noise(4p)|+...)

      这个公式可以让表面沿着x方向形成一个条纹状的结构。Perlin使用这个公式模拟了一些大理石材质。我们的代码如下:

      float noise_sum_abs_sin(vec2 p)
      {
          float f = 0.0;
          p = p * 7.0;
          f += 1.0000 * abs(noise(p)); p = 2.0 * p;
          f += 0.5000 * abs(noise(p)); p = 2.0 * p;
          f += 0.2500 * abs(noise(p)); p = 2.0 * p;
          f += 0.1250 * abs(noise(p)); p = 2.0 * p;
          f += 0.0625 * abs(noise(p)); p = 2.0 * p;
          f = sin(f + p.x/32.0);
      
          return f;
      }
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      我们可以通过改变x分量前面的系数来控制条纹的疏密。

    以上,我们就演示了基本的Perlin噪声的实现。Perlin在1999年Making Noise的演讲8中,还介绍了如何使用噪声来控制纹理动画。他指出,想要一个二维的turbulence纹理动画(例如云、火焰等),我们需要使用三维的噪声,其中第三维对应了时间变量。Shadertoy上有很多这样的例子,例如下面的就是模拟了Perlin演讲中实现的火球效果

    width="500" height="320" src="https://www.shadertoy.com/embed/lsf3RH?gui=true&t=10&paused=false&muted=false" allowfullscreen="">

    有兴趣的可以尝试实现Perlin演讲中实现的云彩飘动效果


    Value噪声

    在理解了Perlin噪声的实现后,Value噪声就很简单了。它把原来的梯度替换成了一个简单的伪随机值,我们也不需要进行点乘操作,而直接把晶格顶点处的随机值按权重相加即可。


    实现

    和Perlin噪声一样,它也是一种基于晶格的噪声,也需要三个步骤:

    1. 定义一个晶格结构,每个晶格的顶点有一个“伪随机”的值(Value)。对于二维的Value噪声来说,晶格结构就是一个平面网格,三维的就是一个立方体网格。
    2. 输入一个点(二维的话就是二维坐标,三维就是三维坐标,n维的就是n个坐标),我们找到和它相邻的那些晶格顶点(二维下有4个,三维下有8个,n维下有2n个),得到这些顶点的伪随机值。
    3. 使用缓和曲线(ease curves)来计算它们的权重和。同样,缓和曲线可以是s(t)=3t22t3(如果二阶导不连续对效果影响较大时)。

    Value噪声比Perlin噪声的实现更加简单,并且需要的乘法和加法操作也更少,它只需要得到晶格顶点的随机值再把它们按权重相加即可。


    效果

    我们再次使用之前在Perlin噪声效果展示时使用的代码,但改变一些参数就可以得到下面的效果:

    这里写图片描述

    它的主要代码如下:

    float value_noise(vec2 p)
    {
        vec2 pi = floor(p);
        vec2 pf = p - pi;
    
        vec2 w = pf * pf * (3.0 - 2.0 * pf);
    
        return mix(mix(hash21(pi + vec2(0.0, 0.0)), hash21(pi + vec2(1.0, 0.0)), w.x),
                   mix(hash21(pi + vec2(0.0, 1.0)), hash21(pi + vec2(1.0, 1.0)), w.x),
                   w.y);
    }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    可以看出,单独的Value噪声(左上角)会有很明显的像素块效果。其实我认为,当把Value噪声纹理的大小调的很大时,它近似就是一张白噪声纹理。不过所幸的是,在通过fbm叠加后,形成的分形噪声效果还是可以接受的,这也是为什么它会被大量应用在很多程序中来代替基于梯度的Perlin噪声。


    Simplex噪声

    最后,我们来介绍本文最难理解的一种噪声。在2001年SIGGRAPH Course上,Ken Perlin进行了一次演讲9,他介绍了对Perlin噪声的一个改进版噪声——Simplex噪声。感兴趣的读者可以看一下Perlin原版的Course Note。我们之前提到过很多次,Simplex噪声的计算复杂度为O(n2)。而且在效果上,Simplex噪声也克服了经典的Perlin噪声在某些视觉问题。但Simplex噪声的问题在于,它比较难理解,以至于当Perlin提出了后好几年的时间里它并没有被广泛使用。


    实现

    Simplex噪声也是一种基于晶格的梯度噪声,它和Perlin噪声在实现上唯一不同的地方在于,它的晶格并不是方形(在2D下是正方形,在3D下是立方体,在更高纬度上我们称它们为超立方体,hypercube),而是单形,simplex。那么什么是单形呢?

    通俗解释单形的话,可以认为是在N维空间里,选出一个最简单最紧凑的多边形,让它可以平铺整个N维空间。我们可以很容易地想到一维空间下的单形是等长的线段(1-单形),把这些线段收尾相连即可铺满整个一维空间。在二维空间下,单形是三角形(2-单形),我们可以把等腰三角形连接起来铺满整个平面。三维空间下的单形,即3-单形就是四面体。更高维空间的单形也是存在的。

    那么使用单形有什么好处呢?这可以从之前对单形的解释看出来——它的顶点数很少,要远小于超立方体(hypercube)的顶点个数。总结起来,在N维空间下,超立方体的顶点数目是2n,这使得我们在计算梯度噪声时可以大大减少需要计算的顶点权重数目。

    在理解了单形后,Simplex噪声的计算过程其实和Perlin噪声基本一样。我们以二维空间下的为例。二维空间下的单形即是等边三角形,如下图所示。这些单形组成了一个单形网格结构,和Perlin噪声类似,这些网格顶点处也存储了伪随机梯度向量。

    这里写图片描述

    当输入一点后,我们找到该点所在的三角形(图中红色三角形),再找到该三角形三个顶点的梯度向量和每个顶点到输入点的差值向量,把每个顶点的梯度向量和插值向量做点乘,得到三个点乘结果。最后,我们把它们按权重进行叠加混合,这个权重与输入点到每个顶点的有关,即每个顶点的噪声贡献度为:

    (r2|dist|2)4×dot(dist,grad)

    其中,dist的取值是0.5或0.6。取0.5时可以保证没有不连续的间断点,在连续性并不那么明显时可以取0.6得到更好的视觉效果。在Perlin原始的论文中,r的取值是0.6(后面我们会讲到0.5的值是如何得到的)。当得到单形每个顶点的噪声贡献度后,就可以把它们相加起来。为了把结果归一到-1到1的范围,我们往往还需要在最后乘以一个系数,这个系数值我们之后会讲到。

    可以看出,Simplex噪声的实现过程和Perlin几乎完全一样。但是,在上面的实现中我们始终忽略了一个问题,就是如何找到输入点所在的单形?在计算Perlin噪声时,判断输入点所在的正方形是非常容易的,我们只需要对输入点下取整即可找到,那么这里能不能也这么计算呢?幸运的是,数学家们已经为我们解决了这个问题:我们可以把单形进行坐标偏斜(skewing),把平铺空间的单形变成一个新的网格结构,这个网格结构是由超立方体组成的,而每个超立方体又由一定数量的单形构成。听不懂是不是?2005年Stefan的一篇论文10里的一张图大概可以解救你!

    这里写图片描述

    我们之前讲到的单形网格如上图中的红色网格所示,它们有一些等边三角形组成(注意到这些等边三角形是沿空间对角线排列的)。经过坐标倾斜后,它们变成了后面的黑色网格,这些网格由正方形组成,每个正方形是由之前两个等边三角形变形而来的三角形组成。这个把N维空间下的单形网格变形成新网格的公式如下:

    x=x+(x+y+...)K1y=y+(x+y+...)K1...K1=n+1‾‾‾‾‾√1n
    x^{'} = x + (x + y + ...) \cdot K1 \\ y^{'} = y + (x + y + ...) \cdot K1 \\ ... \\

    在二维空间下,取n为2即可。这样变换之后,我们就可以按照之前方法判断该点所在的超立方体,在二维下即为正方形。这样我们就有了Simplex噪声的第一步:

    1 坐标偏斜:把输入点坐标进行坐标偏斜,对坐标下取整得到输入点所在的超立方体xi=floor(x),yi=floor(y),...,这些小数部分可以帮助我们进一步判断输入点所在的单形以及计算权重。

    但我们的目标其实是要得到输入点所在的单形,而不是超立方体。因此我们需要继续做判断。还是如之前的图所示,经过坐标偏斜后,一个正方形由两个三角形组成,我们可以判断xf之间的关系来判断输入点位于哪个三角形内,并得到该三角形的三个顶点。由此,我们有了Simplex噪声的第二步:

    2 单形分割:我们把之前得到的(xf,yf,...)

    找到了对应的单形后,后面的工作就比较简单了。我们首先找到该单形各个顶点上的伪随机梯度向量,这就是第三步:

    3 梯度选取:我们在偏斜后的超立方体网格上获取该单形的各个顶点的伪随机梯度向量。

    现在我们需要的东西基本都准备好了,最后一步就是计算所有单形顶点对输出的噪声贡献度。

    4 贡献度取和:我们首先需要把单形顶点变回到之前由单形组成的单形网格。这一步需要使用第一步公式的逆函数来求得:

    x=x+(x+y+...)K2y=y+(x+y+...)K2...K2=1n+11n

    我们由此可以得到输入点到这些单形顶点的位移向量。这些向量有两个用途,一个是为了和顶点梯度向量点乘,另一个是为了得到之前提到的距离值 dist,来据此求得每个顶点对结果的贡献度:
    (r2|dist|2)4×dot(dist,grad)

    现在我们可以来解释r2,它的平方即为0.5。很奇妙的是,不仅是二维,在其他维度下,每个单形顶点到对面边/面的距离都是0.5。


    至此,我们解释了Simplex噪声的实现。虽然理解上Simplex噪声相比于Perlin噪声更难理解,但由于它的效果更好、速度更优,因此很多情况下会替代Perlin噪声。


    效果

    下面是Simplex噪声和fbm组合之后的一些效果:

    这里写图片描述

    它的主要代码如下:

    float simplex_noise(vec2 p)
    {
        const float K1 = 0.366025404; // (sqrt(3)-1)/2;
        const float K2 = 0.211324865; // (3-sqrt(3))/6;
    
        vec2 i = floor(p + (p.x + p.y) * K1);
    
        vec2 a = p - (i - (i.x + i.y) * K2);
        vec2 o = (a.x < a.y) ? vec2(0.0, 1.0) : vec2(1.0, 0.0);
        vec2 b = a - o + K2;
        vec2 c = a - 1.0 + 2.0 * K2;
    
        vec3 h = max(0.5 - vec3(dot(a, a), dot(b, b), dot(c, c)), 0.0);
        vec3 n = h * h * h * h * vec3(dot(a, hash22(i)), dot(b, hash22(i + o)), dot(c, hash22(i + 1.0)));
    
        return dot(vec3(70.0, 70.0, 70.0), n);
    }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    我还是要稍微解释下上面的代码。vec2 i即为我们在第二步中提到的超立方体索引号(也就是超立方体中的(0, 0)点)。vec2 a是在变形前输入点到(0, 0)点的距离向量。接着,我们通过判断a的x分量和y分量的大小(变形前后不会对结果有影响,因此这里直接使用变形前的距离向量),来得到输入点所在的单形顶点。接着,我们计算输入点到第二个单形顶点的距离向量vec2 b以及到第三个单形顶点的距离向量vec2 c。然后,我们计算每个顶点的r2|dist|2,因此最后和的最大值为:

    13416‾‾√2‾‾√2170

    因此,我们最后把结果乘以70。那么,如果r2取0.5时,最后大概需要乘以31.32。


    可平铺的噪声

    这部分是新加的。可平铺的噪声就是指那些可以tiling的、seamless的噪声,因为很多时候我们想要让噪声纹理可以无缝连接,例如在生成地形时。按照我们之前提到的方法直接产生噪声,得到的噪声纹理其实是不可以平铺的,你可以看生成纹理的左右、上下其实是不一样的。那么,怎么生成可平铺的噪声纹理呢?

    我直接说目前公认比较好的一种方法,就是在2n维上计算n维可平铺噪声。我们以二维噪声为例,如果我们想要得到二维的无缝Perlin噪声,就需要用四维噪声算法来产生。这种方法是思想是,由于我们想要每个维度都是无缝的,也就是当该维度的值从0变成1的过程中,0和1之间比较是平滑过渡的,这让我们想起了“圆”,绕圆一周就是对该维度的采样过程,这样就可以保证无缝了。因此,对于二维噪声中的x轴,我们会在四维空间下的xz平面上的一个圆上进行采样,而二维噪声的y轴,则会在四维空间下的yw平面上的一个圆上进行采样。这个转化过程很简单,我们只需要使用三角函数sin和cos即可把二维采样坐标转化到单位圆上。同样,三维空间的也是类似的,我们会在六维空间下计算。这种方法不仅适用于Perlin噪声,像Worley噪声这种也同样是适合的。

    当然上述方法也有自己的缺点,最明显的就是计算量大大增加,一般噪声的复杂度为O(2n)),是指数增加的。但是由于噪声纹理一般只需要前期计算一次即可,因此大部分时候是可以承担的。

    代码的话,Unity Wiki里给出了二维可平铺的Simplex噪声的实现,关键代码如下:

    //X, Y is [0..1]
    public static float SeamlessNoise( float x, float y, float dx, float dy, float xyOffset ) {
        float s = x;
        float t = y;
    
        float nx = xyOffset + Mathf.Cos(s * 2.0f * Mathf.PI) * dx / (2.0f * Mathf.PI);
        float ny = xyOffset + Mathf.Cos(t * 2.0f * Mathf.PI) * dy / (2.0f * Mathf.PI);
        float nz = xyOffset + Mathf.Sin(s * 2.0f * Mathf.PI) * dx / (2.0f * Mathf.PI);
        float nw = xyOffset + Mathf.Sin(t * 2.0f * Mathf.PI) * dy / (2.0f * Mathf.PI);
    
        return Noise(nx, ny, nz, nw);
    }
       
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    其中,xyOffset是指在四维空间某个平面上的偏移,即这个单位圆是以xyOffset为圆心的。所有可以用这种方法来产生无缝噪声的实现都和上面的代码是一样的,它们的区别仅仅在于Noise(nx, ny, nz, nw)的实现,如果它是四维Perlin噪声,那就会产生二维可平铺的Perlin噪声,如果是四维的Worley噪声,就会产生二维可平铺的Worley噪声。

    如果你有兴趣更深入地理解这种方法,可以阅读下面的一些文章:


    扩展阅读

    网上有很多优秀的阅读的资料,这里只是我找到的一小部分(wiki我就不说了,一般是必看的):

    参考文献


    1. Perlin K. Course in advanced image synthesis[C]//ACM SIGGRAPH Conference. 1984, 18.
    2. Perlin K. An image synthesizer[J]. ACM Siggraph Computer Graphics, 1985, 19(3): 287-296.
    3. Perlin K, Hoffert E M. Hypertexture[C]//ACM SIGGRAPH Computer Graphics. ACM, 1989, 23(3): 253-262.
    4. Perlin K. Making noise[C]//Proc. of the Game Developer Conference. 1999.
    5. Perlin K. Improving noise[C]//ACM Transactions on Graphics (TOG). ACM, 2002, 21(3): 681-682.
    6. Perlin K. Improving noise[C]//ACM Transactions on Graphics (TOG). ACM, 2002, 21(3): 681-682.
    7. Perlin K. Improving noise[C]//ACM Transactions on Graphics (TOG). ACM, 2002, 21(3): 681-682.
    8. Perlin K. Making noise[C]//Proc. of the Game Developer Conference. 1999.
    9. Perlin K. Noise hardware[J]. Real-Time Shading SIGGRAPH Course Notes, 2001.
    10. Gustavson S. Simplex noise demystified[J]. Linköping University, Linköping, Sweden, Research Report, 2005.
    11. Gustavson S. Simplex noise demystified[J]. Linköping University, Linköping, Sweden, Research Report, 2005.

    展开全文
  • 以Lighthill方程为基础,采用边界元法并与...研究表明:列车运行速度为270 km/h、频率为2.5 kHz时,声压级在90 dB以上的气动偶极子声源主要分布在车底转向架附近,其最大声源声压级约97 dB,是高速列车主要的气动噪声源区.
  • 图像噪声

    千次阅读 2017-03-05 10:07:39
    分类:1、原因分类:外部噪声:指系统外部干扰以电磁波或经电源串进系统内部而引起的噪声。 如:电气设备,天体放电现象等引起的噪声。内部噪声:分为四种: (1)由光和电的基本性质所引起的噪声. 如:电流的产生...

    分类:

    1、原因分类:

    外部噪声:

    指系统外部干扰以电磁波或经电源串进系统内部而引起的噪声。
    如:电气设备,天体放电现象等引起的噪声。

    内部噪声:

    分为四种:
    (1)由光和电的基本性质所引起的噪声.
    如:电流的产生是由电子或空穴粒子的集合,定向运动所形成.
    因这些粒子运动的随机性而形成的散粒噪声
    导体中自由电子的无规则热运动所形成的热噪声
    根据光的粒子性,图像是由光量子所传输,而光量子密度随时间和空间变化所形成的光量子噪声等. 
    (2)电器的机械运动产生的噪声.
    如:各种接头因抖动引起电流变化所产生的噪声;磁头、磁带等抖动或一起的抖动等.
    (3)器材材料本身引起的噪声.
    如:正片和负片的表面颗粒性和磁带磁盘表面缺陷所产生的噪声.
    随着材料科学的发展,这些噪声有望不断减少,但在目前来讲,还是不可避免的.   
    (4)系统内部设备电路所引起的噪声.
    如:电源引入的交流噪声;偏转系统和箝位电路所引起的噪声等.

    2、从统计理论观点分类:

    平稳和非平稳噪声两种.

    这两种噪声可以理解为:

    其统计特性不随时间变化的噪声称其为平稳噪声.其统计特性随时间变化而变化的称其为非平稳噪声.

    3、按噪声幅度随时间分布形状分类:

    如其幅度分布是按高斯分布的就称其为高斯噪声,而按雷利分布的就称其为雷利噪声.

    4、按噪声频谱形状分类:

    频谱均匀分布的噪声称为白噪声

    频谱与频率成反比的称为 1/f噪声

    而与频率平方成正比的称为三角噪声等.

    5、按噪声和信号之间关系分类:

    加性噪声和乘性噪声:

    6.据影响图像质量的噪声源分类:

    (1)电子噪声   

    (2)光电子噪声 :光电子噪声是由光的统计本质和图像传感器中光电转换过程引起的.

    在弱光照的情况下,其影响更为严重,此时常用具有泊松密度分布的随机变量作为光电噪声的模型.这种分布的标准差等于该随机变量均值的平方根.   
    在光照较强时,泊松分布趋向更易描述的高斯分布;
    而标准差(RSM幅值)仍等于均值的平方根.这意味着噪声的幅度是与信号有关的.

    展开全文
  • 图像噪声简介

    万次阅读 2018-07-11 14:23:47
    一、什么是图像噪声噪声在图像上常表现为一引起较强视觉效果的孤立像素点或像素块。一般,噪声信号与要研究的对象不相关,它以无用的信息形式出现,扰乱图像的可观测信息。通俗的说就是噪声让图像不清楚。二、噪声...
  • 本节为opencv数字图像处理(10):图像复原与重建的第二小节,频率域滤波消除周期噪声,主要包括:带阻滤波器、带通滤波器、陷波滤波器以及最佳陷波滤波器的数学推导。
  • 估计噪声参数

    千次阅读 2019-06-16 19:43:09
    周期噪声往往会生成频率尖峰,这些尖峰通常可通过目视来检测。当噪声尖峰非常明显时,或者存在一些关于干扰频率的知识时,就可能自动分析。 在空间域噪声的情况下,PDF的参数可能通过传感器的技术参数部分地知道,...
  • 1/f噪声是一种低频噪声,其噪声功率与频率成反比。人们不仅在电子装置中观测到1/f噪声,在音乐、生物学乃至经济学中也观察到这种噪声1。关于1/f噪声的来源仍存在很大争议,人们就此仍在开展研究2。 在图1所示ADA462...
  • 放大器噪声分析计算

    千次阅读 2018-06-06 00:05:47
    1.何为运放噪声 放大器的噪声模型如下 大致有三部分组成,运放电压噪声,...因为噪声频率相关,此图表征了噪声包含的各个频率分量的大小。图分两个区间,前面线性下降部分称为闪烁噪声,后半部分为宽白噪声。...
  • 噪声污染

    千次阅读 2008-10-16 15:49:00
    何为噪声污染 随着近代工业的发展,环境污染也随着产生,噪声污染就是环境污染的一种,已经成为对人类的一大危害。...噪声的危害 噪声污染对人、动物、仪器仪表以及建筑物均构成危害,其危害程度主要取决于噪声频率
  • 相位噪声 dBc/Hz

    万次阅读 多人点赞 2017-02-15 10:23:03
    相位噪声和抖动是对同一种现象的两种不同的定量方式。在理想情况下,一个频率固定的完美的脉冲信号(以1 MHz为例)的... 相位噪声频率域的概念。相位噪声是对信号时序变化的另一种测量方式,其结果在频率域内显示。
  • 也许你也会跟我一样认为典型数据中的某些规格难以理解,这是因为其中涵盖了一些你不太熟悉的隐含惯例。对许多RF系统工程师而言,其中一种规格便是锁相环(PLL)中的相位噪声。当信号源被用作本机振荡器(LO)或...
  • 相位噪声

    千次阅读 2013-01-14 13:17:29
    相位噪声和抖动是对同一种现象的两种不同的定量方式。在理想情况下,一个频率固定的完美的脉冲信号(以1 MHz为例)的持续时间应该恰好是1微秒,每500ns有一...相位噪声是对信号时序变化的另一种测量方式,其结果在频率
  • IMU噪声模型

    千次阅读 2019-05-22 11:11:14
    IMU噪声模型目录IMU噪声模型新的改变功能快捷键合理的创建标题,有助于目录的生成如何改变文本的样式插入链接与图片如何插入一段漂亮的代码片生成一个适合你的列表创建一个表格设定内容居中、居左、居右SmartyPants...
  • 图像噪声与去噪

    万次阅读 2017-08-23 08:31:51
    图像的空域噪声以及二维降噪算法介绍 1图像噪声的成因  图像在生成和传输过程中常常因受到各种噪声的干扰和影响而是图像降质,这对后续图像的处理和图像视觉效应将产生不利影响。噪声种类很多,比如:电噪声,...
  •  近年来,国内无线通信系统的快速发展,使得微波频率在卫星通信中引用越来越广泛。通信距离越来越远、灵敏度越来越高对系统的性能提出了更高的要求,通信系统不但要求放大微弱信号中有用信号,同时要求具有较小的...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,583
精华内容 8,633
关键字:

噪声频率表