opengl
Instancing
Поиск…
Вступление
Instancing - это метод рендеринга, который позволяет нам рисовать несколько копий одного и того же объекта в одном обратном вызове. Он обычно используется для визуализации частиц, листвы или больших количеств любых других типов объектов.
Экран по массивам атрибутов Vertex
Инстанция может быть выполнена с помощью модификаций того, как атрибуты вершин предоставляются вершинному шейдеру. Это вводит новый способ доступа к массивам атрибутов, позволяя им предоставлять данные для каждого экземпляра, которые выглядят как обычный атрибут.
Один экземпляр представляет один объект или группу вершин (один лист травы и т. Д.). Атрибуты, связанные с массивными массивами, только продвигаются между экземплярами; в отличие от обычных атрибутов вершин, они не получают новое значение per-vertex.
Чтобы указать, что массив атрибутов задан, используйте этот вызов:
glVertexAttribDivisor(attributeIndex, 1);
Это устанавливает состояние объекта массива вершин. «1» означает, что атрибут продвигается для каждого экземпляра. Передача 0 отключает проверку атрибута.
В шейдере атрибут instanced выглядит как любой другой атрибут вершины:
in vec3 your_instanced_attribute;
Для рендеринга нескольких экземпляров вы можете вызвать одну из Instanced
форм вызовов glDraw*
. Например, это приведет к 1000 экземплярам, причем каждый экземпляр состоит из трех вершин:
glDrawArraysInstanced(GL_TRIANGLES, 0, 3, 1000);
Экранный код массива
Настройка VAO, VBOs и атрибутов:
// 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);
Рисовать вызов:
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);
}
Фрагментный шейдер:
#version 330 core
layout(location = 0) out vec4 color;
void main()
{
color = vec4(1.0, 1.0, 1.0, 1.0f);
}