OpenGL: Пакетный визуализатор: Должны ли преобразования выполняться на процессоре или графическом процессоре?

0

Вопрос

Я разрабатываю 2D-игровой движок, который в будущем будет поддерживать 3D. На данном этапе разработки я работаю над средством пакетной визуализации. Как некоторые из вас, возможно, знают, при объединении графики в пакеты единая поддержка цвета (RGBA), координаты текстуры, идентификатор текстуры (индекс текстуры) и матрица преобразования модели выходят из окна, но вместо этого передаются через буфер вершин. Прямо сейчас я реализовал передачу позиций модели, цвета, координат текстуры и идентификатора текстуры в буфер вершин. Мой формат буфера вершин прямо сейчас выглядит так:

float* v0 = {x, y, r, g, b, a, u, v, textureID};
float* v1 = {x, y, r, g, b, a, u, v, textureID};
float* v2 = {x, y, r, g, b, a, u, v, textureID};
float* v3 = {x, y, r, g, b, a, u, v, textureID};

Я собираюсь интегрировать вычисление того, где объект должен находиться в мировом пространстве, используя матрицу преобразования. Это заставляет меня задать вопрос:

Должна ли матрица преобразования быть умножена на позиции вершин модели на процессоре или графическом процессоре?

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

Вот как будет выглядеть мой формат буфера вершин, если я вычислю преобразование на графическом процессоре:

float* v0 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v1 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v2 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};
float* v3 = {x, y, r, g, b, a, u, v, textureID, m0, m1, m2, m3, m4, m5, m6, m7, m8, m9, m10, m11, m12, m13, m14, m15};

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

c++ glm-math glsl opengl
2021-11-24 03:43:20
2

Лучший ответ

1

Должны ли преобразования происходить на процессоре или графическом процессоре?

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

Какова бы ни была причина, если вы решите применить преобразования на графическом процессоре, есть лучшие способы сделать это, кроме дублирования матрицы для каждой вершины. Вместо этого я бы поместил матрицы преобразований в SSBO:

layout(std430, binding=0) buffer Models {
    mat4 MV[]; // model-view matrices
};

и храните один индекс в каждой вершине в VAO:

struct Vert {
    float x, y, r, g, b, a, u, v;
    int textureID, model;
};

Вершинный шейдер может перейти и получить полную матрицу на основе атрибута индекса:

layout(location = 0) in vec4 in_pos;
layout(location = 1) in int in_model;
void main() {
    gl_Position = MV[in_model] * in_pos;
}

Вы даже можете объединить его с другими атрибутами для каждого объекта, такими как textureID.

ИЗМЕНИТЬ: вы можете добиться чего-то подобного с помощью создания экземпляров и многократного рисования. Хотя, скорее всего, это будет медленнее.

2021-11-24 17:20:51

Можете ли вы подробнее рассказать о том, какой именно будет модель? Я пытаюсь реализовать это и получаю только один спрайт на экране и думаю, что это потому, что я отправляю неверную информацию.
Christopher Barrios Agosto

@ChristopherBarriosAgosto индекс матрицы модели в массиве MV: 0, 1, 2 и т. Д.
Yakov Galka

Поскольку вы визуализируете индивидуально преобразованные квадроциклы, это будет 0,0,0,0,1,1,1,1,2,2,2,2,... если вы визуализируете с помощью glDrawElements.
Yakov Galka

Я все понял! Теперь все работает! Оказывается, я правильно передавал и интерпретировал индексы, но я передавал индекс в виде поплавка в GLSL, когда он ожидал int. Я заставил его получить поплавок и в GLSL привести его к int, а не к правильной интерпретации всех индексов. Я должен сделать это таким образом, потому что буфер вершин имеет тип float. Спасибо вам за все!
Christopher Barrios Agosto

@ChristopherBarriosAgosto: Поздравляю, что вы это поняли. "буфер вершин имеет тип с плавающей точкой" - буферы вершин представляют собой последовательности байтов. Вы можете хранить structs там с некоторыми int поля и некоторые float поля.
Yakov Galka
0

Я не уверен, как на самом деле выглядит ваш код движка, но я предполагаю, что он похож на любую другую программу OpenGL.

Если это так, то, по моему опыту, матрицу преобразования обычно следует передавать в вершинный шейдер и применять с заданной информацией о вершинах на графическом процессоре при рисовании сцены. Например:

//MVP matrix
GLuint MatrixID = glGetUniformLocation(shaderProgID, "MVP");
glUniformMatrix4fv(MatrixID, 1, GL_FALSE, &mvp[0][0]);

Но если вы хотите найти мировые координаты для всех вершин для определенной группы вне функции рендеринга, вам, вероятно, потребуется сделать это на процессоре, или вам потребуется использовать некоторые методы параллельного программирования, такие как OpenCL, для выполнения работы на GPU.

Самое главное, почему именно вам нужна информация о мировых координатах вне процедуры рисования? Если вы просто хотите найти мировые координаты модели, вы можете просто установить центральную координату для каждой модели, которая у вас есть в сцене, и отслеживать только эту единственную координату, а не всю группу сеток.

Информация о вершинах всегда должна быть в координатах модели и храниться в буфере вершин без прикосновения, если только вы не хотите применить к ним какие-либо изменения.

2021-11-24 03:57:24

Я собираю несколько графиков вместе. Поэтому я не могу использовать униформу для передачи преобразований графики, потому что я не смогу изменить униформу для преобразования между вызовами рисования. Тем не менее, я считаю, что использование SSBOs-очень хорошая альтернатива.
Christopher Barrios Agosto

На других языках

Эта страница на других языках

Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
ไทย
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................