タイルマップ描画のメモ

はじめに

もうずいぶん前ですが Tiled Map Editor についてブログに少し書きました。

その後最近になって Tiled Map Editor で作ったマップを描画する部分を OpenGL で実装したりしていたためメモとして書いておきます。

描画の方法

タイルマップのデータを元にしてマス目状にタイルセットの画像を描画していくことになります。

基本的にはテクスチャを貼った三角形をたくさん表示できればいいはずです。

タイル1マスごとにドローコール呼び出したりすると処理に時間がかかってしまうのでまとめて描画するようにします。

大分基礎的なことなので詳しくは別の資料をみてもらった方がいいと思います。

下のページなどが参考になるかなと思います。

www.opengl-tutorial.org

描画順

タイルマップの種類によっては隣り合うタイルが重なりあっていることがあるので気を付ける必要があります。

デプスを使って制御することもできますが、頂点バッファを作るときに描画順に三角形をソートしておくという方法でも制御可能です。

デプスを使わなくてもいいようにしておくとパースペクティブで表示したりもできます (あまり必要ない気もしますが)。

下はパースペクティブで表示してみた画像です。

f:id:tkaaad97:20200831204817p:plain
タイルマップ

インスタンシング

インスタンシングという機能があって、これを使うと3Dモデルの位置や色などを変化させて大量に表示することができます。

インスタンシングについてこちらのページなどが参考になりそうです。

wgld.org

learnopengl.com

タイルマップ描画の場合は幅1で高さ1の四角形メッシュを位置、サイズ、UVを変えてたくさん表示するという感じになります。 インスタンシングで高速化するというよりは頂点バッファに持つデータの量を減らせて扱いやすくなるというのが利点かなと思います。

ちょっと検索してみたところタイルのインスタンシングだとパフォーマンスよくないという感じのことが書かれていました。

gamedev.stackexchange.com

しかし 2D ゲームで使うようなタイルマップのタイル数は多くないのでパフォーマンスで問題になることはそんなにないんじゃないかと思います。 モバイル端末の場合だと問題になったりインスタンシング自体対応していないということもあるかもしれません。

インスタンシングを使わない場合の頂点データは下のようになります。

インスタンシングを使う場合の頂点データは下のようになります。

  • アトリビュート
    • 位置座標
    • タイルサイズ
    • UV座標
    • UVサイズ
  • 頂点数
    • タイル数と同じ

タイルサイズとUVサイズが全体で固定の場合はユニフォームに持つこともできます。 この他に先に触れた幅1で高さ1の四角形メッシュを表す頂点バッファも必要です。

アニメーション表示するには

タイルマップによってはアニメーションするものもあります。 例えば海や川など水の表現ではアニメーションが使われることが多いです。 アニメーションを表示するには一定時間でUV座標を更新してタイル画像を切り替えることになります。

UV座標は頂点バッファに入っているので頂点バッファを定期的に書き換えるというのがやり方としては一番簡単かなと思います。

この他にアニメーションで切り替わるタイルの情報をユニフォームバッファに保持して 頂点バッファにはこれを参照するインデックスを持たせるというようなやり方もできます。 この場合はユニフォームバッファのタイル情報だけを更新するため更新が少なくて済みます。