OpenGLES の頂点データは各頂点要素毎の配列を登録します。
頂点座標や法線など、頂点の構成要素は Direct3D では element、OpenGL では
attribute と呼ばれているようです。
glVertexAttribPointer( vloc, 3, GL_FLOAT, GL_FALSE, sizeof(vec3), v_data ); glVertexAttribPointer( nloc, 3, GL_FLOAT, GL_FALSE, sizeof(vec3), n_data ); glVertexAttribPointer( tloc, 2, GL_FLOAT, GL_FALSE, sizeof(vec2), t_data );
Direct3D の場合は基本的にパックされた頂点データを用います。
いわゆる AOS で、対する OpenGL はベクター単位の SOA になります。
とはいえ実際には Direct3D でも複数の頂点ストリームを与えることが出来るので、
OpenGL のように要素毎に配列を分離することが可能です。
また OpenGL の場合も index は共有なので頂点の位置や配列の大きさも同数です。
stride を指定すれば、Direct3D のようなパックした頂点データのポインタを登録
することができます。
どちらも出来ることや使い方にほとんど差が無くなっています。
struct vtype { float x, y, z; float nx, ny, nz; float tu, tv; }; glVertexAttribPointer( vloc, 3, GL_FLOAT, GL_FALSE, sizeof(vtype), &vp->x ); glVertexAttribPointer( nloc, 3, GL_FLOAT, GL_FALSE, sizeof(vtype), &vp->nx ); glVertexAttribPointer( cloc, 2, GL_FLOAT, GL_FALSE, sizeof(vtype), &vp->tu );
普段 Direct3D 向けにデータを出力している関係上、座標系と同じように D3D と同じ
データが使えれば楽出来ます。
問題はどちらが効率がよいのかと言うこと。
D3D 形式の頂点の持ち方で速度が落ちないかどうかが心配な点です。
キャッシュの利用効率を考えると、一見インターリーブされた D3D タイプの方が
良さそうに見えます。
一度にアクセスするであろうデータが適切な局所性を持つからです。
頂点は index によるランダムアクセスになる可能性があるので、SOA の配列の効率が
必ずしも最善とは限りません。でも GPU は 1頂点分まとめてデータを読み込む
ことがわかっているので、一カ所に集まっていた方がキャッシュを活用できます。
以前そう考えて最適化のつもりで試したものの、逆に遅くなってしまうハードウエア
がありました。インデックスも個別に持てたので、頂点ストリーム毎にキャッシュを
持つなどの特殊な仕組みだったのかもしれません。もしそうなら D3D タイプの
インターリーブは同じデータが重複してキャッシュに乗ることになってしまいます。
ただこれは特殊なケースかもしれません。いろいろ見てみると、やはり最適化手法
としてインターリーブを推奨している場合もあるようです。
普通は D3D と同形式でデータを扱って問題ないと思われます。
これでデータもライブラリコードも D3D と全く同じように扱う準備が出来ました。
関連エントリ
・OpenGLES2.0 D3D座標系
・OpenGLES2.0 シェーダー管理