Recherche…


Bases du framebuffer

Le framebuffer est un type de tampon qui stocke les valeurs de couleur , les informations de profondeur et de gabarit des pixels en mémoire. Lorsque vous dessinez quelque chose dans OpenGL, la sortie est stockée dans le framebuffer par défaut , puis vous voyez réellement les valeurs de couleur de ce tampon à l'écran. Vous pouvez également créer votre propre framebuffer qui peut être utilisé pour beaucoup d'effets de post-traitement, tels que les niveaux de gris, le flou, la profondeur de champ, les distorsions, les réflexions ...

Pour commencer, vous devez créer un objet framebuffer ( FBO ) et le lier comme tout autre objet dans OpenGL:

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

Maintenant, vous devez ajouter au moins une pièce jointe (couleur, profondeur ou gabarit) au framebuffer. Une pièce jointe est un emplacement de mémoire qui agit comme un tampon pour le framebuffer. Il peut s'agir d'une texture ou d'un objet renderbuffer . L'avantage d'utiliser une texture est que vous pouvez facilement utiliser cette texture dans un shaders de post-traitement. La création de la texture est similaire à une texture 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 et la height doivent être identiques à la taille de la fenêtre de rendu. Le pointeur de données de texture est NULL car vous souhaitez uniquement allouer la mémoire et ne pas remplir la texture avec des données. La texture est prête pour que vous puissiez réellement l'attacher au framebuffer:

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

Votre framebuffer devrait être prêt à être utilisé maintenant, mais vous souhaiterez peut-être également ajouter des attachements de profondeur ou des attachements de profondeur et de gabarit. Si vous souhaitez les ajouter en tant que pièces jointes de texture (et les utiliser pour certains traitements), vous pouvez créer d’autres textures comme ci-dessus. La seule différence serait dans ces lignes:

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

Ou ceux-ci si vous souhaitez utiliser l'attachement de profondeur et de gabarit dans une texture unique:

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

Vous pouvez également utiliser un renderbuffer au lieu d'une texture en tant que pièce jointe pour les tampons de profondeur et de gabarit si vous ne souhaitez pas traiter les valeurs ultérieurement. (Cela sera expliqué dans un autre exemple ...)

Vous pouvez vérifier si le framebuffer a été créé et exécuté sans erreur:

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

Et enfin, n'oubliez pas de délier le framebuffer pour ne pas lui rendre accidentellement:

glBindFramebuffer(GL_FRAMEBUFFER, 0);  

Limites

Le nombre maximal de tampons de couleur pouvant être attachés à un seul tampon de trame peut être déterminé par la fonction OGL glGetIntegerv , en utilisant le paramètre GL_MAX_COLOR_ATTACHMENTS :

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

Utiliser le framebuffer

L'utilisation est assez simple. Tout d'abord, vous liez votre framebuffer et y rendez votre scène. Mais vous ne verrez rien encore car votre tampon de rendu n'est pas visible. La deuxième partie consiste donc à rendre votre framebuffer comme une texture de quad plein écran sur l'écran. Vous pouvez simplement le rendre tel quel ou effectuer des effets de post-traitement.

Voici les sommets pour un quad plein écran:

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

Vous devrez les stocker dans un VBO ou les rendre en utilisant des pointeurs d’attributs. Vous aurez également besoin d'un programme de shader de base pour le rendu du quad plein écran avec 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);
}

Note: Vous devrez peut-être ajuster les shaders pour votre version de GLSL .

Maintenant, vous pouvez faire le rendu réel. Comme décrit ci-dessus, la première chose à faire est de rendre la scène dans votre FBO. Pour ce faire, il vous suffit de lier votre FBO, de le vider et de dessiner la scène:

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

Remarque: Dans la fonction glClear , vous devez spécifier toutes les pièces jointes du framebuffer que vous utilisez (Dans cet exemple, pièce jointe couleur et profondeur).

Maintenant, vous pouvez rendre votre FBO comme un quad plein écran sur le framebuffer par défaut pour que vous puissiez le voir. Pour ce faire, il vous suffit de déconnecter votre FBO et de rendre le 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);

Et c'est tout! Si vous avez tout fait correctement, vous devriez voir la même scène qu'auparavant, mais sur un quad plein écran. La sortie visuelle est la même que précédemment, mais vous pouvez désormais facilement ajouter des effets de post-traitement simplement en modifiant le fragment shader. (Je vais ajouter des effets dans un autre exemple et le lier ici)



Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow