Instanciation
L’instanciation est une technique de rendu qui nous permet de dessiner plusieurs copies du même objet en un seul appel. Il est généralement utilisé pour rendre des particules, du feuillage ou de grandes quantités de tout autre type d’objets.
Instanciation par Vertex Attribute Arrays
L’instanciation peut être effectuée via des modifications de la façon dont les attributs de vertex sont fournis au shader de vertex. Cela introduit une nouvelle façon d’accéder aux tableaux d’attributs, leur permettant de fournir des données par instance qui ressemblent à un attribut normal.
Une seule instance représente un objet ou un groupe de sommets (une feuille d’herbe, etc.). Les attributs associés aux tableaux instanciés ne progressent qu’entre les instances ; contrairement aux attributs de sommet réguliers, ils n’obtiennent pas de nouvelle valeur par sommet.
Pour spécifier qu’un tableau d’attributs est instancié, utilisez cet appel :
glVertexAttribDivisor(attributeIndex, 1);
Cela définit l’état de l’objet tableau de sommets. Le “1” signifie que l’attribut est avancé pour chaque instance. Passer 0 désactive l’instanciation de l’attribut.
Dans le shader, l’attribut instancié ressemble à n’importe quel autre attribut de sommet :
in vec3 your_instanced_attribute;
Pour rendre plusieurs instances, vous pouvez invoquer l’une des formes Instanced
des appels de valeur glDraw*
. Par exemple, cela dessinera 1000 instances, chaque instance étant composée de 3 sommets :
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
Code de tableau instancié
Configuration des VAO, VBO et des attributs :
// List of 10 triangle x-offsets (translations)
GLfloat translations[10];
GLint index = 0;
for (GLint x = 0; x < 10; x++)
{
translations[index++] = (GLfloat)x / 10.0f;
}
// vertices
GLfloat vertices[] = {
0.0f, 0.05f,
0.05f, -0.05f,
-0.05f, -0.05f,
0.0f, -0.1f,
};
// Setting VAOs and VBOs
GLuint meshVAO, vertexVBO, instanceVBO;
glGenVertexArrays(1, &meshVAO);
glGenBuffers(1, &instanceVBO);
glGenBuffers(1, &vertexVBO);
glBindVertexArray(meshVAO);
glBindBuffer(GL_ARRAY_BUFFER, vertexVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GLfloat), (GLvoid*)0);
glBindBuffer(GL_ARRAY_BUFFER, instanceVBO);
glBufferData(GL_ARRAY_BUFFER, sizeof(translations), translations, GL_STATIC_DRAW);
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 1, GL_FLOAT, GL_FALSE, sizeof(GLfloat), (GLvoid*)0);
glVertexAttribDivisor(1, 1); // This sets the vertex attribute to instanced attribute.
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArray(0);
Appel de tirage au sort :
glBindVertexArray(meshVAO);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 10); // 10 diamonds, 4 vertices per instance
glBindVertexArray(0);
** Nuanceur de sommet : **
#version 330 core
layout(location = 0) in vec2 position;
layout(location = 1) in float offset;
void main()
{
gl_Position = vec4(position.x + offset, position.y, 0.0, 1.0);
}
** Nuanceur de fragment : **
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 1.0, 1.0, 1.0f);
}