ฉันจะสร้างเขตข้อมูลระยะทางที่ลงนาม (2D) แบบเรียลไทม์ได้อย่างรวดเร็วได้อย่างไร


21

ในคำถามก่อนหน้านี้มีข้อเสนอแนะว่าฟิลด์ระยะทางที่ลงนามแล้วสามารถทำการคำนวณล่วงหน้าโหลดตอนรันไทม์แล้วใช้จากนั้น

ด้วยเหตุผลที่ฉันจะอธิบายในตอนท้ายของคำถามนี้ (สำหรับผู้ที่สนใจ) ฉันต้องสร้างฟิลด์ระยะทางแบบเรียลไทม์

มีเอกสารบางส่วนสำหรับวิธีการที่แตกต่างกันซึ่งควรจะทำงานได้ในสภาพแวดล้อมแบบเรียลไทม์เช่นวิธีการแปลง Chamfer distance และ Voronoi ไดอะแกรมการประมาณตามการแปลง (ตามที่เสนอในงานนำเสนอโดย Pixeljunk Shooter dev guy ) แต่ ฉัน (และอาจเป็นที่คาดเดาของคนอื่น ๆ ) มีช่วงเวลาที่ยากมากจริง ๆ ทำให้พวกเขาใช้เพราะพวกเขามักจะยาวส่วนใหญ่ป่องกับคณิตศาสตร์และอัลกอริทึมไม่มากในการอธิบายของพวกเขา

อัลกอริทึมใดที่คุณจะแนะนำสำหรับการสร้างเขตข้อมูลระยะไกลแบบเรียลไทม์ (อยู่ในเกณฑ์ดีของ GPU) โดยเฉพาะอย่างยิ่งเมื่อพิจารณาถึงคุณภาพของเขตข้อมูลระยะทาง

เนื่องจากฉันกำลังมองหาคำอธิบาย / บทแนะนำที่เกิดขึ้นจริงซึ่งตรงข้ามกับลิงก์ไปยังกระดาษหรือสไลด์อื่นคำถามนี้จะได้รับรางวัลเมื่อมันมีสิทธิ์สำหรับหนึ่ง :-)

นี่คือเหตุผลที่ฉันต้องทำในเวลาจริง:

หากคุณต้องคำนวณ SDF เหล่านี้ล่วงหน้าสำหรับสภาพแวดล้อมแบบ 2D ขนาดใหญ่ (คิดว่าเป็นแผนที่แบบ Terraria ขนาดใหญ่) นี่หมายความว่าคุณยอมรับค่าใช้จ่ายที่ค่อนข้างใหญ่ในพื้นที่เก็บข้อมูล (และเวลาในการสร้างแผนที่) อัลกอริทึมที่ซับซ้อนซึ่งเร็วพอสำหรับการสร้าง SDF แบบเรียลไทม์

ตัวอย่างเช่นแผนที่ขนาดค่อนข้างเล็กที่มี 1,000 * 256 (ความกว้าง * สูง) ที่มีขนาดไทล์ 10 * 10 พิกเซลและขนาดทั้งหมด 10,000 * 2560 พิกเซลจะทำให้คุณมีขนาดประมาณ 2 เมกะไบต์หากคุณเลือกขนาดที่ค่อนข้างเล็ก ความละเอียด SDF ที่ 128x128 โดยสมมติว่าคุณเก็บเฉพาะค่าระยะทางจาก 0 ถึง 255

เห็นได้ชัดว่านี่อาจกลายเป็นเรื่องเร็วเกินไปและเป็นค่าใช้จ่ายที่ฉันไม่ต้องการ

มีอย่างอื่น:

SDF สามารถใช้กับหลาย ๆ อย่าง (เช่นการตรวจจับการชนกัน) และแอปพลิเคชันที่มีประโยชน์บางอย่างอาจยังไม่ถูกค้นพบ ฉันคิดว่าผู้คนจำนวนมากกำลังมองหาสิ่งเหล่านี้ในอนาคตและถ้าเราได้คำตอบที่ครอบคลุมในที่นี้ฉันคิดว่าเราจะช่วยคนจำนวนมาก


ฉัน googled "เขตข้อมูลระยะทางที่ลงนามแล้ว" และการเข้าชมครั้งแรกคือรุ่น GPU: http.developer.nvidia.com/GPUGems3/gpugems3_ch34.html มันค่อนข้างเก่า แต่อาจช่วยการค้นหาของคุณต่อไป
Patrick Hughes

1
บางทีฉันอาจจะพลาดบางสิ่งบางอย่าง แต่ฉันค่อนข้างสับสนกับคำแถลงว่าทำไมคุณต้องทำมันแบบเรียลไทม์ (ไม่น้อยกว่าทำไมมันติดแท็กสปอยเลอร์); ก่อนอื่นคุณจะได้ตัวเลข 2MB สำหรับ SDF ที่ 128x128 เป็นอย่างไร ประการที่สองทำไมคุณถึงใช้งานหน่วยความจำหนักเป็นพิเศษถึง 2MB ฉันเห็นด้วยว่ามันไม่ได้ไร้สาระ แต่ดูเหมือนว่าการใช้หน่วยความจำแผนที่โดยรวมของคุณเพียงเล็กน้อย และประการที่สามการสร้างสนามในเรียลไทม์จะบันทึกหน่วยความจำนั้นได้อย่างไร คุณยังต้องจัดเก็บข้อมูลเดียวกันทุกประการไม่ว่าจะเป็นข้อมูลที่สร้างขึ้นทันทีหรือทำการคำนวณล่วงหน้าใช่ไหม
Steven Stadnicki

ในวงกว้างมันอาจเป็นไปได้ว่า SDF ไม่ใช่เทคนิคที่คุณต้องการ ข้อมูลเพิ่มเติมเกี่ยวกับสถานการณ์เฉพาะของคุณ - การนับสิ่งกีดขวางแบบคงที่การนับสิ่งกีดขวางแบบไดนามิก ฯลฯ - และสิ่งที่คุณคาดหวังที่จะบรรลุผลอย่างแม่นยำจะเป็นประโยชน์ในการพยายามปักหมุดสิ่งที่น่าจะเป็นประโยชน์กับคุณ
Steven Stadnicki

1
หากฉันสร้างฟิลด์ระยะทางแบบเรียลไทม์ฉันจะสร้างเพียง 2MB ต่อครั้งต่อเฟรมเท่านั้น (โอเวอร์เฮดหน่วยความจำทั้งหมดจะเป็นหน่วยความจำที่จำเป็นสำหรับฟิลด์ระยะทางหนึ่งเสมอเพราะฉันต้องการเพียงฟิลด์เดียวสำหรับหน้าจอ) หากฉันมีแผนที่ที่ใหญ่กว่าตัวอย่าง 1000x128 ของฉัน (ฉันคิดว่าแผนที่ Terraria ขนาดใหญ่ไปได้ดีกว่ายุค 10,000) ฉันต้องการหนึ่งใน 2mb เหล่านั้นสำหรับทุก ๆ 1,000x128 ของแผนที่นั้น ทำไมฉันต้องการ SDFs ในตอนแรกอธิบายไว้ในคำถามแรกที่ฉันเชื่อมโยงที่จุดเริ่มต้นของคำถามนี้ (สำหรับการฉายเงา GPU 2D)
TravisG

1
@heishe คุณพยายามสร้างข้อมูล 2Mb หนึ่งครั้งต่อเฟรมหรือไม่ อย่างจริงจัง?
kaoD

คำตอบ:


9

Catalin Zima อธิบายถึงวิธีการทำให้เกิดเงา 2 มิติแบบไดนามิกในบทความของเขา - และเขาใช้เขตข้อมูลระยะทางที่มีการเซ็นชื่อ (จากสิ่งที่ฉันสามารถบอกได้ว่าเป็นเพียงชื่อแฟนซีสำหรับเงาบัฟเฟอร์ในบริบทนี้) วิธีการของเขาต้องการ GPU และการใช้งานของเขาไม่ดีที่สุด (เขาลดลงต่ำกว่า 60 เฮิร์ตที่ประมาณ 20 ไฟบนเครื่องของฉันฉันมีไฟประมาณ 500 ดวง); ซึ่งคาดว่าจะเป็นในขณะที่เขาชื่นชอบความชัดเจนของรหัสผ่านความเร็ว

การดำเนินงาน

ตรงตามที่เขาปฏิบัติ:

  1. แสดงภาพเงาทั้งหมดลงในพื้นผิว
  2. คำนวณระยะห่างจากจุดศูนย์กลางของแสงสำหรับแต่ละพิกเซลและกำหนดค่านั้นให้กับ RGB ของพิกเซลทึบแสง
  3. บิดเบือนภาพเพื่อแสดงว่ากล้อง 3D จะเห็นพิกเซลเหล่านั้นอย่างไร
  4. สควอชภาพให้เป็นภาพขนาด 2xN โดยใช้การปรับขนาดที่ผิดปกติที่อธิบายไว้ในบทความของเขา (การปรับขนาดธรรมดาจะไม่ทำงาน)
  5. ตอนนี้ภาพ 2xN เป็นฟิลด์ระยะทางที่คุณได้ลงนามไว้สำหรับแสงทั้งสี่ด้าน (โปรดจำไว้ว่าหนึ่งควอดเรนท์นั้นเป็น frustum ของกล้องเดี่ยวที่ 90 องศา)
  6. แสดง Lightmap
  7. เบลอภาพแผนที่ (ตามระยะทางจากแสง) เพื่อให้ได้เงาที่นุ่มนวล

การใช้งานขั้นสุดท้ายของฉันคือ (แต่ละขั้นตอนเป็น shader เดียว):

  1. ทำ (1)
  2. ทำ(2) และ (3)
  3. ทำ (4) การใช้งานของเขาช้ามาก: ถ้าคุณลองและใช้ GPGPU กับสิ่งนี้ ฉันไม่สามารถใช้ GPGPU (XNA) ดังนั้นสิ่งที่ฉันทำคือ:
    • ตั้งค่าตาข่ายที่คอลัมน์ N / 2 แรกถูกแทนด้วย N / 2 ล่ามที่มีตำแหน่งเดียวกันที่แน่นอน (ครอบคลุมคอลัมน์แรกของบัฟเฟอร์สุดท้าย) แต่การประสานพื้นผิวที่แตกต่างกัน (สิ่งเดียวกันสำหรับคอลัมน์ N / 2 ที่สอง)
    • ปิดการทดสอบเชิงลึกของ GPU
    • ใช้ฟังก์ชันการผสมพิกเซล MIN
  4. ทำ (6) และ (7)

มันค่อนข้างมีความคิดสร้างสรรค์: มันเป็นการแปลโดยตรงว่าเงาถูกจัดการในแบบ 3 มิติเป็น 2D

ผิดพลาด

หลุมพรางหลักคือวัตถุบางอย่างไม่ควรเงา: ในตัวอย่างของฉันฉันเขียนโคลน Liero (เรียลไทม์) และด้วยเหตุนี้จึงไม่ต้องการตัวอย่างเช่นเวิร์มของผู้เล่นจะต้องเป็นเงา (อย่างน้อยหนึ่ง) บนหน้าจอของผู้เล่นแต่ละคน) สิ่งที่ฉันทำเพื่อวัตถุ 'พิเศษ' เหล่านี้จะถูกวาดใหม่เป็นขั้นตอนสุดท้าย ประชดคือวัตถุส่วนใหญ่ไม่ได้มีเงา (เวิร์มเบื้องหน้าภูมิทัศน์) ดังนั้นจึงมีปัญหาการถอนเงินที่นี่


การปรับตัวของคุณกับวิธีการปรับขนาดเป็นสิ่งเดียวที่จะเร่งความเร็วในการจัดการไฟ 500 ดวงที่สูงกว่า 60fps หรือไม่?
TravisG

ตกลงฉันจะยอมรับคำตอบเพราะมันแก้ปัญหาเดิมของฉัน แต่มันก็ไม่ได้ตอบสิ่งที่ฉันให้เงินรางวัล ฉันจะรอและบางทีอาจมีใครซักคนอธิบายวิธีหนึ่งในหลายวิธีสำหรับการสร้างฟิลด์ระยะทางที่ลงนามแล้ว
TravisG

@ heishe เกี่ยวกับคำถามแรกของคุณ: ไม่แน่ใจ ฉันทำการปรับให้เหมาะสมทั้งหมดในครั้งเดียว - ฉันคิดว่าฉันจำได้ว่าปิดและดูการลดลงอย่างมีนัยสำคัญ การโทรแบบดึงทั้งหมด 6 ครั้งต่อแสงจะฆ่า framerate ของคุณ อย่างที่ฉันบอกว่าดูเหมือนว่าจากสิ่งที่ฉันสามารถบอกได้คุณมีเขตข้อมูลระยะทางที่เซ็นชื่อ 4 ขั้นตอน (5) - แต่คนที่รู้เพิ่มเติมเกี่ยวกับพวกเขาจะต้องยืนยันว่า
Jonathan Dickinson

มันเป็นกรณีพิเศษของเขตข้อมูลระยะทางที่เซ็นชื่อ ในฟิลด์ระยะทางปกติที่มีการเซ็นชื่อทุกพิกเซลจะมีระยะทางถึงสิ่งกีดขวางที่ใกล้ที่สุด ในอัลกอริทึมนี้เขตข้อมูลระยะทางจะมีสิ่งกีดขวางเพียงอย่างเดียวและสิ่งกีดขวางนั้นมีเพียง 1 พิกเซลในภาพทั้งหมด (แหล่งกำเนิดแสง) ซึ่งเป็นสาเหตุที่สนามระยะทางนี้สามารถสร้างขึ้นใน O (N)
TravisG

1
@heishe นี่คือ Shader ฉัน: gist.github.com/2384073 DistPSPS คือ 2 + 3
Jonathan Dickinson
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.