Поиск…


Основы фреймбуферов

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

Для начала вам нужно создать объект фреймбуфера ( FBO ) и связать его, как и любой другой объект в OpenGL:

unsigned int FBO;
glGenFramebuffers(1, &FBO);
glBindFramebuffer(GL_FRAMEBUFFER, FBO);  

Теперь вам нужно добавить по крайней мере одно вложение (цвет, глубина или трафарет) в фреймбуфер. Вложение - это ячейка памяти, которая выступает в качестве буфера для фреймбуфера. Это может быть либо текстура , либо объект renderbuffer . Преимущество использования текстуры заключается в том, что вы можете легко использовать эту текстуру в пост-обрабатывающих шейдерах. Создание текстуры аналогично нормальной текстуре:

unsigned int texture;
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 

width и height должны быть такими же, как размер окна рендеринга. Указатель данных текстуры имеет NULL потому что вы хотите выделить память и не заполнить текстуру любыми данными. Текстура готова, поэтому вы можете привязать ее к фреймбуферу:

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);  

Теперь ваш фреймбуфер должен быть готов к использованию, но вы можете также добавить добавление глубины или вложения глубины и трафарета. Если вы хотите добавить их в качестве вложений текстуры (и использовать их для некоторой обработки), вы можете создать другие текстуры, например, выше. Единственное различие в этих строках:

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT, width, height, 0, 
    GL_DEPTH_COMPONENT, GL_FLOAT, NULL
);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, texture, 0);

Или это, если вы хотите использовать глубину и трафаретную привязку в одной текстуре:

glTexImage2D(
    GL_TEXTURE_2D, 0, GL_DEPTH24_STENCIL8, width, height, 0, 
    GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL
);

glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, texture, 0);

Вы также можете использовать renderbuffer вместо текстуры в качестве вложения для буферов глубины и трафарета, если не хотите обрабатывать значения позже. (Это будет объяснено в другом примере ...)

Вы можете проверить, успешно ли создан и завершен фреймбуфер без каких-либо ошибок:

if(glCheckFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE)
    // do something...

И, наконец, не забудьте отвязать фреймбуфер, чтобы вы не случайно его отбросили:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

рамки

Максимальное количество цветовых буферов, которые могут быть присоединены к буму одного кадра, может быть определено функцией OGL glGetIntegerv , используя параметр GL_MAX_COLOR_ATTACHMENTS :

GLint maxColAttchments = 0;
glGetIntegerv( GL_MAX_COLOR_ATTACHMENTS, &maxColAttchments );

Использование фреймбуфера

Использование довольно простое. Во-первых, вы привязываете фреймбуфер и визуализируете свою сцену. Но вы ничего не увидите, потому что ваш рендеринг не отображается. Итак, вторая часть - сделать ваш фреймбуфер как текстуру полноэкранного квадрата на экране. Вы можете просто визуализировать его так, как есть, или делать некоторые эффекты пост-обработки.

Вот вершины для полноэкранного квадранта:

float vertices[] = {
//   positions     texture coordinates
    -1.0f,  1.0f,  0.0f, 1.0f,
    -1.0f, -1.0f,  0.0f, 0.0f,
     1.0f, -1.0f,  1.0f, 0.0f,

    -1.0f,  1.0f,  0.0f, 1.0f,
     1.0f, -1.0f,  1.0f, 0.0f,
     1.0f,  1.0f,  1.0f, 1.0f
};

Вам нужно будет хранить их в VBO или рендеринг с помощью указателей атрибутов. Вам также понадобится базовая шейдерная программа для рендеринга полноэкранного квадроцикла с текстурой.

Vertex shader:

in vec2 position;
in vec2 texCoords;

out vec2 TexCoords;

void main()
{
    gl_Position = vec4(position.x, position.y, 0.0, 1.0); 
    TexCoords = texCoords;
}  

Фрагментный шейдер:

in vec2 TexCoords;
out vec4 color;

uniform sampler2D screenTexture;

void main()
{ 
    color = texture(screenTexture, TexCoords);
}

Примечание. Возможно, вам потребуется настроить шейдеры для вашей версии GLSL .

Теперь вы можете сделать фактический рендеринг. Как описано выше, первое, что нужно сделать, сделать сцену в вашем FBO. Для этого вы просто связываете свой FBO, очищаете и рисуете сцену:

glBindFramebuffer(GL_FRAMEBUFFER, FBO);
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
// draw your scene here...   

Примечание. В функции glClear вы должны указать все вложения фреймбуфферов, которые вы используете (в этом примере вложение цвета и глубины).

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

glBindFramebuffer(GL_FRAMEBUFFER, 0); // unbind your FBO to set the default framebuffer
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 

shader.Use(); // shader program for rendering the quad  

glBindTexture(GL_TEXTURE_2D, texture); // color attachment texture
glBindBuffer(GL_ARRAY_BUFFER, VBO); // VBO of the quad
// You can also use VAO or attribute pointers instead of only VBO...
glDrawArrays(GL_TRIANGLES, 0, 6); 
glBindBuffer(GL_ARRAY_BUFFER, 0);

И это все! Если вы все сделали правильно, вы должны увидеть ту же сцену, что и раньше, но отображаться на полноэкранном квадранте. Визуальный вывод такой же, как и раньше, но теперь вы можете легко добавить эффекты пост-обработки, просто отредактировав шейдер фрагмента. (Я добавлю эффекты в другой пример (ы) и свяжу его здесь)



Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow