opengl
Instancing
Ricerca…
introduzione
L'istanza è una tecnica di rendering che ci consente di disegnare più copie dello stesso oggetto in una sola chiamata. Di solito viene utilizzato per il rendering di particelle, fogliame o grandi quantità di altri tipi di oggetti.
Istanziazione da array di attributi Vertex
L'istanza può essere eseguita modificando il modo in cui gli attributi dei vertici vengono forniti al vertex shader. Questo introduce un nuovo modo di accedere agli array di attributi, consentendo loro di fornire dati per istanza che assomigliano ad un attributo regolare.
Una singola istanza rappresenta un oggetto o un gruppo di vertici (una foglia d'erba, ecc.). Gli attributi associati agli array istanziati avanzano solo tra le istanze; a differenza degli attributi dei vertici regolari, non ottengono un nuovo valore per-vertice.
Per specificare che un array di attributi è istanziato, usa questa chiamata:
glVertexAttribDivisor(attributeIndex, 1);
Questo imposta lo stato dell'oggetto dell'array di vertici. Il "1" significa che l'attributo è avanzato per ogni istanza. Il passaggio a 0 disattiva l'istanza per l'attributo.
Nello shader, l'attributo istanced ha l'aspetto di qualsiasi altro attributo di vertice:
in vec3 your_instanced_attribute;
Per rendere più istanze, è possibile richiamare una delle Instanced
forme del valore glDraw*
chiamate. Ad esempio, questo disegnerà 1000 istanze, con ogni istanza costituita da 3 vertici:
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
Codice di matrice istanziata
Impostazione di VAO, VBO e attributi:
// 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);
Disegna la chiamata:
glBindVertexArray(meshVAO);
glDrawArraysInstanced(GL_TRIANGLE_STRIP, 0, 4, 10); // 10 diamonds, 4 vertices per instance
glBindVertexArray(0);
Vertex shader:
#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);
}
Fragment shader:
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 1.0, 1.0, 1.0f);
}