我正在学习Perlin噪声,并用Python编写了一个实现。它看起来正确;但是,在绘制时,单位正方形的边不匹配(仅在x坐标方向上)。 so here's a picture很难解释。我绘制了红线以突出显示该线的一侧与另一侧不匹配的区域。请注意,线是如何在相同的“高度”处发生的,这些“高度”在垂直方向上相隔10个点。此处的垂直方向是x方向,每个点之间的距离为0.1,因此确实会在单位正方形之间发生,仅在x方向上。
这是Perlin噪声代码:
def perlin(self, vector: Vector2) -> float:
# Unit square our vector is in: [0, 255]
unit_square: Vector2 = np.array([int(coord) & 255 for coord in vector])
xs: int = unit_square[0]
ys: int = unit_square[1]
# The coordinates of our vector inside its unit square: [0, 1] × [0, 1]
relative_vector: Vector2 = np.array([coord - math.floor(coord) for coord in vector])
x_rel: float = relative_vector[0]
y_rel: float = relative_vector[1]
# Smoothed relative vector: [0, 1] × [0, 1]
smoothed_vector: Vector2 = np.array([self.fade(coord) for coord in relative_vector])
(u, v) = smoothed_vector
# Hashes the vertices of the unit square using Ken Perlin's hash function
# Uses ((xs, ys), (xs, ys+1), (xs+1, ys), (xs+1, ys+1))
vertex_hashes: Tuple[int, int, int, int] = tuple(
self._hash_lookup_table[self._hash_lookup_table[xs + (mask & 2 == 2)] + ys + (mask & 1 == 1)]
for mask in range(4)
)
# Gets the gradient vector for each vertex
gradient_vectors: Tuple[Vector2] = tuple(self._grad_table[hash_] for hash_ in vertex_hashes)
# Dot products between a vertex's gradient vector and the vector from the input to that vertex
grad_1: float = np.dot(gradient_vectors[0], np.array([-x_rel, -y_rel])) # Bottom left
grad_2: float = np.dot(gradient_vectors[1], np.array([-x_rel, 1-y_rel])) # Top left
grad_3: float = np.dot(gradient_vectors[2], np.array([1-x_rel, 1-y_rel])) # Top right
grad_4: float = np.dot(gradient_vectors[3], np.array([1-x_rel, -y_rel])) # Bottom right
x1: float = self.lerp(grad_1, grad_4, u)
x2: float = self.lerp(grad_2, grad_3, u)
val: float = (self.lerp(x1, x2, v) + 1) / 2 # [0, 1]
return val
@staticmethod
# Linear interpolation
def lerp(a: float, b: float, x: float) -> float:
return a + x * (b-a)
@staticmethod
# Ken Perlin's fade function to ease values towards integral values to smooth the noise output: 6t^5 - 15t^4 + 10t^3
def fade(t: float) -> float:
return 6 * t**5 - 15 * t**4 + 10 * t**3
这是“绘图”代码,尽管没关系:
def draw_perlin_plane(rows: int = 50, columns: int = 211, step: float = 0.1, color_precision: int = 6,
gradient: Tuple[Color, Color] = (Color("white"), Color("black"))):
importlib.reload(noise)
gen: noise.PerlinNoiseGenerator = noise.PerlinNoiseGenerator2D()
terrain: List[List[float]] = []
gradient = list(gradient[0].range_to(gradient[1], color_precision))
for x in range(rows):
terrain.append([])
for y in range(columns):
terrain[x].append(gen.perlin((np.array([x * step, y * step]))))
for row in terrain:
line: str = ""
for value in row:
color = gradient[int(value // (1 / color_precision))]
red: int = math.floor(color.get_red() * 255)
green: int = math.floor(color.get_green() * 255)
blue: int = math.floor(color.get_blue() * 255)
line += f"\x1b[38;2;{red};{green};{blue}m#"
print(line)
(与上图中的默认值一起使用。)
我想知道为什么会出现这些锋利的边缘,如果它们是正常的,以及如何解决这些问题。
谢谢