Perlin噪声在单位正方形边缘处不平滑

时间:2019-04-08 19:28:14

标签: python perlin-noise

我正在学习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)

(与上图中的默认值一起使用。)

我想知道为什么会出现这些锋利的边缘,如果它们是正常的,以及如何解决这些问题。

谢谢

0 个答案:

没有答案