2012-01-21 5 views
7

기존 프로젝트를 업그레이드하기 위해 Modern OpenGL을 검색하고 읽은 후 OpenGL 2.1 기반 3D 프레임 워크부터 약간 혼란 스럽습니다. 그래서, 지금까지의 내가 배울현대 OpenGL : VBO, GLM 및 Matrix Stacks

...

우리는 정점, 인덱스, 법선, 색상, UV를에서 우리의 버텍스 버퍼 오브젝트를 생성해야
  • 다음 우리는 매트릭스 변환에 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를 사용하여 계층 적 변환을 할 수 있습니까?)

그렇다면 GLM 및 C++ < 스택> 라이브러리를 사용하여 pushMatrix/popMatrix와 동일한 결과를 얻는 방법은? 당신은 계층 적 변환을 필요로하는 경우

> 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
우리는 정점, 인덱스, 법선, 색상, UV를에서 우리의 버텍스 버퍼 오브젝트를 생성해야

정말 필요가 VBOs를 사용하지 않는 것, 클라이언트 측 버텍스 배열도 잘 작동합니다. 그러나 VBO를 사용하는 것이 강력하게 권장됩니다. 왜냐하면 드라이버의 수명을 길게하고 장기적으로 데이터를 저글링해야하기 때문입니다. 코드 오버 헤드는 무시할 수 있습니다 (텍스처 데이터를 생성하고 업로드하는 것과 거의 같습니다). 성능이 향상됩니다. 마지막으로 우리가 ...이 같은 GLSL 정점 셰이더에 모든 것을 통과

  • 는 우리는 매트릭스 변환을위한 GLM을 사용할 수 있으며, 우리는 메시를 만들거나 조작 할 VBO를 사용

당신에게 GLM에만 국한되지 않습니다. 모든 행렬 수학 라이브러리가 수행합니다. C99에서 사용할 수있는 무언가를 찾고 있다면 linmath.hhttps://github.com/datenwolf/linmath.h (아직도 불완전한) 내 머리글 파일을보고 static inline 기능을 사용하십시오.코드 중복이 성능에 부정적인 영향을 미치는 경우 (코드 크기가 L1 캐시 압력을 생성하는 경우) 아직 벤치마킹을하지 않았습니다.

질문 : 우리가 pushMatrix/popMatrix없이 계층 적 변환을 어떻게해야합니까? (아니면 VBO를 사용하여 계층 적 변환을 수행 할 수 있습니까?)

VBO는 이와 관련이 없습니다. 구식 OpenGL 문제를 겪는 대부분의 사용자에게주는 것은 행렬 스택 함수입니다. OpenGL이 장면 그래프처럼 보입니다. 그러나 그렇지 않습니다.

이전 OpenGL의 행렬 스택을 잊어 버린 경우 계층 적 tranformation을 수행하는 방법이 명확 해집니다. 계층 구조의 각 분기에서 변형 행렬의 복사본을 만들고 그 행렬을 연산합니다. 각 노드마다 대응하는 행렬이 저장되는 계층 적 트리 구조의 트리가 있습니다. 그런 다음이 행렬을 유니폼으로 버텍스 쉐이더에 전달합니다. 하나의 변형 만있는 강체를 그리는 경우 하나의 행렬을 사용합니다. 여러 행렬은 일반적으로 단지 당신이 행렬의 복사본을 만들고 하나에 작업 진행이 그러한 hierachy에 ->을 enounter이

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 

매번 같은 캐릭터의 골격 애니메이션과 같은 deformables을 위해 필요합니다. 트리의 더 높은 레벨로 떨어질 때 다시 그 행렬에서 작업을 시작합니다.

VAO 및 VBO 성능에 관련하여
+1

"얼굴 변형"// 이것 자체가 전체 장입니다 => 턱수염이 포함되어 있습니다 :) – mlvljr

4

예, 다음, 당신이 당신의 자신에 그것을 할 수 있습니다

내가 이런 걸 필요하다고 할 수 있습니다. 그러나 필요한 모든 것이 스택이라면 그것은 아주 사소한 것입니다. 스택의 마지막 항목을 가져다가 적용 할 다음 행렬에 곱하면됩니다. 결과를 스택에 푸시하면됩니다.

[편집 한 질문에 대한] : 스택을 필요로하지 않으며 계층 적 변환도 없습니다. 단일 행렬을 가지고 번역을 적용하고, 그리기, 회전 행렬에 곱하기, 그리기, 배율 조절, 그리기.

+1

? 초기 행렬 M과 변환 T, 회전 R 및 눈금 S가있는 경우 첫 번째 행렬은 M = T이고 두 번째 행렬은 M * = R = (T * R == 번역 첫 번째, 두 번째 회전)이고, 세 번째는 M * = S = (T * R * S == 모든 행렬입니다.) 로봇 팔의 경우, 맨 위에서 시작하여 트리를 따라 가면서 드로 콜을 호출 할 수 있습니다. "스택"이 std :: stack인지 또는 재귀 장면 순회 루틴의 일부인지는 중요하지 않습니다. – Anteru

+0

M * = S를 사용하지 않고 M * S (copy!)를 사용하면 원래의 행렬은 변경되지 않습니다. 스택은 다음과 같이 보일 것입니다 : [M], T (M [M, M]) 스택을 생성 한 다음 pop ([M])을 누른 다음 R ([M, M * R]). 너 문제 없어? – Anteru

+0

의견의 의미를 수정하는 것을 중지하십시오. 난 당신이 스택을 통해 그것을 구현할 수있다, 또는 당신은 그냥 (스택을 암시 적으로) 재귀 드로잉 함수 내에서 매트릭스를 복사 할 수 있습니다. [M, ..] _is stack_, 당신이 이것을 원한다면, 그냥 사용 . 그러나 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보다 적습니다. 하나의 버텍스 속성 만있는 경우에도 글로벌 VAO의 명시 적 업데이트보다 VAO 스위치가있는 OpenGL에 대한 호출 수가 절반입니다. 명백한 "더 적은 API 호출은 더 빠른 실행"관계를 의미하는 것 외에, VAO는 OpenGL 드라이버가 기본 GPU를 프로그래밍하는 데 필요한 정보를 숨길 수있는 장소입니다. GPU로 전송 된 상태 변화의 총량은 같은 방법입니다.

+0

이것은 어떻게 질문과 관련이 있습니까? –