opengl
Instanziierung
Suche…
Einführung
Beim Instanziieren handelt es sich um eine Rendering-Technik, mit der mehrere Kopien desselben Objekts in einem Zeichnungsaufruf gezeichnet werden können. Es wird normalerweise verwendet, um Partikel, Blätter oder große Mengen von anderen Objekten zu rendern.
Instanzierung durch Vertex-Attribut-Arrays
Die Instanziierung kann durch Änderungen an der Art und Weise vorgenommen werden, wie Vertex-Attribute für den Vertex-Shader bereitgestellt werden. Dadurch wird eine neue Methode für den Zugriff auf Attribut-Arrays eingeführt, die es ihnen ermöglicht, Instanzdaten bereitzustellen, die wie ein reguläres Attribut aussehen.
Eine einzelne Instanz repräsentiert ein Objekt oder eine Gruppe von Knoten (ein Grasblatt usw.). Attribute, die mit instanziierten Arrays verknüpft sind, bewegen sich nur zwischen Instanzen. Im Gegensatz zu regulären Vertex-Attributen erhalten sie keinen neuen Wert pro Vertex.
Verwenden Sie diesen Aufruf, um anzugeben, dass ein Attributarray instanziiert ist:
glVertexAttribDivisor(attributeIndex, 1);
Dies setzt den Zustand des Vertex-Array-Objekts. Die "1" bedeutet, dass das Attribut für jede Instanz erweitert wird. Wenn Sie eine 0 übergeben, wird die Instanziierung für das Attribut deaktiviert.
Im Shader sieht das instanzierte Attribut wie jedes andere Vertex-Attribut aus:
in vec3 your_instanced_attribute;
Um mehrere Instanzen zu machen, können Sie eine der aufrufen Instanced
Formen des Wertes glDraw*
Anrufe. Zum Beispiel werden 1000 Instanzen gezeichnet, wobei jede Instanz aus 3 Scheitelpunkten besteht:
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
Instanzierter Array-Code
Einrichten von VAOs, VBOs und den Attributen:
// 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);
Anruf zeichnen:
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);
}