Mendapatkan tekstur dari renderbuffer di OpenGL?


13

Saya punya renderbuffer (DepthStencil) dalam FBO dan saya perlu mendapatkan tekstur darinya. Saya tidak bisa memiliki tekstur DepthComponent dan renderbuffer DepthStencil di FBO, tampaknya, jadi saya perlu beberapa cara untuk mengubah renderbuffer menjadi tekstur DepthComponent setelah saya selesai menggunakannya untuk digunakan nanti di bawah pipa.

Saya sudah mencoba banyak teknik untuk mengambil komponen kedalaman dari renderbuffer selama berminggu-minggu tetapi saya selalu keluar dengan sampah. Yang saya inginkan pada akhirnya adalah tekstur yang sama dengan yang saya dapatkan dari FBO jika saya tidak menggunakan renderbuffer. Adakah yang bisa mengirim beberapa instruksi atau kode komprehensif yang mencakup operasi yang tampaknya sederhana ini?

EDIT:

Tautkan ke versi ekstrak kode http://dl.dropbox.com/u/9279501/fbo.cs

Skrining efek Kedalaman Bidang + FBO - tanpa kedalaman (!) Http://i.stack.imgur.com/Hj9Oe.jpg

Skrining tanpa efek Kedalaman Bidang + FBO - kedalaman berfungsi dengan baik http://i.stack.imgur.com/boOm1.jpg

Jawaban:


2

Sebagai alternatif, Anda bisa langsung menggeser dari satu FBO ke yang lain, seperti dari yang berbasis renderbuffer ke yang berbasis tekstur. Saya melakukannya dengan cara ini:

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);

(Dalam kasus Anda, di mana Anda ingin menambah buffer, Anda dapat menggunakan GL_DEPTH_BUFFER_BIT alih-alih GL_COLOR_BUFFER_BIT)

Setelah masuk ke renderbuffer berbasis tekstur, Anda dapat menggunakan tekstur seperti biasa; menyerahkannya ke shader sebagai seragam atau apa pun yang kamu suka.


1

Tidak, itu tidak mungkin. Paling-paling Anda dapat glReadPixels data ke CPU, dan membuat teksturnya, tetapi itu akan rumit dan lambat. Renderbuffers tidak dimaksudkan untuk itu, fungsionalitas itu hanya disediakan oleh tekstur.


Mengingat itu, apa alternatifnya? Bagaimana Anda bisa mempertahankan kedalaman di buffer draw Anda dan juga mendapatkan komponen kedalaman sebagai tekstur?
Rushyo

@Rushyo: Alternatifnya bisa dengan menyingkirkan buffer stensil (jika mungkin!) Dan menjadikan renderbuffer kedalaman tekstur kedalaman. Mengapa Anda menggunakan stensil?
Calvin1602

Intinya setiap kali saya mendapatkan tekstur kedalaman, tes kedalaman saya pecah. Jika saya melampirkan lampiran kedalaman ke FBO saya, FBO tidak menulis informasi kedalaman apa pun di tempat lain - jadi ketika saya mencoba mengambil lampiran warna tidak ada pengujian mendalam di atasnya (yang biasanya jika saya tidak memiliki lampiran kedalaman ). Saya telah mencoba setiap kombinasi yang dapat saya pikirkan, termasuk metode 'rumit dan lambat' yang disebutkan di atas. Apa pun yang saya lakukan, saya tidak bisa mendapatkan rendering 'tipikal' adegan saya dalam satu tekstur dan hanya kedalaman di tekstur lainnya.
Rushyo

@ Calvin1602 Ketika saya mencoba-coba dengan renderbuffer, saya menemukan bahwa menggunakan lampiran kedalaman tanpa lampiran stensil menghasilkan hasil yang tidak diinginkan.
Rushyo

@Rushyo Saya yakin Anda tidak mengatur tekstur dengan benar, kode posting akan memungkinkan kami untuk membantu :)
Matias Valdenegro

1

Apa yang Anda minta dimungkinkan di OpenGL 3.2. Saya punya FBO saya memuntahkan warna menyebar ke tekstur warna, normals ke tekstur warna lain, dan kedalaman ke tekstur kedalaman - tidak diperlukan renderbuffers. Faktanya, renderbuffer hanyalah masalah, karena Anda tidak dapat mengambil sampel darinya, jadi Anda harus menggunakan glReadPixels(...)atau dengan cara lain menyalin data dari RBO dan menjadi tekstur pada CPU, alih-alih hanya mempertahankan semua yang ada dalam memori GPU. Begitu...

Jika Anda benar-benar ingin, Anda dapat menulis kode dalam shader first-pass Anda untuk secara manual menampilkan hal-hal seperti kedalaman, ke lampiran tekstur warna yang terpisah di FBO Anda. Itu akan untuk digunakan oleh Anda dalam shader pasca-pass Anda. Untuk penggunaan OpenGL dalam pengujian kedalaman internal, Anda juga membutuhkan RBO atau tekstur yang ditetapkan sebagai GL_DEPTH_ATTACHMENT FBO Anda. Tetapi Anda dapat mengatur satu tekstur untuk melayani keduanya - ini lebih efisien & lebih mudah digunakan.

Kode pengaturan tekstur kedalaman saya terlihat seperti ini (Java, abaikan saja hal-hal ByteBuffer ... dan perhatikan saya menggunakan "id" untuk merujuk ke bilangan bulat pegangan / pointer, karena konsep itu tidak benar-benar cocok dengan 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);

Dan kemudian:

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

Anda sekarang dapat lulus gBufferDepthTexture(atau apa yang Anda miliki) sebagai seragam untuk shaders fragmen pass kedua, ketiga Anda. Saya pikir kita dapat dengan aman berasumsi bahwa Anda dapat melakukan hal yang persis sama dengan buffer stensil.


0

Anda harus dapat membuat tekstur (bukan RenderBuffer) menggunakan format GL_DEPTH_STENCIL. Saya tidak yakin dengan proses yang tepat untuk menggunakan kedalaman dari tekstur seperti itu dalam program shader (yang saya anggap Anda gunakan, karena Anda menggunakan FBO), tetapi spesifikasi OpenGL harus menentukan saluran warna mana yang mendapatkan nilai mana ( Dugaan saya adalah bahwa R, G, dan B semuanya diatur ke kedalaman dan A diatur ke stensil).

Saya menargetkan OpenGL 3.2 hari ini, jadi Anda mungkin perlu memverifikasi bahwa format tekstur bisa diterapkan untuk Anda. Saya tidak pernah ingat versi mana yang memperkenalkan fitur yang berbeda.


Masalahnya kemudian bukan menangkap komponen GL_DEPTH_STENCIL dalam tekstur, tetapi kenyataan bahwa semua informasi mendalam hilang di FBO setiap kali Anda melakukannya. FBO menjadi tidak berguna untuk kemudian menampilkan adegan ke draw drawer. Karenanya saya menggunakan Renderbuffer dengan harapan dapat melewati masalah ini. Saya pikir untuk saat ini saya tidak punya pilihan selain membuat dua lintasan untuk mengambil kedalaman + menggambar informasi secara terpisah = (mahal sekali sampai saya dapat menemukan jalan
keluarnya

@Rushyo Saya memposting jawaban untuk pertanyaan kuno ini :) Anda mungkin ingin melihatnya, meskipun Anda mungkin sudah memecahkannya tahun lalu.
Insinyur

@NickWiggill saya berharap! Membohongi sesuatu dan melanjutkan hidupku. Tidak dapat benar-benar menguji jawaban Anda sampai saya menciptakan kembali aset yang saya gunakan dalam prototipe ini. Mungkin bisa melakukannya pada beberapa titik ...
Rushyo
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.