天狗会議録 Posts Pages About

wgpuでFPSゲームを作る

#cg #game #webgpu #rust
2024/8/8

概要

本記事はWebGPU及びwgpuの解説記事ではない。 そして、FPSゲームの制作方法の解説記事でもない。 wgpuを用いてFPSゲームを作ったときの所感や苦労を書き連ねた記事である。

この頃、3DCGを用いそうなゲームの開発環境について悩むことが多かった。 経験したことのあるそれぞれの環境について、次のように考えていた。

WebGPUに対しては次のように考えていた。

しかし、実際に使ってみて、次のように考えが変わった。 他にも色々思ったことがあるため、以降の章で随時書く。

ソースコードはこちら

Rust及びwinit所感

そもそもwgpuはRust製であるため、Rustを主要使用言語に選べる。 私はRustが好きであるため、ありがたくRustを使った。 しかし、OOPをサポートしないRustでのゲーム開発には無理があるなと感じた。 次の点である。

ウィンドウを作成するためにwinit 0.30を用いた。 winitは0.29から0.30に変わるときに、かなり大きく仕様を変更した。 しかし、ほぼ殆どすべての参考記事ではwinit 0.29が用いられており、winit 0.30の仕様も手伝ってかなり苦労した。 次の点である。

WebGPU(wgpu)所感

まず、相変わらずサンプルプログラムが貧弱だなとも思った。 一つのポリゴンしか描かないとか、一つのシェーダしか使わないとか、カメラもポリゴンも動かないとか、そんなんじゃまともなアプリケーションは作れまい。 ただ、Web系の技術であるからか、Vulkanよりは多いようにも感じた。 このまま振興して、より丁寧で実践的な解説が増えてくれるとありがたい。

左手座標系であることに驚いた。 XxYxZが[-1,1]x[-1,1]x[0,1]である。 WindowsでのデフォルトバックエンドがVulkanであるのに、Direct3Dと同じ座標系を採用したのは何のためであろうか。

また、頂点入力バッファにインスタンシングのためのバッファを設けられるようだが、最大float32x4単位で渡さなければならないことに驚いた。 座標変形行列を渡したい場合は4個に分けて渡さなければならない。 メリットがないように感じたたため、ユニフォームバッファとして渡すのが良いだろう。

BindGroupの意義がわからなかった。 どうせすべてのグループのすべてのバインディングに値が入っている必要があるので、すべて同じグループでも良いはずである。 カメラとサンプラを分けるといった、役割の異なるバインディングを異なるグループに分けるコードも見かけたが、メリットがないように感じた。

また、少なくともGPUを積んでいないノートPC(Windows)のバックエンドをVulkanにすると垂直同期が取られなかった。 少なくともUbuntu 24.04のマシン(NVIDIA RTX 3060)では非常に重くなった。

球の作成

素材を使っても良かったが、球体モデルを自作した。 ほぼ殆どこの参考文献から流用したが、次のようなアルゴリズムである。

次のように期待通りのモデルが生成できた。


壁の当たり判定

WebGPUとは全く関係ないが、FPSゲームを作るにあたって、壁の当たり判定の実装に苦労した。 次のように解決した。

  1. 壁(直方体)のx-y平面上の4点の座標を得る
  2. その4点を外側に1ずつ移動する
  3. その4点に直方体の回転を適応する
  4. その4点におけるプレイヤーの座標の内外判定(ベクトルの回転方向を見る)を行う

参考文献