himeshi’s blog

Simutrans本体改造まわりのお話をつらつらと

続・アドオンの減色について

前回はアドオンの減色のしくみについて解説したので、今回はなぜ減色がされているのか、今後減色が解消される見込みはあるのかなどについて考えたいと思います。
himeshi.hateblo.jp


アドオン減色について語るには、まずSimutransの描画処理まわりをおさらいする必要があります。
Simutransに限らず大半のGUIプログラムは、描画処理を何らかのライブラリに任せる形で行っています。言い換えると、描画ライブラリと呼ばれるプログラムに対して描画命令をすることで画面が描画されるということです。Simutransは描画ライブラリとしてallegro、GDI、OpenGLSDL、SDL2をサポートしています。今回は描画ライブラリをSDL2として話を進めることにします。
なお描画ライブラリの命令は描画ライブラリごとに異なるので、simsys.hが描画命令を共通化する役割を持っています。SDL2の場合の実装ファイルはsimsys_s2.ccです。

描画手順は各ライブラリごとに若干異なりますが、概ね次の手順で行われます。まずSimutransは描画するピクセルデータを描画バッファと呼ばれる変数に格納します。描画バッファにピクセルデータを格納し終えたらライブラリの画面更新命令を呼びます。これで、描画バッファに格納されたピクセルデータが画面に反映されるのです。
Simutransの描画処理は、地面を描き、線路を描き、車両を描き・・・と続いていきます。地面画像の上に線路画像や車両画像が塗り重ねられていき、最終的にすべて塗り重ねた結果を描画ライブラリに渡しています。よってピクセルを塗り重ねていく処理はSimutrans自身が行うことになります。塗り重ねの処理はdisplay/simgraph16.ccにかかれています。なおsimgraph0.ccGUIを起動しないサーバーモード用の処理であり、描画処理を行いません。

simgraph16.ccの386行目で、描画バッファ変数は次のように宣言されています。

/*
 * Output framebuffer
 */
static PIXVAL* textur = NULL;

PIXVAL型の実体はuint16です。この時点で、画像の塗り重ね処理自体が16bit整数で行われていることがわかります。減色されたアドオン画像を256階調RGBに復元しているわけではないのです。ちなみに画像のアルファ値はライブラリに渡されるのではなく、simutrans自身が重ね塗りをするときに吸収しています。

さて、描画処理自体が16bit(内訳はRGBそれぞれ5bitずつで本当は15bit)で行われていることがわかりましたが、32bitで扱うのとくらべてどのような違いがあるのでしょうか?大きな違いは主に2つです。

  • 描画処理のパフォーマンスに差が出る
  • アドオンpakファイルサイズが2倍になる

32bit化するとアドオンサイズが2倍になるのは良いと思います。1ピクセルにつき従来は16bitで表現されていたものが32bitで表現されますからね。
描画処理のパフォーマンスに差が出るというのは、まずピクセル計算に必要なメモリが倍になります。それに伴ってメモリとCPUのデータやりとりも2倍になります。ひめしはあまりグラフィックに詳しくないのでこれがどのレベルまでパフォーマンスに影響を与えるかはよくわかりません。
ともかく、色を32bitで扱うようにするとストレージや処理系の負担になることは事実です。が、近年のコンピュターのパフォーマンスを考えればそろそろ32bit化をしても良い気はしてきます。実は32bit化の足かせになるのはここではありません。Simutransの描画系が16bitから32bitに移行するに当たって困難なのは次の二点です。

  • 実装量が膨大であること
  • アドオンの互換性を担保しなければならないこと

画像描画まわりのコードは膨大です。新しく32bitでの描画をサポートしようとすれば、最低限display/simgraph.hで宣言されている関数をすべて実装しなければなりません。simgraph.hは宣言ファイルですが、このファイルだけで381行あります。16bit色描画を実装したsimgraph16.ccは5336行あります。
実装するのはsimgraphまわりだけではありません。makeobjでpng画像をコンパイルする過程もそうですし、なによりGDIやSDLといった各ライブラリとのインターフェースも32bit色表現に対応させる必要があります。すべての描画ライブラリできちんと動作することを担保せねばなりません。
ちなみに現行Simutransがアルファ対応をするときに32bit化せず16bit空間でゴリ押したのは実装量低減とパフォーマンスの問題とされています。(ソース:
https://forum.simutrans.com/index.php/topic,15314.0.html

アドオンの互換性も大きな課題です。Simutransにはプレイヤーカラーや発光色といった特殊色があります。16bit色環境ではこれらは特殊色として専用の値を割り当てていましたが、32bit色環境でも似た処理を採用するのが望ましいでしょう。するとARGB各成分それぞれフルに8bitを割り当てるわけには行きません。おそらくALPHA成分は5bitにするといった策が現実的になると考えられます。
32bit色環境は間違いなくパフォーマンス面で悪影響をもたらすので、オプションとして提供されるのが望ましいでしょう。すると、アドオンは16bit環境と32bit環境の双方をサポートする必要が出てきます。16bit色環境実行時のパフォーマンスが落ちては元も子もないので、32bit色でコンパイルされたアドオンを16bit色環境でスムーズに表示できるよう工夫が必要です。16bit画像をpakに含めてしまうのは一つの策ですが、明らかにファイルサイズが無駄に大きくなります。32bit色表現で、16bit色環境実行時にスムーズに読み出せるbit配置に工夫するのが良い作戦かと思います。


だらだらと書きましたが、要点はこんな感じです。

  • 減色ナシ化はパフォーマンスが悪化する。それを受け入れれば可能。(ただしアルファチャンネルは若干のビット落ちがあるかも)
  • 本体を減色ナシに対応させるのであれば、減色版本体も同時に提供する必要。
  • 実装はかなり大変。
  • アドオンの互換性をどうするか(減色環境での軽量動作をどう担保するか)の検討が必要

アドオン製作者の皆さんはどうお考えでしょうか?