3

OpenGL ES を使用して 2D ゲームでスプライトのレンダリングを最適化する作業を行っていますが、GLSL と頂点シェーダーに関する知識の限界に達しました。

単一の glDrawArrays 呼び出しを実行するために、複数のスプライト用に頂点座標とテクスチャ座標 (最終的にはこれが 1 つのバッファーになります) を含む 2 つの大きな float バッファーがあります。これは機能しますが、変換マトリックスを頂点シェーダーに渡すときに問題が発生しました。

私のシェーダーコードは次のとおりです。

uniform mat4 u_MVPMatrix; 
attribute vec4 a_Position;      
attribute vec2 a_TexCoordinate; 
varying vec2 v_TexCoordinate; 

void main()
{
    v_TexCoordinate = a_TexCoordinate;
    gl_Position = u_MVPMatrix * a_Position;
}

Java (Android) では、頂点/テクスチャ データを格納するために FloatBuffer を使用しています。これは次のようにシェーダーに提供されます。

mGlEs20.glVertexAttribPointer(mVertexHandle, Globals.GL_POSITION_VERTEX_COUNT, GLES20.GL_FLOAT, false, 0, mVertexCoordinates);   
mGlEs20.glVertexAttribPointer(mTextureCoordinateHandle, Globals.GL_TEXTURE_VERTEX_COUNT, GLES20.GL_FLOAT, false, 0, mTextureCoordinates);

(Globals.GL_POSITION_VERTEX_COUNT などは現在、値が 2 の単なる整数です)

そして、次のように MVP (モデル/ビュー/プロジェクション) マトリックス バッファーを渡しています。

GLES20.glUniformMatrix4fv(mMVPMatrixHandle, 1, false, mModelCoordinates); 

(mModelCoordinates は、各スプライトの MVP マトリックスを表す 16 個の float シーケンスを含む FloatBuffer です)

これでシーンがレンダリングされますが、すべてのスプライトが同じ変換を共有するため、2 番目のパラメーターとして "1" を渡しているため、バッファから最初の 16 要素のみを選択することは明らかです。このメソッドのドキュメントには次のように書かれています。

「対象となる均一変数が行列の配列でない場合、これは 1 であり、行列の配列である場合は 1 以上である必要があります。」

そこで、ほとんどのシナリオに対応するのに十分な大きさの固定サイズの配列でシェーダーを変更してみました。

uniform mat4 u_MVPMatrix[1000];

しかし、これによりシェーダーでエラーが発生します。

「float の 4X4 行列の一様配列」から「float の位置 4 成分ベクトル」に変換できません

とにかく、シェーダーがいつ次のマトリックスに移行するかを知る方法がはっきりしないので、これはとにかく間違っているようです。

シェーダーが遭遇する 4 つの頂点ごとに、MVP バッファーから異なる MVP マトリックス (つまり、NEXT 16 フロート) を取得する方法を知っている人はいますか? (私は GL_TRIANGLE_STRIP を使用しているので、各スプライトには 4 つの頂点があります)。

ありがとう!

4

1 に答える 1

0

一度にレンダリングするスプライトの数は? スプライトアトラスを使用していますか? 一般的に言えば、変換マトリックスを設定し、スプライトを一度に 1 つずつ描画するのが最もクリーンな方法です。それが大幅な速度低下を引き起こしている場合は、多くのスプライトを描画しています。

通常、状況に応じてユニフォーム バッファ オブジェクトをお勧めしますが、OpenGL ES がそれをサポートしていることを示唆するドキュメントは見つかりません。

変換の性質は何ですか? 他のデータを使用して行列を推測できる場合があります。たとえば、単純な変換を行うと、スプライトの頂点データとともに渡すことができます。

于 2012-10-31T16:15:24.783 に答える