หลีกเลี่ยงการต่อสู้ด้วยพื้นผิวที่บังเอิญ


26

เมื่อเรนเดอร์พื้นผิว co-planar สองอันที่ทับซ้อนกันปัญหาทั่วไปคือ "z-fighting" ซึ่งตัวเรนเดอร์ไม่สามารถตัดสินใจได้ว่าพื้นผิวใดของทั้งสองพื้นผิวนั้นอยู่ใกล้กับกล้องมากขึ้น

วิธีการแก้ปัญหามาตรฐานนี้คือเพื่อให้พื้นผิวมีการชดเชยเล็กน้อยเมื่อออกแบบแบบจำลอง มีวิธีแก้ปัญหาอื่น ๆ อีกไหม?


2
คุณสามารถชำระเงินบัฟเฟอร์ความลึกแบบลอการิทึม มีบทความเกี่ยวกับgamasutra
สบู่

1
เมื่อคุณพูดว่า "co-planar" คุณหมายถึง "เกือบ" หรือ "ที่แน่นอน" co-planar และถ้าต่อมาพื้นผิวเหล่านั้นเคยเป็นพื้นผิว / สามเหลี่ยมที่เหมือนกันหรือไม่? ฮาร์ดแวร์การแสดงผลควรถูกกำหนดไว้ล่วงหน้า (สมมติว่าคุณไม่ได้ส่งแบบสุ่ม) สำหรับกรณีสุดท้ายและไม่ต้องต่อสู้ หากเป็นกรณีของพื้นผิวที่ไม่เหมือนกัน แต่มีส่วนร่วมอย่างแน่นอนคุณสามารถอัปเดตโมเดลเพื่อแยกพื้นผิวออกเป็นส่วนที่ทับซ้อนกันและไม่ทับซ้อนได้หรือไม่?
Simon F

@SimonF โดย "co-planar" ฉันหมายถึง "co-planar" โซลูชันของ Soapy ใช้งานได้เฉพาะในกรณี "เกือบร่วมกับภาพถ่าย"
ทำเครื่องหมาย

คุณยกตัวอย่างพื้นผิวของคุณได้ไหม สิ่งเดียวที่ฉันคิดได้จากส่วนบนของหัวคือสามเหลี่ยมที่ซ้ำกันตามที่ @SimonF พูดถึง
RichieSams

@RichieSams กรณีที่พบบ่อยที่สุดที่ฉันคิดได้คือ decals ซึ่งคุณไม่จำเป็นต้องใช้รูปสามเหลี่ยมซ้ำกัน
rys

คำตอบ:


10

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

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

ในกรณีตัวอย่างของคุณใน Screen Space Decals (SSD) วิธีแก้ปัญหาทั่วไปคือการใช้ออฟเซ็ตหรือที่เรียกว่าคิวบ์แบบบาง ดูการนำเสนอของ Warhammer 40k เกี่ยวกับ SSD สำหรับการอ้างอิง หรือโพสต์ของ Bart Wronski ซึ่งจัดการปัญหาอื่น ๆ เกี่ยวกับสติ๊กเกอร์ แต่ยังเชื่อมโยงไปยังการนำเสนออื่น ๆ เกี่ยวกับ SSD


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

@NathanReed ถูกต้อง ขอบคุณสำหรับคำชี้แจง
RichieSams

1
ในการรับฟังก์ชั่นดังกล่าวคุณจะต้องใช้ตัวระบุแบบคงที่ใน glsl: opengl.org/wiki/Type_Qualifier_%28GLSL%29#Invariance_qualifiers
ashleysmithgpu

โปรดทราบว่าการแสดงออกของ Shader ที่เหมือนกัน (และอินพุตอย่างชัดเจน) เมื่อประเมินตำแหน่งจุดสุดยอดอาจไม่เพียงพอที่จะได้ผลลัพธ์ที่เหมือนกันเนื่องจากการเพิ่มประสิทธิภาพบางอย่างอาจขึ้นอยู่กับส่วนที่เหลือของ Shader GLSL มีคำหลัก "ไม่แปรเปลี่ยน" เพื่อประกาศเอาต์พุต shader ที่จะต้องได้รับการประเมินเหมือนกันในส่วนที่แตกต่างกัน
Firadeoclus

2

นี่เป็นวิธีที่ฉันแก้ไขในอดีต:

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

หมายเหตุวัตถุต้องถูกวาดอย่างต่อเนื่องเพื่อให้สามารถใช้งานได้


0

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

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

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