だから人間は大嫌いだ!!

ゲームプログラミングとか、気になるWebのサービスのこととか

HoloLensとメモリプールデザインからみた、仮想世界との距離

人間は、本当に新しい技術に弱いんですね。マイクロソフトがHoloLensなんてものを発表したのだけど、その時にデモでやっていた現実世界にコンピューターによる拡張を行う技術「AR」に、凄くメロメロになったという噂じゃないですか。

実は、私も製品発表会でこいつのデモを観たのだけれど、これがまた寝付けなくなるぐらいにワクワクする。「現実世界は、どんどんコンピューターの生み出す仮想世界とつながっていくんだ!!」なんて、中二臭い言葉を叫びだした深夜4時。英語で言うと、エキサイティング!!!していたわけなのです。

このままいくと、コンピューターは現実世界の延長を作り出すことができるんじゃないか!と錯覚するのですが、実際のところはどうだろう。そのことに対して、プログラマーたる私は、常にNOと答え続けるでしょうね。

例えば、ゲームの中じゃ、時間の最小単位は「1/60秒」になってしまう。0/60秒と1/60秒の間には、世界が存在していない。現実世界は線だとしたら、仮想世界は点が凄く短い距離間で並ぶことで現実世界っぽく見えているだけなの。コンピューターが今の仕組みを続けていく以上は、こういう嘘っぱちな世界しか生み出すことができない。現実世界は0/60秒と1/60秒の間には世界が存在しているからこそ、オリンピック選手は0.01秒を競う。しかし仮想世界じゃそうもいかず、例えば高橋名人なんかも「おれは16連射できるけど、ゲームが15フレーム/秒だから無理」なんて言っていたりするわけですよ。

仮想世界が現実世界に近づく3つのこと?

仮想世界が現実世界を置き換えることは、今のテクノロジーの延長上には到底できない。だけど、近づくことぐらいはできるし、今もずっと世界中のエンジニアがそういう戦いをしている。

では、どうしたらコンピューターの作る仮想世界が、現実世界に近づけるのか?私はその答え、とってもシンプルだと思っている。さっき紹介した1/60秒問題も含めてなんだけど、次の3つを頑張っていけばいいだけなんじゃないかと。

  1. フレームレート:時間の最小単位。4次元空間の粒度。
  2. 情報処理量:時間が進むと何がどう変わるのかを計算。3次元空間の粒度。
  3. アルゴリズム:世界を表現するための物理数学。1と2を現実的に動かすために必要な嘘と真実。

この3つは「現実世界と仮想世界の距離」と言っても過言ではなく、この距離の埋め方・嘘の作り方が、プログラマーをクリエーターやアーティストに変えてくれると思うのです。

有名な話、非プログラマーには、このあたりのことが全く理解されず、ディレクターやマネージャーが「無視」を貫き通すのが日本のソフトウェア業界には多いだとか。けど、マイクロソフトGoogleAppleみたいなエンジニアが主人公みたいな会社なら、きっと面白いコンピューターの芸術を生み出してくれるはず。だから私は、HoloLensには超期待しているのです。

プログラマーにとっての芸術とは?

知っている人もいると思うけど、私もゲームを作っているプログラマーだったりするわけで。やはり、自分が作りたい世界をなんとか実現してやろうと、数年前に「Fullmoon」というゲームエンジンを作ったわけです。自分の目の前にあるのはWindows/DirectXのネイティブのAPIC++だけ。これって、何もない砂漠で、水と種だけを与えられて、そこからどうやって大都市にどうやって発展させるのかを作り上げていくようなもの。吉里吉里とかRPGツクールみたいな「道も電線も整備済み!」みたいなものもあるけど、私はあえてそっちを選ばなかったわけです。

で、それがまた凄く凄く面白い。そりゃ、コンピューターの箱の中、基板の上の線を流れる電流の動きまで制御するわけですから、なんだってやりたい放題。中でも私が面白いと思っているのが、「メモリプール」なる仕組み。こいつがまた奥が深くて、アーティスティックだと思っているのです。

メモリプールとはなにか?簡単に説明してみようと思う。以下は、私が作ったゲームのスクリーンショット

f:id:sakura_q:20150206154041j:plain

敵が全然いないし、ショットも弾幕もいない。この間、世界に存在するのは自機と少しの敵だけ。ほんの少しの物体だけが存在するわけですね。ところが…

f:id:sakura_q:20150206154128j:plain

しばらくすると、画面上は敵とか弾幕とかアイテムで、一気に溢れかえりました。この時、世界に大量の物体が存在するわけです。

こんな感じで、仮想世界の中では現実世界と同様に物体が存在したり存在しなかったりする。ゲームの場合、そいつらの存在は情報化してメモリに置いてやらんといかんわけですよ。で、増えたり減ったりするわけですから、メモリも確保したり捨てたり自由に扱えるようになってなくちゃいけない。だから、大量のメモリを予め確保しておいて、存在しなくなった物体用のメモリを新たに存在しはじめた別の物体に流用できるようにする。

これが「メモリプール」という仕組みなのです。

例として「固定長メモリプール」を取り上げみる

せっかくなので、Githubに上げた。

内容を日本語に直して、gistにも置いて、このブログから見えるようにしてみた。こいつはさっきのスクショで見せたゲームのメモリプールなんだけど、弾幕が大量に画面を埋めて、アイテムが何万個も画面を埋め尽くすようなタイプのゲームを動かすことが求められた。それでもって、アイテム自体は、存在するために必要な情報量は少ないという特徴を持つ。だから、小出しでたくさん出せるようなデザインにしてみた。

このゲームでは、全ての物体がALLOCATE_CHUNK_SIZE分、つまり224バイト(256byte-32byte)しか持つことができない。ただそのかわり、POOL_CHUNK_COUNT分、つまり、98,304個もの物体を同時に存在させることができるようになっていて、それでもメモリ消費量が4MBにもいかないという、最近のアプリケーションにしてはなかなかのエコ仕様。敵が落としたアイテムが98,000個ぐらい処理落ちせずに画面を埋めつくなんてこともできてしまう。…じつは、もっとアイテムを落とせるようにしようとチューニングしたのだけれど、この数がGPUの限界だった!

このメモリプールのモデルは、特定の物体がものすごく複雑な動作を伴う(つまり情報量が一つだけ爆発的に大きい)なんてことになると破綻するわけで、その場合は、可変長メモリプールにしてやらんといかん。ただそうすると、今度はCPU側がその計算をしなくちゃいけなくて、オーバーヘッドというやつが大きくなる。また、すべての物体が3Dとかで関節とかもいっぱいあってものすごく複雑な動きになる場合は、もっともっとベースとなるメモリの確保量を増やさんといかん。その分、メモリの無駄も大きくなる。

逆にインベーダーゲームみたいなオブジェクトあたりの情報量がすごく小さいゲーム。情報量が少ないから、224バイトなんていわず、8バイトまで落とそうぜなんていうと、これがまた「アラインメント」という問題がでてきたり。CPUにはキャッシュというのがいるので、そいつをうまくかつようできるようにZeroMemory()みたいな特殊なやつを使ってCPUの命令そのものを変えてあげなくちゃいけなかったり。

こんなかんじで、ジレンマがいっぱいあって、プログラマーは生み出そうとしている仮想世界において何を優先して何を諦めて、何をごまかしてそれっぽくみせるかを考えなくちゃいけない。これが、凄く凄く面白いのです。

今回、あんまりプログラミングわからんって人にもわかるように頑張って説明してみたけれど、どうだろう。面白さは伝わったかな?HoloLensも所詮はコンピューターなので、変な企画者とかに潰されたりせず、プログラマーの手で試行錯誤して可能性を広げていって欲しいと切に願っております。

モバイルとかガジェットとか、そういうハードウェアの制約が大きい物は、今回のメモリプールのジレンマ然り、色んな調整を何度も繰り返して洗練されていく。そういう取り組みがないと、今までにない新しい体験は生み出せないんじゃないのかな?仮想世界と現実の距離は埋まらないんじゃないか?なんてことを思うのです。