2012-01-21 8 views
7

私の既存のプロジェクトをアップグレードするためにModern OpenGLについて検索して読んだら、私の3DフレームワークはOpenGL 2.1に基づいているので、ちょっと混乱します。そう、私の知る限り学ぶよう最新の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
  • 私たちは、それがVBOsを使用することが本当に必要はありません

などの頂点、インデックス、法線、色、UVが、から私たちの頂点バッファ・オブジェクトを生成する必要がありますクライアント側の頂点配列も同様に機能します。しかし、VBOを使用することを強くお勧めします。これは、ドライバの寿命を長くし、長期間に渡ってデータをやりとりする必要があるためです。コードオーバーヘッドは無視できます(テクスチャデータの生成とアップロードとほぼ同じです)。パフォーマンスは向上します。

  • その後、我々はマトリックス変換にGLMを使用することができ、我々は唯一のメッシュを作成したり、操作するためVBOを使用し、最終的に我々はこのようなGLSLの頂点シェーダにすべてを渡す...

あなたはGLMに限定されません。任意の行列数学ライブラリが行います。 C99で使うことができるものを探しているなら、linmath.hhttps://github.com/datenwolf/linmath.hという私の(まだ不完全な)ものを見てください。これはただのヘッダファイルで、static inlineの機能を持っています。コードの重複がパフォーマンスに悪影響を及ぼしている(コードサイズによってL1キャッシュ圧が発生する)場合は、まだベンチマークを行っていません。

QUESTION:我々はpushMatrix/popMatrixずに階層的な変換を行う方法は? VBOを使用して階層的な変換を行うことも可能ですか?

VBOはこれとは関係ありません。旧式のOpenGLの問題を抱えているほとんどのユーザーには、OpenGLがシーングラフのように見えるマトリックススタック関数があります。そうではありません。

古いOpenGLの行列スタックを忘れてしまった場合、階層的な変換を行う方法が明らかになります。階層の各枝で変換行列のコピーを作成し、それを操作します。変換の階層ツリーが得られ、各ノードに対応する行列が格納されます。次に、それらの行列を頂点シェーダにユニフォームとして渡します。 1つの変換のみを持つ剛体オブジェクトを描画している場合は、1つの行列だけです。複数の行列は、あなたが正常にのみ、このような文字の骨格アニメーションのような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 

のためにあなたは行列のコピーを作成し、その1つの上で作業進まなhierachyに->をenounter毎回必要です。より高いレベルのツリーに落ちると、その行列から再び作業を開始します。 VAOとVBOパフォーマンスに関しては

+1

"顔の変形" //これは自分の全体の章です =>顎の落ち込みを含みます:) – mlvljr

4

をあなたは、階層的な変換が必要な場合は、[はい、あなたは自分でそれをしなければなりません。しかし、必要なものがスタックであれば、それはかなり簡単です。スタックの最後のエントリを取得し、それを適用する次の行列に掛けて、結果をスタックにプッシュします。

[編集した質問について]:スタックを一切必要とせず、階層的な変換もありません。ただ1つの行列を持ち、あなたの翻訳を適用し、描画し、回転行列でそれを掛け、描画し、スケーリングを掛けて、描画します。

+1

?あなたが初期行列Mと並進T、回転R、およびスケールSを持っていれば、最初の行列はM = Tで、2番目の行列はM * = R =(T * R ==平行移動、 )、3番目はM * = S =(T * R * S ==すべての行列)です。ロボットアームの場合は、上から開始し、ツリーを下っている間にドローコールを発行できます。 "スタック"がstd :: stackか再帰的シーントラバーサルルーチンの一部かどうかは関係ありません。 – Anteru

+0

M * = SではなくM * S(copy!)を使用すると元の行列は変更されません。あなたのスタックは次のようになります:[M]、Tを押すと(スタック[M、M * T])、ポップ([M])した後、R([M、M * R] )。あなたの問題はありませんか? – Anteru

+0

コメントの意味の編集を停止します。私はあなたがスタックを介してそれを実装することができますか、または(スタックを暗黙的に作成する)再帰的な描画関数の中であなたの行列をコピーすることができると言った。[M、..] _isスタック_ 。しかし、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よりも検証するパラメータが少なくなります。頂点属性が1つしかない場合でも、グローバルVAOの明示的な更新よりも、VAOスイッチ付きのOpenGLへの呼び出しが半分になります。明白な「より少ないAPI呼び出しはより速い実行を意味する」関係に加えて、VAOは、OpenGLドライバが基礎となるGPUをプログラムするために必要な情報を隠すことができる場所です。 GPUに送信される州の変更の総量はいずれの場合も同じです。

+0

これはどのように質問に関連していますか? –