独創アプリ開発日記 312〜326日目 インターリーブ配列ベンチマーク

今回は、WebGLを描画するキャンバスのフルスクリーン表示対応を行っていました。

PCは簡単でしたが、iOSのSafariはフルスクリーンに対応してなかったので、ウィンドウサイズに合わせてキャンバスを調整して、なるべくキャンバスの領域を大きくすることで対応しました。

あとは、インターリーブ配列にするかどうかでWebGLのパフォーマンスがどのくらい変わるかを確認していました。

こちらが利用前、こちらがインターリーブ配列利用のページです。

インターリーブ配列とは、頂点毎にデータをまとめて、GPUのメモリアクセスの負荷を下げてパフォーマンスをあげる工夫です。(詳しくはググればいっぱい情報出てくるよ!)

ソースコードの、以下部分がインターリーブ配列を処理している箇所ですね。

gl.bindBuffer(gl.ARRAY_BUFFER, _vboAry);
gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, _data.vbo.itemSizeV, gl.FLOAT, false, 20, 0);
gl.vertexAttribPointer(shaderProgram.textureCoordAttribute, _data.vbo.itemSizeT, gl.FLOAT, false, 20, 12);

意外にも、インターリーブ配列を利用しない方がパフォーマンスが上がりました。ドウイウコトデスカ?

ヽ(`д´)ノ うわーん

独創アプリ開発日記 311日目 プラットフォーム/ブラウザ別WebGLベンチマーク

前回の予告通り、今回は各環境/各ブラウザでのWebGLのベンチマークを取って見ました。WebGLとの比較のために、C++やC#(OpenTK)のネイティブアプリでの計測も行いました。計測条件は以下の通りです。

計測条件:
・テクスチャ付きの立方体を200 * 200 * 200 = 8,000,000個 描画
・開始から60秒経過時の”total”FPSを記録
・WebGLはこのページで計測(コード)
・C#(OpenTK)はこのコードで計測
・C++はこのコードで計測
・ハードウェアは環境によって異なる
 (各テーブルの先頭に記述)
・EDGE?なにそれ?
・IE?滅びろ。

結果は以下の通りです。

3770K+GTX1070
OS Browser WebGL C# C++
Ubuntu Chrome 29.72 39.51 38.77
FireFox 39.60
Windows Chrome 45.86 38.26 31.00
FireFox 33.47
Macbook Pro 15-inch, Mid 2015
(2.5GHz Corei7+RadeonR9 M370X 2048MB)
OS Browser WebGL C# C++
Mac Chrome 6.57 7.06 6.94
FireFox 6.84
Safari 2~3くらい
iPhoneX
OS Browser WebGL C# C++
iOS 11 Safari 4.67

WebGLに比べてネイティブアプリは1.5倍〜2倍程度速いことがわかりました。また、ブラウザ別では、Chromeに比べてFireFoxの方が1.1〜1.5倍程度速いです。SafariもFireFox程度の速度が出ていることがわかりました。
8/22修正:WebGLだけ両面描画するようになってしまっていたため、裏面を描画しないように修正して再計測しました。なんと、WindowsのChromeでWebGLがネイティブアプリを凌駕しています。これは例外としても、WebGLはネイティブアプリに比べて同等~最大で30%程度劣るパフォーマンスとなりました。まずまずの結果で十分実用になるパフォーマンスです。

ブラウザ別では、SafariがChromeやFirefoxに対して半分未満のFPSという結果となりました。ただ、iPhoneXのSafariはMacのFPSを超えており、これはMacのSafariに何か問題があるのか、iPhoneXがすごいのか、どちらかは分かりませんが、いずれにしてもスマホでもある程度のパフォーマンスがでるようです。iOSでChromeやFireFoxの測定をしていませんが、レンダリングエンジンの制約があるため、iOS上でブラウザ間のパフォーマンスにはあまり差が無い筈です。

iPhoneやMacを使ってる人は、あまりブラウザを標準のSafariから変えない傾向があると考えます。Windows使ってる人は、標準以外のブラウザを使う人が多いですね!

以上から、WebGLでアプリを開発した場合、Ubuntu/Win用にChromeもしくはFireFoxを、Mac/iPhone用にSafariをサポートすれば良さそうです。

独創アプリ開発日記 297-310日目 WebGLで自由になろう

前回の投稿でappleを褒めていて何ですが、また、個人的にiPhoneは好きなのですが、流石にちょっと最近はappleのアプリ開発者に対する扱いのずさんな面に目を瞑ることが出来なくなって来ました。

その具体的な内容として、

・64bit移行時の32bitアプリ切り捨て
・バージョンアップに伴うObjective-CやSwiftの頻繁な仕様変更
・OpenGL切り捨て予告

・ギャンブル系アプリ(個人開発者だけ。大手はスルー)の予告なしの販売停止

等があります。もちろん、より良いアプリ市場となるようなappleの方針が元となっており、ユーザー目線が理由ではあるのですが、これらの対応が、開発者(主に私)の信頼を失ってしまう後戻り出来ない一線を超えてしまったように思います。

そこで、開発の軸足をiPhoneアプリから外すことにしました。

なお、Androidは嫌い(何となく)なので、WebGLを使って、ブラウザベースでマルチプラットフォームアプリを開発できないか考えることとしました。

はい、と言うわけで最近C#(OpenTK)c++で作成していたマルチプラットフォーム対応のOpenGLでの立方体描画コードをWebGLに移植しました。

このリンクから、WebGLが実際に動作するページに飛ぶことができます。飛んだ先はもう、そこはかとなくたくさんの立方体がくるくる回ってますよ。

ページ下部のx, y, z の数字を変えて「apply」を押すと、描画する立方体の数を変更することができます。あまりにたくさんの立方体を表示しようとすると、生半可なスペックのPCではブラウザが重くなったり固まったりすると思うので注意して下さいね。

次回は、各OS各ブラウザでベンチマーク(FPS)を取って見たいと思います。ネイティブアプリも比較対象として測定する予定です。

独創アプリ開発日記 284-296日目 アップルのユーザー目線

・・・iOS12ではOpenGLが非推奨となるようです。

アップルの言うOpenGL非推奨というのは、アップルの本音を分かりやすく言うと

「メタル使えやコラ。Metal使えやコラ。せっかく用意したんやから、めぇたぁるぅ、使えやゴルァ!OpenGLは無駄がおおいねん。最適化されてないねん。おいらのiPhoneやMacのバッテリー無駄食いするねんゴルァ!」

という意味です。

Metal(メタル)はアップルのオペレーティングシステム上でサポートされる、オーバーヘッドの小さいローレベル (low level) なコンピュータグラフィックスAPIで、iOSやmacOSに特化している代わりに速くてしかも省エネの3D描画の仕組みです。

OpenGLが使えなくなるのは、開発者から大顰蹙(ひんしゅく)を買っています。OpenGLとは、Win/Mac/Linux全て共通で利用できるAPIです。これがiOS/macOSで使えなくなったら、OpenGLに加えてMetalのコードも開発/維持していかなければなりません。大企業ならともかく、中小や個人開発者にとって開発リソースの増大は死活問題です。

開発者の苦労など微塵も考えて居ません。でもそこがアップルの良いところです。ユーザー目線なのです。

ユーザーからしてみれば、自分の使っていない機器まで考慮した汎用性のために、バッテリーの持ちが悪くなってはたまったものではないのです。

なお、MSはその逆です。Windows10に見られる自社都合でユーザー目線度外視のその姿勢は、今後永久にユーザーの信頼を取り戻すことはないでしょう。強制アップデートとかedge強制とか、ユーザーの皆さん、なめられてるんですよ。

・・・え?Windowsのシェアそんなに落ちてないって?みんな使ってるから惰性でみんなつられて使ってるだけだよ!

少なくとも私は信頼してないし!この信頼していないよ感を生涯周りに出しつづけるつもりだよ!影響力ないかもしれないけど・・・

・・・うん。こんなブログで書いてても影響力全くないな。早く次のアプリ開発しよっと。

独創アプリ開発日記 282-283日目 武器/防具/宝石/アイテム

今回は、新アプリに登場する武器/防具/カード/アイテムをいくつか考えます。

【武器】

・小石 — 前方10マス 攻撃力1 ※使うと無くなる
・棒 — 前方1マス 攻撃力1
・槍 — 前方2マス 攻撃力2

【防具】

・ジャケット — 防御力1
・ヘルメット — 防御力3
・スニーカー — 移動距離10%アップ

【宝石】※使うと無くなる

・アイオライト — 他プレーヤーの近くに自身を転送する。距離に関係なく、どのプレーヤーの近くに転送されるかは完全ランダム。
・アンバー — 100マス以内の他プレーヤーを、自分の隣に強制転送する。
・クリスタル — 一番近くの他プレーヤー周囲100マスを確認できる。
・ラピスラズリ — 72時間、地面から10マスの範囲を浮遊出来る。
・ダイヤモンド — 72時間、防御力を50%アップする。

【アイテム】

・青いフラグ — 設置した場所を中心に上下+四方10マスを自分の領域にする。自分の領域では他プレーヤーが地形を変更できなかったり、自分の防御力が30%上がる。
・赤いフラグ — 設置しておくと、自分が死んだ場合にこの場所に復活する。復活後、赤いフラグは消える。1箇所のみ設置可。

※死んだ場合、24時間行動不能になります。24時間経過後、赤いフラグを設置済みの場合はその場所に、設置して居ない場合は死んだ地点の周辺100マス以内のランダムな場所で復活します。

独創アプリ開発日記 280〜281日目 次回作のアプリ企画確定

次回作のアプリ企画が確定しました。いや、会社じゃなくて個人開発なので別に会議とかで確定したわけではないのですが、私の頭の中で確定しました。10年くらい悩みました・・・がやっと決まりました。

以下、確定したアプリの仕様を大まかに箇条書きします。

・アプリを起動したユーザはマイクラのような3Dマップのフィールドに全員降り立つ。1億人いても全員同じフィールドに降り立つ。フィールドは世界地図を基にしたもので、とても広い。

・どこでもいつでも誰にでも攻撃できる。全員相手の超巨大PVPである。

・レベルはなく、防具や武器などのアイテムを装備することで強くなる。

・他のプレーヤーを倒すと、所持品を全て奪うことが出来る。

・ラグを無くすために、ターン制バトルとする。ターン制と言っても全員相手なので、特定時間が経つと全員のターンが同時に来る特殊ターン制である。

・ゲームをプレイしていなくても、プレーヤーのキャラはサーバに24時間居続ける。ターン制なので特定時間毎に操作すれば一方的に他のプレーヤーにやられることはない。また、この”特定時間”が結構長いので問題にならない。

・この世界には”壁”や”扉”や”罠”のアイテムがあり、フィールド上のどの場所にも置くことができる。自分を”壁”や”扉”や”罠”で囲うことで他のプレーヤーから身を守ることができる。

基本は以上で、以下は様子を見ながら、調整しつつ追加実装出来れば良いと考えています。

・アイテムは、自分の”陣地”で製作することができる。陣地内では、他のプレーヤーによる”破壊活動”を受けない。製作に必要なお金は自分の陣地の広さが大きければ大きいほど多くもらえる。陣地を広げるための壁や扉も陣地の中で生産できる。

・プレーヤーは、”ボット”と呼ばれる自動で動く機械を所有し、自分の陣地を警備させることができる。

・”ボット”は、プレーヤーがアプリを立ち上げていなくても、サーバ上で24時間勝手に動く。

・”ボット”は、他のプレーヤーやボットとの攻防を繰り広げているうちに、その動作ロジックが進化していく。

・”ボット”は、他のプレーヤーと売り買い出来る。

全員同時参加型のPVPということで、技術的には、サーバをスケールアウトして、ボトルネックなしに処理能力をサーバ台数に比例して線形で増加させていける仕組みにしたいと思います。

プラットフォームは、アプリの性質と、慣れているという理由でiOSで作りますが、大部分をC++で実装してゆくゆくはSteamでマルチプラットフォーム対応したいと考えています。

明日の予定:

自分の頭をスケールアウトする。

   _┓_ 
  ‹‹ ( ´ ω ` ) ›› 
  =〔∪ ̄ ̄〕

独創アプリ開発日記 279日目 ねこマタバージョンアップ完了

昨日申請したねこマタですが、もうバージョンアップ完了して、アプリストアに反映されました。最近は審査早いな・・・。私が開発始めた2009年頃は2週間程度、ちょっと前までは1週間くらいかかったのにな・・・。

今日はバージョンアップ内容に合わせてアプリストアの説明文やWebサイトのアプリ紹介ページをちまちま直していました。

独創アプリ開発日記 275〜278日目 ねこマタバージョンアップ

今日はねこマタの新バージョンをアップルに申請しました。

変更は以下の2点です。

・対人戦の1日3回の制限が無くなりました。
・対人ステージ”P”を追加しました。

なんか難しそうなアプリだな・・・と思った方は、

しつこいくらい詳しく解説 — ねこマタ入門(JAPANESE ONLY)

をご覧ください。只今日本語限定で詳しく解説しています。日本人でよかったですね。

立った立った!
  クララが立った!
      \|/
⊂⌒⊃   ― ● ―
  ⊂⊃  /|\
     ⊂⊃  ⊂⊃
/~\へ/~\へヘ/~\
ハ`ハハハハ`ハハ`ハハハハハ`ハハハハ
” “””” “”” “””” “”””
∥=∥=∥=∥=∥=∥=∥
” “∧_∧” “”” “””” ”
” (´∀`) “e@@e”””
“⊂  ⊃” (・∀・)_ノ
○(  ノ””とと__つ
“” )_)) “” ” “” “”ミ
“” “” ∧∧” “”” __
” “” (∀・;) “” | ∥
“””⊂⊂⌒ヽ “” |_∥
“” プル )) )○∠_/)
“” (( (_(_ノ ))プル ◎
||” “”||” “”||” “”||
||二二||二二||二二||

c++でマルチプラットフォーム対応(GUI込)のOpenGLコード253〜274日目

先日作成したC#(OpenTK)のコードをC++に変換し、共通のソースコードでMac,Ubuntu(Linux),Windowsの各種環境において3D図形を描画することに成功しました!Write once, run anywhere!

そして・・・

祝!脱MS環境依存!!

(੭ु ›ω‹ )੭ु⁾⁾♡

OSはもちろん、開発言語等もMSに依存しなくなったよ。

以下が完成したC++のコードです。

https://github.com/ukaapple/cubeTest-cpp/blob/master/CubeInsWindow.cpp

立方体を100x100x100で、合計100万描画します。

TriangleStripで、かつ Instancing使っているので高効率です。メモリ12MB程度しか使わずに済んでいます。

TriangleStripに関しては、過去の日記で記述しています。こんな感じでテクスチャを貼るやり方のことです。

InstancingとはOpenGLの用語で、同じ形状を、位置情報だけいっぱい与えていろんな場所に描画することです。描画速度向上や使用メモリ量削減が期待できます。

ちなみにInstancingを使わないとメモリ使用量が340MBに跳ね上がります。以下が使わない場合のソースです。

https://github.com/ukaapple/cubeTest-cpp/blob/master/CubeWindow.cpp

以下のコードで CubeInsWindow を CubeWindow に変更すると、Instancingを使わない描画に切り替えることが出来ます。

https://github.com/ukaapple/cubeTest-cpp/blob/master/Program.cpp

タイトルバーにfpsを表示するようにしてるので、OpenGLのベンチマーク目的でいろんな環境で実行するのも良いかもしれません。

ちなみに、ハードウェアが同じならば、OSが同じでもベンチマーク結果はほぼ同じでした。

ただし、Windowsを除いて。なぜかWindowsだけ、明らかにFPSが5〜8%低かったです。

これでSteamでの開発準備ができました。次のアプリ、iOSで出そうかな?それともSteamで出そうかな。

(੭ु ›ω‹ )੭ु⁾⁾♡

独創アプリ開発日記 252日目 C++によるマルチプラットフォーム対応のOpenGLコード第一歩 Windows編

先日作成したマルチプラットフォーム対応のOpenGLコードを、macLinux(Ubuntu 18.04 LTS)に続いて、Windowsで動作させます。

Windows7で試しました。

さすが、過去にLinuxを癌だと言っていた会社です。邪悪な独自仕様を進化させたそのOSは、マルチプラットフォーム対応コードの動作を阻む高い壁の名残があるようです。動作させるために面倒な準備が必要になりました。

まずMinGWCMakeMakeをインストールします。インストール後、PATHを適切に設定してください。

次に、glfwのソースを持ってきてビルドします。(バイナリ持ってきても動きませんでした)

CMakeでMinGW用のビルドファイルを生成し、makeコマンドを実行して、最終的に生成されるlibglfw3.aをMinGW\libフォルダの中にコピーします。また、ヘッダーファイルをMinGW\include\GLFWの中にコピーします。

さらに、glewのソースを持ってきてビルドします。(こちらもバイナリを持ってきても動きませんでした)

glfwと同様に、CMakeでMinGW用のビルドファイルを生成後、makeコマンドを実行して、最終的に生成されるlibglew32.aとlibglew32.dll.aをMinGW\libフォルダの中にコピーします。また、ヘッダーファイルをMinGW\include\GLの中にコピーします。更に、glew32.dllをパスの通っている場所にコピーしておきます。

尚、CMakeやMakeコマンドの実行時は、セキュリティソフトのリアルタイム保護を無効にしてください。

何故かウィルスと判断されて作業が失敗してしまいます。

うーん・・・

以上で準備完了です。目的のコードをコンパイルして実行しましょう。

g++ Program.cpp -lglfw3 -lglew32 -lgdi32 -lopengl32

やっと動きました。

え?Visual Studio?何それ?