サンプルはこちら

HSP標準命令のmref でウィンドウの画面データを取得することがでる。それをpeek や pokeなどでいじるのが定番だが、今回はHSPSHADを使えばシェーダに送り込ませることができますよ、という記事。

D3DFMT_L8フォーマットはint 8bitの明度情報を1ドットとするレンダリングバッファである。
これはHSP画面データのRGB(8bit+8bit+8bit)を1ドットとするものの3分の1の容量。

なのでD3DFMT_L8で640×480の3倍の大きさのバッファ1920×480を作って、そこにmrefで取得したデータを転送。シェーダで扱えるような形式にする。
今度はD3DFMT_L8の640×480の大きさを3つ作り、それぞれをR要素、G要素、B要素を格納するバッファとする。

そして私の作ったピクセルシェーダーでRGB要素に分解する。

-------------------------------------------------------------------------------------------------------
PS_OUTPUT  PStyusyutu(VS_OUTPUT In) : COLOR
{
 PS_OUTPUT Out;
float ss1;
ss1=tex2D(gputex00,In.Tex0+float2(0.5/(WIDTH*3.0)+dot0,0.5/HEIGHT));
Out.Color=ss1;
return Out;
}
-------------------------------------------------------------------------------------------------------

dot0やWIDTH、HEIGHTはHSP側から変更できる任意の変数


これでR要素、G要素、B要素に分解したバッファができた。
サンプルでは、ここでR要素のバッファを以下のピクセルシェーダーに流す。
これはクリックした点を中心として円状に減算する処理だ。中心点からの距離で減算値が変わる。

---------------------------------------------------------------------------------------------------------

PS_OUTPUT  PScircle(VS_OUTPUT In) : COLOR
{
 PS_OUTPUT Out;
float4 ss1;
float xxx,yyy;
ss1=tex2D(gputex00,In.Tex0+float2(0.5/WIDTH,0.5/HEIGHT));
xxx=In.Tex0.x-mousexf;
yyy=(In.Tex0.y-mouseyf)/WIDTH*HEIGHT;
if (xxx*xxx+yyy*yyy<0.04){
ss1-=3.0*(xxx*xxx+yyy*yyy+0.04);
}
Out.Color=ss1;
return Out;
}
-------------------------------------------------------------------------------------------------------------------- 


同じようにGB要素も様々なピクセルシェーダに流す。


mref実験



一番気になるFPSだが、私の環境のcore i7 3820 + GTX550ti では約8~10であった。
あまり喜ばしい数値ではないが、HSPの画面データをGPUに転送して分解して、さらに3つのシェーダ使って、統合して、GPUからHSPに戻す、というあまりに重い処理をしているだけに仕方がないのだろう。


もちろんbuffer命令で作成した任意の大きさのバッファでも、mrefで取得して同じことができるはずなので小さいバッファならリアルタイムでいけるかもしれない。
さらに当然、高速化できる部分は多く残されているのでもっとFPSは上がる可能性は十分にある。


数値計算用に作ってきたプラグインであったが、mrefと組み合わせることで思わぬ副産物を生み出すことができた。
これからシェーダーがHSPで格段に扱いやすくなるだろう!


※PC環境によってはD3DFMT_L8に対応してなくて、クリックしてもうまく↑の画像のようにならないかもしれません