2012-01-21 2 views
7

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

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

  • Мы должны генерировать наши Vertex-буфера объектов из вершин, индексов, нормалей, цветов, УВС и т.д.

  • затем мы можем использовать 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? (или, возможно, мы делаем иерархическое преобразование, используя наши VBOs, возможно ли это?)

Если это невозможно, то как достичь такого же результата, как pushMatrix/popMatrix, используя GLM и C++ < stack> library?

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

> 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 
+1

@ BЈовић: [OpenGL Mathematics (GLM)] (http://glm.g-truc.net/), только для C++ библиотеки для матричной/векторной математики. – genpfault

ответ

5
  • Мы должны генерировать наши Vertex-буфера объектов из вершин, индексов, нормалей, цветов, УВС и т.д.

Это на самом деле не нужно использовать РВО, Вершинные массивы на стороне клиента тоже работают. Однако настоятельно рекомендуется использовать VBO, потому что это облегчает жизнь водителю и, в конечном счете, также и ваш, который должен манипулировать данными. Накладные расходы кода не учитываются (это примерно так же, как генерация и загрузка данных текстур), и производительность будет только возрастать.

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

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

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

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

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

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 

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

+1

«лицевая деформация» // это целая глава собственного => включает в себя челюсть: – mlvljr

4

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

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

+1

Er? Если у вас есть начальная матрица M и трансляция T, вращение R и шкала S, то ваша первая матрица равна M = T, вторая - M * = R = (T * R == перевод сначала, второе вращение), а третья - M * = S = (T * R * S == все матрицы.) Для руки робота вы можете так же начинать вверху и вызывать призывы к вызову, идя вниз по вашему дереву. Не имеет значения, является ли «стек» std :: stack или просто частью вашей рекурсивной процедуры обхода сцены. – Anteru

+0

Если вы не делаете M * = S, но просто используйте M * S (копировать!), Тогда исходная матрица не изменяется. Ваш стек будет выглядеть так: [M], затем вы нажимаете T (в результате получается стек [M, M * T]), затем вы поп ([M]), затем снова нажимаете R ([M, M * R]). У меня нет твоей проблемы? – Anteru

+0

Прекратите изменять значение ваших комментариев. Я сказал, что вы можете реализовать его через стек или просто скопировать свои матрицы внутри своей рекурсивной функции рисования (которая неявно создает стек.) [M, ..] _ является стеком_, если вы этого хотите, просто используйте его , Но вы можете легко уйти без какого-либо std :: stack. – Anteru

4

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

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); 
0

В связи с ВАО и VBO производительности я не согласен, что ВБО быстрее, я предлагаю, чтобы увидеть эту ссылку

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

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

+0

Как это связано с вопросом? –