Saturday, May 23, 2015

Android StudioのGUIを使わずにビルド→インストール→起動

以下のようなバッチファイルをgradlew.batと同じ位置に作っておくことで、Android Studioを起動せずともコマンドライン又はエクスプローラからビルド、インストール、起動ができるようになります。NDKを使用している場合のビルドまで問題なく出来ました。

※ パッケージ名は、com.pinotnoir.adamasを、アクティビティ名はcommon.pinotnoir.glactivity.PinotGLActivityを置き換えてください。

ところで、"ADB server didn't ACK" というエラーに悩まされていたのですが、原因はNsight Tegra Visual Studio Editionでした。これが内部でADBをつかっているため衝突するようです。Visual Stuidio起動中に上のバッチファイルが使えない場合、Visual Studioを終了すると使えるようになりました。



Nsight Tegra Visual Studio Editionを一時停止することはできないようです。Visual StudioとAndroid Studioを同時に使いつつ、Nsight Tegraも使いたい場合、面倒なことになりそうです。Nsight Tegraをアンインストールすると衝突は起こらなくなりました。

Thursday, May 14, 2015

GitHubのDirectXTKをgit submoduleとして組み込む

MicrosoftのGitHubアカウントでDirectXTKが公開されています。gitのsubmoduleとして組み込めるので格段に管理しやすくなりそうです。早速組み込んでみました。

組み込み方


git bashからDirectXTKを組み込みたいプロジェクトのディレクトリに移動し、以下のように入力すればDirectXTKフォルダ以下にDirectXTKのプロジェクトファイルが生成され、DirectXTKを参照するコミットを生成できます。

$ git submodule init
$ git submodule add https://github.com/Microsoft/DirectXTK.git DirectXTK
$ git commit -m "DirectXTK added as a submodule"

submoduleの何が良いのか


自分のレポジトリに外部のgitレポジトリの参照を加えることで、(半自動的に)一緒にチェックアウトできるようになります。自分のレポジトリを肥大化せずに外部モジュールを取り込めるわけです。また、参照にはバージョンも含まれているのでバージョンを取り違えてビルドに失敗することもありません。何より外部モジュールの組み込み方をgitが標準化したという側面が大きいです。

当然ながら、取り込みたいモジュールがgitレポジトリとして公開されているのが前提条件になるのですが、MicrosoftもGitHubでプロジェクトを公開してくれるようになりました。ありがたいですね。

submoduleは以下が詳しいです。

→ Git のさまざまなツール - サブモジュール

レポジトリについて


→ https://github.com/yorung/dx11x

D3DXやDirectX SDKを使わないモダンなDirectX11で.xファイルを読み込んで表示するプログラムです。スキニングも含めてアニメーションもひととおり対応しています。




Saturday, May 2, 2015

OpenGL ES 2.0のvec4配列でUBOもどきを作る際の注意点

OpenGL ES 3.0ではUBOやVAOのような現状のハードウェアで効率的に動作するAPIが使えるようになります。しかし、開発者はモダンなAPIへの対応作業を迫られる一方、ES 2.0もサポートし続けなければいけません。https://developer.android.com/about/dashboards/index.html にもあるように未だに65%のデバイスはOpenGL ES 2.0であり、この状況は当分続きそうです。
「じゃあES2.0だけでいいや」では時代遅れになるので、ES2.0でもモダンなフリをしながら両バージョンでコードを共有する方法を模索してみます。

複数のuniform変数を配列化してひとつに


http://on-demand.gputechconf.com/gtc/2013/presentations/S3032-Advanced-Scenegraph-Rendering-Pipeline.pdf の24ページ目でuniform block(UBO)を使えない場合に、複数のuniformを配列にまとめて使う方法が提案されています。これは効率的であるのみならず、C側では構造体で転送するデータを管理できるので、UBOを使ったES 3.0のコードとのアーキテクチャの差を吸収できそうです。
https://devtalk.nvidia.com/default/topic/777618/scenix/announcing-nvpro-pipeline-a-research-rendering-pipeline/ この掲示板に動画もありますね。

mat4かvec4かfloatか


複数のuniformをまとめる際、どのような型の配列として渡すか決めなければなりません。行列だけのバッファならmat4の配列、色やベクトルだけならvec4配列にします。

mat4とvec4の混合のバッファを作りたい場合もあるかもしれません。そういうときはvec4の配列とするとよさそうです。mat4配列でもよいのですがバッファサイズがfloat16個単位になってしまうので柔軟性に欠けるからです。次のようにしてGLSL側でvec4を4つまとめてmat4を復元します。


ならば、vec4配列よりfloat配列のほうが柔軟そうですが、float4つを1単位とする癖をつけたほうが良いかもしれません。以下のポストはDirectX11のもので、NVIDIAによるものなので他のGPU全てに当てはまるかはわかりませんが、float4つ単位にしなかった場合の速度低下の可能性を示唆しています。
https://developer.nvidia.com/content/understanding-structured-buffer-performance

UBOとuniform vec4配列の違い


上のように、ES3.0のUBOのようなものをES 2.0で実現してみましたが、同一ではありません。UBOはシェーダから独立したバッファで、複数シェーダで共有可能です。uniformはシェーダの一部であってC側から書き換え可能な変数です。あるuniform vec4配列を複数のシェーダ間で共有したい場合、シェーダを切り替える度にglUniform4fvでバッファを転送してあげなければなりません。

OpenGL ES特有のprecisionの問題


ES特有のつまづきそうなポイントです。uniformはシェーダ間で共有できませんが、同じprogramに属するvertex shaderとfragment shaderに限って同じ名前のuniform変数を宣言すると共有されます。しかし、precisionが違うと共有できません(glLinkProgramでエラーになります)。vertex shaderではhighp、fragment shaderではmediump、のような使い方をすることが多いと思うので注意します。(fragment shaderでhighpがエラーになる機種もある)