การทำความเข้าใจเสียงเพอร์ลิน


31

ฉันกำลังเล่นกับ Perlin Noise หลังจากทำงานกับ Diamond Square ฉันติดตามการใช้งานโดย Hugo Eliasซึ่งโดยทั่วไปสร้างชุดฟังก์ชันด้วย x, y เพื่อป้อนค่าแต่ละค่าพิกัด

รหัส PHP ของฉันอยู่ที่นี่ :

ฉันมีสองคำถาม:

ฉันจะใช้อัลกอริทึมเพื่อสร้างแผนที่ความสูงในอาร์เรย์ได้อย่างไร ฉันไม่เข้าใจอย่างเต็มที่และเพิ่งส่งไปยัง PHP รหัสเทียม แต่ทำฟังก์ชั่นสุดท้าย (map_perlined) หลังจากอ่านที่ไหนสักแห่งว่าอัลกอริธึม "น่าอัศจรรย์" ให้ค่าการเปลี่ยนสำหรับแต่ละ x, y ชี้ให้ (ชัดโดยไม่ต้องอ่าน ค่าติดกัน) ฉันเพิ่งได้สิ่งนี้เมื่อใช้เป็นฟังก์ชั่นแบบสุ่มmt_rand(-100,100)/100;

ป้อนคำอธิบายรูปภาพที่นี่

และสิ่งนี้เมื่อใช้การเข้ารหัสลับ: 1.0-(($n*($n*$n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0;(อันไหน BTW สามารถดำเนินการ "ตามที่เป็น" ใน PHP?):

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นสรุปคำถามที่สาม:

  1. รหัสของฉันถูกต้องหรือไม่
  2. ฟังก์ชั่นแบบสุ่มสามารถย้ายไปยัง PHP ตามที่อธิบายไว้ในรหัสได้หรือไม่ มันไม่มีข้อผิดพลาด แต่ผลลัพธ์ไม่ได้อยู่ที่นั่น
  3. ฉันจะใช้อัลกอริทึมจริงได้อย่างไร

UPDATE

ตกลงทำพอร์ต PHP ของรหัสที่แสดงในกระดาษ Gustavson และตามที่ผู้เขียนโค้ดคนอื่นบอกว่ามันแค่สร้างอ็อกเทฟเดียว มีไซต์ / กระดาษ / คู่มืออื่น ๆ เกี่ยวกับวิธีใช้สิ่งนี้กับแนวคิดของอ็อกเทฟหลายแอมพลิจูดความถี่ ฯลฯ เพื่อควบคุมฟังก์ชั่นเสียงรบกวนหรือไม่? บนกระดาษของกุสตาฟสันแสดงผลลัพธ์ไม่ใช่การใช้อัลกอริทึมจริง ๆ บางทีฉันอาจพลาดอะไรบางอย่าง?

อัปเดต 2
@NATHAN

ฉันทำบางสิ่งเช่น:

$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);

และหลังจากปรับค่าปกติเป็น 0..1 ฉันได้รับแผนที่ความสูงที่ค่อนข้างทึบเช่น:

ป้อนคำอธิบายรูปภาพที่นี่

ฉันจะหว่านเมล็ดแผนที่ได้อย่างไร บางทีสิ่งที่ฉันต้องใช้คือ 3d version ที่มีค่าที่สามเป็นความสูงแบบสุ่ม? แต่ถ้าเป็นเช่นนั้นฉันจะต้องคำนึงถึงคุณค่าของเพื่อนบ้านซึ่งฉันจะลงท้ายด้วยบางอย่างเช่นอัลกอริธึมแบบสี่เหลี่ยมจัตุรัสซึ่งเป็นสิ่งที่ฉันไม่ต้องการทำ

อัพเดท 3

Perlin ทำงานมากขึ้น ฉันยังไม่พบวิธีที่จะนำเสียงไปสู่ผลลัพธ์ของฉัน ตรวจสอบอ็อกเทฟเหล่านี้และผลลัพธ์สุดท้าย:

อ็อกเทฟ I ถึง IV

Octave1Octave2Octave3Octave4

สรุป

ผลรวมของเลอะเลือน 1-4

ระดับแปดเสียงแต่ละคู่ค่อนข้างเท่ากัน ตรวจสอบรหัส:

$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);

ผลลัพธ์จะถูกทำให้เป็นมาตรฐาน คุณจะใช้อะไรมีอิทธิพลอย่างมากต่อการพัฒนาเสียง ฉันเห็นตัวอย่างที่การเปลี่ยนแอมพลิจูดให้พื้นผิวที่นุ่มหรือขรุขระ แต่แม้ว่าฉันจะให้แอมพลิจูดขนาดใหญ่ แต่ฉันก็เห็นความแตกต่างเล็กน้อย


เพียงเพิ่มหลายอินสแตนซ์เข้าด้วยกันเพิ่มความถี่และลดขนาดแอมพลิจูดในแต่ละครั้งเช่น: perlin (x) + 0.5 * perlin (2 * x) + 0.25 * perlin (4 * x) + ... คุณต้องการ). คุณสามารถลองปรับเปลี่ยนปัจจัยต่างๆเพื่อให้ได้รูปลักษณ์ที่แตกต่างกัน พวกเขาไม่จำเป็นต้องเป็นพลังของ 2
นาธานรีด

1
โพสต์อัปเดตดูเหมือนว่าคุณไม่ได้ปรับสเกล Y อย่างถูกต้อง - ฉันเหนื่อยเกินกว่าจะคลาน PHP (เพราะฉันไม่รู้ PHP) แต่ฉันพบปัญหาที่คล้ายกันในภาษาที่บ้านของฉันเมื่อใช้งาน perlin เป็นครั้งแรก นอกจากนี้ยังฆ่าอ็อกเทฟและเพียงแค่ debug หนึ่งระดับของ perlin
Jonathan Dickinson

ทุกคนสำหรับการอัพเดท III ของฉัน
Gabriel A. Zorrilla

คำตอบ:


28

สิ่งที่คุณนำไปใช้ไม่ใช่เสียงเพอร์ลิน ฉันไม่แน่ใจว่าทำไม Hugo Elias บอกว่ามันเป็น แต่เขาสับสน นี่คือการดำเนินการอ้างอิงของ Ken Perlin มันไม่ได้เรียกตัวสร้างตัวเลขสุ่มภายนอกใด ๆ แต่ใช้ฟังก์ชันแฮชในตัวเพื่อสร้างเวกเตอร์ไล่ระดับสีเทียมหลอกเทียม

โปรดทราบว่าเสียง Perlin ประกอบด้วยเพียงหนึ่งคู่ การสรุปหลายอ็อกเทฟ (ฟังก์ชั่นปรับขนาดของเสียง) ตามที่ Hugo Elias แนะนำเป็นเทคนิคที่มีประโยชน์ แต่ไม่ใช่ส่วนหนึ่งของเสียงเพอร์ลิน สิ่งที่คุณได้รับจากการทำเช่นนั้นเรียกว่าเสียงแฟร็กทัลบางครั้ง "เสียงแฟร็กทัลบราวน์" (เพราะความคุ้นเคยกับการเคลื่อนไหวบราวเนียน)

หากคุณต้องการเข้าใจเรขาคณิตในสิ่งที่อัลกอริทึมกำลังทำอยู่ให้ลองบทความนี้ มันเกี่ยวกับเสียงที่แตกต่างที่เรียกว่า "เสียงรบกวนง่าย ๆ " แต่ยังรวมถึงคำอธิบายของเสียง Perlin แบบคลาสสิก บังเอิญว่าเสียงของ simplex นั้นถูกคิดค้นโดย Perlin และก็ควรที่จะปรับปรุงเสียงรบกวนแบบคลาสสิกของเขาดังนั้นคุณอาจลองใช้มันด้วยหากคุณสนใจที่จะเล่นกับฟังก์ชั่นเสียงรบกวน


2
+1 สำหรับกระดาษของ Gustavson มันอธิบายทั้งเสียงเพอร์ลินและซิมเพล็กซ์อย่างชัดเจนที่สุดเท่าที่ฉันเคยเห็นมา เห็นได้ชัดว่ากฎเสียงรบกวนง่าย!
FxIII

ฉันยังพบว่ากระดาษเมื่อเร็ว ๆ นี้ แต่ของ Hugo ดูง่ายขึ้น ฉันจะอ่านและให้มันยิง! ขอบคุณ!
Gabriel A. Zorrilla

2
ระวังเมื่อดาวน์โหลดสัญญาณรบกวนแบบง่าย ๆ , มันอาจมีไวรัส;)
bobobobo

ฉันรู้ว่านี่เป็นหัวข้อเก่า แต่การบอกว่าการใช้งานอ้างอิงไม่ได้ใช้ตัวเลขสุ่มไม่ถูกต้อง เมื่อไลบรารีถูกกำหนดค่าเริ่มต้น (หรือครั้งแรกที่มีการเรียกใช้ฟังก์ชั่นเสียงรบกวน) จะสร้างการไล่ระดับสีแบบสุ่ม 256 การแปลงค่าที่คุณอ้างถึงเป็นเพียงการบีบบังคับจำนวนเต็มจำนวนอนันต์ลงในช่วง [0, 255] ที่แคชไว้ โดยพื้นฐานแล้วนี่เป็นเพียงการเพิ่มประสิทธิภาพของตารางค้นหาและอัลกอริธึมทำงานได้ดีเช่นถ้าคุณสร้าง PRNG ด้วยพิกัดกริดและใช้สิ่งนั้นเพื่อสร้างการไล่ระดับสีมันช้ากว่ามาก
bcrist

@bcrist ฉันคิดว่าคุณหมายถึงเสียง Perlin รุ่นเก่ากว่า "สัญญาณรบกวนที่ดีขึ้น" ของ Perlin ซึ่งฉันเชื่อมโยงใช้ชุดเวกเตอร์เกรเดียนต์ไล่ระดับคงที่จำนวน 12 ชุดไม่ใช่แบบสุ่ม 256 อัน มันใช้ตารางเรียงสับเปลี่ยนเป็นฟังก์ชันแฮชเพื่อแมปพิกัดกริดกับหนึ่งใน 12 เวกเตอร์ไล่ระดับสี
Nathan Reed

11

นั่นเป็นความเข้าใจผิดที่พบบ่อย สิ่งที่ฮูโก้อีเลียสเรียกว่าเสียง "Perlin" ในความเป็นจริงเป็นเศษส่วนหรือสีชมพูเสียง เพื่อทำความเข้าใจสิ่งที่ Perlin เสียงคือคุณสามารถอ่านบทความ Perlin ของการเชื่อมโยงในคำตอบของนาธานกกหรือเอกสาร libnoise (มีข้อผิดพลาดเดียวกันนั่น Perlin เสียงคือสิ่งที่พวกเขาเรียกว่าการไล่โทนสีเสียง) หรือเอกสาร CoherentNoise

ตอนนี้เพื่อตอบคำถามของคุณจริง ๆ : คุณไม่ได้รับผลลัพธ์ที่คาดหวังเพราะความถี่เสียงรบกวนสูงเกินไป ความถี่ของคุณเริ่มต้นที่ 1 และเพิ่มขึ้นหมายความว่าทุกพิกเซลในแผนที่ผลลัพธ์มีค่าแบบสุ่ม หากต้องการดูโครงสร้างที่ละเอียดยิ่งขึ้นของแผนที่คุณต้อง "ซูมเข้า" บนจุดรบกวน ฉันไม่ได้พูด PHP จริงๆ แต่ฉันคิดว่ารหัสควรมีลักษณะเช่นนี้:

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

นั่นคือคุณ "ยืด" เสียงหนึ่งรอบบนแผนที่ทั้งหมดของคุณ แน่นอนคุณสามารถใช้สัมประสิทธิ์อื่น ๆ - ลองใช้ค่าอื่นดูว่าเกิดอะไรขึ้น


ขอบคุณสำหรับเอกสารเสียงที่สอดคล้องกัน! ฉันเห็นว่าคุณเขียนแล้ว :) ข้อผิดพลาดในเอกสาร libnoise คืออะไร? เสียง Perlin ไม่ใช่เสียงไล่ระดับสีหรือไม่
ตำนาน 2k
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.