Suche…


Grundlagen von Framebuffers

Bildpuffer ist eine Art Puffer, den Farbwert, die Tiefe und Schabloneninformationen von Pixeln im Speicher speichert. Wenn Sie etwas in OpenGL zeichnen, wird die Ausgabe im Standard-Framebuffer gespeichert und Sie sehen tatsächlich die Farbwerte dieses Puffers auf dem Bildschirm. Sie können auch Ihren eigenen Framebuffer erstellen, der für viele coole Nachbearbeitungseffekte wie Graustufen, Unschärfe, Schärfentiefe, Verzerrungen, Reflexionen usw. verwendet werden kann.

Zunächst müssen Sie ein Framebuffer-Objekt ( FBO ) erstellen und es wie jedes andere Objekt in OpenGL binden:

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

Nun müssen Sie dem Framebuffer mindestens einen Anhang (Farbe, Tiefe oder Schablone) hinzufügen. Ein Anhang ist ein Speicherort, der als Puffer für den Framebuffer dient. Dies kann entweder ein Textur- oder ein Renderbuffer-Objekt sein . Der Vorteil der Verwendung einer Textur besteht darin, dass Sie diese Textur leicht in Nachbearbeitungs-Shadern verwenden können. Das Erstellen der Textur ähnelt einer normalen Textur:

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

Die width und height sollte der Größe Ihres Renderfensters entsprechen. Der Texturdatenzeiger ist NULL da Sie nur den Speicher zuweisen und die Textur nicht mit Daten füllen möchten. Die Textur ist fertig, sodass Sie sie tatsächlich an den Framebuffer anhängen können:

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

Ihr Framebuffer sollte jetzt betriebsbereit sein, aber Sie möchten möglicherweise auch Tiefenanhänge oder sowohl Tiefen- als auch Schablonenanhänge hinzufügen. Wenn Sie diese als Texturanhänge hinzufügen (und für einige Verarbeitungszwecke verwenden) möchten, können Sie weitere Texturen wie oben erstellen. Der einzige Unterschied wäre in diesen Zeilen:

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

Oder diese, wenn Sie Tiefen- und Schablonenbefestigung in einer einzigen Textur verwenden möchten:

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

Sie können auch einen Renderbuffer anstelle einer Textur als Anhang für Tiefen- und Stencilpuffer verwenden, wenn Sie die Werte später nicht verarbeiten möchten. (Es wird in einem anderen Beispiel erklärt ...)

Sie können überprüfen, ob der Framebuffer erfolgreich erstellt und fehlerfrei abgeschlossen wurde:

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

Und schließlich vergessen Sie nicht, den Framebuffer zu lösen, damit Sie nicht versehentlich darauf rendern:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

Grenzen

Die maximale Anzahl der Farbpuffer , die an einen einzelnen Frame-Puffer angehängt werden können, kann durch die OGL-Funktion glGetIntegerv mit dem Parameter GL_MAX_COLOR_ATTACHMENTS :

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

Verwenden des Framebuffers

Die Verwendung ist ziemlich unkompliziert. Zuerst binden Sie Ihren Framebuffer und rendern Ihre Szene darin. Sie sehen jedoch noch nichts, da Ihr Renderbuffer nicht sichtbar ist. Der zweite Teil ist also, Ihren Framebuffer als Textur eines Vollbild-Quad auf dem Bildschirm darzustellen. Sie können es einfach so rendern, wie es ist, oder einige Nachbearbeitungseffekte.

Hier sind die Eckpunkte für ein Vollbild-Quad:

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

Sie müssen sie in einem VBO speichern oder mit Attributzeigern rendern. Sie benötigen auch ein einfaches Shader-Programm zum Rendern des Quad-Bildschirms mit Textur.

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

Hinweis: Möglicherweise müssen Sie die Shader für Ihre Version von GLSL anpassen.

Jetzt können Sie das eigentliche Rendering durchführen. Wie oben beschrieben, müssen Sie zunächst die Szene in Ihrem FBO rendern. Dazu binden Sie einfach Ihren FBO, löschen Sie ihn und zeichnen Sie die Szene:

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

Hinweis: In der glClear Funktion sollten Sie alle verwendeten Framebuffer-Anhänge angeben (in diesem Beispiel Farb- und Tiefenanhang).

Jetzt können Sie Ihren FBO als Vollbild-Quad auf dem Standard-Framebuffer darstellen, damit Sie ihn sehen können. Dazu lösen Sie einfach Ihren FBO und rendern das 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);

Und das ist alles! Wenn Sie alles richtig gemacht haben, sollten Sie dieselbe Szene wie zuvor sehen, aber auf einem Vollbild-Quad gerendert werden. Die visuelle Ausgabe ist dieselbe wie zuvor, aber Sie können jetzt einfach Nachbearbeitungseffekte hinzufügen, indem Sie den Fragment-Shader bearbeiten. (Ich füge Effekte in anderen Beispielen hinzu und verknüpfe sie hier)



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow