2023/11/27(月) [n年前の日記]
#1 [hsp] HGIMG3のhgrotateやhgrectのバグについて調べてた
プログラミング環境 HSP には、DirectXを利用して描画できる HGIMG3 プラグインが同梱されているのだけど。この HGIMG3 で直接描画(ダイレクト描画)ができる hgrotate や hgrect という命令について、奇数サイズを指定して描画しようとしても偶数サイズになってしまうというバグがあると今頃になって知った。
*1
_hgimg3のhgrotate命令で奇数サイズのコピーが出来ません - HSPTV!掲示板
本当にそうなるのか、Windows10 x64 22H2 + HSP 3.7 beta 7 で動作確認してみた。
 _hgimg3のhgrotate命令で奇数サイズのコピーが出来ません - HSPTV!掲示板
本当にそうなるのか、Windows10 x64 22H2 + HSP 3.7 beta 7 で動作確認してみた。
◎ 結果 :
 hgrotate で、16x16 の画像を、14x16, 15x16, 16x16, 17x16, ... 21x16 と描画してみたところ、以下のようになった。
8倍に拡大。

たしかに、奇数サイズを指定しても、偶数サイズになってしまっている…。
hgrect はどうなるだろう。これも、14x16, 15x16, 16x16, 17x16, ... 21x16 のサイズで描画してみた。

こちらも、奇数サイズを指定しているのに偶数サイズになってしまっている…。
これは参った…。hgrotate さえあれば、やりたい描画処理はおおよそできるだろうと安易に思っていたけれど、こんなバグがあるのでは…。
つまるところ、HGIMG3を使って拡大縮小描画をすると、画像の外枠と言うか、輪郭に関しては、ウインドウ解像度の約1/4の解像度でしか描画できませんよ、という状態になるのだな…。 *2
HGIMG3 は開発終了ということになっているので、このバグは修正されない可能性が高いのだろうな…。困る…。hsp3dish や HGIMG4 でスクリーンセーバを作れるなら HGIMG3 を使う必要も無さそうなのだけど、今のところ高速描画するスクリーンセーバを HSP で作りたいとなると HGIMG3 を使うしかないわけで…。まあ、「高速描画できる代わりに解像度は1/4相当」と割り切っちゃうのもアリかもしれんけど…。
8倍に拡大。

たしかに、奇数サイズを指定しても、偶数サイズになってしまっている…。
hgrect はどうなるだろう。これも、14x16, 15x16, 16x16, 17x16, ... 21x16 のサイズで描画してみた。

こちらも、奇数サイズを指定しているのに偶数サイズになってしまっている…。
これは参った…。hgrotate さえあれば、やりたい描画処理はおおよそできるだろうと安易に思っていたけれど、こんなバグがあるのでは…。
つまるところ、HGIMG3を使って拡大縮小描画をすると、画像の外枠と言うか、輪郭に関しては、ウインドウ解像度の約1/4の解像度でしか描画できませんよ、という状態になるのだな…。 *2
HGIMG3 は開発終了ということになっているので、このバグは修正されない可能性が高いのだろうな…。困る…。hsp3dish や HGIMG4 でスクリーンセーバを作れるなら HGIMG3 を使う必要も無さそうなのだけど、今のところ高速描画するスクリーンセーバを HSP で作りたいとなると HGIMG3 を使うしかないわけで…。まあ、「高速描画できる代わりに解像度は1/4相当」と割り切っちゃうのもアリかもしれんけど…。
◎ ソース :
hgrotate の検証に使ったソースは以下。
_10_hgrotate_bug2.hsp
使用画像は以下。
_tex.png
hgrectの検証に使ったソースは以下。
_12_hgrect_bug.hsp
_10_hgrotate_bug2.hsp
    ; hgimg3 hgrotate bug
    ; hgrotateで奇数サイズを指定しても偶数サイズにされてしまうバグの動作確認
    ; 16x16ドットの画像を、14x16, 15x16, 16x16, ... 21x16 で描画してみた
    ; たしかに、奇数サイズは偶数サイズになってしまった
    ; 2023/11/27, use HSP 3.7 beta 7
    
    #include "hgimg3.as"
    
    #packopt name   "10_hgrotate_bug2"  ; file name
    #packopt type   0   ; generate ".exe"
    
    #define TEXFILE     "tex.png"
    #pack   TEXFILE
    
    #define KB_ESC      $00080
    
    screen 0, 512, 288, 0       ; initialize screen
    wdw_w = ginfo_winx          ; get window size
    wdw_h = ginfo_winy
    hgini                       ; initialize hgimg3
    
    ; load texture
    ; * texload : alpha channel not support
    ; * texload2 : alpha channel support
    texload2 TEXFILE
    texid = stat            ; get texture ID
    
    clscolor $4080c0        ; set clear color
    
*mainloop
    stick k, 0                      ; check keyboard
    if k & KB_ESC : goto *job_end   ; ESC key to exit
    
    hgdraw          ; draw start
    
    repeat 8
        ; draw image
        
        ; set src size 16x16
        gmode gmode_rgb0, 16, 16
        
        ; set position
        x = wdw_w / 2
        y = 80 + (16 + 4) * cnt
        pos x, y
        
        src_x = 0
        src_y = 0
        rot = 0.0
        dst_w = 14 + cnt
        dst_h = 16
        hgrotate texid, src_x, src_y, rot, dst_w, dst_h   ; draw texture
    loop
    
    hgsync 15       ; draw end and wait
    goto *mainloop
*job_end
    hgbye       ; release HGIMG3 plugin
    end
使用画像は以下。
_tex.png
hgrectの検証に使ったソースは以下。
_12_hgrect_bug.hsp
    ; hgimg3 hgrect bug
    ; 2023/11/27
    ; hgrectで奇数サイズを指定しても偶数サイズにされてしまうバグについて動作確認
    ; 14x16, 15x16, 16x16, ... 21x16 で描画してみる。
    
    #include "hgimg3.as"
    
    #packopt name   "12_hgrect_bug"  ; file name
    #packopt type   0   ; generate ".exe"
    
    #define KB_ESC      $00080
    
    screen 0, 512, 288, 0       ; initialize screen
    wdw_w = ginfo_winx          ; get window size
    wdw_h = ginfo_winy
    hgini                       ; initialize hgimg3
    
    clscolor $4080c0        ; set clear color
    
*mainloop
    stick k, 0                      ; check keyboard
    if k & KB_ESC : goto *job_end   ; ESC key to exit
    
    hgdraw          ; draw start
    
    repeat 8
        gmode 0
        color 1, 1, 1
        
        ; draw rectangle
        x = wdw_w / 2
        y = 80 + (16 + 1) * cnt
        rot = 0.0
        dst_w = 14 + cnt
        dst_h = 16
        hgrect x, y, rot, dst_w, dst_h
    loop
    
    hgsync 15       ; draw end and wait
    goto *mainloop
*job_end
    hgbye       ; release HGIMG3 plugin
    end
◎ dxgrotateを使ってみる :
前述の掲示板でのやり取りの中で、奇数サイズを指定しても正しく反映して描画できる、dx8_grot.as (dxgrotate) という追加ライブラリが紹介されている。
_hgimg3のhgrotate命令で奇数サイズのコピーが出来ません - HSPTV!掲示板 (NO.88437 を参照のこと)
コレを使えば正しく描画されるのかどうか確認してみた。

たしかに、奇数サイズも正しく反映されているように見えた。素晴らしい。
ただ、若干動作が怪しいところもあって…。横方向のサイズのみを変化させているのに、縦方向の描画内容までずれてしまう時がある。上記のスクリーンショットで言えば、25x16 を指定して描画した際に、描画結果がおかしくなっている。
また、d3dx9_39.dll を要求するあたりも少し厳しいかもしれない。OSによってはDirectXランタイムのインストールが別途必要になりそうなので…。
検証に使ったソースと画像は以下。dx8_grot.as は、掲示板で紹介されていたものを、ほぼそのまま利用。(*main 以下は除外してある。) ありがたや。
_11_hgrotate_bugfix2.hsp
_dx8_grot.as
_tex.png
_hgimg3のhgrotate命令で奇数サイズのコピーが出来ません - HSPTV!掲示板 (NO.88437 を参照のこと)
コレを使えば正しく描画されるのかどうか確認してみた。

たしかに、奇数サイズも正しく反映されているように見えた。素晴らしい。
ただ、若干動作が怪しいところもあって…。横方向のサイズのみを変化させているのに、縦方向の描画内容までずれてしまう時がある。上記のスクリーンショットで言えば、25x16 を指定して描画した際に、描画結果がおかしくなっている。
また、d3dx9_39.dll を要求するあたりも少し厳しいかもしれない。OSによってはDirectXランタイムのインストールが別途必要になりそうなので…。
検証に使ったソースと画像は以下。dx8_grot.as は、掲示板で紹介されていたものを、ほぼそのまま利用。(*main 以下は除外してある。) ありがたや。
_11_hgrotate_bugfix2.hsp
_dx8_grot.as
_tex.png
◎ hglineはどうだろう :
画像を描画する hgrotate、矩形を描画する hgrect は奇数サイズが反映されないのは分かったけれど、線を描画する hgline はどうだろう。気になったので確認してみた。
ドットエディタ EDGE2 で該当部分(左上部分)を拡大表示。

さすがに hgline は奇数サイズも描画できるっぽい…。良かった。
いや。ちょっと待て。コレもしかして描画位置がずれてないか…? (0,0)-(0,0), (0,2)-(1,2), (0,4)-(2,4), ... と描いてるはずだけど、始点座標は描画されていないように見える…。
検証に使ったソースは以下。
_13_hgline_bug.hsp
標準機能の line を使うとどうなるだろう。試してみた。

_13_normaline.hsp
こちらは逆に、終点座標が描画されない模様。
line にしろ、hgline にしろ、始点座標か終点座標のどちらかは描画されないのだろう…。
ドットエディタ EDGE2 で該当部分(左上部分)を拡大表示。

さすがに hgline は奇数サイズも描画できるっぽい…。良かった。
いや。ちょっと待て。コレもしかして描画位置がずれてないか…? (0,0)-(0,0), (0,2)-(1,2), (0,4)-(2,4), ... と描いてるはずだけど、始点座標は描画されていないように見える…。
検証に使ったソースは以下。
_13_hgline_bug.hsp
    ; hgimg3 hgline bug sample
    ; hglineで奇数サイズを指定した場合も偶数サイズにされるかどうか動作確認
    ; 2023/11/27, use HSP 3.7 beta 7
    
    #include "hgimg3.as"
    
    #packopt name   "13_hgline_bug"  ; file name
    #packopt type   0   ; generate ".exe"
    
    #define KB_ESC      $00080
    
    screen 0, 512, 288, 0       ; initialize screen
    wdw_w = ginfo_winx          ; get window size
    wdw_h = ginfo_winy
    hgini                       ; initialize hgimg3
    
    clscolor $4080c0        ; set clear color
    
*mainloop
    stick k, 0                      ; check keyboard
    if k & KB_ESC : goto *job_end   ; ESC key to exit
    
    hgdraw          ; draw start
    
    gmode 0
    color 128, 128, 128
    hgrect 8, 8, 0.0, 16, 16
    
    repeat 8
        gmode 0
        color 1, 1, 1
        
        ; draw rectangle
        x = 0
        y = 0 + (2 * cnt)
        w = cnt
        hgline x + w, y, x, y
    loop
    
    hgsync 15       ; draw end and wait
    goto *mainloop
*job_end
    hgbye       ; release HGIMG3 plugin
    end
標準機能の line を使うとどうなるだろう。試してみた。

_13_normaline.hsp
こちらは逆に、終点座標が描画されない模様。
line にしろ、hgline にしろ、始点座標か終点座標のどちらかは描画されないのだろう…。
[   ツッコむ ]
以上、1 日分です。




