mieki256's diary



2023/09/27(水) [n年前の日記]

#1 [hsp] 疑似3D道路その20

_昨日 の続き。HSP 3.6 を使って、疑似3D道路が作れないか試しているところ。環境は Windows10 x64 22H2。

拡大縮小描画に gzoom を使っていたけど、grotate や gsquare を使っても拡大縮小描画ができると今頃になって知ったので、処理速度がどのくらい違うのか試していた。

拡大縮小描画について :

今まで、HSP 3.6 で拡大縮小描画をしたかったら gzoom という命令を使うしかないのかなと思い込んでいたのだけど、その後ググってたら、grotate や gsquare という命令を使っても拡大縮小描画ができると知った。名前からして grotate は回転描画しかできないのかなと思い込んでた…。

_grotateとgzoom - HSPTV!掲示板
_gzoomにgmodeを適用する方法 - HSPTV!掲示板
_透明色付き縮小コピーのやり方がわからない! - HSPTV!掲示板
_gmodeが効かない - HSPTV!掲示板
_標準命令での解像度設定について - HSPTV!掲示板

gzoom は、RGB=(0,0,0) を透明色として扱うための gmode gmode_rgb0 の指定が反映されないので、透明部分を含んだ画像を拡大縮小描画しようとすると少し面倒なことになる。仮バッファを用意して、一旦仮バッファに gzoom で拡大縮小描画をしてから、その仮バッファの内容を gcopy で画面に転送することで透明部分を扱ってるように見せかけるのだけど、本来なら1回の描画で済みそうなところを、2回描画してるわけだから、処理も遅くなるだろうと容易に想像できるわけで…。

その点、grotate や gsquare は、gmode gmode_rgb0 の指定を反映しつつ拡大縮小描画ができるので、1回の描画で済む。その代わり、gzoom と比べると精度が粗いそうで…。

命令メリットデメリット
gzoom精度がそこそこ良いので描画結果が比較的マシ処理が重い。透明色を扱えない(gmode設定が反映されない)ので、透明部分を含む画像を扱う時は実質2回描画することになるから遅い。
grotate透明色を扱える。1回の描画で済むから処理が速い。回転描画もできる精度が粗い。描画結果はよろしくない。描画座標として中心点を指定するあたりでミスしがち
gsquare透明色を扱える。1回の描画で済むから処理が速い。四角形を任意の形で描画できる精度が粗い。描画結果はよろしくない。引数を配列で渡すあたりは少し面倒臭い

試しに、今まで gzoom で描画していた部分を、grotate や gsquare で置き換えてみた。該当部分だけ抜き出して貼ってみる。

    ; sx, sy, sw, sh : 転送元の x, y, 幅, 高さ
    ; dx, dy, dw, dh : 転送先の x, y, 幅, 高さ
    ; srcid : 転送元イメージバッファID
    ; dstid : 転送先イメージバッファID
    ; tmpid : 仮イメージバッファID

    switch zoom_kind@
    case 0
        ; gzoomで処理
        ; gzoom は透明色を扱えない(gmode設定が反映されない)ので小技が必要
        ; 一旦、仮バッファに拡大縮小描画する
        gsel tmpid
        pos 0, 0
        gzoom dw, dh, srcid, sx, sy, sw, sh, 0

        ; 仮バッファから実スクリーンに gcopy で転送
        ; gcopy なら RGB=(0,0,0) を透明色として扱える
        gsel dstid
        gmode gmode_rgb0    ; RGB=(0,0,0)を透明色として扱う
        pos dx, dy
        gcopy tmpid, 0, 0, dw, dh
        swbreak

    case 1
        ; grotateで処理
        ; grotate なら一発で透明色(RGB=(0,0,0))を扱えるので処理が速い
        ; その代わり精度が荒くて描画結果がプルプルと震える
        gsel dstid
        gmode gmode_rgb0, sw, sh            ; 転送元サイズをここで指定
        pos dx + (dw / 2), dy + (dh / 2)    ; 中心座標を転送先座標として指定
        grotate srcid, sx, sy, 0, dw, dh    ; 転送元座標、転送先サイズを指定
        swbreak

    case 2
        ; gsquareで描画
        ; gsquareも一発で透明色(RGB=(0,0,0))を扱えるので処理が速い
        ; その代わりこれも精度が荒い。プルプルする
        dim _dx, 4
        dim _dy, 4
        dim _sx, 4
        dim _sy, 4
        
        ; 転送先座標
        _dx(0) = dx
        _dy(0) = dy
        _dx(1) = dx + dw - 1
        _dy(1) = dy
        _dx(2) = dx + dw - 1
        _dy(2) = dy + dh - 1
        _dx(3) = dx
        _dy(3) = dy + dh - 1
        
        ; 転送元座標
        _sx(0) = sx
        _sy(0) = sy
        _sx(1) = sx + sw - 1
        _sy(1) = sy
        _sx(2) = sx + sw - 1
        _sy(2) = sy + sh - 1
        _sx(3) = sx
        _sy(3) = sy + sh - 1
        
        gsel dstid
        gmode gmode_rgb0
        gsquare srcid, _dx, _dy, _sx, _sy
        swbreak
    swend


grotate や gsquare で描画してみたところ、劇的に処理が軽くなった。ちなみに CPU は AMD Ryzen 5 5600X の環境。
  • gzoom 利用時は、仮想画面サイズを 1280x720 にすると 15FPSが限界だった。
  • grotate、gsquare 利用時は、仮想画面サイズを 1280x720 にしても 30FPSが出せた。
単純計算では、描画回数(描画面積)が半分になっているわけだから、半分の処理時間で済むということかなと…。さすがに60FPSは無理だったけど、30FPSなら、まあ、全然見れる雰囲気。

ただ、描画結果は少々厳しいことになった。じわじわと拡大率が変わっていく状況では、ビルボード(スプライト)がプルプルと震える…。

これが例えばアウトランシリーズのように、スゴイスピードでビュンビュン走っていく疑似3D道路だったら、そのプルプル感は全然気にならないのだけど。今回、スクーターでトロトロとのんびり走っていく雰囲気にしたいので、このプルプル感はちょっとなあ、という気もする…。しかし、この処理の軽さは捨てがたい…。gzoom ならプルプルしないけど、その代わりフレームレートを半分まで落とさないといかんし…。

FPS測定について :

実際どのくらいのFPSが出てるのか測定したいと思って、あちこちの解説記事を眺めていたのだけど。HSP 3.6 の場合、d3module という拡張プラグインの中に、FPSを取得する命令、d3getfps() があったので、試しに使ってみたところ、あっさりと表示できてしまった。これでいいんじゃないかな…。

_OHDL - d3getfps
_OHDL - sample_08_ball.hsp

昔の HSP では、このあたり自前で用意しないといけなかったようだなと…。

時間待ちをするawaitについて :

時間待ちをしてフレームレートを一定にする await についても、昔と今とでは状況が違うらしい。

昔は使っているタイマーの精度が低かったから、自前で似たような処理を書いてフレームレートの安定化を試みないといけなかったようだけど。HSP 3.31β1 の時点で使うタイマーを変えて精度が上がったようで。HSP 3.6 なら await を使うだけでもそこそこ真っ当なフレームレートになってくれる、という話を見かけた。

_hsp3関連 更新履歴
_ゲーム等を作るときのウェイトについて - HSPTV!掲示板

ちなみに await は、wait と違って、前回呼ばれてから今回呼ばれるまでの時間を測っていて、あとどのくらい sleep すればいいかをその都度変えている、とのことらしい。

_HSPのwaitとawaitの違い - まどろみの思考空間
_await命令の、説明文がわかりません。 - HSPTV!掲示板

余談。ふと思ったけど、await が、指定されたミリ秒より多い時間がかかったか、かかってないかをフラグで返してくれたら、そのフラグを見て次のフレームは描画をスキップ、といったこともできるのではなかろうか…。

でもまあ、前回のフレームからの経過時間を自前で調べて、その時間を使って各オブジェクトの移動量を求めるほうが妥当かもしれないけど。例えばLove2Dなどは、そういう感じの処理を推奨してるようだし。

以上、1 日分です。

過去ログ表示

Prev - 2023/09 - Next
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

カテゴリで表示

検索機能は Namazu for hns で提供されています。(詳細指定/ヘルプ


注意: 現在使用の日記自動生成システムは Version 2.19.6 です。
公開されている日記自動生成システムは Version 2.19.5 です。

Powered by hns-2.19.6, HyperNikkiSystem Project