Работа с framebuffer

Версия Minecraft
1.7.10
1,015
9
102
Как я понял, framebuffer это матрица из пикселей, которые получились после прохождения пайплайна рендринга. Можно ли как-нибудь перед выводом на экран достать зарендренный кадр и изменить его? Можно ли при этом использовать fragment shader? Или только с пом. CPU можно?
 
Решение
Во фрейбуффере вроде есть поле textureID. Суть в том что тебе нужно передать эту текстуру во фрагментный шейдер и отрисовать ее на весь экран.
Ну или можешь достать все пиксели с помощью glGet и в ручную провести изменения и загрузить обратно на GPU конечно, но этого делать не стоит.
2,505
81
397
Можно конечно же. Это постпроцессинг. Рисуешь сцену в отдельное фбо, затем биндишь начальный фреймбуфер и рисуешь текстуру, которая прикреплена к тому отдельному фбо. Майн 1.7.10 так и делает.
 
1,111
47
420
Во фрейбуффере вроде есть поле textureID. Суть в том что тебе нужно передать эту текстуру во фрагментный шейдер и отрисовать ее на весь экран.
Ну или можешь достать все пиксели с помощью glGet и в ручную провести изменения и загрузить обратно на GPU конечно, но этого делать не стоит.
 
1,015
9
102
В итоге получилась такая вот ахинея... Я так и не додумался как надо тут использовать свой framebuffer. Черно-белое от шейдера

Java:
    @SubscribeEvent
    public void renderHUD(RenderGameOverlayEvent.Post e){
        glPushMatrix();
        ScaledResolution res = new ScaledResolution(mc, mc.displayWidth, mc.displayHeight);
        Tessellator tes = Tessellator.instance;
        glColor4f(1, 1, 1, 1);
        Minecraft.getMinecraft().getFramebuffer().bindFramebufferTexture();
        ModShaders.blackWhite.start();
        tes.startDrawingQuads();
        tes.addVertexWithUV(0, res.getScaledHeight(), 0, 0, 1);
        tes.addVertexWithUV(res.getScaledWidth(), res.getScaledHeight(), 0, 1, 1);
        tes.addVertexWithUV(res.getScaledWidth(), 0, 0, 1, 0);
        tes.addVertexWithUV(0, 0, 0, 0, 0);
        tes.draw();
        ModShaders.blackWhite.stop();
        glPopMatrix();
    }


Безымянный.png
 
2,505
81
397
Смотри как происходит в Майне по дефолту, если поддерживается фреймбуфер. Создаётся фбо. В начале каждого кадра он биндится, и в него рисуется вообще все (включая гуи и худ). А в конце кадра биндится дефолта фреймбуфер (0), и в него рисуется полноэкранный квад текстуры из фбо, в который все рендерилось.
Ещё в Майне есть механизм постпроцессинга после рендера мира. Это те самые секретные настройки. Смысл в том, что после того, как отрендерился мир, биндится новый временный фбо. В него рисуется полноэкранный квад мира, применяя шейдером какой-нибудь эффект. А затем биндится исходное майнофбо, в который рендерился мир изначально, и в него блитится (рисуется полноэкранный квад простейшим шейдером) текстура временного фбо. Таких цепочек может быть сколько угодно, все настраивается в файле программы.

Лично я выпилил эту систему постпроцессинга, потому что она, мягко говоря, не удобная. Но она поможет понять, как использовать фбошки.
 
1,990
18
105
Лучший способ, конечно, ничего не копировать и
Использовать для глубины не рендер буфер, а текстуру, например.

Но если приперло, то вот инструкция:
Шоб достать существующий буфер глубины достаточно просто сделать блит из одного FBO в другой, но для этого надо уметь немного работать с ними.

Создание аттачмента для глубины
Секцию где устанавливается glRead/DrawBuffer можно пропустить, если у фбошки есть color аттачменты.

Дальше нужно установить из какого FBO в какой копируем.
Kotlin:
GL30.glBindFramebuffer(GL_READ_FRAMEBUFFER, sourceFbo.id)
GL30.glBindFramebuffer(GL_WRITE_FRAMEBUFFER, targetFbo.id)

Собсна, копирование глубины:
Код:
GL30.glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_DEPTH_BUFFER_BIT, GL_NEAREST)
 
Сверху