Hiểu tiếng ồn Perlin


31

Tôi đang chơi với Perlin Noise sau một số hoạt động với Diamond Square. Tôi đã theo dõi triển khai của Hugo Elias , về cơ bản, tạo ra một loạt các hàm với x, y làm đầu vào để ném từng giá trị tọa độ.

Mã PHP của tôi ở đây :

Tôi có hai câu hỏi:

Làm cách nào để sử dụng thuật toán để tạo bản đồ chiều cao trong một mảng? Tôi đã không hiểu đầy đủ về nó và chỉ chuyển sang mã giả mã PHP, nhưng thực hiện chức năng cuối cùng (map_perlines) sau khi đọc ở đâu đó thuật toán "kỳ diệu" cung cấp cho bạn các giá trị được chuyển đổi cho mỗi điểm x, y đưa ra (rõ ràng, mà không cần phải đọc nó giá trị liền kề), tôi chỉ nhận được điều này khi sử dụng như hàm ngẫu nhiênmt_rand(-100,100)/100;

nhập mô tả hình ảnh ở đây

Và điều này khi sử dụng mật mã: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(mà, BTW, có thể được triển khai "nguyên trạng" trong PHP không?):

nhập mô tả hình ảnh ở đây

Vì vậy, tóm tắt, ba câu hỏi:

  1. Mã của tôi có đúng không?
  2. Hàm ngẫu nhiên có thể được chuyển sang PHP như được mô tả trong mã? Nó ném không có lỗi, nhưng kết quả không có ở đó.
  3. Làm thế nào để tôi thực sự sử dụng thuật toán?

CẬP NHẬT

Ok, đã tạo một cổng PHP của mã được hiển thị trong bài viết của Gustavson và như các lập trình viên khác đã nói, nó chỉ tạo ra một quãng tám. Có bất kỳ trang web / giấy / hướng dẫn hữu ích nào khác về cách sử dụng điều này với các khái niệm về nhiều quãng tám, biên độ, tần số, v.v. để kiểm soát chức năng nhiễu không? Trên bài báo của Gustavson chỉ cho thấy kết quả, chứ không phải việc triển khai thực tế thuật toán, có lẽ tôi đang thiếu một cái gì đó?

CẬP NHẬT 2
@NATHAN

Tôi đã làm một cái gì đó như:

$persistence = 0.5;

for ($j = 0; $j < $size; $j++) {
    for ($i = 0; $i < $size; $i++) {

        for ($o = 0; $o < 8; $o++) {
            $frequency = pow(2,$o);
            $amplitude = pow($persistence, $o);
            $value += SimplexNoise($i*$frequency, $j * $frequency) * $amplitude;
            }

            //$value = SimplexNoise($i, $j) + 0.5 * SimplexNoise($i, $j) + 0.25 * SimplexNoise($i, $j);
            $this->mapArray[$i][$j] = new Cell($value);

Và sau khi bình thường hóa các giá trị thành 0..1, tôi nhận được một bản đồ chiều cao khá buồn tẻ, chẳng hạn như:

nhập mô tả hình ảnh ở đây

Làm thế nào để tôi gieo hạt bản đồ? Có lẽ những gì tôi cần thực hiện là phiên bản 3d với giá trị thứ ba một chiều cao ngẫu nhiên? Nhưng nếu vậy, tôi phải tìm hiểu xem xét các giá trị lân cận, mà tôi sẽ kết thúc bằng thứ gì đó giống như thuật toán hình vuông kim cương, chính xác là điều tôi không muốn làm.

CẬP NHẬT 3

Thêm Perlin làm việc. Tôi vẫn chưa tìm được cách hướng dẫn tiếng ồn đến kết quả của mình. Kiểm tra các quãng tám và kết quả cuối cùng:

Octave I đến IV

Tháng 10Tháng 10Tháng 10Tháng 10

Tóm tắt

Octaves 1-4 tóm tắt

Mỗi quãng tám là khá nhiều như nhau. Kiểm tra mã:

$persistence = 0.5;

    for ($j = 0; $j < $size; $j++) {
      for ($i = 0; $i < $size; $i++) {
        $value = 0;

        for ($o = 0; $o < 4; $o++) {
          $frequency = pow(2,$o);
          $amplitude = pow($persistence, $o);
          $value += improved_noise($i*$frequency, $j*$frequency, 0.5)*$amplitude;

        }
        $this->map[$i][$j] = new Cell($value);

Kết quả được bình thường hóa. Những gì bạn sẽ sử dụng có ảnh hưởng mạnh mẽ trong sự phát triển của tiếng ồn? Tôi thấy các ví dụ trong đó việc thay đổi biên độ cho bề mặt mềm hoặc nhám, nhưng ngay cả khi tôi cho biên độ lớn, tôi cũng thấy rất ít sự khác biệt.


Chỉ cần thêm nhiều trường hợp, tăng tần số và giảm biên độ mỗi lần, như: perlin (x) + 0,5 * perlin (2 * x) + 0,25 * perlin (4 * x) + ... (cho nhiều quãng tám như bạn muốn). Bạn cũng có thể thử thay đổi các yếu tố để có được vẻ ngoài khác nhau; họ không cần phải là sức mạnh của 2.
Nathan Reed

1
Sau khi cập nhật, có vẻ như bạn không mở rộng chính xác Y - Tôi quá mệt mỏi để tìm kiếm PHP (vì tôi không biết PHP); nhưng tôi đã gặp một vấn đề tương tự trong ngôn ngữ nhà của tôi khi thực hiện perlin lần đầu tiên. Cũng giết các quãng tám và chỉ gỡ lỗi một cấp độ của perlin.
Jonathan Dickinson

Bất cứ ai cho bản cập nhật III của tôi?
Gabriel A. Zorrilla

Câu trả lời:


28

Những gì bạn thực hiện không phải là tiếng ồn Perlin. Tôi không chắc tại sao Hugo Elias nói vậy, nhưng anh ấy bối rối. Đây là cách thực hiện tham khảo của Ken Perlin. Nó không thực sự gọi bất kỳ trình tạo số ngẫu nhiên bên ngoài nào, nhưng sử dụng hàm băm tích hợp để tạo ra các vectơ gradient giả ngẫu nhiên.

Cũng lưu ý rằng tiếng ồn Perlin chỉ bao gồm một quãng tám. Tổng kết nhiều quãng tám (các trường hợp tỷ lệ của hàm nhiễu), như Hugo Elias gợi ý, là một kỹ thuật hữu ích, nhưng không phải là một phần của nhiễu Perlin. Những gì bạn nhận được bằng cách làm điều đó được gọi là tiếng ồn fractal, đôi khi là "tiếng ồn fractal Brown" (vì được cho là giống với chuyển động Brownian).

Nếu bạn muốn hiểu về mặt hình học thuật toán đang làm gì, hãy thử bài viết này . Đó là về một loại tiếng ồn khác gọi là "tiếng ồn đơn giản", nhưng cũng bao gồm một lời giải thích về tiếng ồn Perlin cổ điển. Ngẫu nhiên, tiếng ồn đơn giản cũng được Perlin phát minh và được cho là một cải tiến so với tiếng ồn cổ điển của anh ấy, vì vậy bạn cũng có thể thử thực hiện nó nếu bạn thích chơi với các chức năng tiếng ồn.


2
+1 cho bài viết của Gustavson. Nó giải thích cả tiếng ồn perlin và Simplex theo cách rõ ràng nhất mà tôi đã thấy cho đến nay. Rõ ràng quy tắc tiếng ồn đơn giản!
FxIII

Tôi cũng đã tìm thấy tờ giấy này một thời gian trước nhưng Hugo trông đơn giản hơn. Tôi sẽ đọc nó và cho nó một shot! Cảm ơn!
Gabriel A. Zorrilla

2
hãy cẩn thận khi tải xuống tiếng ồn đơn giản, nó có thể có vi-rút;)
bobobobo

Tôi biết đây là một chủ đề cũ, nhưng nói rằng việc triển khai tham chiếu không sử dụng một số ngẫu nhiên là không chính xác. Khi thư viện được khởi tạo (hoặc lần đầu tiên một hàm nhiễu được gọi), 256 độ dốc ngẫu nhiên được tạo. Băm mà bạn đề cập chỉ đơn thuần là ép buộc bộ số nguyên vô hạn vào phạm vi [0, 255] được lưu trong bộ nhớ cache. Về cơ bản, đây chỉ là một tối ưu hóa bảng tra cứu và thuật toán cũng hoạt động tốt nếu, ví dụ, bạn chọn một PRNG với tọa độ lưới và sử dụng nó để tạo ra độ dốc, nó chỉ chậm hơn (rất nhiều).
bcrist

@bcrist Tôi nghĩ bạn đang đề cập đến một phiên bản tiếng ồn Perlin cũ hơn. "Tiếng ồn được cải thiện" của Perlin, mà tôi liên kết đến , sử dụng một bộ 12 vectơ gradient cố định, chứ không phải 256 vectơ ngẫu nhiên. Nó sử dụng bảng hoán vị làm hàm băm để ánh xạ tọa độ lưới tới một trong 12 vectơ gradient.
Nathan Reed

11

Đó là một quan niệm sai lầm phổ biến. Cái mà Hugo Elias gọi là tiếng ồn "Perlin" trên thực tế là tiếng ồn fractal, hay màu hồng. Để hiểu rõ hơn về tiếng ồn của Perlin là gì, bạn có thể đọc bài viết của Perlin được liên kết trong câu trả lời của Nathan Reed hoặc các tài liệu libnoise (có cùng một lỗi ở đó: Tiếng ồn Perlin là những gì họ gọi là nhiễu Gradient) hoặc tài liệu CoherentNiri .

Bây giờ, để thực sự trả lời câu hỏi của bạn: bạn đã không nhận được kết quả như mong đợi vì tần suất tiếng ồn quá cao. Tần số của bạn bắt đầu bằng 1 và tăng lên, nghĩa là mọi pixel trong bản đồ kết quả có một giá trị ngẫu nhiên. Để xem cấu trúc tốt hơn của bản đồ, bạn cần "phóng to" tiếng ồn. Tôi không thực sự nói PHP, nhưng tôi cho rằng mã sẽ giống như thế này:

$arrayMap[$i][$j] = PerlinNoise_2D($i/$width, $j/$height, $p, $octaves);

Đó là, bạn "kéo dài" một khoảng thời gian nhiễu trên toàn bộ bản đồ của bạn. Tất nhiên, bạn có thể sử dụng các hệ số khác - chỉ cần thử các hệ số khác nhau, xem điều gì sẽ xảy ra.


Cảm ơn các tài liệu tiếng ồn mạch lạc! Tôi thấy rằng bạn đã viết nó :) Lỗi gì trong tài liệu libnoise? Không phải tiếng ồn Perlin là một loại tiếng ồn gradient?
huyền thoại2k
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.