OpenGL में रेंडरबफ़र से एक बनावट प्राप्त करना?


13

मुझे एक FBO में एक रेंडरबफ़र (डेप्थस्टलीन) मिला है और मुझे इससे एक बनावट प्राप्त करने की आवश्यकता है। मेरे पास FBO में डेप्थकम्पोनेंट टेक्सचर और डेप्थकैंसिल रेंडरबफ़र दोनों नहीं हो सकते हैं, ऐसा लगता है, इसलिए रेंडरबफ़र को डेप्थकॉम्पेनेंट टेक्सचर में बदलने के लिए मुझे किसी तरह की ज़रूरत होती है क्योंकि मैं इसके साथ पाइप लाइन का उपयोग करने के लिए कर रहा हूँ।

मैंने हफ्तों के लिए रेंडरबफ़र से गहराई घटक को खींचने के लिए बहुत सारी तकनीकों की कोशिश की है, लेकिन मैं हमेशा कबाड़ के साथ बाहर आता हूं। अंत में मैं चाहता हूँ कि एक ही बनावट है जो मुझे एक FBO से मिलेगी अगर मैं रेंडरबफ़र का उपयोग नहीं कर रहा था। क्या कोई ऐसा व्यापक निर्देश या कोड पोस्ट कर सकता है जो इस सरल ऑपरेशन को कवर करता हो?

संपादित करें:

कोड के एक निकालने संस्करण से लिंक 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 से दूसरे में ब्लिट कर सकते हैं, जैसे कि रेंडरबफ़र-आधारित एक से बनावट-आधारित एक। मैं इसे इस तरह से करता हूं:

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 का उपयोग कर सकते हैं)

बनावट-आधारित रेंडरबफ़र में ब्लिटिंग के बाद, आप फिर बनावट को सामान्य रूप से उपयोग कर सकते हैं; इसे एक समान या जो कुछ भी आप चाहते हैं के रूप में shaders में पास करना।


1

नहीं, यह संभव नहीं है। अधिकांश पर आप CPU में डेटा को GlReadPixels कर सकते हैं, और इसकी बनावट बना सकते हैं, लेकिन यह बोझिल और धीमा होगा। Renderbuffers इसके लिए नहीं हैं, यह कार्यक्षमता केवल बनावट द्वारा प्रदान की गई है।


यह देखते हुए कि विकल्प क्या है? आप अपने ड्रॉ बफर में गहराई कैसे बनाए रख सकते हैं और बनावट के रूप में गहराई घटक भी प्राप्त कर सकते हैं?
रशियो

@Rushyo: स्टैंसिल बफर से छुटकारा पाने के लिए एक विकल्प हो सकता है (यदि संभव हो!) और गहराई रेंडरबफ़र को एक गहराई बनावट बनाएं। आप एक स्टैंसिल का उपयोग क्यों कर रहे हैं?
केल्विन 1602

अनिवार्य रूप से जब भी मैं गहराई की बनावट का अधिग्रहण करता हूं, मेरी गहराई के परीक्षण टूट जाते हैं। अगर मैं अपने FBO से गहराई से लगाव रखता हूं, तो FBO किसी भी गहराई की जानकारी कहीं और नहीं लिखता है - इसलिए जब मैं रंग के अनुलग्नक को पुनः प्राप्त करने का प्रयास करता हूं तो उस पर कोई गहराई परीक्षण नहीं होता है (जो कि सामान्य रूप से यदि मुझे गहराई से लगाव नहीं है )। मैंने हर संयोजन की कोशिश की है जो मैं सोच सकता हूं, जिसमें उपरोक्त 'बोझिल और धीमी' विधि भी शामिल है। जो कुछ भी मैं करता हूं मुझे एक बनावट में अपने दृश्य के एक 'ठेठ' रेंडर दोनों नहीं मिल सकते हैं और बस दूसरे में गहराई हो सकती है।
रशियो

@ Calvin1602 जब मैं रेंडरबफ़र के साथ डबिंग कर रहा था, तो मैंने पाया कि स्टैंसिल अटैचमेंट के बिना गहराई से लगाव का उपयोग करने से अवांछित परिणाम उत्पन्न हुए।
रुशियो

@ रूशियो मुझे यकीन है कि आप बनावट को सही ढंग से स्थापित नहीं कर रहे हैं, पोस्टिंग कोड हमें मदद करने की अनुमति देगा :)
मटियास वाल्डेनेग्रो

1

आप जो पूछ रहे हैं वह OpenGL 3.2 में संभव है। मैं अपने FBO बाहर रंग फैलाने के लिए एक रंग बनावट, एक और रंग बनावट के लिए मानदंडों और एक गहराई बनावट के लिए गहराई से मिल गया है - कोई ज़रूरत नहीं सौंपनेवाला। वास्तव में रेंडरबफर्स ​​केवल एक समस्या है, क्योंकि आप उनसे नमूना नहीं ले सकते हैं, इसलिए आपको glReadPixels(...)केवल जीपीयू मेमोरी में सब कुछ बनाए रखने के बजाय, आरबीओ से बाहर डेटा का उपयोग करना होगा या सीपीयू पर बनावट में कॉपी करना होगा। इसलिए...

यदि आप वास्तव में चाहते हैं, तो आप अपने पहले पास-पास के शेडर में कोड को गहराई से आउटपुट सामग्री के रूप में लिख सकते हैं, अपने FBO में एक अलग रंग बनावट अनुलग्नक के लिए। यही कारण है कि द्वारा उपयोग के लिए होगा आप अपनी पोस्ट-पास shaders में। के लिए ओपन के अपने आंतरिक गहराई परीक्षण में उपयोग करते हैं, आप अतिरिक्त या तो एक RBO या अपने FBO के GL_DEPTH_ATTACHMENT के रूप में बनावट सेट की आवश्यकता होगी। लेकिन आप दोनों की सेवा करने के लिए एक एकल बनावट सेट कर सकते हैं - यह अधिक कुशल और उपयोग करने में आसान है।

मेरी गहराई बनावट सेटअप कोड इस तरह दिखता है (जावा, बस बाइटबफ़र सामान को अनदेखा करें ... और ध्यान दें कि मैं पूर्णांक हैंडल / पॉइंटर्स को संदर्भित करने के लिए "आईडी" का उपयोग करता हूं, क्योंकि यह अवधारणा वास्तव में जावा में अच्छी तरह से नहीं बैठती है):

        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आप अपने दूसरे, तीसरे पास के टुकड़े के लिए वर्दी के रूप में (या आपके पास क्या है) पास कर सकते हैं । मुझे लगता है कि हम सुरक्षित रूप से मान सकते हैं कि आप स्टैंसिल बफर के साथ एक ही काम कर सकते हैं।


0

आपको GL_DEPTH_STENCIL प्रारूप का उपयोग करके एक बनावट (RenderBuffer के बजाय) बनाने में सक्षम होना चाहिए। मैं एक shader प्रोग्राम में ऐसी बनावट से गहराई का उपयोग करने के लिए सटीक प्रक्रिया के बारे में निश्चित नहीं हूं (जो मैं मानता हूं कि आप उपयोग कर रहे हैं, क्योंकि आप FBO का उपयोग कर रहे हैं), लेकिन ओपनजीएल कल्पना को निर्दिष्ट करना चाहिए कि कौन से रंग चैनल को कौन से मान मिलते हैं ( मेरा अनुमान है कि आर, जी, और बी सभी गहराई तक सेट हो जाते हैं और ए स्टेंसिल पर सेट हो जाता है)।

मैं इन दिनों OpenGL 3.2 को लक्षित करता हूं, इसलिए आपको यह सत्यापित करने की आवश्यकता हो सकती है कि बनावट प्रारूप आपके लिए व्यावहारिक है। मुझे कभी याद नहीं आता कि कौन से संस्करण विभिन्न विशेषताओं को पेश करते हैं।


तब समस्या GL_DEPTH_STENCIL घटक को बनावट में कैप्चर नहीं कर रही है, लेकिन यह तथ्य कि जब भी आप ऐसा करते हैं, तो सभी गहराई की जानकारी FBO में खो जाती है। एफबीओ ड्रॉ बफर के दृश्य को प्रस्तुत करने के लिए बेकार हो जाता है। इसलिए मैं इस मुद्दे को दरकिनार करने की उम्मीद में एक Renderbuffer का उपयोग कर रहा था। मुझे लगता है कि मेरे पास अब कोई विकल्प नहीं है लेकिन गहराई को पकड़ने के लिए दो पास बनाने के लिए + अलग से जानकारी खींचना = (महंगा-जैसा-नरक जब तक मैं इसके चारों ओर एक रास्ता नहीं खोज सकता।
रशियो

@Rushyo मैंने इस प्राचीन प्रश्न का उत्तर पोस्ट किया :) आप एक नज़र रखना चाह सकते हैं, हालाँकि आप शायद इस साल पहले हल कर चुके हैं।
इंजीनियर

@NickWiggill काश! कुछ कहा और मेरे जीवन के साथ आगे बढ़ा। वास्तव में आपके उत्तर का परीक्षण नहीं कर सकता जब तक कि मैं इस संपत्ति का उपयोग नहीं करता हूं जो मैंने इस प्रोटोटाइप में उपयोग किया था। कुछ बिंदु पर हो सकता है कि चारों ओर ...
रशियो
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.