Получение текстуры из рендеринга в OpenGL?

13

У меня есть рендер-буфер (DepthStencil) в FBO, и мне нужно получить текстуру из него. Кажется, у меня не может быть как текстуры DepthComponent, так и рендербуфера DepthStencil в FBO, поэтому мне нужен какой-то способ преобразовать рендер-буфер в текстуру DepthComponent после того, как я закончу с этим для использования позже по конвейеру.

Я испробовал множество методов, чтобы извлечь компонент глубины из рендеринга в течение нескольких недель, но я всегда получаю ненужные вещи. Все, что я хочу в конце, это та же самая текстура, которую я получил бы от 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

Rushyo
источник

Ответы:

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)

После перехода в рендер-буфер на основе текстуры вы можете использовать текстуру как обычно; передавая его в шейдеры как униформу или как угодно.

Тревор Пауэлл
источник
1

Нет, это невозможно. Самое большее, вы можете glReadPixels данные в CPU и создать их текстуру, но это будет громоздко и медленно. Renderbuffers не предназначены для этого, эта функциональность обеспечивается только текстурами.

Матиас Вальденегро
источник
Учитывая это, какая альтернатива? Как вы можете поддерживать глубину в буфере рисования, а также получать компонент глубины как текстуру?
Rushyo
@Rushyo: Альтернативой может быть избавление от буфера трафарета (если возможно!) И создание буфера глубины как текстуры глубины. Почему вы используете трафарет?
Calvin1602
По сути, всякий раз, когда я получаю текстуру глубины, мои тесты глубины ломаются. Если я прикрепляю прикрепление глубины к своему FBO, FBO не записывает никакой информации о глубине в другом месте - поэтому, когда я пытаюсь получить цветное вложение, на нем не проводится проверка глубины (что обычно происходит, если у меня нет прикрепления к глубине). ). Я перепробовал все возможные комбинации, включая вышеупомянутый «громоздкий и медленный» метод. Что бы я ни делал, я не могу получить и «типичный» рендер моей сцены в одной текстуре, и только глубину в другой.
Rushyo
@ Calvin1602 Когда я занимался рендерингом буфера, я обнаружил, что использование присоединения глубины без прикрепления трафарета приводит к нежелательным результатам.
Rushyo
@Rushyo Бьюсь об заклад, вы не настраиваете текстуру правильно, размещение кода позволит нам помочь :)
Matias Valdenegro
1

То, что вы спрашиваете, возможно в OpenGL 3.2. Мой FBO выплевывает диффузный цвет на текстуру цвета, нормали на текстуру другого цвета и текстуру глубины на глубину - никаких буферов рендеринга не требуется. На самом деле, рендер-буферы - это просто проблема, потому что вы не можете сэмплировать их, поэтому вам придется использоватьglReadPixels(...) или каким-либо другим образом копировать данные из RBO и в текстуру на CPU, а не просто поддерживать все в памяти GPU. Так...

Если вы действительно этого хотите, вы можете написать код в своем шейдере первого прохода, чтобы вручную выводить такие вещи, как глубина, в отдельное вложение цветовой текстуры в вашем FBO. Это было бы для использования вами в ваших шейдерах post-pass. Для использования 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(или что у вас есть) как форму вторым, третьим проходным фрагментным шейдерам. Я думаю, что мы можем с уверенностью предположить, что вы можете сделать то же самое с буфером трафарета.

инженер
источник
0

Вы должны быть в состоянии создать текстуру (вместо RenderBuffer), используя формат GL_DEPTH_STENCIL. Я не уверен в точном процессе использования глубины от такой текстуры в шейдерной программе (которую я предполагаю, что вы используете, так как вы используете FBO), но спецификация OpenGL должна указывать, какие цветовые каналы получают какие значения ( я думаю, что R, G и B все установлены на глубину, а A настроен на трафарет).

Сейчас я ориентируюсь на OpenGL 3.2, поэтому вам может потребоваться проверить, что формат текстур подходит для вас. Я никогда не могу вспомнить, какие версии вводят различные функции.

Бранан
источник
Проблема тогда заключается не в захвате компонента GL_DEPTH_STENCIL в текстуре, а в том, что вся информация о глубине теряется в FBO всякий раз, когда вы это делаете. FBO становится бесполезным для рендеринга сцены в буфер рисования. Поэтому я использовал Renderbuffer в надежде обойти эту проблему. Я думаю, что пока у меня нет выбора, кроме как сделать два прохода, чтобы захватить глубину + рисовать информацию отдельно = (дорогой, как ад, пока я не смогу обойти это.
Rushyo
@Rushyo Я отправил ответ на этот древний вопрос :) Возможно, вы захотите взглянуть, хотя вы, вероятно, решили это несколько лет назад.
инженер
@ НикВиггилл, я хочу! Что-то выдумал и продолжил свою жизнь. На самом деле не могу проверить ваш ответ, пока я не воссоздаю ресурсы, которые я использовал в этом прототипе.
Возможно