มีวิธีใดบ้างในการแสดงความโปร่งใสใน OpenGL


14

การผสมอัลฟ่าสามารถเปิดได้เพื่อให้พื้นผิวโปร่งใสเช่น:

glDisable(GL_DEPTH_TEST); //or glDepthMask(GL_FALSE)? depth tests break blending
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

แต่จะใช้งานได้ก็ต่อเมื่อแสดงวัตถุในลำดับหลังไปข้างหน้าเท่านั้น มิฉะนั้นสิ่งที่อยู่ในพื้นหลังจะปรากฏขึ้นด้านหน้าวัตถุที่ใกล้กว่าเช่นพื้นในภาพด้านล่าง สำหรับอนุภาคและองค์ประกอบ GUI การเรียงลำดับจะตกลง แต่สำหรับตาข่ายสามเหลี่ยมดูเหมือนว่ามันจะเป็นความพยายามมากเกินไปและช้าตามที่กล่าวไว้ที่นี่: https://www.opengl.org/wiki/Transparency_Sorting

อะไรคือวิธีการทั่วไปในการจัดการกับสิ่งนี้? ฉันรู้ว่านี่ค่อนข้างกว้างและไม่ใช่รายละเอียดการใช้งานในเชิงลึกเพียงแค่คำอธิบายสั้น ๆ เกี่ยวกับวิธีการบางอย่างและสิ่งที่อาจเกี่ยวข้อง

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


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

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

คำตอบ:


11

ชุดของเทคนิคเพื่อหลีกเลี่ยงการสั่งซื้อที่ชัดเจนไปภายใต้ชื่อของ Order Independent Transparency (OIT for short)

มีเทคนิค OIT มากมาย

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

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

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

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

สำหรับสิ่งที่จำเป็นสำหรับ OIT Weighted Blended ไม่มีเป้าหมายการเรนเดอร์เพิ่มเติมเกินสองเป้าหมาย หนึ่งที่คุณกรอกด้วยสีอัลฟ่าก่อนวัยอันควร (color * alpha) และอัลฟาทั้งน้ำหนักตาม อีกอันสำหรับน้ำหนักเท่านั้น


6

ทางเลือกหนึ่งคือการใช้การลอกแบบลึก

โดยพื้นฐานแล้วหนึ่งประมวลผลฉากจำนวนครั้ง (พูด, nครั้ง) เพื่อกำหนดที่ใกล้เคียงที่สุดที่ใกล้เคียงที่สุดที่สองใกล้เคียงกับnชิ้นส่วนที่ใกล้เคียงที่สุดของฉาก

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

การใช้การทดสอบความลึกอีกครั้งจะส่งคืนเลเยอร์ที่สอง ทำซ้ำตามต้องการ

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


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

1
@jozxyqk ถูกต้องจำเป็นต้องใช้บัฟเฟอร์ความลึกสองตัวสำหรับโพรซีเดอร์นี้
es1024

1

creme de la creme ของ single-pass no (หรือน้อย) ประนีประนอมความโปร่งใสใน OpenGL คือ A-buffer ด้วย OpenGL ที่ทันสมัยมันเป็นไปได้ที่จะใช้:

http://blog.icare3d.org/2010/06/fast-and-accurate-single-pass-buffer.html

มันหลีกเลี่ยงการลอกลึกหลายครั้งและไม่จำเป็นต้องใช้การคัดแยกที่ยุ่งยาก


3
อุดมคติแล้วคำตอบควรอยู่ในตัวเองและพึ่งพาลิงก์ภายนอกอย่างละเอียด การมีลิงค์ดีสำหรับเนื้อหาเสริม แต่คำตอบไม่ควรประกอบด้วยคำหลัก หากคุณสามารถรวมรายละเอียดบางอย่างเกี่ยวกับสิ่งที่ A-buffer และวิธีการทำงานที่จะปรับปรุงคำตอบของคุณ
Martin Ender
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.