CCSpriteBatchNode
aと法線の主な違いは、 aはスプライトごとにではなく、すべてのスプライトのすべてのデータを一度に GPU に送信するCCSprite
という事実です。CCSpriteBatchNode
CCSprite
ドローコールは次のように機能します。
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (void*) (offset + diff));
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (void*)(offset + diff));
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (void*)(offset + diff));
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
基本的に、スプライトのデータを設定するために 3 つの呼び出しが行われ、次に への呼び出しglDrawArrays
が行われます。100 個のスプライトがある場合、このコードは 100 回実行されます。
次に見てみましょうCCSpriteBatchNode
(別の可能な最適化である VAO なしの実装を選択しました):
glVertexAttribPointer(kCCVertexAttrib_Position, 3, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, vertices));
glVertexAttribPointer(kCCVertexAttrib_Color, 4, GL_UNSIGNED_BYTE, GL_TRUE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, colors));
glVertexAttribPointer(kCCVertexAttrib_TexCoords, 2, GL_FLOAT, GL_FALSE, kQuadSize, (GLvoid*) offsetof( ccV3F_C4B_T2F, texCoords));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffersVBO_[1]);
glDrawElements(GL_TRIANGLE_STRIP, (GLsizei) n*6, GL_UNSIGNED_SHORT, (GLvoid*) (start*6*sizeof(indices_[0])) );
このコードは、連続したメモリに格納されているため、すべてのスプライトのすべてのデータを一度に設定します。この呼び出しは、スプライトの数に関係なく、1、10、100 で同じです。
そのため、より効率的ですが、同時に、データがメモリに連続して格納されるため、子が削除、追加、または変更されると、それに応じて配列を変更し、GPU で更新する必要があります。これが、追加と削除のコストが発生する場所です (または、非表示の CCSprite はレンダリング フェーズをスキップするだけで、バッチ ノードの非表示の CCSprite はスキップしないという事実からも)。
個人的な経験から言えば、通常、コストはごくわずかであり、可能な場合は常に を使用する必要がありますCCSpriteBatchNode
(スプライトごとではなく、ノード全体をブレンドするなどの制限があるため)。同じ種類/理由の複数のスプライトを描画する。
ただし、自分でベンチマークするのは簡単なはずです。