Sunday, March 22, 2015

OpenGLで異種混合インスタンシングを考える

レンダリングの高速化のためにはGPUとCPUの平行動作が重要で、一発のDrawCallで大量のモデルを描画するためにOpenGLの拡張が続けられています。2014年にはNVIDIA、AMD、INTEL各社がインスタンシングやbindless texture等の技術講義を行っていたようですね。

オーバーヘッドを減らすといえば、先日GDC2015で発表されたVulkanや、DX12の登場が待ち遠しいところですが、現状で使える最強のDrawCallはglMultiDrawElementsIndirectかと思われます。

伝統的なインスタンシングは同じモデルを大量に描画できるのに対し、glMultiDrawElementsIndirectは異なるモデルを一回のDrawCallに含められる点が頭一つ抜きん出ています。

GDC2014のスライド、
http://www.slideshare.net/CassEveritt/approaching-zero-driver-overhead
が網羅的に解説しています。

また、NVIDIAのスライド
http://www.slideshare.net/CassEveritt/beyond-porting?related=1
はモダンな描画方法の何がいいのかわかりやすく解説しています。NVIDIAのサンプルプログラムMultiDrawIndirectは異種混合インスタンシングを実現したサンプルです。

原理は簡単で、同一の頂点バッファに複数のモデルを含めておくだけです。頂点バッファのどの部分を描画に使うかは、DrawElementsIndirectCommand構造体の変数が指し示します。glMultiDrawElementsIndirectにはDrawElementsIndirectCommandを配列で渡せるので異種混合インスタンシングができます。ただし、同じ頂点フォーマット、同じシェーダー、同じレンダーステートどうしでないと一緒に描画できません。

また、残念なのはAndroidでは現状で最も機能豊富なAndroid Extension Packに対応していてもglMultiDrawElementsIndirectは使えなさそうなことです。

AndroidではglDrawElementsIndirectがES 3.1から、glDrawElementsInstancedがES 3.0から使えます。これらは基本的に一回のDrawCallで同じモデルを複数描画することができます。OpenGL ESでどうしても異種混合インスタンシングをしたいなら、ボーンを操作したりモーフィングしたりで形を変えながら別のモデルに見せることは出来るかもしれません。しかし、基本的にインスタンスごとにインデックスバッファを変えたり頂点数を変えたりできないです。

現状では異種混合インスタンシングはPC、あるいはフルスペックのOpenGLをサポートしたSHIELD tablet等でしか使えなさそうです。


No comments:

Post a Comment