Akashic Advent Calendar 2019 十八日目の記事です。
Akashic Engine は2D専用ゲームエンジンです。コンソール機で言えばスーパーファミコンやメガドライブの世代とも言えますが、そんな時代にも本物の3Dのゲームがありました。この記事では ソフトウェア3Dレンダラー amber を使った Akashic Engine での3Dゲーム開発を検討します。
amber とは
amber はソフトウェアによる3Dレンダラーです。ハードウェアの機能やWebGLのようなAPIを利用しません。
画像は README から転載。
次の機能が用意されています。
- テクスチャマッピング
- フラットシェーダ
- シーングラフ
- カリング(AABB)
- OBJファイルの読み込み
- プログラマブルシェーダ
- TS/JS で記述。
一方、半透明やアニメーションはサポートされていません。
amber の導入
amber は npmjs に publish されていません。GitHubからインストールします
npm install blackspotbear/amber
Akashic Engine からの利用
amber 付属のサンプルは Akashic Engine への組み込み例となっています。 3Dモデルの描画方法の説明はサンプルに譲り、ここでは amber の組み込み手順のみ取り上げます。
amber を組み込む際は amber とゲームエンジンをつなぎ合わせる2つの機能を実装する必要があります。
ObjResource
amber がobjファイルをパースする時、マテリアルやテクスチャといった関連ファイルを読み込む機能を提供します。ファイル読み込みの方法はゲームエンジンごとに異なるので、ユーザがこのインターフェースを実装することになります。
interface ObjResource {
getTextureData(name: string): { width: number; height: number; rgba: Uint8ClampedArray};
getMaterialText(name: string): string;
}
サンプルコードの main.ts#L31-L47 が実装例です。
FrameBuffer
amber はレンダリング結果を FrameBuffer
に書き込みます。 FrameBuffer
の内容を実際に画面上に表示することはユーザの責務になります。
interface FrameBuffer {
resolution: {
width: number;
height: number;
};
colorBuffer: number[];
zBuffer: number[];
}
サンプルコードの FrameBuffer.ts#L20-L62 が実装例です。
amber と ゲームエンジンを結びつける実装は以上となります。
どんなゲームが作れるのか?
amber は描画の全てをJSエンジン上で実行します。そのためポリゴン数の大きなモデルの描画には時間がかかります。また FrameBuffer
を大きくすることも負荷につながります(デモは低解像度でレンダリングしたものを拡大して表示している)。ゲームでの利用を考えるとフレームレートが安定するように気をつける必要があります。どのくらいの頂点数まで利用できそうか調べてみます(解像度はデモと同じとする)。
デモに付属するモデルのうち、ロケットの頂点数は 646 でした。 akashic-sandbox のプロファイラでCPU利用時間を調べてみます。筆者の MacBook Pro (1.4 GHz Intel Core i5) での結果です。
1フレームあたり 9[ms] 程度かかっているようです。 30[FPS] のゲームでは1フレームあたり 33.3[ms] で処理を終える必要があります。描画に使える時間を 15[ms] とすると 646 x 15 / 9 = 1076 で 1000 頂点が目安になりそうです。単純に 3 で割れば 333 ポリゴンです。
スーファミ版スターフォックス や メガドライブ版バーチャレーシング くらいが限界でしょうか。
最後に
ソフトウェア3Dレンダラー amber を利用することで Akashic Engine で 3D ゲームを開発することを検討しました。かなり厳しい制約があることがわかりました。損得や合理性より大切なものがある人が人生を楽しむのに適当なアプローチかと思います。