2023/11/14(火) [n年前の日記]
#1 [hsp] HGIMG3のhgcaptureについて調べてる。その3
Windows10 x64 22H2 + HSP 3.7 beta7 で、仮想画面相当に HGIMG3 で描画して、その結果をメイン表示ウインドウに持ってこれないか実験中。
hgcapture を使えば、HGIMG3 で描画した結果を、HSP標準のイメージバッファに持ってくることができるわけだけど、フレームレートが安定しなくてそのあたりを試していた。hgsync で時間待ちをせずに await で時間待ちをしたら比較的安定しているように見えたのだけど…。こういう呼び方で正しいのかどうか…。
ハードウェアスペックは、CPU : AMD Ryzen 5 5600X (6C12T、3.7 - 4.6GHz)、GPU : NVIDIA GeForce GTX 1060 6GB、RAM : 16GB。
hgcapture を使えば、HGIMG3 で描画した結果を、HSP標準のイメージバッファに持ってくることができるわけだけど、フレームレートが安定しなくてそのあたりを試していた。hgsync で時間待ちをせずに await で時間待ちをしたら比較的安定しているように見えたのだけど…。こういう呼び方で正しいのかどうか…。
ハードウェアスペックは、CPU : AMD Ryzen 5 5600X (6C12T、3.7 - 4.6GHz)、GPU : NVIDIA GeForce GTX 1060 6GB、RAM : 16GB。
◎ ソース :
とりあえず以下のようなソースになった。
_07_hgcapture.hsp
使用画像は以下。
_tex.png
実行結果は以下。
ポイントとしては…。hgdraw → hgrotate で描画 → hgsync で時間待ちをした後、hgcapture を呼んで、そこからHSPの標準描画機能で各描画をして、最後に await で本来待つべき時間待ちをする、みたいな流れになっているところだろうか。色々順番を入れ替えてみたけど、この順番ならフレームレートが安定してくれたように見えた。
ただ、hgsync や await が具体的にどんな処理をしているのか、そのあたり自分は全く分かってないので…。もし分かってる人が見たら、「あ…それをやられてしまうとマズイんだけど」と眉をしかめる状態になっている可能性もあるかもしれない。あるいは他の環境で動かしたらかえってフレームレートが不安定になる可能性もあったりするかもしれない。
余談。上記のソースでは、仮想画面相当のウインドウも画面に表示しているけれど。screen 命令でウインドウを新規作成する際に、screen_hide というモード値を指定すれば、非表示のウインドウになる。実際に本番(?)の処理として書く場合は、仮想画面相当のウインドウは非表示にするだろうなと。
_07_hgcapture.hsp
; hgcapture使用サンプル
#include "hgimg3.as"
#include "d3m.hsp"
; 以下の行をコメントアウトするとウインドウ表示になる
#define FULLSCR
#packopt name "07_hgcapture" ; file name
#packopt type 0 ; generate ".exe"
#define TEXFILE "tex.png"
#pack TEXFILE
#define KB_ESC 128
framerate = 60
title "Screen 0"
; メイン表示ウインドウを確保
dispid = 2
#ifdef FULLSCR
; get desktop size
dispw = ginfo_dispx
disph = ginfo_dispy
bgscr dispid, dispw, disph, 0, 0, 0, dispw, disph
#else
dispw = 1600
disph = 900
screen dispid, dispw, disph, 0
title "Screen " + dispid
#endif
; hgcapture用バッファを確保
vscrw = 800
vscrh = 450
tbufid = 6
buffer tbufid, vscrw, vscrh
; 仮想画面相当の表示ウインドウを確保
vscrid = 5
;modevalue = screen_hide
modevalue = 0
screen vscrid, vscrw, vscrh, modevalue
title "Screen " + vscrid
hgini
; load texture
texload2 TEXFILE
texid = stat ; get texture ID
texw = 512
texh = 512
clscolor $4080c0 ; set clear color
angle = 0.0
time_start = d3timer()
*mainloop
repeat
; get FPS
tm = d3timer() - time_start
fps = d3getfps()
; ESC key to exit
stick k, 0
if k & KB_ESC : break
angle += 0.5
hgdraw
; draw images (HGIMG3)
objmax = 96
repeat objmax
r = double(vscrh) * 0.5
a = angle + (270.0 / double(objmax)) * double(cnt)
x = int(r * cos(deg2rad(a))) + (vscrw / 2)
y = int(r * sin(deg2rad(a))) + (vscrh / 2)
d = double(cnt) / double(objmax)
src_x = (idx \ 2) * texw
src_y = ((idx / 2) \2) * texh
idx = (cnt \ 4)
rot = deg2rad(angle * 2.0 + 360.0 * d)
; scale = 1.0 - (0.75 * d)
scale = 2.0 - (1.75 * d)
dst_w = int(double(texw) * scale)
dst_h = int(double(texh) * scale)
; draw image by celput
gmode gmode_rgb0, texw, texh
pos x, y
hgrotate texid, src_x, src_y, rot, dst_w, dst_h
loop
if 0 {
t = (1000 / framerate) - 1
if t <= 0 : t = 1
hgsync t
} else {
hgsync 12
}
; HGIMG3 の描画結果をキャプチャしてbuffer(ID=tbufid)にコピー
; 右端と下端に数ドット黒部分が出るのはバグらしい
gsel tbufid
; redraw 0
hgcapture
; redraw 1
; メイン表示ウインドウにHGIMG3の描画結果を描画していく
gsel dispid
redraw 0
; tbufid から dispid に拡大描画 (HSP標準描画機能)
if 1 {
gmode gmode_gdi
pos 0, 0
gzoom dispw, disph, tbufid, 0, 0, vscrw, vscrh, 0
} else {
gmode gmode_gdi, vscrw, vscrh
pos (dispw / 2), (disph / 2)
grotate tbufid, 0, 0, 0.0, dispw, disph
}
; draw text (HSP標準描画機能)
if 1 {
font "Tahoma", 20, 1, 2
objcolor 255, 255, 255
color 16, 16, 16
pos 16, 16
mes strf("[%dx%d] %d FPS", vscrw, vscrh, fps), 4
}
redraw 1
await (1000 / framerate)
loop
*mainloop_end
end
使用画像は以下。
_tex.png
実行結果は以下。
ポイントとしては…。hgdraw → hgrotate で描画 → hgsync で時間待ちをした後、hgcapture を呼んで、そこからHSPの標準描画機能で各描画をして、最後に await で本来待つべき時間待ちをする、みたいな流れになっているところだろうか。色々順番を入れ替えてみたけど、この順番ならフレームレートが安定してくれたように見えた。
ただ、hgsync や await が具体的にどんな処理をしているのか、そのあたり自分は全く分かってないので…。もし分かってる人が見たら、「あ…それをやられてしまうとマズイんだけど」と眉をしかめる状態になっている可能性もあるかもしれない。あるいは他の環境で動かしたらかえってフレームレートが不安定になる可能性もあったりするかもしれない。
余談。上記のソースでは、仮想画面相当のウインドウも画面に表示しているけれど。screen 命令でウインドウを新規作成する際に、screen_hide というモード値を指定すれば、非表示のウインドウになる。実際に本番(?)の処理として書く場合は、仮想画面相当のウインドウは非表示にするだろうなと。
[ ツッコむ ]
以上、1 日分です。