微妙に高速化しました。
ConwayのLifegameで一番処理時間がかかる部分は各”セル”の生死を決定する箇所です。
死んでいる状態のセルの回りに、ちょうど3つの生きているセルがいれば、その死んでいる状態のセルは生き返ります。
生きている状態のセルの回りに、2つか3つの生きているセルがいれば、そのセルは生を維持します。2つか3つ以外ならば死んでしまいます。
次回はこの部分をGPU(シェーダー)に処理させて高速化したいと思います。
微妙に高速化しました。
ConwayのLifegameで一番処理時間がかかる部分は各”セル”の生死を決定する箇所です。
死んでいる状態のセルの回りに、ちょうど3つの生きているセルがいれば、その死んでいる状態のセルは生き返ります。
生きている状態のセルの回りに、2つか3つの生きているセルがいれば、そのセルは生を維持します。2つか3つ以外ならば死んでしまいます。
次回はこの部分をGPU(シェーダー)に処理させて高速化したいと思います。
今日は、CPUやメモリの効率無視で、とりあえず動くバージョンのライフゲームを作成しました。
このページです。
タップ/クリックする毎に処理量(ドット数)が4倍になります。ある程度以上のFPSが出ていなかった場合はタップ/クリックしても処理量が増えないように制限をかけています。
処理量を増やしていくと、どんどん速度が低下するのが分かりますね。明日からはこれを高速化していく予定です。
今日は”点”の表示を行いました。
このページです。
中心に赤い点が表示されますね。これだけです。
・・・さて、みなさん、OpenGLのプログラミングで一番難しいのは何かお分かりでしょうか?
・・・実は、そう、実は上記のように、たった1つだけの点だとしても、その点が画面に表示されるまでが一番難しいのです。
図形が表示されるまでに乗り越えるべき壁は山ほどあります。
GPUに渡す頂点データは正しいのか?
頂点データを渡すAPIの使い方は正しく、APIの全ての引数はちゃんと正しい値になっているのか?(OpenGL関係のAPIは実に引数の数が多く、かつ内容がややこしいです。)
図形を描画するための頂点シェーダやフラグメントシェーダは正しいのか?
渡した頂点データとの整合性は取れているのか?
シェーダーの記述は正しいのか?
描画した図形の座標はちゃんと描画画面内に入っているのか?
環境による利用可能なAPIのバージョンはあっているのか?
etc etc etc…まだまだたくさんあります。
上記のどれか1つ、そう、たった1つでも間違っていると画面に何も図形が表示されない可能性が高いです。図形が表示されないと、どこが間違っているのかわからず悩みまくることになります。本気で悩みまくって数年単位で解決できないこともあります。大げさではありません。
例えるならば、1万人の大縄跳びを成功させようとしているようなものなのです。たった1回飛ぶのがとてつもなく難しいのです。
ですから今日赤い点を表示できたことは素晴らしい成果なのです。
さあ、そういうことを分かった上でじっくりこの点を見てみましょう。感動しますよね?
・・・
・・
・
いや感動しないな。単なる赤い点だな。
ʕ•̫͡•ʕ*̫͡*ʕ•͓͡•ʔ-̫͡-ʕ•̫͡•ʔ*̫͡*ʔ-̫͡-ʔ
明日から引き続き実装を頑張ります。
今回はマインクラフトをパクるために、マインクラフトのブロックベースの世界を構築するための準備を行っていました。
今回は新しいアプリを作るための準備として、WebGLを利用した動作テストを行っていました。
こちらがWebGLで製作した画面です。
なるべく少ないメモリで、また高速動作するよう、考えに考え抜いて作成したつもりです。頭の良い人はもっと効率の良い洗練されたコード書くと思うけど、私はWebGL/OpenGL初心者なりに頑張りました。
左上のアイコンをクリック/タップすることでフルスクリーンになります。顧客を軽視するMSのIEやEDGEを除くシェアの高いFireFoxやChrome,Safariのブラウザにおいて、良い感じにフルスクリーン動作すると思います。iOSではフルスクリーンが制限されており実現できませんが、ブラウザの領域全体を使って出来る限り大きな画面を描画するようにしています。
で、WebGLをある程度使ってみて感じたのですが、GLSLにもっと詳しくなれば、より高速でより洗練されたアプリが作れるのではないかと思いました。
そこで、新アプリの前にConwayのLifegameをWebGLで構築することとしました。今決めました。
だらだら作業するのも嫌なので、スケジュールを決めます。以下の実装内容は大まかなものです。実装途中でより良いアイデアなどが浮かぶと内容が変わってくると思います。
356日目:ポイントスプライトでとりあえず画面にドットを表示
357日目:とりあえずライフゲームが動く。ドットの大きさやエフェクトなど、各種設定値は固定。
358〜360日目:シェーダー(GLSL)を利用し、GPUでライフゲームを高速で動作させる。エフェクトなどはなし。
361〜363日目:エフェクトなどを考慮した上で、シェーダー(GLSL)を利用してライフゲームを高速で動作させる。
364〜366日目:各種設定値を指定するためのGUIのライブラリを作成する。これは、PCでもスマホでもどちらからでも容易に操作が可能とする。
365日目:ドットの大きさを調整可能とする。
366日目:ドットの色を変更可能とする。
367日目:ドットにイメージを指定可能とする。
368日目:ライフの状態変化時にエフェクト適用。
369日目:縦横ドット数を細かく指定可能に。
370〜371日目:セーブ機能の実装
372〜373日目:ロード機能の実装
374〜380日目:課金処理の実装(と、それに見合うプレミアム機能/エフェクトの実装。課金に見合う内容が出来るのか?)
・・・最後に課金処理の実装となっていますが、ライフゲームで課金してくれる人はあまりいないと思います。将来的な課金処理の実装練習的な意味合いが大きいです。でも課金してくれるほどのブラウザベースのライフゲームが出来たらすごいよな。世界初だよな。がんばろっと。
今回は、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);
意外にも、インターリーブ配列を利用しない方がパフォーマンスが上がりました。ドウイウコトデスカ?
ヽ(`д´)ノ うわーん
前回の予告通り、今回は各環境/各ブラウザでの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をサポートすれば良さそうです。
前回の投稿で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)を取って見たいと思います。ネイティブアプリも比較対象として測定する予定です。
・・・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のシェアそんなに落ちてないって?みんな使ってるから惰性でみんなつられて使ってるだけだよ!
少なくとも私は信頼してないし!この信頼していないよ感を生涯周りに出しつづけるつもりだよ!影響力ないかもしれないけど・・・
・・・うん。こんなブログで書いてても影響力全くないな。早く次のアプリ開発しよっと。
今回は、新アプリに登場する武器/防具/カード/アイテムをいくつか考えます。
【武器】
・小石 — 前方10マス 攻撃力1 ※使うと無くなる
・棒 — 前方1マス 攻撃力1
・槍 — 前方2マス 攻撃力2
【防具】
・ジャケット — 防御力1
・ヘルメット — 防御力3
・スニーカー — 移動距離10%アップ
【宝石】※使うと無くなる
・アイオライト — 他プレーヤーの近くに自身を転送する。距離に関係なく、どのプレーヤーの近くに転送されるかは完全ランダム。
・アンバー — 100マス以内の他プレーヤーを、自分の隣に強制転送する。
・クリスタル — 一番近くの他プレーヤー周囲100マスを確認できる。
・ラピスラズリ — 72時間、地面から10マスの範囲を浮遊出来る。
・ダイヤモンド — 72時間、防御力を50%アップする。
【アイテム】
・青いフラグ — 設置した場所を中心に上下+四方10マスを自分の領域にする。自分の領域では他プレーヤーが地形を変更できなかったり、自分の防御力が30%上がる。
・赤いフラグ — 設置しておくと、自分が死んだ場合にこの場所に復活する。復活後、赤いフラグは消える。1箇所のみ設置可。
※死んだ場合、24時間行動不能になります。24時間経過後、赤いフラグを設置済みの場合はその場所に、設置して居ない場合は死んだ地点の周辺100マス以内のランダムな場所で復活します。
次回作のアプリ企画が確定しました。いや、会社じゃなくて個人開発なので別に会議とかで確定したわけではないのですが、私の頭の中で確定しました。10年くらい悩みました・・・がやっと決まりました。
以下、確定したアプリの仕様を大まかに箇条書きします。
・アプリを起動したユーザはマイクラのような3Dマップのフィールドに全員降り立つ。1億人いても全員同じフィールドに降り立つ。フィールドは世界地図を基にしたもので、とても広い。
・どこでもいつでも誰にでも攻撃できる。全員相手の超巨大PVPである。
・レベルはなく、防具や武器などのアイテムを装備することで強くなる。
・他のプレーヤーを倒すと、所持品を全て奪うことが出来る。
・ラグを無くすために、ターン制バトルとする。ターン制と言っても全員相手なので、特定時間が経つと全員のターンが同時に来る特殊ターン制である。
・ゲームをプレイしていなくても、プレーヤーのキャラはサーバに24時間居続ける。ターン制なので特定時間毎に操作すれば一方的に他のプレーヤーにやられることはない。また、この”特定時間”が結構長いので問題にならない。
・この世界には”壁”や”扉”や”罠”のアイテムがあり、フィールド上のどの場所にも置くことができる。自分を”壁”や”扉”や”罠”で囲うことで他のプレーヤーから身を守ることができる。
基本は以上で、以下は様子を見ながら、調整しつつ追加実装出来れば良いと考えています。
・アイテムは、自分の”陣地”で製作することができる。陣地内では、他のプレーヤーによる”破壊活動”を受けない。製作に必要なお金は自分の陣地の広さが大きければ大きいほど多くもらえる。陣地を広げるための壁や扉も陣地の中で生産できる。
・プレーヤーは、”ボット”と呼ばれる自動で動く機械を所有し、自分の陣地を警備させることができる。
・”ボット”は、プレーヤーがアプリを立ち上げていなくても、サーバ上で24時間勝手に動く。
・”ボット”は、他のプレーヤーやボットとの攻防を繰り広げているうちに、その動作ロジックが進化していく。
・”ボット”は、他のプレーヤーと売り買い出来る。
全員同時参加型のPVPということで、技術的には、サーバをスケールアウトして、ボトルネックなしに処理能力をサーバ台数に比例して線形で増加させていける仕組みにしたいと思います。
プラットフォームは、アプリの性質と、慣れているという理由でiOSで作りますが、大部分をC++で実装してゆくゆくはSteamでマルチプラットフォーム対応したいと考えています。
明日の予定:
自分の頭をスケールアウトする。
_┓_
‹‹ ( ´ ω ` ) ››
=〔∪ ̄ ̄〕