3.7 Association (Attachment)

Nos différents buffers sont maintenant créés et prêts à être utilisés. Cependant ils ne sont pas d'une grande utilité pour le moment, ils sont tous éparpillés dans plusieurs attributs et OpenGL ne connaît même pas leur existence. Pour remédier à ce problème, nous allons les associer au FBO, un peu comme nous avons associé les shaders au programme.

Pour faire cela, nous aurons besoin de deux fonctions : l'une est dédiée aux Color Buffers et l'autre aux Render Buffers. Je vais vous demander un peu d'attention pour leur explication car ce sont certainement les fonctions OpenGL les plus importantes de ce chapitre.

La première s'appelle glFramebufferTexture2D() (un peu compliqué comme nom) :

1
void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
  • target : Le paramètre target du FBO, soit GL_FRAMEBUFFER ici
  • attachment : Paramètre SUPER important que nous allons développer dans un instant
  • textarget : Le paramètre target de la texture cette fois, soit GL_TEXTURE_2D
  • texture : L'identifiant de la texture à associer. Nous utiliserons le getter getID() de notre Color Buffer
  • level : Paramètre que l'on a déjà rencontré dans le chapitre sur les textures. Nous l'avions laissé à 0 et c'est ce que nous allons faire ici aussi

Le paramètre auquel il faut faire attention ici est évidemment le paramètre attachment. Ce dernier correspond au point d'attache, ou plus grossièrement à l'index du Color Buffer. N'oubliez pas que nous pouvons en créer jusqu'à 16, il faut qu'OpenGL donne un index à chacun d'entre eux pour pouvoir les reconnaître au moment de l'affichage.

C'est précisément ce que fait le paramètre attachment, il permet de différencier les buffers au moment de les associer. Les valeurs qu'il peut prendre correspondent aux constantes allant de GL_COLOR_ATTACHMENT0 à GL_COLOR_ATTACHMENT15. Dans notre cas, nous n'utiliserons que la première car nous n'avons qu'un seul buffer à gérer.

Au final, l'appel à la fonction glFramebufferTexture2D() ressemblera à ceci :

1
2
// Association du Color Buffer
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffers[0].getID(), 0);

La seconde fonction d'association ressemble fortement à la première, ses paramètres sont assez semblables sauf qu'ils permettent de gérer les Render Buffers. La fonction s'appelle glFramebufferRenderbuffer() :

1
void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
  • target : Le paramètre target du FBO, soit GL_FRAMEBUFFER
  • attachment : Paramètre que l'on va développer dans un instant
  • renderbuffertarget : Le paramètre target du Render Buffer cette fois, celui que nous avons utilisé pour le configurer. Nous lui donnerons donc la constante GL_RENDERBUFFER
  • renderbuffer : L'identifiant du Render Buffer à associer. Nous lui donnerons l'attribut m_depthBufferID qui contient le Depth et le Stencil Buffer

Le principe du paramètre attachment ne change pas vraiment par rapport au précédent on parle toujours du point d'attache, sauf qu'ici OpenGL n'attend plus un index mais le type de Render Buffer que l'on souhaite associer.

Là-aussi, nous devrions en théorie appeler cette fonction deux fois pour le Depth et le Stencil Buffer, cependant avec la fusion de ces derniers, nous n'aurons besoin que d'un seul appel.

Le paramètre attachment prendra une constante assez proche de celle que l'on a utilisée pour la méthode creerRenderBuffer() et qui s'appelle : GL_DEPTH_STENCIL_ATTACHMENT. L'appel à la fonction glFramebufferRenderbuffer() ressemblera donc à ceci :

1
2
// Association du Depth et du Stencil Buffer
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferID);

Avec cet appel, on associe le double-buffer que l'on a créé précédemment avec le point d'attache GL_DEPTH_STENCIL_ATTACHMENT. Le FBO possède maintenant tous les buffers dont il a besoin pour fonctionner.

Si on récapitule tout ça :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
bool FrameBuffer::charger()
{
	// Vérification d'un éventuel ancien FBO
	if(glIsFramebuffer(m_id) == GL_TRUE) glDeleteFramebuffers(1, &m_id);

	// Génération d'un id
	glGenFramebuffers(1, &m_id);

	// Verrouillage du Frame Buffer
	glBindFramebuffer(GL_FRAMEBUFFER, m_id);

	// Création du Color Buffer
	Texture colorBuffer(m_largeur, m_hauteur, GL_RGBA, GL_RGBA, true);
	colorBuffer.chargerTextureVide();

	// Ajout au tableau
	m_colorBuffers.push_back(colorBuffer);

	// Création du Depth et du Stencil Buffer
	creerRenderBuffer(m_depthBufferID, GL_DEPTH24_STENCIL8);

	// Association du Color Buffer
	glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_colorBuffers[0].getID(), 0);

	// Association du Depth et du Stencil Buffer
	glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER, m_depthBufferID);

	// Déverrouillage du Frame Buffer
	glBindFramebuffer(GL_FRAMEBUFFER, 0);
}