なんだか雲行きの怪しい雑記帖

ぐだぐだ日記とメモと,あと不定期更新

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

【HSP】【DXLib】標準のCEL系命令をDXLibの命令で置き換えるモジュール


前置き

表題の通りですが,なぜそれをやるのかについて簡単に.

DXLibはプリミティブな命令の集まり

そもそもDXLibはかなりプリミティブというか,命令体系(という言葉が正確な表現かどうかはさておき)としてはHSP標準のソレと似ていてます.

具体的には,一つの画面を構成するために行う処理が,いずれも「画面のこの場所にこの画像を描画する」といった命令の積み重ねでできていること,です.

ちょうどHSPの標準命令と体系が似ているのであれば,単純に置き換えが簡単そうです.

なんだかんだDirectXって高速

更に,DXLibは内部でDirectXを使って描画を行っているため,HSPの標準命令が行うGDIよりは高いパフォーマンスが見込める点があります.

ついでに言うと,GDI(GDI+ではない)では扱えない透過情報を持った画像が扱えるようになる,というのもメリットが大きい.
(そういえばGDI+を使ったArtlet2Dというライブラリもあるのですが,あんまり早いという話は聞かない)


今回目指したこと

最初に言っておくと,あんまり大きいことは目指さなかったデス.

そもそもこれをやった理由が
・案外HSPerの方でDXLibに興味ある人が多そう(主観)
・「でも今からDXLib使ってみるのもな…置き換えコストが大きくて嫌だなぁ」とか思っている人って実は沢山居そう(願望)
の二点であり,根本的に勘違いの可能性も捨てきれないからです...

HSPの標準命令を網羅的に置き換えるのは無理ですが,命令数も少ないCEL系の命令だったらDXLibにも置き換えられそうだし費用効果が高そうなので,今回はそこを着地点としました.

モジュール本体は続き。

モジュール本体以外に必要なもの


DxLib本体とHSPからそれを使うモジュール。

DxLib本体はこちら
DxLib.as本体はあちら

モジュール本体


特に作り方の説明とかはせず,モジュールはこうなりました.

//------------------------------------------------------------------------------
//
// DxLib cel for HSP (2015/08/10)
// http://fe0km.blog.fc2.com/
// https://twitter.com/exrd
// by exrd
//
//
//------------------------------------------------------------------------------
//
// inoviaさんの DxLib for HSP に触発されて作ったもの
//
// ●既存のHSPの命令の枠組みをDXライブラリの命令によって実現することで,
// ”スクリプトはそのままに”DirectXを使った高速なレンダリングが可能にならないか,の実験
// ※ただし,全ての機能が代替される訳ではないため,正しく動かないものもあります
//
// ●使い方サンプルは「sample.hsp」を参照してください
// 現状対応している(書き換えている)命令は次
// screen, buffer, celload, celiv, redraw, gsel, gcopy, boxf, line, circle, font, mes, await, wait
// むしろ,対応してないのは次
// axobj, bmpsave, bgscr, chgdisp, cls, gradf, groll, grotate, gsquare, gzoom, pallete, picload, pget, print, pset
// モジュール側から弄ってないけど普通に使えるのは次
// color, dialog, hsvcolor, pos, syscolor, sysfont, title
//
// ●明らかに標準と違うのは
// ・gmode 3とかの半透明の影響がmesやboxfにもでること(ある意味いいところでもある)
// ・作れるスクリーンは1個だけ
// ・redraw 0~redraw 1は必ず挟む必要がある(redraw 1しないとScreenFlipしないため)
// ・起動が遅い(内部で色々初期化しているのでしょうがない)
// ・grotateがない(celputへ移行する必要がある)
// ・透明色,アルファが有効(PNGなどアルファ値を含む画像がフルにサポートされているため)
// ・gmode 7は使えません
// ・bufferの前にscreenを書く必要がある
// 正確には,screenのタイミングをDXライブラリ初期化のタイミングとしています
// また,メインのスクリーンはid 0と決め打ちしています
// つまり,最初にid 0のスクリーンを作る必要があります(サンプルの通りの流れが必要)
// そして,二回目以降のscreenによる初期化においては,それまで作ったbufferが全部消えます
// ・パレットモードは未サポート
// ※本来的にはちゃんとモジュール書きなおせば動くハズ
//
// ●その他注意事項
// ・DxLibは3.14系以降が安定しています
// ※API互換の関係で少なくとも3.13e以降でないと動かないです
//
//
//------------------------------------------------------------------------------
//
// license : NYSL Version 0.9982 : for detail, see http://www.kmonos.net/nysl/
//
// A. 本ソフトウェアは Everyone'sWare です。このソフトを手にした一人一人が、
// ご自分の作ったものを扱うのと同じように、自由に利用することが出来ます。
// A-1. フリーウェアです。作者からは使用料等を要求しません。
// A-2. 有料無料や媒体の如何を問わず、自由に転載・再配布できます。
// A-3. いかなる種類の 改変・他プログラムでの利用 を行っても構いません。
// A-4. 変更したものや部分的に使用したものは、あなたのものになります。
// 公開する場合は、あなたの名前の下で行って下さい。
// B. このソフトを利用することによって生じた損害等について、作者は
// 責任を負わないものとします。各自の責任においてご利用下さい。
// C. 著作者人格権は exrd(えくー) に帰属します。著作権は放棄します。
// D. 以上の3項は、ソース・実行バイナリの双方に適用されます。
//
//
//------------------------------------------------------------------------------
//
//


#ifndef __INC_DXLIBCEL_HSP__
#define __INC_DXLIBCEL_HSP__

#include "DxLib.as"

#module "dxlibcel"


#define DXLIBCEL_SCREEN_NUM_MAX (128)
#define DXLIBCEL_SCREEN_DIV_NUM_MAX (128)

#define DXLIBCEL_REPLACE_EMBEDDED_COMMANDS

#define dxlibcelInit _dxlibcelInit
#deffunc _dxlibcelInit
if ( is_init ) : return 1
is_init = 1

SetOutApplicationLogValidFlag 0// disable log output
SetWaitVSyncFlag 0// do not wait vsync
SetUseFPUPreserveFlag 1// compatibility is prior than speed, in this context
SetUseDXArchiveFlag 0//
SetUseDirect3DVersion DX_DIRECT3D_9EX// we use dx9ex

is_transColor_sync = 0

draw_rect_srcX = 32 : draw_rect_srcY = 32
font_size = 12

dim buffer_handle, DXLIBCEL_SCREEN_NUM_MAX
ddim buffer_rot_cx, DXLIBCEL_SCREEN_NUM_MAX
ddim buffer_rot_cy, DXLIBCEL_SCREEN_NUM_MAX
dim buffer_handle_div, DXLIBCEL_SCREEN_NUM_MAX, DXLIBCEL_SCREEN_DIV_NUM_MAX

_dxlibcelClear
return

#deffunc _dxlibcelDestroy onexit
DxLib_IsInit
if ( stat ) {
DxLib_End
_dxlibcelClear
}
return

#deffunc _dxlibcelClear
screen_id = -1

repeat DXLIBCEL_SCREEN_NUM_MAX
t_idx = cnt
buffer_handle(t_idx) = -1
buffer_rot_cx(t_idx) = 0.0
buffer_rot_cy(t_idx) = 0.0
repeat DXLIBCEL_SCREEN_DIV_NUM_MAX
buffer_handle_div(t_idx,cnt) = -1
loop
loop
return


// screen_id, width, height, mode, px, py, cx, cy
#define global dxlibcelScreen( %1 =0, %2 =640, %3 =480, %4 =0, %5 =-1, %6 =-1, %7 =-1, %8 =-1 ) _dxlibcelScreen %1, %2, %3, %4, %5, %6, %7, %8
#deffunc _dxlibcelScreen int p1, int p2, int p3, int p4, int p5, int p6, int _p7, int _p8, local p7, local p8, local l_colorDepth
dxlibcelInit
DxLib_IsInit : if ( stat ) : _dxlibcelDestroy// already initialized
// fix width, height
if ( _p7 < 0 ) : p7 = p2 : else : p7 = _p7
if ( _p8 < 0 ) : p8 = p3 : else : p8 = _p8
// create
screen@hsp p1, p2, p3, p4, p5, p6, p7, p8
//
l_colorDepth = 32
if ( p4 & 1 ) : l_colorDepth = 16// 厳密には全然違うのだが,とりあえず…
SetGraphMode p1, p2, l_colorDepth, 60// refresh rate is hardcoded
ChangeWindowMode 0// not using full-screen
SetUserWindow hwnd// use hsp window
SetUserWindowMessageProcessDXLibFlag 1// deny processing
DxLib_Init// init!
// set default
SetDrawMode DX_DRAWMODE_BILINEAR
SetUseTransColor 0// not use trans color
SetUseTransColorGraphCreateFlag 0// too
SetBackgroundColor 255, 255, 255
SetDrawBlendMode DX_BLENDMODE_NOBLEND, 0
// cur
SetDrawScreen DX_SCREEN_BACK
ClearDrawScreen 0
return ( stat >= 0 )

// screen_id, width, height, mode
#define global dxlibcelBuffer( %1 =0, %2 =640, %3 = 480, %4 =0 ) _dxlibcelBuffer %1, %2, %3, %4
#deffunc _dxlibcelBuffer int p1, int p2, int p3, int p4
DxLib_IsInit : if ( stat == 0 ) : return 0// not initialized yet
dxlibcelReleaseBuffer p1
MakeScreen p2, p3
buffer_handle(p1) = stat
return 1

// screen_id
#deffunc dxlibcelReleaseBufferDiv int p1
if ( buffer_handle(p1) == -1 ) : return 0
repeat DXLIBCEL_SCREEN_DIV_NUM_MAX
if ( buffer_handle_div(p1,cnt) != -1 ) {
DeleteGraph buffer_handle_div(p1,cnt)
}
buffer_handle_div(p1,cnt) = -1
loop
return 1

// screen_id
#deffunc dxlibcelReleaseBuffer int p1
if ( buffer_handle(p1) == -1 ) : return 0
dxlibcelReleaseBufferDiv p1
DeleteGraph buffer_handle(p1)
buffer_handle(p1) = -1
return 1


// filename, screen_id, mode : return new screen id
#define global dxlibcelLoad( %1, %2 =-1, %3 =0 ) _dxlibcelLoad %1, %2, %3
#deffunc _dxlibcelLoad str p1, int _p2, int p3, local p2, local l_graphHandle, local l_graphSizeX, local l_graphSizeY, local l_prevBlendModeX, local l_prevBlendModeY, local l_prevDrawScreen
// load graph
LoadGraph p1
l_graphHandle = stat
if ( l_graphHandle < 0 ) : return -1// load failed
// get size
l_graphSizeX = 0 : l_graphSizeY = 0
GetGraphSize l_graphHandle, varptr( l_graphSizeX ), varptr( l_graphSizeY )
// make new screen
if ( _p2 < 0 ) {
// search empty
repeat DXLIBCEL_SCREEN_NUM_MAX
if ( buffer_handle(cnt) == -1 ) {
p2 = cnt
}
loop
} else {
p2 = _p2
}
_dxlibcelBuffer p2, l_graphSizeX, l_graphSizeY
// copy
l_prevBlendModeX = 0 : l_prevBlendModeY = 0
GetDrawScreen : l_prevDrawScreen = stat
SetDrawScreen buffer_handle(p2)
GetDrawBlendMode varptr( l_prevBlendModeX ), varptr( l_prevBlendModeY )
SetDrawBlendMode DX_BLENDMODE_NOBLEND, 0
DrawGraph 0, 0, l_graphHandle, 0
DeleteGraph l_graphHandle
// restore
SetDrawScreen l_prevDrawScreen
SetDrawBlendMode l_prevBlendModeX, l_prevBlendModeY
//
buffer_rot_cx(p2) = 0.0
buffer_rot_cy(p2) = 0.0
return p2

// screen_id, divX, divY, rotCX, rotCY
#define global dxlibcelDiv( %1 =1, %2 =0, %3 =0, %4 =0, %5 =0 ) _dxlibcelDiv %1, %2, %3, %4, %5
#deffunc _dxlibcelDiv int p1, int _p2, int _p3, int p4, int p5, local p2, local p3, local l_graphSizeX, local l_graphSizeY, local l_divNumX, local l_divNumY
dxlibcelReleaseBufferDiv
if ( buffer_handle(p1) == -1 ) : return 0// no graph
// get size
l_graphSizeX = 0 : l_graphSizeY = 0
GetGraphSize buffer_handle(p1), varptr( l_graphSizeX ), varptr( l_graphSizeY )
if ( _p2 <= 0 ) : p2 = l_graphSizeX : else : p2 = _p2
if ( _p3 <= 0 ) : p3 = l_graphSizeY : else : p3 = _p3
// make division
l_divNumX = l_graphSizeX/p2// + ( ( l_graphSizeX\p2 ) != 0 )
l_divNumY = l_graphSizeY/p3 + ( ( l_graphSizeY\p3 ) != 0 )
t_idx = 0
repeat l_divNumY
t_y = cnt
repeat l_divNumX
t_x = cnt
DerivationGraph t_x*p2, t_y*p3, p2, p3, buffer_handle(p1)
buffer_handle_div(p1,t_idx) = stat
t_idx++
loop
loop
// set param
buffer_rot_cx(p1) = double(p4)
buffer_rot_cy(p1) = double(p5)
return 1

// screen_id, idx, zoomX, zoomY, rad
#define global dxlibcelPut( %1, %2 =0, %3 =1.0, %4 =1.0, %5 =0.0 ) _dxlibcelPut %1, %2, %3, %4, %5
#deffunc _dxlibcelPut int p1, int p2, double p3, double p4, double p5, local l_graphHandle
if ( p2 == 0 ) {
if ( buffer_handle_div(p1,0) == -1 ) {// no division
l_graphHandle = buffer_handle(p1)
} else {
l_graphHandle = buffer_handle_div(p1,p2)
}
} else {
l_graphHandle = buffer_handle_div(p1,p2)
}
if ( l_graphHandle == -1 ) : return 0
// draw
dxlibcelSyncDrawMode
DrawRotaGraph3 ginfo_cx, ginfo_cy, buffer_rot_cx(p1), buffer_rot_cy(p1), p3, p4, p5, l_graphHandle, 1, 0
return 1


// screen_id, x, y, w, h
#define global dxlibcelGcopy( %1, %2 =0, %3 =0, %4, %5 ) _dxlibcelGcopy %1, %2, %3, %4, %5
#deffunc _dxlibcelGcopy int p1, int p2, int p3, int p4, int p5, local l_graphHandle
l_graphHandle = buffer_handle(p1)
if ( l_graphHandle == -1 ) : return 0
// draw
dxlibcelSyncDrawMode
DrawRectGraph ginfo_cx, ginfo_cy, p2, p3, p4, p5, l_graphHandle, 1, 0
return 1

// screen_id, x, y, rad, w, h
#define global dxlibcelGrotate( %1 =0, %2 =0, %3 =0, %4 =0.0, %5 =-1, %6 =-1 ) _dxlibcelGrotate %1, %2, %3, %4, %5, %6
#deffunc _dxlibcelGrotate int p1, int p2, int p3, double p4, int _p5, int _p6, local p5, local p6, local l_graphHandle, local l_graphSizeX, local l_graphSizeY
l_graphHandle = buffer_handle(p1)
if ( l_graphHandle == -1 ) : return 0
// get size
l_graphSizeX = 0 : l_graphSizeY = 0
GetGraphSize buffer_handle(p1), varptr( l_graphSizeX ), varptr( l_graphSizeY )
// determin size
if ( _p5 < 0 ) : p5 = draw_rect_srcX : else : p5 = _p5
if ( _p6 < 0 ) : p6 = draw_rect_srcY : else : p6 = _p6
// draw
dxlibcelSyncDrawMode
DrawRotaGraph3 ginfo_cx, ginfo_cy, l_graphSizeX/2, l_graphSizeY/2, double(p5)/double(draw_rect_srcX), double(p6)/double(draw_rect_srcY), p4, l_graphHandle, 1, 0
return 1


//
#define global dxlibcelGmode( %1 =0, %2 =32, %3 =32, %4 =0 ) _dxlibcelGmode %1, %2, %3, %4
#deffunc _dxlibcelGmode int p1, int p2, int p3, int p4, local l_graphMode
gmode@hsp p1, p2, p3, p4

SetUseTransColor 0
is_transColor_sync = 0
switch( p1 )
case 2 : l_graphMode = DX_BLENDMODE_NOBLEND : SetUseTransColor 1 : SetTransColor 0, 0, 0 : swbreak
case 3 : l_graphMode = DX_BLENDMODE_ALPHA : swbreak
case 4 : l_graphMode = DX_BLENDMODE_ALPHA : is_transColor_sync = 1 : SetUseTransColor 1 : swbreak
case 5 : l_graphMode = DX_BLENDMODE_ADD : swbreak
case 6 : l_graphMode = DX_BLENDMODE_SUB : swbreak
default : l_graphMode = DX_BLENDMODE_NOBLEND : swbreak
swend
SetDrawBlendMode l_graphMode, p4
draw_rect_srcX = p2 : draw_rect_srcY = p3
return

// sync
#deffunc dxlibcelSyncDrawMode
if ( is_transColor_sync ) {
SetTransColor ginfo_r, ginfo_g, ginfo_b
}
return

// flip
#deffunc dxlibcelScreenFlip
ScreenFlip
ProcessMessage
return

// screen_id
#define global dxlibcelScreenSel( %1 =0, %2 =0 ) _dxlibcelScreenSel %1, %2
#deffunc _dxlibcelScreenSel int p1, int p2, local l_graphSizeX, local l_graphSizeY
gsel@hsp p1, p2
if ( p1 == 0 ) {
SetDrawScreen DX_SCREEN_BACK
} else {
SetDrawScreen buffer_handle(p1)
// get size
l_graphSizeX = 0 : l_graphSizeY = 0
GetGraphSize buffer_handle(p1), varptr( l_graphSizeX ), varptr( l_graphSizeY )
// rewrite window size
mref t_dumBmscr, 67

}
return

// mode
#deffunc dxlibcelRedraw int p1
if ( p1 ) : dxlibcelScreenFlip
return


// boxf
#define global dxlibcelBoxf( %1 =0, %2 =0, %3 =-1, %4 =-1 ) _dxlibcelBoxf %1, %2, %3, %4
#deffunc _dxlibcelBoxf int p1, int p2, int _p3, int _p4, local p3, local p4, local l_graphHandle, local l_graphSizeX, local l_graphSizeY
p3 = _p3 : p4 = _p4
if ( (p3<0) || (p4<0) ) {
GetDrawScreen : l_graphHandle = stat
if ( l_graphHandle == -1 ) : return 0
// get size
l_graphSizeX = 0 : l_graphSizeY = 0
GetGraphSize l_graphHandle, varptr( l_graphSizeX ), varptr( l_graphSizeY )
if ( p3 < 0 ) : p3 = l_graphSizeX
if ( p4 < 0 ) : p4 = l_graphSizeY
}
p3++ : p4++
//
GetColor ginfo_r, ginfo_g, ginfo_b
DrawBox p1, p2, p3, p4, stat, 1
return 1

// line
#define global dxlibcelLine( %1 =0, %2 =0, %3 =-1, %4 =-1 ) _dxlibcelLine %1, %2, %3, %4
#deffunc _dxlibcelLine int p1, int p2, int _p3, int _p4, local p3, local p4
p3 = _p3 : p4 = _p4
if ( p3 < 0 ) : p3 = ginfo_cx
if ( p4 < 0 ) : p4 = ginfo_cy
//
GetColor ginfo_r, ginfo_g, ginfo_b
DrawLine p1, p2, p3, p4, stat
pos p1, p2
return 1

// circle
#define global dxlibcelCircle( %1 =0, %2 =0, %3, %4, %5 =1 ) _dxlibcelCircle %1, %2, %3, %4, %5
#deffunc _dxlibcelCircle int p1, int p2, int p3, int p4, int p5
//
GetColor ginfo_r, ginfo_g, ginfo_b
DrawOval (p1+p3)/2, (p2+p4)/2, abs(p3-p1)/2, abs(p4-p2)/2, stat, p5, 1
return 1

// font
#define global dxlibcelFont( %1, %2 =12, %3 =0 ) _dxlibcelFont %1, %2, %3
#deffunc _dxlibcelFont str p1, int p2, int p3
font@hsp p1, p2, p3
ChangeFont p1
SetFontSize p2
SetFontThickness 0
font_size = p2
return

// mes
#define global dxlibcelMes( %1 ) _dxlibcelMes %1
#deffunc _dxlibcelMes str p1
GetColor ginfo_r, ginfo_g, ginfo_b
DrawString ginfo_cx, ginfo_cy, p1, stat
pos , ginfo_cy +font_size
return

// wait
#define global dxlibcelWait( %1 =100 ) _dxlibcelWait %1
#deffunc _dxlibcelWait int p1
wait@hsp p1
ProcessMessage
return

// await
#define global dxlibcelAwait( %1 =0 ) _dxlibcelAwait %1
#deffunc _dxlibcelAwait int p1
await@hsp p1
ProcessMessage
return


// replace
#ifdef DXLIBCEL_REPLACE_EMBEDDED_COMMANDS

#undef screen
#define global screen dxlibcelScreen

#undef buffer
#define global buffer dxlibcelBuffer

#undef celload
#define global celload dxlibcelLoad

#undef celdiv
#define global celdiv dxlibcelDiv

#undef celput
#define global celput dxlibcelPut

#undef redraw
#define global redraw dxlibcelRedraw

#undef gsel
#define global gsel dxlibcelScreenSel

#undef gmode
#define global gmode dxlibcelGmode

#undef gcopy
#define global gcopy dxlibcelGcopy

#if 0
#undef grotate
#define global grotate dxlibcelGrotate
#endif

#undef boxf
#define global boxf dxlibcelBoxf

#undef line
#define global line dxlibcelLine

#undef circle
#define global circle dxlibcelCircle

#undef font
#define global font dxlibcelFont

#undef mes
#define global mes dxlibcelMes

#undef wait
#define global wait dxlibcelWait

#undef await
#define global await dxlibcelAwait


#endif// DXLIBCEL_REPLACE_EMBEDDED_COMMANDS

#global// dxlibcel

#endif// __INC_DXLIBCEL_HSP__


ファイルでも置いておきます,こちら


サンプル


基本的にはCEL系で必要となる命令が置き換えられるので,スクリプトとしては標準のHSPと同じ感じです.

    // コメントアウトしてもその他のスクリプトは同じままで実行可能
#include "dxlibcel.hsp"

screen 0, 640, 480
title "dxlibcel sample"

celload "kame.png", 2
celdiv 2, 30, 30, 0, 0

gsel 0

repeat
redraw 0
frameCounter = cnt

gmode 0// 通常のHSPと違い,boxfやlineなども半透明の影響を受けるため,このgmode0は必要

// boxf
color 255, 255, 255 : boxf

// line
pos 200, 30 : color 255, 0, 0
repeat 8
t_rad = deg2rad(360*cnt/8)
line 200+cos(t_rad)*20, 10+sin(t_rad)*20
loop

// circle
color 0, 255, 255
circle 300, 10, 350, 30, 1

// mes
font "MS 明朝", 20, 0
color 0, 0, 255
pos 200, 300 : mes "sample string"

// celput
pos 150, 180 : celput 2, 0, 1.0, 1.0, deg2rad(20)

// celput with div : use alpha blend
gmode 3, , , 128
repeat 3
t_y = cnt
repeat 3
t_x = cnt
pos t_x*50, t_y*50 : celput 2, t_y*3+t_x, 2.0, 1.0, deg2rad(20.0+frameCounter)
loop
loop

redraw 1// redraw 1しないとScreenFlipしない
await 20
loop


簡単なベンチマーク


作って動いて満足するだけならまだしも,そもそもこのモジュールの目指すところに「高速性」を掲げているため,簡単ではありますがどれくらい早くなったのかベンチマークをとっておきます.

モジュールのメインターゲットとしては,実際にゲームとかのアプリケーションで使うならテクスチャのコピーがメインになると思うので,比較対象としてはテクスチャのコピーだけに注目してみました.

また,描画にかかった時間って厳密に求めるのってかなり難しい(プログラム側からはGPUにコマンドを送っているだけのため,どこからどこまでを描画にかかった時間とするかが曖昧だったりする)ため,1秒間に何回描画できたかを表す指標であるFPSで比較します.

スクリプトは次.
hgimg4はシェーダとか基本的なリソースがないと何も言わず落ちるのでサンプルから「res」をコピーしてくる必要がある(どっかに書いてあるのかなぁこれ).

#define ENABLE_DXLIBCEL// dxlibcelを使える場合
#define ENABLE_HGIMG4// hgimg4が使える場合
#define ENABLE_HGIMG4DX// hgimg4DXが使える場合 : ENABLE_HGIMG4が定義されている時のみ有効
#define ENABLE_HGIMG3// hgimg3を使える場合


#define USE_DXLIBCEL 0
#define USE_HGIMG4 0
#define USE_HGIMG3 0
#define USE_EMBEDDED 0

#ifdef ENABLE_DXLIBCEL
#undef USE_DXLIBCEL
#define USE_DXLIBCEL 1
#else
#ifdef ENABLE_HGIMG4
#undef USE_HGIMG4
#define USE_HGIMG4 1
#else
#ifdef ENABLE_HGIMG3
#undef USE_HGIMG3
#define USE_HGIMG3 1
#else
#undef USE_EMBEDDED
#define USE_EMBEDDED 1
#endif// ENABLE_HGIMG3
#endif// ENABLE_HGIMG4
#endif// ENABLE_DXLIBCEL


#if USE_DXLIBCEL
// コメントアウトしてもその他のスクリプトは同じままで実行可能
#include "dxlibcel.hsp"
#endif// USE_DXLIBCEL

#if USE_HGIMG4
#ifdef ENABLE_HGIMG4DX
#include "hgimg4dx.as"
#else
#include "hgimg4.as"
#endif// ENABLE_HGIMG4DX
#endif// USE_HGIMG4

#if USE_HGIMG3
#include "hgimg3.as"
#endif// USE_HGIMG3

#uselib "winmm.dll"
#func timeGetTime "timeGetTime"


#define SCRX (640.0)
#define SCRY (480.0)

#define N (1000)


*begin

screen 0, SCRX, SCRY
title "dxlibcel speedtest"

#if USE_HGIMG4
gpreset
setcls 0, $ffffff
#endif// USE_HGIMG4

#if USE_EMBEDDED || USE_DXLIBCEL || USE_HGIMG4
celload "kame.png", 2
//cls 0
#endif

#if USE_HGIMG3
hgini
texload "kame.png"
kame_tex_id = stat
clscolor 0xffffff
#endif// USE_HGIMG3

ddim box_x, N : ddim box_y, N
ddim box_vx, N : ddim box_vy, N

randomize 10
repeat N
box_x(cnt) = double( rnd( SCRX ) )
box_y(cnt) = double( rnd( SCRY ) )
box_vx(cnt) = double( rnd( 1000 ) + 100 ) /1000
if ( rnd(2) ) : box_vx(cnt) = -box_vx(cnt)
box_vy(cnt) = double( rnd( 1000 ) + 100 ) /1000
if ( rnd(2) ) : box_vy(cnt) = -box_vy(cnt)
loop

*main

#if USE_HGIMG4
getreq st, SYSREQ_TIMER
#else
timeGetTime : st = stat
//st = gettime( 7 )
#endif// USE_HGIMG4
fps = 0 : dispFps = 0
repeat

#if 0
// 更新処理
repeat N
box_x(cnt) += box_vx(cnt)
box_y(cnt) += box_vy(cnt)
if ( ( box_x(cnt) < 0.0 ) || ( box_x(cnt) > SCRX ) ) : box_vx(cnt) = -box_vx(cnt)
if ( ( box_y(cnt) < 0.0 ) || ( box_y(cnt) > SCRY ) ) : box_vy(cnt) = -box_vy(cnt)
loop
#endif


#if USE_EMBEDDED || USE_DXLIBCEL || USE_HGIMG4
redraw 0

gmode 0
color 255, 255, 255 : boxf

gmode 3, , , 64
repeat N
pos box_x(cnt), box_y(cnt)
celput 2, 0, 0.2, 0.2, deg2rad(cnt)
loop

//color 0, 0, 255 : pos 0, 0 : mes "FPS:"+dispFps+""

redraw 1
#endif

#if USE_HGIMG3
hgdraw
gmode 3, 107, 82, 64

repeat N
pos box_x(cnt), box_y(cnt)
hgrotate kame_tex_id, 0, 0, deg2rad(cnt), 21, 16
loop

hgsync 0
#endif// USE_HGIMG3

await 0

fps++
#if USE_HGIMG4
getreq cur, SYSREQ_TIMER
#else
timeGetTime : cur = stat
//cur = gettime( 7 )
#endif// USE_HGIMG4
if ( cur-st > 1000 ) {
dispFps = fps
fps = 0
st = cur
title "fps="+dispFps
}
loop


結果:

dxlibcel : 240 fps
hgimg4 : 190 fps
hgimg3 : 500 fps
embedded : 80 fps

ということで,私のノートPC(Core i5 1.8GHz,グラボ無し(Intel HD Graphics 4000),Win7)だと上記な結果になりました.
思っていたよりはhgimg4が早かったなー,OpenGLベースだけどそこそこな速度がでている.
hgimg3は本当に謎の速度がでているが,確認したところ本当にそれぐらい早かったのできっと本当なんだろう.
ただ,dxlibcelは内部でHSPのモジュールを噛ませているせいでそもそも描画命令にかかるサイクルが違うため,実は正確に比較できないのだけれど,そこはひとまず置いておきましょう.
しかし,ふーむ….

終わりに


という訳で,DXLibの命令を使ってHSPのCEL系を置き換えてみました.

結果としてhgimg4よりは早いけどhgimg3よりは遅い,でも標準よりは全然早いという何ともな感じになりました.
ただ,hgimg4もhgimg3もそして勿論DXLibも想定された使い方をするともっとパフォーマンスがでるハズなので,それに合わせてスクリプト側も変更すれば早くなるのでしょう.(結局,ですが…)

というか今回の比較実験でhgimg4触ってて思ったんですけど、既にhgimg4がCEL系互換じゃん、DxLibを使ったCEL系置き換えの意味とはいずこに…。

結論としては「hgimg3またはhgimg4使え!」ということになってしまいましたが,速度以外に目を向ければhgimg系はHSPのランタイムを差し替えるため外部プラグインが不調になったりする欠点がありますし,DXLibが得意な処理もあるでしょうし,単純にこのモジュールを利用するだけではなく,DXLibを使いはじめるきっかけにでもなったらいいなと思います.

…当初の予定とかなり違った結果になったので自分でもちょっと現実逃避.

それでは今回はこの辺で.
関連記事
スポンサーサイト

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック

トラックバック URL
http://fe0km.blog.fc2.com/tb.php/119-72368047
この記事にトラックバックする(FC2ブログユーザー)

FC2Ad

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。