Làm cách nào để tạo tiếng ồn rắn có thể điều chỉnh để tạo bản đồ?


16

Chào các bạn, tôi đang cố gắng tìm ra cách tạo ra các fractals có thể điều chỉnh được trong mã (đối với bản đồ trò chơi, nhưng điều đó không liên quan ) Tôi đã cố gắng sửa đổi bổ trợ Solid Noise được cung cấp với GIMP (với sự hiểu biết cực kỳ hạn chế của tôi về cách mã hoạt động) nhưng tôi không thể làm cho tôi hoạt động chính xác.

Mã sửa đổi của tôi cho đến nay (Java)

Mô-đun tiếng ồn rắn của GIMP mà tôi dựa vào mã của mình từ (C)

Đây là những gì tôi đang cố gắng để đạt được nhưng đây là những gì tôi đang nhận được

Vì vậy, nếu bất cứ ai cũng có thể thấy những gì tôi đã làm sai, hoặc có một gợi ý về cách tôi có thể làm điều đó khác đi, tôi đánh giá rất cao nó. Cảm ơn trước. Và nếu tôi hỏi đường nhiều hay chỉ là một thất bại lớn trong cuộc sống, tôi xin lỗi.


Hãy thử sử dụng phép nội suy bicubic thay vì song tuyến? Tôi không biết đó có phải là vấn đề của bạn không, nhưng nó LOOKS giống như vậy.
Stephen Furlani

Câu trả lời:


4

Tôi không theo dõi mã của bạn một cách chính xác, nhưng đây là một mô tả đơn giản về thuật toán sẽ đạt được hiệu quả gần như (dựa trên hình ảnh bạn đã đăng).

Giải thích sau đây không phải là phiên bản siêu tối ưu, nhưng là một phiên bản rõ ràng về mặt khái niệm (tôi hy vọng). Một khi bạn đã có nó chạy, bạn có thể tối ưu hóa nó (thực tế khá quyết liệt).

  1. Tạo n lớp nhiễu ngẫu nhiên đồng nhất (chỉ các pixel thang độ xám ngẫu nhiên).
  2. Bây giờ hãy lấy mẫu từng loại này bằng cách lấy mẫu từng pixel 1, 2, 4, 8, ... 2 ^ (n-1) và nội suy các pixel trung gian. Mỗi lớp mịn hơn lớp trước.
  3. Bây giờ tỷ lệ của các lớp này với hệ số 1, 2, 4, 8, v.v ... Mỗi lớp tối hơn lớp trước.
  4. Thêm tất cả những thứ này lại với nhau.
  5. Bình thường hóa bằng cách chia từng pixel với (1 + 2 + 4 + 8 + ... 2 ^ (n-1)).

Bước khó khăn là bước lấy mẫu và nội suy. Giả sử chúng ta đang trong lớp bỏ qua lấy mẫu mỗi pixel thứ m. Đây là ý tưởng cơ bản cho m> 1 (nếu m là 1, chúng tôi sử dụng hình ảnh như hiện tại):

for each pixel x and y
   left_sample_coord = m *(x / m) //(integer division, automatically truncated)
   right_sample_coord = (left_sample_point + m) % image_width
   top_sample_point = m*(y / m) 
   bottom_sample_coord = (top_sample_point + m) % image_height

   horizontal_weight = (x - left_sample_point) / (m - 1)
   vertical_weight = (y - top_sample_point) / (m - 1)

   sample_top_left = image(left_sample_coord, top_sample_point)
   //and the same for the other four corners

   //now combine the top two points
   top_interpolate = sample_top_left * horizontal_weight + sample_top_right * (1-horizontal_weight)

  //now combine the bottom two points
  bottom_interpolate = sample_bottom_left * horizontal_weight + sample_bottom_right * (1-horizontal_weight)

  //and combine these two last obtained values

  smooth_noise(x, y) = top_interpolate * vertical_weight  + bottom_interpolate * (1 - vertical_weight)

IT tiên boa:

  • Kết quả của thuật toán ở trên có vẻ hơi bị rửa trôi. Bạn có thể giảm hiệu ứng này bằng cách sử dụng cùng một lớp nhiễu cho tất cả các lớp hoặc tương phản để tăng cường hình ảnh sau đó.
  • Thuật toán trên sử dụng phép nội suy tuyến tính, nhưng phép nội suy cosine (thực hiện tìm kiếm) cho kết quả tốt hơn nhiều.
  • Làm cho nó có thể xem xét các lớp của bạn một cách riêng biệt trong tất cả các phần của thuật toán. Điều này sẽ giúp bạn tuôn ra lỗi nhanh chóng.

3

Có vẻ như pastebin ban đầu của tôi đã hết hạn bằng cách nào đó, vì vậy tôi không có cách nào để so sánh mã không hoạt động của mình, nhưng trên trò chơi hiện tại của tôi, tôi đã trải qua và dịch mã GIMP sang java một lần nữa và nó dường như hoạt động tốt.

Nếu bất cứ ai có kế hoạch sử dụng mã này, tôi khuyên bạn nên sửa đổi hàm tạo để sửa đổi các tham số cài đặt (chi tiết và kích thước) để bạn có thể làm cho nó hoạt động theo cách bạn muốn. EDIT: Tôi nhận ra câu hỏi ban đầu của tôi là về việc làm cho nó trở nên dễ hiểu, vì vậy hãy nhớ đặt tilable thành đúng!

Mã: http://pastebin.com/KsfZ99Xa

Thí dụ: ví dụ máy phát điện perlin


2

Chỉ cần lướt qua các phiên bản Java và C và nhận thấy một sự khác biệt nhỏ trong cách bạn sử dụng chức năng tiếng ồn. Đây là của bạn:

int val = Math.abs((int) Math.floor(255.0 * noise(((double)col/(double)width), ((double)row/(double)height))));

Mã C:

val = (guchar) floor (255.0 * noise ((col - xoffset) / width,

                                           (row - yoffset) / height));

Tại sao bạn chọn không trừ phần bù? (col - xoffset) và (hàng - yoffset)

Chỉ cần tự hỏi. Tôi không có thời gian để phân tích đầy đủ về mã.

Hi vọng điêu nay co ich.


xoffset và yoffset là để tính toán theo cách GIMP chia hình ảnh thành các lưới, nhưng tất cả chương trình của tôi hoạt động trên một ô sao cho x và y bù sẽ là 0
Nick Badal

2

Tôi không biết liệu nó có giúp được gì không nhưng mẹo sau đây có tác dụng đối với tôi:

http://www.gamedev.net/blog/33/entry-2138456-siền-noise /

Đồng nghiệp này đang sử dụng hàm nhiễu 4d và chỉ cần cung cấp các giá trị xy của hai vòng tròn dưới dạng giá trị xyzw cho nhiễu 4d. Kết quả là vòng lặp hoàn hảo.

Đây là ý tưởng (đơn giản hóa) cho hình ảnh 1000 * 1000:

for(i = 0;i < 1000; i++){

  for(j = 0; j < 1000; j++){

    nx = cos((i/1000) * 2 * PI);
    ny = cos((j/1000) * 2 * PI);
    nz = sin((i/1000) * 2 * PI);
    nw = sin((j/1000) * 2 * PI);

    looped_noise = noise_4D( nx, ny, nz, nw, octaves, persistence, lacunarity, blah...);
    noise_buffer[(i*1000)+j] = looped_noise;

  }
}

1

Tôi khuyên bạn nên sử dụng thuật toán hình vuông kim cương , còn được gọi là fractal plasma hoặc fractal dịch chuyển giữa điểm ngẫu nhiên. Sử dụng thuật toán này, rất dễ dàng để hạn chế các cạnh có cùng giá trị. Khi bạn tạo một giá trị cho một cạnh, sao chép nó vào cạnh tương ứng ở phía bên kia. Điều này mang lại một bản đồ ốp lát hoàn hảo.


0

Có một bài viết tuyệt vời về việc tạo tiếng ồn ở đây . Đó không phải là nhiễu Perlin như bài báo tuyên bố (thực ra đó là nhiễu hồng), nhưng vẫn cực kỳ hữu ích để hiểu cách tạo ra các hình ảnh nhiễu.

Vì vậy, để thực sự trả lời câu hỏi của bạn: để tạo ra một hình ảnh nhiễu có thể điều chỉnh được, bạn chỉ cần giữ "độ mềm" trong suốt thế hệ. Đó là, khi tiếng ồn được làm mịn, bạn làm mịn nó như thể nó được lặp đi lặp lại vô tận theo mọi hướng - lát gạch.


0

Từ ảnh chụp màn hình, tôi đoán rằng chỉ có các lớp "lớn" được tạo ra, đó là lý do tại sao nhiễu xuất hiện quá thường xuyên và thiếu chi tiết.

Điều này nghe có vẻ ngu ngốc, nhưng bạn đã thử tăng biến "chi tiết" (dòng 16) chưa? Trong mã của bạn, nó được đặt thành 1, có nghĩa là thuật toán sẽ chỉ tạo hai lớp chi tiết trước khi dừng. Hãy thử tăng nó lên thành 8.


0

Bạn cũng nên xem Simplex Noise , được phát triển bởi Ken Perlin để khắc phục một số thiếu sót của tiếng ồn Perlin.

Tôi đang thực hiện triển khai Simplex Noise cho trò chơi C ++. Nó hỗ trợ nhiễu đa tần số 1D / 2D / 3D / 4D. Ngay bây giờ, kết cấu tích hợp duy nhất là đá cẩm thạch, nhưng bạn có thể dễ dàng thêm nhiều hơn:

(http://code.google.com.vn/p/battlestar-tux/source/browse/trunk/src/lib/procedural/)

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.