複数の行列を頂点シェーダーに送信するにはどうすればよいですか?


9

ボーン/スキニングを使ったアニメーションを練習しています。頂点ごとに1つのマトリックスをシェーダーに送信しようとしています。私はこれら2つのアプローチを考えることができます。

方法1

このように各骨マトリックスに1つの均一なハンドルがあります

u_Bone0 = GLES20.glGetUniformLocation(mProgram, "u_Bone[0]");
u_Bone1 = GLES20.glGetUniformLocation(mProgram, "u_Bone[1]");

そして、onDraw私はそれらのそれぞれをシェーダーに送ります: GLES20.glUniformMatrix4fv(u_Bone0, 1, false, matrix0, 0);

マトリックスが多数ある場合、これは明らかに良い方法ではありません。リファクタリングするコードがたくさんあるのでまだ試していない私の2番目のアイデア

方法2

を使用しglUniformMatrix4fvてそれらを一度にすべて送信することです(20個の行列があると仮定します)

GLES20.glUniformMatrix4fv(u_Bones, 20, false, matrices, 0);

はどこmatricesですかfloat[16 * 20]。ただし、各ボーンのマトリックスを変更するのは少し面倒になります。たとえば、3番目の行列を取得する場合、次の行に沿って何かが必要です。

float[] _3rd = Arrays.copy(matrices, 3*16, 4*16);

値を保存すると、さらに煩わしくなります。


私は現在方法1を使用していますが、あまりスマートに見えません...

複数のマトリックスをOpenGL ES 2シェーダーに送信する最良の方法は何ですか?

LE:私はAndroidを使用しているので、Javaソリューションを探しています。


余談ですが、行列が多すぎる場合は、fpテクスチャ経由で送信することもできます。
クロムスター

回答:


2

複数の行列をシェーダーに送信するのは簡単です。

シェーダー:

uniform mat4 mBones[20]; //20 matrices
.. skipped code ..
vec4 vert = vec4(vPosition, 1.0) * mBones[int(vaBoneId)];

プログラム:

glUniformMatrix4fv(fShaderUnitSkeletal.uBones, 20, False, @bones20[0]); // Passing 20 matrices

ただし、各ボーンのマトリックスの変更は、それらをシェーダーに渡す方法とは関係ありません。数値の配列の代わりに構造体を使用する場合は、変更をより簡単にすることができます。

bones20: array of TMatrix; // Declare array of matrices
bones20[2] := TMatrix.Identity; //Reset 3rd matrix

1
Android / Javaを使用しています。したがって、「構造」やその他のデータ型を使用することはできません(簡単なコメントのため申し訳ありませんが、ATMについて詳しく説明することはできませんが、後で戻ってきます)
非同期14

2

VBOの使用をお勧めします。VBOに行列を入力し、ユニフォームではなく属性を使用して渡します。このようにして、VBOは、シェーダーで頂点パスごとに新しいmat4を配布します。

描画する前にVBOをバインドする場合(またはこれらの状態のVAOを作成する場合):

  • 頂点属性を有効にする(glEnableVertexAttribArray)
  • 頂点属性の除数を0に設定します(glVertexAttribDivisor)
  • 頂点属性ポインターを設定する(glVertexAttribPointer)

属性としてmat4を渡す方法を見てくださいhttps ://stackoverflow.com/questions/17355051/using-a-matrix-as-vertex-attribute-in-opengl3-core-profile

お役に立てれば


1
面白い。ただし、マトリックスは非常に頻繁に変更される可能性があります(たとえば、フレームごとに1つの回転を追加する場合があります)。彼らは同じままではありません。VBOはこのシナリオに適していますか?
非同期の2014年

はい、glBufferDataを使用してフレームごとに新しいマトリックスをアップロードするだけです
Luka

0

メソッド1は、配列を使用してコード内の行列の数を抽象化するように拡張できます(javaを想定)。

int[] u_Bone=new int[NUM_MATRICES];

for(int i=0;i<u_Bone.length;i++)
   u_Bone[i]=GLES20.glGetUniformLocation(mProgram, "u_Bone["+i+"]");

行列を設定すると、次のことができます

for(int i=0;i<matrix.length;i++)
    GLES20.glUniformMatrix4fv(u_Bone[i], 1, false, matrix[i], 0);

私はこれを実装することになったが、それでもそれほど改善されていない。しかし、これまでのところ、それが最善のアプローチである可能性があります。
非同期2014
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.