疑問
glTF 2.0 のアクセサ(accessor
)とバッファビュー(bufferView
)の違いがよく分からなかった。
バッファビューはバッファの特定範囲を示すもので、アクセサはバッファビューの特定範囲のデータ型を示すもの。
それなら、例えば、バッファビューの持つ情報を全部アクセサに持たせて、アクセサがバッファの特定範囲を直接参照するようにすれば、バッファビューは不要になるんじゃないか?
glTF 2.0 の公式の仕様書とチュートリアルはひと通り読んだが、アクセサとバッファビューが別々に存在するその辺りの理由は分からなかった。もしかしたら glTF のコミュニティでも議論が行われていたかもしれないが、さすがにコミュニティ上の全記事を探して読む気にはなれない。
ということで、自分で考えてみた。
考察
まず、バッファのデータは、適切なタイミングで適切な量をグラフィックメモリに転送する必要がある。具体的には、メッシュを描画する際に、アクセサが(バッファビューを介して間接的に)参照するバッファデータをグラフィックメモリに転送する必要がある。
では、1 つのメッシュを描画するために、どの範囲のデータを GPU に転送すれば良いのか。
バッファビューがない場合には、まずメッシュの持つプリミティブをすべて走査し、プリミティブのターゲットが使用するアクセサを寄せ集め、それらのアクセサが指示する範囲をすべて包含できる最小の転送範囲をいくつか決定する。
しかし、メッシュを描画するたびに最小転送範囲を計算するくらいなら、それを最初から定義して glTF に持たせておけば良い。 それぞれの最小転送範囲は glTF ファイルの完成時には静的に定まるものだし、同一メッシュ内のアクセサの示すデータを近くに寄せ集めるなど、うまく設計すれば最小転送範囲を小さく効率よくまとめることができる。
これが、アクセサとは別にバッファビューが存在する理由のひとつなのかと思う。
結論
メッシュを描画する際に、まず必要となる(1~数個程度の)バッファビューのデータをグラフィックメモリに転送する。
そして、アクセサの情報はシェーダーに渡し、シェーダーがグラフィックメモリ内のデータを個別にアクセスする。
つまり、
- バッファビューはグラフィックメモリへのブロック転送用
- アクセサはシェーダーでのアクセス用
ということで、自分の中では落ち着いた。
もちろん、glTF の仕様書にはここまでの言及はないので、アクセサを転送の単位として使ったりするような自由な設計も許されるはずだとは思う。