opengl
instancing
Zoeken…
Invoering
Instance is een renderingtechniek waarmee we meerdere exemplaren van hetzelfde object in één tekenoproep kunnen tekenen. Het wordt meestal gebruikt om deeltjes, bladeren of grote hoeveelheden andere soorten objecten te maken.
Instancing door Vertex Attribute Arrays
Instance kan worden gedaan via wijzigingen in hoe hoekpuntkenmerken aan de hoekpuntshader worden verstrekt. Dit introduceert een nieuwe manier om toegang te krijgen tot attributenmatrices, waardoor ze gegevens per instantie kunnen aanbieden die eruit zien als een normaal kenmerk.
Een enkele instantie vertegenwoordigt één object of groep hoekpunten (één grasblad enz.). Attributen die zijn gekoppeld aan instantie-arrays gaan alleen tussen instanties door; in tegenstelling tot reguliere hoekpuntattributen, krijgen ze geen nieuwe waarde per hoekpunt.
Gebruik deze aanroep om aan te geven dat een attribuutmatrix wordt geïnstanceerd:
glVertexAttribDivisor(attributeIndex, 1);
Dit stelt de hoekpuntobjectstatus in. De "1" betekent dat het kenmerk voor elke instantie geavanceerd is. Als u een 0 doorgeeft, wordt instancing voor het kenmerk uitgeschakeld.
In de arcering lijkt het instanced-kenmerk op elk ander hoekpuntkenmerk:
in vec3 your_instanced_attribute;
Als u meerdere exemplaren wilt weergeven, kunt u een van de Instanced
van de waarde glDraw*
aanroepen. Dit tekent bijvoorbeeld 1000 instanties, waarbij elke instantie uit 3 hoekpunten bestaat:
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
Instanced Array Code
VAO's, VBO's en de attributen instellen:
// 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);
Draw call:
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);
}