2012-01-21 43 views
7

在搜索並閱讀關於Modern OpenGL以升級現有項目之後,我有點困惑,因爲我的基於OpenGL 2.1的3D框架。現代OpenGL:VBO,GLM和矩陣堆棧

所以,據我瞭解...

  • 我們需要生成頂點,索引,法線,顏色的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我們的頂點緩衝區對象等

它不是真的有必要用維也納組織,客戶端Vertex Arrays也可以工作。不過,強烈建議使用VBO,因爲它可以讓駕駛員的生活更輕鬆,並且從長遠來看也是您必須處理數據的人。代碼開銷是可以忽略的(它與生成和上傳紋理數據大致相同),性能只會增加。

  • 那麼我們可以使用GLM矩陣轉換的,而我們只用VBO來創建或操縱網格,最後我們通過萬事成GLSL頂點着色器這樣的...

你不限於GLM。任何矩陣數學庫都可以。如果您正在尋找可以在C99中使用的東西,請查看我的(尚未完成的)linmath.hhttps://github.com/datenwolf/linmath.h,它只是一個包含static inline函數的頭文件。如果代碼重複對性能有負面影響(代碼大小會產生L1緩存壓力),我還沒有進行基準測試。

問:我們如何分級的轉換,而不pushMatrix/popMatrix? (或者我們可以通過使用我們的維也納組織來進行等級轉換,有可能嗎?)

維也納國際中心與此無關。大多數老式OpenGL麻煩的用戶是那些矩陣堆棧函數,這使得OpenGL看起來有點像場景圖。但事實並非如此。

如果您忘記了舊的OpenGL的矩陣堆棧,就會明白如何進行層次轉換:在層次結構中的每個分支上創建一個轉換矩陣的副本並對其進行操作。你得到一個變換的分層樹,在每個節點存儲相應的矩陣。然後將這些矩陣作爲制服傳遞給頂點着色器;或者只是繪製一個只有一個轉換的剛體的矩陣。多個矩陣,你通常只需要像你一樣在這樣的層次結構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你做矩陣的副本,並繼續上一個工作。當你回到樹的更高層時,你再次從該矩陣開始工作。

+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(複製!),那麼原始矩陣不會改變。你的堆棧看起來像這樣:[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

至於VAO和VBO表現我不同意VBO是快,我建議看看這個鏈接

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

您可以從以上結果看,至少在我們的小樣本集,VAO在所有實施中速度更快。原因很簡單 - 調用glBindVertexArray時要驗證的參數比glBindBuffer或glVertexAttribPointer要少。即使只有一個頂點屬性,使用VAO開關調用OpenGL的次數也會少於顯式更新全局VAO的次數。除了「更少的API調用意味着更快的執行」關係之外,VAO還是OpenGL驅動程序可以存儲編程底層GPU所需信息的地方。發送到GPU的狀態更改總量也是相同的。

+0

這與這個問題有什麼關係? –