Атрибуты вершины — использование short вместо float для позиций вершин

В настоящее время у меня есть следующие настройки, которые работают хорошо на данный момент.

struct Vertex {
glm::vec3 position;
glm::vec3 normal;
glm::vec2 texCoord;
}
std::vector<Vertex> vertices;

Атрибуты вершин:

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, Vertex::position));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, Vertex::normal));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), (void*) offsetof(Vertex, Vertex::texCoord));

Теперь я хочу повысить свою производительность, изменив атрибуты вершины с плавающей на короткую.
Я пытался начать с позиций вершин.

Рекомендации OpenGL по спецификациям вершин говорит мне это:

позиции […] Для этого вы переставляете данные пространства модели так, чтобы все позиции были упакованы в поле [-1, 1] вокруг начала координат. Вы делаете это, находя минимальные / максимальные значения в XYZ среди всех позиций. Затем вы вычитаете центральную точку поля min / max из всех положений вершин; с последующим масштабированием всех позиций на половину ширины / высоты / глубины поля min / max. Вы должны держать центральную точку и коэффициенты масштабирования вокруг.
Когда вы строите матрицу модели для просмотра (или матрицу для модели), вам необходимо применить смещение центральной точки и масштаб в верхней части стека преобразования (так в конце, прямо перед рисованием).

Я тоже это читаю Нить.

Вот почему я добавил этот шаг предварительной обработки, отображающий все вершины в [-1,1]

for (auto& v : vertices) {
v.position = (v.position - center) * halfAxisLengths;
}

и вызвать его в вершинный шейдер

vec4 rescaledPos = vec4(in_pos, 1.0) * vec4(halfAxisLengths, 1.0) + vec4(center, 0.0);
gl_Position = P * V * M * rescaledPos;

Мой атрибут вершины, используя GL_SHORT вместо GL_FLOATи нормализовать установить на GL_TRUE:

glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_SHORT, GL_TRUE, sizeof(Vertex), (void*) offsetof(Vertex, Vertex::position));

В результате я просто получаю хаос из треугольников, но не мою модель с увеличенным fps.

Это правильный способ установить атрибуты вершины на короткий?

Или я должен изменить свою полную структуру Vertex?
Если да, каков наилучший способ сделать это (векторы glm с шортами?).

Работающий пример был бы великолепен, я не смог его найти.

0

Решение

Я настроил структуру данных для буфера вершин:

struct newVertex {
GLshort position[4]; // for GL_SHORT
GLint normal; // for GL_INT_2_10_10_10_REV
GLshort texCoord[2]; // for GL_SHORT
};

В результате я получаю ~ 20% увеличение производительности.

1

Другие решения

Или я должен изменить свою полную структуру Vertex?

Да, OpenGL волшебным образом не сделает преобразование за вас. Но тогда, если производительность ваша цель …

Теперь я хочу повысить свою производительность, изменив атрибуты вершины с плавающей на короткую.

Это на самом деле повредит производительности. Графические процессоры оптимизированы для обработки векторов как значений с плавающей запятой. Это, в свою очередь, влияет на интерфейс памяти, который предназначен для обеспечения максимальной производительности при 32-битных выравниваемых доступах. Передавая 16-битное целое число, вы заставляете текущую линейку графических процессоров выполнять неоптимальный доступ к памяти и промежуточный шаг преобразования.

Если ваша цель — производительность, придерживайтесь одинарной точности. Если вы мне не верите: сравните это.

0

По вопросам рекламы [email protected]