Perlin噪声

perlin基本信息

Perlin噪声(Perlin noise,又称为柏林噪声)指由Ken Perlin发明的自然噪声生成算法,具有在函数上的连续性,并可在多次调用时给出一致的数值。 在电子游戏领域中可以透过使用Perlin噪声生成具连续性的地形;或是在艺术领域中使用Perlin噪声生成图样。

由于一些历史原因,Simplex噪声和分形噪声(texture synthesis)都曾在学术论文中被单独称作Perlin噪声。

经典Perlin噪声

perline噪声是基于晶格的方法。它属于梯度噪声,其原理就是将坐标系划分成一块一块的晶格,之后在晶格的顶点出生成一个随机梯度,通过与晶格顶点到晶格内点的向量进行点乘加权计算后得到噪声。

实现perlin噪声的过程需要插值

  • 对于一维:插值使用的是一个在0处为1,在1处为0,在0.5处为0.5的连续单调递减函数。例如对,设c0,c1为左右两个整数点的数值,t为该点距离左边点的距离,使用(1t)作为插值函数,则该点的值为c1(1t)+c0t

但是(1t)是线性插值,人工痕迹比较严重,并且在整数点上不连续。Perlin建议使用3t22t3作为插值函数。后来建议使用6t515t4+10t3作为插值函数。事实上,只有在区间[0,1]内的连续函数f,有f(0)=1,f(1)=0f(0)=f(1)=0的函数皆可作为插值函数。 * 对于二维:对于点(x,y),令i=x,j=y,它所在的晶格的四个顶点分别为(i,j)(i+1,j)(i+1,j+1)(i,j+1)。令u=xi,v=yj,这四个顶点对点(x,y)的贡献可以使用它们的梯度(g00,g10,g11,g01)(x,y)点与这四个顶点的方向((u,v),(u1,v),(u1,v1),(u,v1))进行点积获得。但是在二维的情况下,插值更为复杂。首先需要对 (i,j)(i+1,j) 两点在x方向插值,得到点(x,j)的值;之后对(i,j+1)(i+1,j+1)两点在x方向插值,得到点(x,j+1)的值;最后对(x,j)(x,j+1)y方向插值,得到(x,y)的值。

code

完整代码

def interpolant(t):
    return t*t*t*(t*(t*6 - 15) + 10)


def generate_perlin_noise_2d(
        shape, res, tileable=(False, False), interpolant=interpolant
):
    delta = (res[0] / shape[0], res[1] / shape[1])
    d = (shape[0] // res[0], shape[1] // res[1])
    grid = np.mgrid[0:res[0]:delta[0], 0:res[1]:delta[1]]\
             .transpose(1, 2, 0) % 1
    # Gradients
    angles = 2*np.pi*np.random.rand(res[0]+1, res[1]+1)
    gradients = np.dstack((np.cos(angles), np.sin(angles)))
    if tileable[0]:
        gradients[-1,:] = gradients[0,:]
    if tileable[1]:
        gradients[:,-1] = gradients[:,0]
    gradients = gradients.repeat(d[0], 0).repeat(d[1], 1)
    g00 = gradients[    :-d[0],    :-d[1]]
    g10 = gradients[d[0]:     ,    :-d[1]]
    g01 = gradients[    :-d[0],d[1]:     ]
    g11 = gradients[d[0]:     ,d[1]:     ]
    # Ramps
    n00 = np.sum(np.dstack((grid[:,:,0]  , grid[:,:,1]  )) * g00, 2)
    n10 = np.sum(np.dstack((grid[:,:,0]-1, grid[:,:,1]  )) * g10, 2)
    n01 = np.sum(np.dstack((grid[:,:,0]  , grid[:,:,1]-1)) * g01, 2)
    n11 = np.sum(np.dstack((grid[:,:,0]-1, grid[:,:,1]-1)) * g11, 2)
    # Interpolation
    t = interpolant(grid)
    c0 = n00*(1-t[:,:,0]) + t[:,:,0]*n10
    c1 = n01*(1-t[:,:,0]) + t[:,:,0]*n11
    return np.sqrt(2)*((1-t[:,:,1])*c0 + t[:,:,1]*c1)

结果

  • Perlin 2D噪声

  • 3D perline噪声

  • 给人物图像添加perlin噪声

posted @   九叶草  阅读(541)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示