GPU ไหลคำนวณน้ำ


15

ฉันมีพื้นฐานด้านวิศวกรรมโยธาและทำการวิเคราะห์ไฮดรอลิกและอุทกวิทยาอย่างสม่ำเสมอ พวกเขาขายดีกรีของสิ่งนั้น แต่มันไม่ใช่วิทยาศาสตร์จรวด ฉันเพิ่งได้รับในใจของฉันเพื่อใช้กระบวนการ hydrologic และไฮดรอลิกทั้งหมดสำหรับภูมิประเทศบน GPU ฉันเพิ่งเรียนรู้การคำนวณเฉดสีเมื่อเร็ว ๆ นี้ดังนั้นฉันจึงติดอยู่กับงานวิศวกรรมได้ดีกว่าการออกแบบเวิร์กโฟลว์ GPU แบบขนาน

คุณสามารถคำนวณปริมาณน้ำที่เกิดขึ้นระหว่างเหตุการณ์ปริมาณน้ำฝนโดยใช้สูตร:
Q (CF/S) = c * I (in/hr) * A (acres)

ฉันมีปัญหาในการเคลื่อนที่เกินกว่าการคำนวณ "พื้นที่" ของพื้นที่แม้แต่ส่วนแรก

ภาพรวมการใช้งานปัจจุบัน:

  1. ภูมิประเทศเป็นตารางจุดยอดปกติตามช่วงเวลา 1 หน่วย
  2. heightmap ประกอบด้วยค่าความสูง R32 หนึ่งค่าสำหรับแต่ละจุดยอด
  3. ขณะนี้ฉันอนุญาตให้ไหลใน 4 ทิศทางสำคัญเท่านั้น (ไม่มีเส้นทแยงมุม)
  4. ฉันใช้ Texture2D [int] เป็นลายฉลุสำหรับจุดยอดที่ฉันได้วิเคราะห์ไปแล้ว

อัลกอริทึมปัจจุบัน:

  1. เมื่อเครื่องมือภูมิประเทศทำงานอยู่และเป็นตอนนี้ไม่ใช่ ...
  2. ล้าง "stencil"
  3. สแกนภูมิประเทศทั้งหมดเพื่อหาระดับความสูงต่ำสุด
  4. จุดเดียวนั้นคืออินพุตเริ่มต้นสำหรับ CS_Flood
  5. CS_Flood ทำการผ่านแกน X
  6. จุดยอดอินพุตแต่ละอันจะถูกฉายในทิศทาง X- และ X + สูงสุด 2048 เท่า
  7. การค้นหาจุดสุดยอดที่อยู่ติดกันด้วยพิกัด OOB บ่งชี้ถึงขอบของภูมิประเทศในทิศทางนี้ CurrentPoint ถูกต่อท้ายบัฟเฟอร์ BoundaryPoints และวนรอบการฉายสำหรับทิศทางนั้นถูกยกเลิก มันง่ายและใช้งานได้ดีทุกครั้ง
  8. จุดยอดที่อยู่ติดกันที่มีความสูง> = ความสูงของจุดยอดปัจจุบันถูกทำเครื่องหมายใน stencil และเพิ่มลงในบัฟเฟอร์ NextPass
  9. จุดยอดที่อยู่ติดกันที่มีความสูง <ความสูงของจุดยอดในปัจจุบันแสดงถึงจุดสูงสุดของสันเขาและยุติการวนรอบการฉาย การวนซ้ำในอนาคตของการเติมน้ำท่วมอาจไหลไปรอบ ๆ ฐานของสันเขาขึ้นด้าน "หลัง" ของมันและตรวจจับสันเขาเดียวกันเป็นครั้งที่สอง
  10. จุดสูงสุด / สันเขาใด ๆ ที่ตรวจพบได้มากกว่าหนึ่งครั้งจะไม่เป็น BoundaryPoint สำหรับจุดประสงค์นี้
  11. จุดสูงสุด / จุดริดจ์ที่ตรวจพบครั้งเดียวจะถูกผนวกเข้ากับ BoundaryPoints และการวนรอบการฉายภาพในทิศทางนั้นจะถูกยกเลิก
  12. CS_Flood สร้างรหัสผ่านแกน Z ด้วยรหัสเดียวกันโดยใช้จุดที่สร้างขึ้นจากรหัสผ่านแกน X เป็นอินพุต
  13. ตอนนี้ CS_Flood ยังคงสลับกันระหว่างสองทิศทางอย่างต่อเนื่อง ในที่สุดฉันจะยุติลูปโดยรวมเมื่อใดก็ตามที่ CS_Flood เสร็จสมบูรณ์และบัฟเฟอร์ NextPass ว่างเปล่า

หากเป็นอย่างนั้น ณ จุดนั้น BoundaryPoints จะมีจุดสุดยอดแต่ละจุดที่เกิดขึ้นในการแบ่งการระบายน้ำตามธรรมชาติ หยดน้ำลงจอดภายในขอบเขตในที่สุดก็ไหลไปที่จุดต่ำสุดเดียวกัน หยดน้ำลงจอด ouside ขอบเขตไป "ที่อื่น"

แล้ว:

  1. โดยไม่ต้องล้างลายฉลุให้สแกนภูมิประเทศอีกครั้งเพื่อหาจุดสุดยอดที่ต่ำที่สุดและไม่มีลายฉลุ
  2. ซ้ำ CS_Flood
  3. ทำซ้ำจนกระทั่งลายฉลุเต็ม (หรือคล้ายกัน)

3D ยากที่จะรับรู้ด้วยสีเหล่านี้ สิ่งนี้แสดงให้เห็นถึงเส้นชั้นความสูงที่อินทิเกรต:
(หลุมล้อมรอบด้วยเขื่อนใกล้กับขอบ) ขอบ berm

มีวิธีที่ไม่ซ้ำกันประมาณ 10 วิธีในการระบายข้ามจุดสุดยอด; ให้แต่ละสีมีลักษณะเฉพาะดังนี้:
(เครื่องหมายเครื่องมือแบบวงกลมที่มองเห็นได้ "สันเขา" ปรากฏขึ้นอย่างสวยงาม) ป้อนคำอธิบายรูปภาพที่นี่

สิ่งนี้แสดงให้เห็นทุกจุดที่สร้างขึ้นโดย CS_Flood ขอบเขตหรืออื่น ๆ ในฐานะ POINTLIST: ป้อนคำอธิบายรูปภาพที่นี่

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

จุดที่ขาดหายไป

MissingPoint! สามารถรวมเข้าด้วยกันโดยใช้แบนด์ช่วยอัลกอริทึมเพื่อเพิ่ม BoundaryPoint ใหม่ทุกตัวที่ตรวจพบในบัฟเฟอร์ NextPass ในระหว่างการส่งผ่านครั้งต่อไปคะแนน 99% ที่สร้างโดยตัวช่วยแถบนั้นจะเสียเวลาของ GPU เพียงเล็กน้อยซึ่งกำหนดว่าพวกเขาไม่สามารถไปไหนได้และไม่ทำอะไรเลย ในระหว่างการส่งครั้งแรกการส่งคะแนนต่ำสุดพร้อมกับคะแนน NextPass อื่น ๆ จะจัดการสถานการณ์เฉพาะนี้

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


ดังนั้นคุณหมายถึงคุณต้องการคำนวณว่าที่ใดที่ท่อระบายน้ำไหลไปสู่ภูมิประเทศ?
EvilTak

@ EvilTak ฉันคิดว่าฉันใช้อัลกอริทึมที่ดี แต่ฉันยังคงได้รับ "สิ่งแปลกประหลาด" ที่ฉันไม่มีประสบการณ์ที่จะอธิบาย หากคุณเก่งเรื่อง GPU แบบขนานโปรดไปที่: gamedev.stackexchange.com/questions/118556/…
Jon

คำตอบ:


1

เมื่อดร็อป "พยายาม" ไปที่จุดสุดยอดสเตนซิลถูกทำเครื่องหมายด้วยการInterlockedExchangeใช้ "ค่าดั้งเดิม" เพื่อตรวจสอบว่ามันถูกสเตรจแล้ว (แม้ว่าฉันจะเขียนทับมันก็ตาม)

อัลกอริทึมที่ดีที่สุดที่ฉันคิดไว้คือทำให้ "แผ่นรอยขีดข่วน" และกฎเดียว: "ไม่ไหลลงเขา" (ความสูงเท่ากับหรือมากกว่า) นั่นเป็นการทดสอบที่ซับซ้อนเกือบทั้งหมด ในขณะที่ดีโดยทั่วไปที่ไม่ไหลผ่านยอดเขา / แนวมันจะไหลไปตามพวกเขาเพราะจุดยอดที่อยู่ติดกันคือ "แบน" บางครั้งการทำเช่นนี้จะช่วยให้หยดลงผ่านแนวสันเขาได้

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

แต่ละจุด "ไกลเกินไป" คือ "ไหล" และจะไหล "ลงใน" พื้นที่ระบายน้ำ (หยุดที่ 1) หรือไม่ (หยุดที่ 0) "nots" ถูกทิ้งและแผ่นรอยขีดข่วนที่ถูกต้องจะถูกคัดลอกลงใน "final" หากขั้นตอนสุดท้ายมีการทำลายฉลุแล้วแผ่นรอยขีดข่วนจะถูกยกเลิก (ในอนาคต: การชนเหล่านั้นควรเป็นตัวแทนเขตแดนด้านนอกของพื้นที่ระบายน้ำในปัจจุบัน)

ที่ 10FPS:

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

"nots" จะแสดงเป็นสีแดงเมื่อพื้นที่ขนาดใหญ่ถูกคัดลอกลงในขั้นสุดท้ายและกลายเป็นสีเขียวแล้วอัลกอริทึมจะทำซ้ำสำหรับพื้นที่ที่ไม่ได้ถูกวาดซ้ำ

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.