ฉันจะใช้การทดสอบเชิงลึกและความโปร่งใสของพื้นผิวร่วมกันในโลก 2.5D ของฉันได้อย่างไร


11

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

ฉันสร้างเกมภาพสามมิติ "2.5D" โดยใช้ OpenGL ES (JOGL) โดย "2.5D" ฉันหมายความว่าโลกนี้เป็น 3D แต่มันถูกสร้างการแสดงผลโดยใช้แผ่นกระเบื้องสามมิติแบบสองมิติ

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

อย่างไรก็ตามฉันประสบปัญหา หากคุณใช้GL_DEPTH_TESTและGL_BLENDร่วมกันมันจะสร้างเอฟเฟกต์ที่วัตถุจะถูกผสมกับพื้นหลังก่อนที่จะ "เรียงลำดับ" ตามลำดับ z (หมายความว่าคุณได้รับการทับซ้อนแบบแปลก ๆ ที่ควรมีความโปร่งใส)

ปัญหาความเหลื่อมซ้อนของความโปร่งใส

นี่คือรหัสหลอกที่ควรแสดงให้เห็นถึงปัญหา (โดยบังเอิญฉันใช้ libgdx สำหรับ Android)

create() {
    // ...
    // some other code here
    // ...

    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
    Gdx.gl.glEnable(GL10.GL_BLEND);
}

render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    Gdx.gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);

    // ...
    // bind texture and create vertices
    // ...
}

ดังนั้นคำถามคือฉันจะแก้ปัญหาเหลื่อมซ้อนของความโปร่งใสได้อย่างไร


2
เพียงความคิดเห็นที่จะบอกคุณว่าฉันได้ไปเช่นเดียวกับคุณสำหรับเครื่องมือ 2D ของฉัน: ครั้งแรกที่พยายามที่จะฉลาดและเรียงลำดับกระเบื้อง Z ตัวเองแล้วตระหนักว่าไม่มีเหตุผลที่ฉากควรจะแบนดังนั้นให้กระเบื้องของฉัน พิกัด Z และเปิดใช้งานการทดสอบอัลฟา ไม่แน่ใจว่าคุณพูดถูกหรือไม่ แต่คุณไม่ใช่คนเดียว :-)
sam hocevar

คำตอบ:


7

ตกลงดังนั้นนี่คือทางออกของฉัน (โปรดแสดงความคิดเห็นหากสามารถทำได้ดีกว่า) ...

ปรากฎว่าในความเป็นจริงฉันควรจะใช้การทดสอบอัลฟา (แม้ว่าฉันค้นพบโดยบังเอิญดังนั้นฉันไม่แน่ใจว่าทำไมมันใช้งานได้)

create() {
    // ...
    // some other code here
    // ...

    Gdx.gl.glEnable(GL10.GL_DEPTH_TEST);
    Gdx.gl.glEnable(GL10.GL_ALPHA_TEST);
}

render() {
    Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
    Gdx.gl10.glAlphaFunc(GL10.GL_GREATER, 0);

    // ...
    // bind texture and create vertices
    // ...
}

หมายเหตุ: การใช้และGL_ALPHA_TESTglAlphaFunc


มันแก้ไขปัญหาของฉันด้วย ขอบคุณสำหรับการแบ่งปัน. คุณเก่งมาก
Mathlover

2

การทดสอบอัลฟ่าใช้เพื่อหยุดพิกเซลการวาดภาพของ renderer ไปยังบัฟเฟอร์ใด ๆ รวมถึงบัฟเฟอร์ z การผสมอัลฟ่าเป็นเพียงสิ่งที่มองเห็นได้ - ค่ายังคงถูกเขียนไปยัง zbuffer ซึ่งอาจทำให้เกิดปัญหาเช่นนี้ - พิกเซลที่มองไม่เห็นเป็นพิกเซลที่เรนเดอร์หน้าซึ่งหมายความว่าพวกมันจะล้มเหลว ztest เมื่อคุณวาดพิกเซลใหม่ นี่คือสิ่งที่คุณเห็นในภาพที่คุณให้ซึ่งเป็นความล้มเหลว

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


1
ฉันคิดว่าการวาดสิ่งของจากด้านหลังไปข้างหน้านั้นง่ายในเกม iso 2D เฉพาะเมื่อคุณมีเครื่องบิน Y คงที่และนักออกแบบสามารถควบคุมโลกได้อย่างเต็มที่ อย่างไรก็ตามเมื่อสิ่งต่าง ๆ สามารถมีอยู่ทุกที่ในพื้นที่ 3 มิติและคุณอนุญาตให้ผู้ใช้เปลี่ยนสิ่งต่าง ๆ มันจะซับซ้อนมากขึ้น ฉันคิดว่าการใช้บัฟเฟอร์ความลึกจะทำให้ชีวิตของฉันง่ายขึ้นมาก
Nick Bolton
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.