Vertex 屬性陣列的例項化
Version >= 3.3
可以通過修改如何將頂點屬性提供給頂點著色器來完成例項化。這引入了一種訪問屬性陣列的新方法,允許它們提供看起來像常規屬性的每個例項資料。
單個例項表示一個物件或一組頂點(一個草葉等)。與例項化陣列關聯的屬性僅在例項之間前進; 與常規頂點屬性不同,它們不會獲得每頂點的新值。
要指定屬性陣列是例項化的,請使用以下呼叫:
glVertexAttribDivisor(attributeIndex, 1);
這設定了頂點陣列物件狀態。1
表示每個例項的屬性都是高階的。傳遞 0 會關閉屬性的例項化。
在著色器中,instanced 屬性看起來像任何其他頂點屬性:
in vec3 your_instanced_attribute;
要渲染多個例項,你可以呼叫值 glDraw*
呼叫的 Instanced
形式之一。例如,這將繪製 1000 個例項,每個例項由 3 個頂點組成:
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
例項陣列程式碼
設定 VAO,VBO 和屬性:
// 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);
頂點著色器:
#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);
}
片段著色器:
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 1.0, 1.0, 1.0f);
}