Ricerca…


Nozioni di base sui framebuffer

Framebuffer è un tipo di buffer che memorizza i valori dei colori , la profondità e le informazioni sullo stencil dei pixel in memoria. Quando si disegna qualcosa in OpenGL, l'output viene memorizzato nel framebuffer predefinito e quindi si vedono effettivamente i valori dei colori di questo buffer sullo schermo. Puoi anche creare il tuo framebuffer che può essere utilizzato per molti effetti di post-elaborazione come la scala di grigi, la sfocatura, la profondità di campo, le distorsioni, i riflessi ...

Per iniziare devi creare un oggetto framebuffer ( FBO ) e collegarlo come qualsiasi altro oggetto in OpenGL:

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

Ora devi aggiungere almeno un allegato (colore, profondità o stencil) al framebuffer. Un allegato è un percorso di memoria che funge da buffer per il framebuffer. Può essere una texture o un oggetto renderbuffer . Il vantaggio di usare una texture è che puoi facilmente utilizzare questa texture in shader post-elaborazione. La creazione della trama è simile a una trama normale:

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

La width e l' height dovrebbero essere uguali alle dimensioni della finestra di rendering. Il puntatore di dati di trama è NULL perché si desidera solo allocare la memoria e non riempire la trama con alcun dato. La texture è pronta per poterla allegare al framebuffer:

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

Il framebuffer dovrebbe essere pronto per l'uso ora, ma potresti anche voler aggiungere un allegato di profondità o entrambi gli allegati di profondità e stencil. Se vuoi aggiungerli come allegati di texture (e usarli per qualche elaborazione) puoi creare un'altra texture come sopra. L'unica differenza sarebbe in queste righe:

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 questi se si desidera utilizzare l'allegato di profondità e stencil in una singola trama:

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

È inoltre possibile utilizzare un renderbuffer anziché una texture come allegato per i buffer di profondità e stencil se non si desidera elaborare i valori in un secondo momento. (Sarà spiegato in un altro esempio ...)

Puoi verificare se il framebuffer è stato creato e completato correttamente senza errori:

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

Infine, non dimenticare di separare il framebuffer in modo da non renderlo accidentalmente visibile:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

limiti

Il numero massimo di buffer colore che possono essere collegati a un singolo frame buffer può essere determinato dalla funzione OGL glGetIntegerv , utilizzando il parametro GL_MAX_COLOR_ATTACHMENTS :

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

Usando il framebuffer

L'utilizzo è abbastanza semplice. Innanzitutto leghi il tuo framebuffer e ti mostri la scena. Ma in realtà non vedrai ancora nulla perché il tuo renderbuffer non è visibile. Quindi la seconda parte è di rendere il framebuffer come una trama di un quad a schermo intero sullo schermo. Puoi semplicemente renderlo così com'è o fare alcuni effetti di post-elaborazione.

Ecco i vertici per un quad a schermo intero:

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

Dovrai memorizzarli in un VBO o renderizzare usando i puntatori degli attributi. Avrai anche bisogno di un programma shader di base per il rendering del quad a schermo intero con texture.

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

Fragment shader:

in vec2 TexCoords;
out vec4 color;

uniform sampler2D screenTexture;

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

Nota: potrebbe essere necessario regolare gli shader per la versione di GLSL .

Ora puoi fare il rendering attuale. Come descritto sopra, la prima cosa è rendere la scena nel tuo FBO. Per farlo basta legare il tuo FBO, cancellarlo e disegnare la scena:

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: nella funzione glClear è necessario specificare tutti gli allegati framebuffer che si stanno utilizzando (in questo esempio, l'allegato per colore e profondità).

Ora puoi renderizzare il tuo FBO come quad a schermo intero sul framebuffer predefinito in modo che tu possa vederlo. Per fare ciò basta semplicemente smistare il tuo FBO e rendere il 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);

E questo è tutto! Se hai fatto tutto correttamente dovresti vedere la stessa scena di prima ma renderizzata su un quad a schermo intero. L'output visivo è lo stesso di prima, ma ora puoi facilmente aggiungere effetti di post-elaborazione semplicemente modificando lo shader del frammento. (Aggiungerò effetti in un altro esempio (s) e collegarlo qui)



Modified text is an extract of the original Stack Overflow Documentation
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow