เทคนิคการเพิ่มประสิทธิภาพการเรนเดอร์ทั่วไปสำหรับเรขาคณิตผ่านในเรนเดอร์แรเงาที่เลื่อนออกไปเป็นอย่างไร [ปิด]


16

ฉันพัฒนาเครื่องมือเกมโดยใช้ OpenGL 3 และ C ++ (และ glfw สำหรับการจัดการหน้าต่าง) ฉันได้ก้าวหน้าไปแล้วทำสิ่งต่าง ๆ ให้เสร็จยกเว้นเสียงและการปรับให้เหมาะสมที่สุด เอ็นจิ้นใช้การแรเงาที่เลื่อนออกไปดังนั้นเนื่องจากการแรเงาที่เลื่อนออกไปนั้นเป็นกระบวนการที่น่าเบื่อสำหรับ GPU โดยเฉลี่ยฉันต้องการเพิ่มประสิทธิภาพของกระบวนการเรนเดอร์ให้มากที่สุด

ระบบปัจจุบันประกอบด้วยฉากที่มี Renderer std::vectorsและโลกปัจจุบันและโลกถือหน่วยงานและหน่วยงานที่แยกออกจากแสง

ดังนั้นโดยทั่วไปทุกครั้งที่ซีนถูกเรียกโดย->render()และมันเรียกว่า Renderer ผ่านโลกเป็นพารามิเตอร์และรับเอนทิตีซ้ำจากทั่วโลกดึงพวกมันไปยัง FBO จากนั้นผ่านหน่วยแสงสำหรับการผ่านครั้งที่สอง และฉันคิดว่ามันไม่เพียงพอ

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

คำตอบ:


41

การแรเงาที่รอการตัดบัญชีเป็นเพียงเทคนิคในการ "เลื่อน" การแรเงาที่เกิดขึ้นจริงสำหรับขั้นตอนต่อไปนี่เป็นวิธีที่ยอดเยี่ยมในการลดจำนวนการผ่านที่จำเป็น (ตัวอย่าง) เพื่อแสดง 10 ไฟซึ่งต้องการ 10 รอบ ประเด็นของฉันคือไม่คำนึงถึงเทคนิคการเรนเดอร์ที่คุณใช้มีการเพิ่มประสิทธิภาพการเรนเดอร์ที่เป็นไปได้บางอย่างซึ่งลดจำนวนของวัตถุ (จุดยอด, บรรทัดฐาน ฯลฯ ) ที่ไพพ์ไลน์เรนเดอร์ของคุณต้องการประมวลผล

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

การเรนเดอร์แบบพยายามจะแก้ปัญหาเมื่อจำนวนไฟเพิ่มขึ้นซึ่งในการเรนเดอร์ไปข้างหน้าอาจทำให้จำนวนการส่งผ่านเกิดการระเบิด

เทคนิคเหล่านั้นไม่ได้เพิ่มประสิทธิภาพส่วนแรเงาที่รอการตัดบัญชีโดยตรง แต่ตามคำอธิบายของคุณส่วนการแรเงาที่เลื่อนออกไปไม่ใช่ปัญหาของคุณ แม้ว่าปัญหาของคุณคือคุณกำลังส่งฉากทั้งหมดไปสู่การเรนเดอร์ไปป์ไลน์ ดังนั้นเครื่องยนต์ของคุณจะต้องประมวลผล (ตัวอย่างเช่นยอด 100 ล้านยอดทั้งหมด) ในฉากของคุณเพื่อให้สามารถส่งผลลัพธ์ไปยัง g-buffer ในขณะที่ 100 ล้านจุดยอดเหล่านี้ส่วนใหญ่สามารถถูกกำจัดได้เล็กน้อยและไม่ส่งไปยัง จุดสุดยอดก่อนกระบวนการและชิ้นส่วนผ่าน

ในกรณีที่ไปข้างหน้าแสดงผลยอด N จะได้รับการประมวลผลโดยขั้นตอนจุดสุดยอดเป็นทั้งหมดvertex count*lights countและขั้นตอนส่วนเป็นผลรวมของการfragments count*number Lightsรอการตัดบัญชีแรเงาได้อย่างมีประสิทธิภาพช่วยลดการนี้เท่านั้นvertex countสำหรับขั้นตอนจุดสุดยอดและfragments countสำหรับการนับชิ้นก่อนที่จะแก้ไข การแรเงาที่เกิดขึ้นจริง แต่ยังไม่มีข้อความที่จะประมวลผลมากเกินไปโดยเฉพาะอย่างยิ่งเมื่อพวกเขาส่วนใหญ่สามารถเลือกสรรได้เล็กน้อย

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

Frustum Culling

เฉพาะวัตถุที่รวมอยู่ทั้งหมดหรือบางส่วนในมุมมอง frustum จำเป็นต้องส่งไปยังไปป์ไลน์เรนเดอร์ นี่เป็นแนวคิดพื้นฐานของการคัดแยก frustum แต่น่าเสียดายที่การตรวจสอบว่าตาข่ายเข้า / ออกจากมุมมอง frustum อาจเป็นการทำงานที่มีราคาแพงดังนั้นนักออกแบบเครื่องยนต์จึงใช้ปริมาตรที่มีขอบเขตโดยประมาณเช่น (AABB) Axis Aligned bounding box หรือ bounding sphere แม้ว่าสิ่งนี้อาจไม่แม่นยำเท่ากับการใช้ mesh จริง แต่ความแตกต่างของความแม่นยำนั้นไม่คุ้มค่ากับปัญหาในการตรวจสอบกับ mesh จริง

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

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

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

ลำดับขั้นของปริมาณเสียง

คัดกลับใบหน้า

นี่คือสิ่งที่ต้องทำทำไมต้องวาดใบหน้าที่ไม่สามารถมองเห็นได้ API การแสดงผลมีส่วนต่อประสานเพื่อเปิด / ปิดการคัดแยกใบหน้า ถ้าคุณไม่มีเหตุผลที่ดีที่จะไม่เปิดใช้งานเช่นแอปพลิเคชั่น CAD บางตัวที่จำเป็นต้องวาดแบ็คเฟชในบางสถานการณ์นี่เป็นสิ่งที่ต้องทำ

การบดเคี้ยว

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

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

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

ตัวอย่างในโลกแห่งความเป็นจริงที่ยิ่งใหญ่ของเทคนิคดังกล่าวอยู่ใน GTA5 ที่ตึกระฟ้าวางอยู่ที่ใจกลางเมืองไม่เพียง แต่การตกแต่งแต่ยังทำงานเป็น occluders แยกส่วนที่เหลือของเมืองได้อย่างมีประสิทธิภาพและป้องกันไม่ให้ถูก rasterized

ล็อด

ระดับของรายละเอียด

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

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

เกิดอะไรขึ้นถ้าสิ่งเหล่านี้ไม่ทำงาน

นั่นเป็นคำถามที่ดี

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

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

เทคนิคการเพิ่มประสิทธิภาพ GPU ทั่วไป:

  • หลีกเลี่ยงการแตกกิ่งเป็นชิ้น
  • ลองโครงสร้างจุดสุดยอดที่แตกต่างกันเช่น{VNT}interleaved ในอาร์เรย์เดียวกันหรือ{V},{N},{T}ในอาร์เรย์ที่แตกต่างกัน
  • วาดฉากด้านหน้าไปด้านหลัง
  • ปิด Z-buffer ในบางจุดเช่นหากรูปภาพไม่ต้องการการทดสอบ Z
  • ใช้พื้นผิวที่บีบอัด

เทคนิคการเพิ่มประสิทธิภาพ CPU ทั่วไป:

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

แต่ถ้าคอขวดของฉันอยู่ในการแรเงาที่เลื่อนออกไป

ในกรณีนี้เนื่องจากการแรเงาที่รอการตัดบัญชีมีความกังวลเกี่ยวกับแสงมากขึ้นส่วนที่ชัดเจนที่สุดคือการคำนวณการแรเงาที่เกิดขึ้นจริง บางจุดที่ต้องจับตามอง:

  • แสดงแสงที่กระทบกับภาพสุดท้ายจริง ๆ กล่าวอีกนัยหนึ่งก็คือกำจัดไฟที่ไม่ได้มีส่วนร่วม สิ่งนี้สามารถนำไปปฏิบัติได้อย่างมีประสิทธิภาพโดยใช้การบดเคี้ยวที่ฉันกล่าวถึงก่อนหน้านี้
  • แสงนี้ต้องการ specular หรือส่วนประกอบอื่น ๆ หรือไม่? อาจจะไม่.
  • แสงนี้หล่อเงาหรือไม่? แสงบางชนิดไม่จำเป็นต้องมีเงา
  • การคำนวณแสงนี้สามารถคำนวณล่วงหน้าได้หรือไม่? หากมันไม่เคลื่อนไหวอาจเป็นไปได้ว่าบางด้านสามารถคำนวณล่วงหน้า

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

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

มันโง่มาก ๆ ที่จะสร้างเครื่องมือที่เลื่อนออกไปโดยไม่มีการคัดแยก frustum ดังนั้นเครื่องยนต์จะประมวลผลตัวอย่างเช่น (100 ล้านจุดสุดยอด) เพื่อให้สามารถส่งผลลัพธ์ไปยัง g-buffer ได้ การแรเงาที่แตกต่างกันช่วยแก้ปัญหาที่แตกต่างกันซึ่งไม่ใช่ปัญหาของเขาปัญหาของเขาคือการส่งรูปทรงเรขาคณิตทั้งหมดไปยังท่อส่ง
concept3d

แม้ว่าฉันจะเห็นด้วยกับส่วนที่การเพิ่มประสิทธิภาพบางอย่างควรเกิดขึ้นกับการคำนวณแสงและหากการคำนวณแสงไม่ได้โดดเด่นแล้วก็รอการตัดบัญชีเป็นวิธีที่ผิดไป แต่นั่นไม่ใช่ปัญหาของเขา
concept3d

ฉันจะถอน downvote ของฉันถ้าคุณทำให้มันชัดเจนว่าการเพิ่มประสิทธิภาพเหล่านี้เป็นจริงมีประสิทธิภาพน้อยสำหรับ renderer รอการตัดบัญชีที่มันยืนคุณยังไม่ได้แสดงให้เห็นว่าเขา / เธอ + ชาว Google ว่าปัญหาประสิทธิภาพการทำงานมีอะไรจะทำอย่างไรกับการแรเงารอการตัดบัญชี
MickLH

6

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

เมื่อคุณเสร็จสิ้นกับสิ่งที่ concept3d ได้อธิบายแล้วหากคุณพบว่าคุณต้องการปรับshader ที่เลื่อนออกไปให้เหมาะสม(ซึ่งตรงข้ามกับ rasterization pass ทั้งหมด) คุณสามารถใช้การแรเงาแบบอิงเดสก์ได้

หากคุณไม่ได้ถูก จำกัด ด้วยจำนวนไฟแบบไดนามิกคุณควรพิจารณาว่าทำไมคุณถึงใช้การแรเงาแบบเลื่อนออกไปเลย แต่ถ้าคุณเป็นเช่นนั้นคุณจะต้องลองการเพิ่มประสิทธิภาพที่ทำให้ Battlefield 3 เป็นไปได้ (พวกเขาพูดถึงมันในสไลด์ 10 ของไฟล์ PDF สาธารณะ: http://dice.se/wp-content/uploads/GDC11_DX11inBF3_Public.pdf )

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