RGSS2を知る(20)

20回目になった。
おおまかな所はわかってきた気がするが、細かいところに謎が多すぎる。
ソースが無いのでしょうがない。


RGSSはソフトウェアで描画しているような気はしているのだが、ソフト描画で高速に行うのが難しいのは拡大・縮小・回転。
とりあえず回転に関してはマニュアルに「遅い」とわざわざ書いてあるぐらいだから、遅いのだろう。
でも今回の話題は速度ではなく、その品質について。


Planeクラスを使ってこのようなコードを書く。

b = Bitmap.new(100,100)
b.fill_rect(Rect.new(0,0,100,100), Color.new(0,255,0))
b.fill_rect(Rect.new(1,1,98,98), Color.new(0,0,0))

c = Color.new(255,255,255)
for x in 0..49
  for y in 1..98
    b.set_pixel(x*2, y, c)
  end
end
  
Graphics.resize_screen(320,240)

p = Plane.new
p.bitmap = b
#p.zoom_x = 1.01

loop do
  Graphics.update
end

1行コメントにしてあるのは、あとでこれを有効にしてどうなるかを比較するためで、まずは拡大しない描画。
100*100の画像に緑で枠を描いて、その中に白い縦線を1ピクセルおきに引き、Planeで画面いっぱいに並べる。

細かい描画なので画面を小さくして等倍で貼り付けた。いつもはJPEGなのだが今回はPNGで。
左端の緑の線が白で上書きされて消えているのは意図的じゃなくてバグだが、目的は達することができるのでよいとする。
では次、コメントアウトをはずした画像。

この2つを比較すると、1.01倍したほうの左端がちょっと太くなっているのがわかる。
この結果から、拡大処理のアルゴリズムを導くことができる。
ようするに0スタートで100/101を足して切り捨てたピクセルから色を取っている。浮動小数点を使わずブレゼンハムアルゴリズムかもしれないが、どっちでも結果は同じだ。
線形補間はしていないので、拡大処理としてはおそらく最も高速だろう。
縮小は同じアルゴリズムで間引きが行われる。ブレンドはされないから、たとえば0.5倍にすると1ピクセルおきに取得されて、今回の場合だと真っ白になり、描画を1ピクセルずらすと真っ黒になる。


ちなみにDXRubyではデフォルトで線形補間をしていて、Window.magFilter=TEXF_POINTの指定でRGSSと同様の処理にもできる。
線形補間してもGPUによる並列処理なので処理時間は隠蔽される。
このあたりは3D描画を応用したハードウェア処理の強みだ。
なお、現在開発中のFreeRGSS(仮名)ではこのような描画になる。

ピクセルのしわ寄せが真ん中に来ているのは、ズレを左右の端に半分ずつ適用しているからだろう。
これはうちのノートの例であって、ビデオカードやドライバの作りによって結果が変わってくる可能性がある。