import random,math
class Noise:
def __init__(self):
nums = [i for i in range(256)]
permutation = [nums[random.randint(0, len(nums) - 1)] for i in range(256)]
self.p = [permutation[x % 256] for x in range(512)]
#噪声重复的区间范围
self.repeat = 0
#噪声的频率
self.frequency = 50
#噪声的振幅
self.amplitude = 10
self.vs = [0+1j, 1+0j, 1+1j, 0-1j, -1+0j, -1-1j, 1-1j, -1+1j]
def perlin(self,x:int,y:int)->float:
x /= 1000
y /= 1000
x *= self.frequency
y *= self.frequency
#确定柏林噪声重复的区间
if self.repeat > 0:
x %= self.repeat
y %= self.repeat
#取xy的整数部分用于确定坐标落在了哪个晶格内
xi = math.floor(x)%255
yi = math.floor(y)%255
#取xy的小数部分用于确定坐标在晶格内的位置
xf = x - math.floor(x)
yf = y - math.floor(y)
#对坐标的小数部分使用缓和曲线插值
u = self.fade(xf)
v = self.fade(yf)
# 通过哈希运算确定晶格4个顶点的哈希值(用于在self.grad函数中确定顶点的梯度向量)
# b-----c
# | |
# | |
# a-----d
p = self.p
a = hash((xi,yi))
b = hash((xi,self.inc(yi)))
c = hash((self.inc(xi), self.inc(yi)))
d = hash((self.inc(xi), yi))
#计算4个顶点的梯度向量与输入点-顶点向量之间的点积的加权平均值
x1 = self.lerp(self.grad(a, xf, yf), self.grad(d, xf - 1, yf), u)
x2 = self.lerp(self.grad(b, xf, yf - 1), self.grad(c, xf - 1, yf - 1), u)
z = self.lerp(x1, x2, v)
return z * self.amplitude
def fade(self,t):
# 6t^5 - 15t^4 + 10t^3
return t * t * t * (t * (t * 6 - 15) + 10)
def inc(self,num):
num += 1
if self.repeat > 0:
num %= self.repeat
return num
def lerp(self, a, b, x):
return a + x * (b - a)
def grad(self, hash, x, y):
print(self.vs[hash % 8])
return abs(self.normalized(self.vs[hash % 8]) * (x+y*1j))
#归一化
def normalized(self, v):
m = abs(v)
return v/m