Атрибуты вершины - использование 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 Vertex Specification говорят мне следующее:
Позиции [...] Для этого вы переставляете данные пространства модели так, чтобы все позиции были упакованы в поле [-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 с шортами?).
Работающий пример был бы великолепен, я не смог его найти.
2 ответа
Я настроил структуру данных для буфера вершин:
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% увеличение производительности.
Или я должен изменить свою полную структуру Vertex?
Да, OpenGL волшебным образом не сделает преобразование за вас. Но тогда, если производительность ваша цель...
Теперь я хочу повысить свою производительность, изменив атрибуты вершины с плавающей на короткую.
Это на самом деле повредит производительности. Графические процессоры оптимизированы для обработки векторов как значений с плавающей запятой. Это, в свою очередь, влияет на интерфейс памяти, который предназначен для обеспечения максимальной производительности при 32-битных выравниваемых доступах. Передавая 16-битное целое число, вы заставляете текущую линейку графических процессоров выполнять субоптимальный доступ к памяти и выполнять промежуточный шаг преобразования.
Если ваша цель - производительность, придерживайтесь одинарной точности. Если вы мне не верите: сравните это.