Проблема с glVertexArrayVertexBuffer () / glVertexArrayAttribFormat () в разных макетах буфера - PullRequest
1 голос
/ 25 мая 2020

Я пытаюсь ускорить свой код OpenGL с помощью прямого доступа к состоянию и внимательно следил за кодом из Руководства по современным функциям OpenGL . У меня есть небольшой тестовый проект с некоторыми вершинами и цветами в виде:

std::vector<float> vertices;
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
    for (float x = -1.0f; x < 1.1f; x += 1.0f) {
        vertices.emplace_back(x);
        vertices.emplace_back(y);
        vertices.emplace_back(0.5f);
        vertices.emplace_back(0.5f);
        vertices.emplace_back(0.5f);
    }
}

Визуальное представление этих вершин и их индексов:

enter image description here

Мой основной код отрисовки примерно такой:

unsigned int vbo = 0;
glCreateBuffers(1, &vbo);
glNamedBufferStorage(vbo, sizeof(float) * vertices.size(), vertices.data(), GL_DYNAMIC_STORAGE_BIT);

// Indices
unsigned int indices[]{ 0,1,3,5,8,7 };
unsigned int ibo = 0;
glCreateBuffers(1, &ibo);
glNamedBufferStorage(ibo, sizeof(unsigned int) * 6, indices, GL_DYNAMIC_STORAGE_BIT);

int bindingindex_a = 1;
int bindingindex_b = 2;
int pos_location = 3;
int color_location = 4;

unsigned int vao = 0;
glCreateVertexArrays(1, &vao);
glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));
glVertexArrayElementBuffer(vao, ibo);

glEnableVertexArrayAttrib(vao, pos_location);
glEnableVertexArrayAttrib(vao, color_location);

glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 2*sizeof(float));

glVertexArrayAttribBinding(vao, pos_location, bindingindex_a);
glVertexArrayAttribBinding(vao, color_location, bindingindex_b);

Итак, я рисую два серых треугольника с индексами 0,1,3 и 5,8,7. Расположение атрибутов в моем шейдере указано в коде cpp:

layout (location = 3) in vec2 pos;
layout (location = 4) in vec3 col;

И это работает!:

enter image description here

Даже когда я увеличиваю сложность и добавляю одно значение с плавающей запятой впереди, я могу отрегулировать смещение в функции glVertexArrayVertexBuffer() на 4 байта.

Проблема в том, когда я хочу go из макета буфера A в B:

enter image description here

Я настраиваю заполнение данными l oop, чтобы сначала записать позиции, а затем цвета:

for (float y = -1.0f; y < 1.1f; y += 1.0f) {
    for (float x = -1.0f; x < 1.1f; x += 1.0f) {
        vertices.emplace_back(x);
        vertices.emplace_back(y);
    }
}
for (float y = -1.0f; y < 1.1f; y += 1.0f) {
    for (float x = -1.0f; x < 1.1f; x += 1.0f) {
        vertices.emplace_back(0.5f);
        vertices.emplace_back(0.5f);
        vertices.emplace_back(0.5f);
    }
}

и настройте вызовы на glVertexArrayVertexBuffer() и glVertexArrayAttribFormat():

glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));

glVertexArrayAttribFormat(vao, pos_location, 2, GL_FLOAT, GL_FALSE, 0);
glVertexArrayAttribFormat(vao, color_location, 3, GL_FLOAT, GL_FALSE, 0);

Итак, теперь мое глобальное смещение цвета составляет 18 значений с плавающей запятой (9 позиций, умноженных на два компонента), а мое relativeoffset (вот как khronos.org называет это) 0 для обоих. Это отображает серые вещи, но не так, как раньше. Моя ментальная модель того, как эти вещи работают, явно неверна - где?

1 Ответ

2 голосов
/ 25 мая 2020

Параметр смещение для glVertexArrayVertexBuffer - это смещение первого элемента буфера в байтах, формирует начало буфера, а шаг - расстояние между последовательными атрибутами в буфере.


Спецификация вершины для случая A неверна:

glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 0, 5 * sizeof(float));

Каждый кортеж атрибутов вершин состоит из 5 компонентов ( х, у, г, ж, б).

(x1, y1, r1, g1, b1,   x2, y2, r2, g2, b2,   x3, y3, r3, g3, b3, ...)

Следовательно, смещение для атрибута цвета равно 2*sizeof(float):

glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 5 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 2 * sizeof(float), 5 * sizeof(float));

Смещение в байтах x1 равно 0.
байтовое смещение r1 равно 2 * sizeof(float).
Расстояние в байтах от x1 до x2 равно 5 * sizeof(float).
Расстояние в байтах форма r1 to r2 is 5 * sizeof(float).


Смещение для случая B правильное:

glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18*sizeof(float), 3 * sizeof(float));

В случае B есть 9 координат вершин, за которыми следуют 3 цветовых атрибута. Кортеж вершин имеет w компонентов, а кортеж цвета - 3 компонента:

(x1, y1, x2, y2, ... x9, y9,  r1, g1, b1, r2, g2, b2, ..., r9, g9, b9)

Следовательно, смещение начала атрибута цвета равно 9*sizeof(float) (3 * (x, y)):

glVertexArrayVertexBuffer(vao, bindingindex_a, vbo, 0, 2 * sizeof(float));
glVertexArrayVertexBuffer(vao, bindingindex_b, vbo, 18 * sizeof(float), 3 * sizeof(float));

Смещение в байтах x1 равно 0.
Смещение в байтах r1 равно 18 * sizeof(float).
Расстояние в байтовой форме x1 до x2 равно 2 * sizeof(float).
Расстояние в байтах от r1 до r2 равно 3 * sizeof(float).

...