Buscar..


Fundamentos de framebuffers

Framebuffer es un tipo de búfer que almacena los valores de color , la profundidad y la información de la plantilla de los píxeles en la memoria. Cuando dibuja algo en OpenGL, la salida se almacena en el framebuffer predeterminado y luego se ven los valores de color de este búfer en la pantalla. También puede crear su propio framebuffer que se puede usar para muchos efectos de posprocesamiento geniales, como escala de grises, desenfoque, profundidad de campo, distorsiones, reflejos ...

Para comenzar necesitas crear un objeto de framebuffer ( FBO ) y enlazarlo como cualquier otro objeto en OpenGL:

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

Ahora debe agregar al menos un archivo adjunto (color, profundidad o plantilla) al framebuffer. Un archivo adjunto es una ubicación de memoria que actúa como un búfer para el framebuffer. Puede ser una textura o un objeto renderbuffer . La ventaja de usar una textura es que puede usar esta textura fácilmente en un sombreado de post-procesamiento. Crear la textura es similar a una textura normal:

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

El width y la height deben ser iguales al tamaño de la ventana de renderizado. El puntero de datos de textura es NULL porque solo desea asignar la memoria y no rellenar la textura con ningún dato. La textura está lista, por lo que puedes adjuntarla al framebuffer:

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

Su framebuffer debería estar listo para usar ahora, pero es posible que también desee agregar adjuntos de profundidad o adjuntos de profundidad y de plantilla. Si desea agregarlos como archivos adjuntos de textura (y usarlos para algún procesamiento) puede crear otras texturas como las de arriba. La única diferencia sería en estas líneas:

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

O estos si desea utilizar profundidad y apego de plantilla en una sola textura:

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

También puede usar un tampón de renderizado en lugar de una textura como un archivo adjunto para los búferes de profundidad y de plantilla si no desea procesar los valores más adelante. (Se explicará en otro ejemplo ...)

Puede comprobar si el framebuffer se ha creado y completado correctamente sin ningún error:

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

Y, por último, no olvides desenlazar el framebuffer para que no le rindas accidentalmente:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

Límites

La función OGL glGetIntegerv puede determinar el número máximo de búferes de color que se pueden adjuntar a un solo búfer de cuadro mediante el parámetro GL_MAX_COLOR_ATTACHMENTS :

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

Usando el framebuffer

El uso es bastante sencillo. En primer lugar, unes tu framebuffer y renderizas tu escena en él. Pero aún no verás nada porque tu renderbuffer no es visible. Por lo tanto, la segunda parte es hacer que el framebuffer sea una textura de un cuadrante de pantalla completa en la pantalla. Solo puedes renderizarlo como está o hacer algunos efectos de post-procesamiento.

Aquí están los vértices para un quad de pantalla completa:

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

Deberá almacenarlos en un VBO o renderizar utilizando punteros de atributos. También necesitarás un programa de sombreado básico para representar el cuadrante de pantalla completa con textura.

Sombreador de vértices:

in vec2 position;
in vec2 texCoords;

out vec2 TexCoords;

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

Sombreador de fragmentos:

in vec2 TexCoords;
out vec4 color;

uniform sampler2D screenTexture;

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

Nota: Es posible que deba ajustar los sombreadores para su versión de GLSL .

Ahora puede hacer la representación real. Como se describió anteriormente, lo primero es renderizar la escena en su FBO. Para hacerlo, simplemente enlace su FBO, bórrelo y dibuje la escena:

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...   

Nota: En la función glClear debe especificar todos los archivos adjuntos de framebuffer que está utilizando (en este ejemplo, el archivo de color y profundidad).

Ahora puedes renderizar tu FBO como un cuadrante de pantalla completa en el framebuffer predeterminado para que puedas verlo. Para hacer esto, simplemente desvincula tu FBO y renderiza el quad:

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

¡Y eso es todo! Si has hecho todo correctamente, deberías ver la misma escena que antes pero renderizada en un quad de pantalla completa. La salida visual es la misma que antes, pero ahora puede agregar fácilmente efectos de posprocesamiento simplemente editando el sombreador de fragmentos. (Agregaré efectos en otro ejemplo (s) y lo vincularé aquí)



Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow