Современный OpenGL: стеки VBO, GLM и Matrix - PullRequest
7 голосов
/ 21 января 2012

После поиска и чтения о Modern OpenGL, чтобы обновить существующий проект, я немного запутался, поскольку мой 3D-фреймворк основан на OpenGL 2.1.

так что, насколько я узнаю ...

  • Нам нужно сгенерировать наши объекты Vertex-Buffer-Objects из вершин, индексов, нормалей, цветов, uvs и т. Д.

  • тогда мы можемиспользовать GLM для преобразования матрицы, и мы используем только VBO для создания или манипулирования сетками, наконец, мы передаем все в вершинный шейдер GLSL, как это ...

    glm::mat4 MVP = projection * view * model;
    glUniformMatrix4fv(glGetUniformLocation(shaderProgramID, "MVP"), 1, GL_FALSE, glm::value_ptr(MVP)); //or &MVP[0][0]
    
    // uniform mat4 MVP;
    // in vec3 Vertex;
    // void main(void)
    // {
    //    gl_Position = MVP * vec4(Vertex, 1.0); //instead of ftransform();
    // }
    

ВОПРОС: Как мы делаемиерархические преобразования без pushMatrix / popMatrix?(или, может быть, мы делаем иерархическое преобразование, используя наши VBO, это возможно?)

Если это невозможно, то как достичь того же результата, что и pushMatrix / popMatrix, с помощью библиотек GLM и C ++ ?

Допустим, мне нужно что-то вроде этого:

> Set identity
> Translate to X, Y, Z
> Draw Mesh 1
> Rotate 0.5 by X axis
> Draw Mesh 2
> Scale down to 0.1
> Draw Mesh 3

Ответы [ 4 ]

5 голосов
/ 21 января 2012
  • Нам нужно сгенерировать наши Vertex-Buffer-Objects из вершин, индексов, нормалей, цветов, uvs и т. Д.

Нет необходимости использовать VBO, клиентские Vertex Arrays также работают. Тем не менее, настоятельно рекомендуется использовать VBO, потому что это облегчает жизнь водителю, и в конечном итоге вы как тот, кто должен манипулировать данными. Затраты кода незначительны (это примерно то же самое, что генерирование и загрузка текстурных данных), и производительность будет только увеличиваться.

  • тогда мы можем использовать GLM для преобразования матрицы, и мы используем только VBO для создания или манипулирования сетками, наконец, мы передаем все в вершинный шейдер GLSL, как это ...

Вы не ограничены GLM. Подойдет любая матричная математическая библиотека. Если вы ищете что-то, что вы можете использовать в C99, взгляните на мой (все еще не полный) linmath.h https://github.com/datenwolf/linmath.h, который является просто файлом заголовка с функциями static inline. Я пока не тестировал, если дублирование кода отрицательно влияет на производительность (размер кода создает нагрузку на кэш-память первого уровня).

ВОПРОС: Как мы выполняем иерархические преобразования без pushMatrix / popMatrix? (или, может быть, мы делаем иерархическое преобразование, используя наши VBO, это возможно?)

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

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

worldtransform -> 
    pelvis ->
        left upper leg -> left lower leg -> left foot
        right upper leg -> right lower leg -> right foot
    torso ->
        neck -> head ->
             left eye
             right eye
             facial deformation // this is a whole chapter of it's own
        left upper arm -> left lower arm -> left hand
        right upper arm -> right lower arm -> right hand

Каждый раз, когда вы вводите -> в такой иерархии, вы делаете копию матрицы и продолжаете работать над ней. Возвращаясь к более высокому уровню дерева, вы снова начинаете работать с этой матрицей.

4 голосов
/ 21 января 2012

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

void renderMesh(Matrix transform, Mesh mesh)
{
    // here call glDrawElements/glDrawArrays and send transform matrix to MVP uniform
    mesh->draw(transform);

    // now render all the sub-meshes, then will be transformed relative to current mesh
    for (int i=0; i<mesh->subMeshCount(); i++)
    {
        Matrix subMeshTransform = mesh->getSubMeshTransform(i);
        Mesh subMesh = mesh->getSubMesh();

        renderMesh(subMeshTransform * transform, subMesh);
    }
}

// somwhere in main function
...
Matrix projection = Matrix::perspective(...);
Matrix view = camera->getViewMatrix();

Matrix transform = view * projectIon;
renderMesh(transform, rootMesh);
4 голосов
/ 21 января 2012

Да, если вам нужны иерархические преобразования, то вы должны сделать это самостоятельно.Однако это довольно тривиально, если все, что вам нужно, это стек.Просто возьмите последнюю запись в стеке и умножьте ее на следующую матрицу, которую вы хотите применить, и поместите результат в стек.

[По вашему отредактированному вопросу]: Вам вообще не нужен стекдля этого, и нет никакой иерархической трансформации.Просто создайте одну матрицу и примените свой перевод, нарисуйте, умножьте его на свою матрицу вращения, нарисуйте, умножьте масштабирование, нарисуйте.

0 голосов
/ 09 мая 2014

Что касается производительности VAO и VBO, я не согласен с тем, что VBO быстрее, я предлагаю посмотреть эту ссылку

http://www.openglsuperbible.com/2013/12/09/vertex-array-performance/

Из приведенных выше результатов видно, что, по крайней мере для нашего небольшого набора выборок, VAO быстрее во всех реализациях. Разумеется, при вызове glBindVertexArray меньше параметров для проверки, чем в glBindBuffer или glVertexAttribPointer. Даже когда имеется только один атрибут вершины, в OpenGL с переключателем VAO вдвое меньше вызовов, чем с явным обновлением глобальной VAO. Помимо очевидного отношения «меньше вызовов API означает более быстрое выполнение», VAO - это место, где драйвер OpenGL может хранить информацию, необходимую для программирования базового графического процессора. Общее количество изменений состояния, отправленных на графический процессор, одинаково.

...