รับพื้นผิวจาก renderbuffer ใน OpenGL หรือไม่?


13

ฉันมี renderbuffer (DepthStencil) ใน FBO และฉันต้องการรับพื้นผิวจากมัน ฉันไม่สามารถมีทั้งพื้นผิว DepthComponent และ DepthStencil renderbuffer ใน FBO ได้ดังนั้นฉันต้องการวิธีในการแปลง renderbuffer เป็นพื้นผิว DepthComponent หลังจากที่ฉันใช้เพื่อใช้ในภายหลัง

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

แก้ไข:

เชื่อมโยงไปยังรุ่นแยกของรหัส http://dl.dropbox.com/u/9279501/fbo.cs

ผลของความลึกของฟิลด์ + FBO - ไม่มีความลึก (!) http://i.stack.imgur.com/Hj9Oe.jpg

หน้าจอที่ไม่มีความชัดลึกของสนามเอฟเฟกต์ + FBO - ทำงานได้ลึกดี http://i.stack.imgur.com/boOm1.jpg

คำตอบ:


2

อีกทางหนึ่งคุณสามารถแยกจาก FBO หนึ่งไปอีกอันหนึ่งเช่นจาก renderbuffer-based หนึ่งไปยังพื้นผิวตาม ฉันทำอย่างนี้:

glBindFramebufferEXT(GL_READ_FRAMEBUFFER_EXT, m_renderBufferSurface->m_fbo);
glBindFramebufferEXT(GL_DRAW_FRAMEBUFFER_EXT, m_textureSurface->m_fbo);
glBlitFramebufferEXT(0, 0, m_renderBufferSurface->m_width, m_renderBufferSurface->m_height, 0, 0, m_textureSurface->m_width, m_textureSurface->m_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);

(ในกรณีของคุณที่คุณต้องการบัฟเฟอร์ความลึกคุณสามารถใช้ GL_DEPTH_BUFFER_BIT แทน GL_COLOR_BUFFER_BIT)

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


1

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


ระบุว่าเป็นทางเลือกอะไร คุณจะรักษาความลึกในบัฟเฟอร์การวาดและรับองค์ประกอบความลึกเป็นพื้นผิวได้อย่างไร
Rushyo

@Rushyo: ทางเลือกอื่นอาจเป็นการกำจัด stencil buffer (ถ้าเป็นไปได้!) และทำให้ renderbuffer ลึกเป็นพื้นผิวที่ลึก ทำไมคุณใช้ลายฉลุ?
Calvin1602

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

@ Calvin1602 เมื่อฉันเล่นน้ำกับ renderbuffer ฉันพบว่าการใช้สิ่งที่แนบมาในเชิงลึกโดยไม่ต้องแนบลายฉลุทำให้เกิดผลลัพธ์ที่ไม่พึงประสงค์
Rushyo

@Rushyo ฉันเดิมพันว่าคุณไม่ได้ตั้งค่าพื้นผิวอย่างถูกต้องรหัสการโพสต์จะช่วยให้เรา :) :)
Matias Valdenegro

1

สิ่งที่คุณถามเป็นไปได้ใน OpenGL 3.2 ฉันได้ FBO ของฉันออกมากระจายสีให้กับพื้นผิวสีเป็นบรรทัดฐานของพื้นผิวสีอื่นและความลึกของพื้นผิวที่ลึก - ไม่จำเป็นต้องใช้ renderbuffers ในความเป็นจริง renderbuffers เป็นเพียงปัญหาเพราะคุณไม่สามารถสุ่มตัวอย่างจากพวกเขาดังนั้นคุณต้องใช้glReadPixels(...)มิฉะนั้นคัดลอกข้อมูลออกจาก RBO และอย่างใดอย่างหนึ่งลงในพื้นผิวบน CPU แทนที่จะรักษาทุกอย่างในหน่วยความจำ GPU ดังนั้น...

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

รหัสการตั้งค่าความลึกของพื้นผิวของฉันมีลักษณะเช่นนี้ (Java เพียงเพิกเฉยสิ่งที่ ByteBuffer ... และโปรดทราบว่าฉันใช้ "id" เพื่ออ้างถึงตัวจัดการ / พอยน์เตอร์จำนวนเต็มเนื่องจากแนวคิดนั้นไม่ค่อยดีใน ​​Java):

        gBufferDepthTexture = new Texture();
        gBufferDepthTexture.id = glGenTextures();
        gBufferDepthTexture.unit = 2;
        gBufferDepthTexture.width = Display.getWidth();
        gBufferDepthTexture.height = Display.getHeight();
        gBufferDepthTexture.bytes = ByteBuffer.allocateDirect(Display.getWidth()*Display.getHeight() * 4);
        glActiveTexture(gBufferDepthTexture.unit + GL_TEXTURE0); //eg. 0 + 33984 = GL_TEXTURE0, while 31 + 33984 = GL_TEXTURE31.
        glBindTexture(GL_TEXTURE_2D, gBufferDepthTexture.id);

        glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, gBufferDepthTexture.width, gBufferDepthTexture.height, 0, GL_DEPTH_COMPONENT, GL_FLOAT, gBufferDepthTexture.bytes);
        //...GL_UNSIGNED_INT or GL_UNSIGNED_BYTE may work better for you, instead... YMMV.

        //glPixelStorei(GL_PACK_ALIGNMENT, 4);
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);

และหลังจากนั้น:

        glBindFrameBuffer(GL_DRAW_FRAMEBUFFER, fbo.id);
        //your existing glFramebufferTexture2D(...) calls here
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, gBufferDepthTexture.id, 0);

ตอนนี้คุณสามารถส่งผ่านgBufferDepthTexture(หรือสิ่งที่มีคุณ) เป็นเครื่องแบบไปที่ชิ้นที่สองและสามของคุณ ฉันคิดว่าเราสามารถสรุปได้อย่างปลอดภัยว่าคุณสามารถทำสิ่งเดียวกันกับบัฟเฟอร์ stencil


0

คุณควรจะสามารถสร้างพื้นผิว (แทนที่จะเป็น RenderBuffer) โดยใช้รูปแบบ GL_DEPTH_STENCIL ฉันไม่แน่ใจเกี่ยวกับกระบวนการที่แน่นอนสำหรับการใช้ความลึกจากพื้นผิวในโปรแกรม shader (ซึ่งฉันคิดว่าคุณกำลังใช้เนื่องจากคุณใช้ FBOs) แต่ข้อมูลจำเพาะ OpenGL ควรระบุช่องสีที่จะได้รับค่าใด ( ฉันเดาว่าคงเป็นว่า R, G และ B ทุกคนจะถูกกำหนดให้มีความลึกและ A จะถูกตั้งเป็นลายฉลุ)

ฉันกำหนดเป้าหมาย OpenGL 3.2 ในวันนี้ดังนั้นคุณอาจต้องตรวจสอบว่ารูปแบบพื้นผิวนั้นใช้งานได้สำหรับคุณ ฉันจำไม่ได้ว่าเวอร์ชันใดที่นำเสนอคุณสมบัติที่แตกต่าง


ปัญหานั้นไม่ได้รวบรวมองค์ประกอบ GL_DEPTH_STENCIL ในพื้นผิว แต่ความจริงที่ว่าข้อมูลเชิงลึกทั้งหมดจะหายไปใน FBO เมื่อใดก็ตามที่คุณทำเช่นนั้น FBO กลายเป็นไร้ประโยชน์สำหรับการเรนเดอร์ฉากไปยังบัฟเฟอร์การวาด ดังนั้นฉันใช้ Renderbuffer ในความหวังของการข้ามปัญหานี้ ฉันคิดว่าตอนนี้ฉันไม่มีทางเลือกอื่นนอกจากผ่านไปสองครั้งเพื่อดึงความลึก + ดึงข้อมูลแยกต่างหาก = (แพงมากเหมือนนรกจนกระทั่งฉันหาทางรอบ ๆ ได้เลย
Rushyo

@Rushyo ฉันโพสต์คำตอบสำหรับคำถามโบราณนี้ :) คุณอาจต้องการที่จะดูแม้ว่าคุณอาจจะแก้ไขปีที่ผ่านมา
วิศวกร

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