だから私は 2D スケルトン アニメーション システムで作業しています。
X 個のボーンがあり、各ボーンには少なくとも 1 つの部分 (四角形、2 つの三角形) があります。平均して、骨は 20 個ほど、パーツは 30 個あります。ほとんどのボーンは親に依存しており、ボーンはフレームごとに移動します。アニメーションごとに合計 1000 フレームまであり、約 50 のアニメーションを使用しています。一度に合計約 50,000 フレームがメモリにロードされます。パーツは、スケルトンのインスタンス間で異なります。
私が取った最初のアプローチは、各ボーンの位置/回転を計算し、各パーツに対してこれで構成される頂点配列を構築することでした:
[x1,y1,u1,v1],[x2,y2,u2,v2],[x3,y3,u3,v3],[x4,y4,u4,v4]
そして、これをフレームごとに glDrawElements に渡します。
これは見栄えがよく、必要なすべてのシナリオをカバーし、メモリをあまり使用しませんが、犬のように機能します。iPod 4 では、これらのスケルトンを 10 個レンダリングすると、おそらく 15 fps を得ることができます。
フレームごとに非常に多くの頂点データをコピーすることで、ほとんどのパフォーマンスが損なわれていることがわかりました。私は別の極端に行くことに決め、アニメーションを「事前計算」し、各キャラクターの開始時に頂点バッファーを構築しました。これには、単一のキャラクターのすべてのフレーム、すべてのパーツの xyuv 座標が含まれていました。次に、特定の時間に使用する必要があるフレームのインデックスを計算し、現在のフレームと次のフレームの XY 位置の間を補間するために使用されるシェーダーに渡されるデルタ値を計算します。
頂点はフレームごとにこのように見えました
[--------------------- Frame 1 ---------------------],[------- Frame 2 ------]
[x1,y1,u1,v1,boneIndex],[x2, ...],[x3, ...],[x4, ...],[x1, ...][x2, ...][....]
頂点シェーダーは次のようになります。
attribute vec4 a_position;
attribute vec4 a_nextPosition;
attribute vec2 a_texCoords;
attribute float a_boneIndex;
uniform mat4 u_projectionViewMatrix;
uniform float u_boneAlpha[255];
varying vec2 v_texCoords;
void main() {
float alpha = u_boneAlpha[int(a_boneIndex)];
vec4 position = mix(a_position, a_nextPosition, alpha);
gl_Position = u_projectionViewMatrix * position;
v_texCoords = a_texCoords;
}
現在、パフォーマンスは素晴らしく、これらの 10 個が画面に表示され、50 fps で快適に使用できます。しかし今では、1 トンのメモリを使用しています。現在は ushort になっている xyuv の精度をいくらか落とすことで、これを最適化しました。
ボーン依存性が失われるという問題もあります。親と子の 2 つのボーンがあり、子のキーフレームが 0 秒と 2 秒で、親のキーフレームが 0 秒、0.5 秒、1.5 秒、2 秒の場合、子は 0.5 秒と 2 秒の間で変更されません。 1.5秒です。
私は、この骨の問題を解決する解決策を思いつきました。つまり、子に親と同じポイントにキーフレームを持たせることです。しかし、これはさらに多くのメモリを使用し、基本的にボーン階層のポイントを殺します。
これが私が今いるところです。パフォーマンスとメモリ使用量のバランスを見つけようとしています。ここには冗長な情報がたくさんあることはわかっています (特定のパーツのすべてのフレームで UV 座標が同一であるため、約 30 回繰り返されます)。また、パーツのセットごとに新しいバッファーを作成する必要があります (一意の XYUV 座標を持ちます。パーツによってサイズが異なるため、位置が変わります)。
現時点では、キャラクターごとに 1 つの頂点配列を設定して、すべてのパーツの xyuv を設定し、各パーツのマトリックスを計算して、シェーダーで再配置してみます。これが機能することはわかっていますが、最初に行っていた各フレームの XYUV をアップロードするよりもパフォーマンスが良くならないのではないかと心配しています。
得たパフォーマンスを失わずにこれを行うより良い方法はありますか?
私が試すことができるワイルドなアイデアはありますか?