これを使うと、様々な画像加工ができるようです。
俺「描画の速さが売りのDXライブラリの機能なんだし、このシェーダーとやらを使えば、
画像加工、ひいては計算処理が高速にできるワンチャンあるんじゃないか?(情弱並の感想)」
とりあえず使ってみる。
main.cpp
#include "DxLib.h"
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
SetGraphMode(512,512,32);
if(ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
int imageHandle,shaderHandle;
VERTEX2DSHADER vert[6]={};
vert[0].pos=VGet(0.0f,0.0f,0.0f);
vert[0].rhw=1.0f;
vert[0].u=0.0f;
vert[0].v=0.0f;
vert[1].pos=VGet(512.0f,0.0f,0.0f);
vert[1].rhw=1.0f;
vert[1].u=1.0f;
vert[1].v=0.0f;
vert[2].pos=VGet(512.0f,512.0f,0.0f);
vert[2].rhw=1.0f;
vert[2].u=1.0f;
vert[2].v=1.0f;
vert[3].pos=VGet(0.0f,0.0f,0.0f);
vert[3].rhw=1.0f;
vert[3].u=0.0f;
vert[3].v=0.0f;
vert[4].pos=VGet(512.0f,512.0f,0.0f);
vert[4].rhw=1.0f;
vert[4].u=1.0f;
vert[4].v=1.0f;
vert[5].pos=VGet(0.0f,512.0f,0.0f);
vert[5].rhw=1.0f;
vert[5].u=0.0f;
vert[5].v=1.0f;
imageHandle=LoadGraph("../lenna_orig.bmp");
shaderHandle=LoadPixelShader("shader.pso");
SetUseTextureToShader(0,imageHandle);
SetUsePixelShader(shaderHandle);
DrawPolygon2DToShader(vert,2);
WaitKey();
InitShader();
DxLib_End();
return 0;
}
struct PS_INPUT {
float4 DiffuseColor : COLOR0;
float4 SpecularColor : COLOR1;
float2 TextureCoord0 : TEXCOORD0;
float2 TextureCoord1 : TEXCOORD1;
};
struct PS_OUTPUT {
float4 Output : COLOR0;
};
sampler DiffuseMapTexture : register(s0);
PS_OUTPUT main(PS_INPUT PSInput) {
PS_OUTPUT PSOutput;
float4 nowColor;
nowColor=tex2D(DiffuseMapTexture,PSInput.TextureCoord0);
PSOutput.Output.r=1.0f-nowColor.r;
PSOutput.Output.g=1.0f-nowColor.g;
PSOutput.Output.b=1.0f-nowColor.b;
PSOutput.Output.a=nowColor.a;
return PSOutput;
}
さらに、重いC++のコンパイルをしなくても、軽いfxのコンパイルをするだけで行う加工を変えられるというのも便利です。
では、もう少し複雑なことをしてみましょう。
main.cpp
#include "DxLib.h"
char Key[256];
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
SetGraphMode(512,512,32);
if(ChangeWindowMode(TRUE) != DX_CHANGESCREEN_OK || DxLib_Init() == -1 ) return -1; //初期化処理
int imageHandle,shaderHandle;
VERTEX2DSHADER vert[6]={};
vert[0].pos=VGet(0.0f,0.0f,0.0f);
vert[0].rhw=1.0f;
vert[0].u=0.0f;
vert[0].v=0.0f;
vert[1].pos=VGet(512.0f,0.0f,0.0f);
vert[1].rhw=1.0f;
vert[1].u=1.0f;
vert[1].v=0.0f;
vert[2].pos=VGet(512.0f,512.0f,0.0f);
vert[2].rhw=1.0f;
vert[2].u=1.0f;
vert[2].v=1.0f;
vert[3].pos=VGet(0.0f,0.0f,0.0f);
vert[3].rhw=1.0f;
vert[3].u=0.0f;
vert[3].v=0.0f;
vert[4].pos=VGet(512.0f,512.0f,0.0f);
vert[4].rhw=1.0f;
vert[4].u=1.0f;
vert[4].v=1.0f;
vert[5].pos=VGet(0.0f,512.0f,0.0f);
vert[5].rhw=1.0f;
vert[5].u=0.0f;
vert[5].v=1.0f;
FLOAT4 embosParam;
embosParam.x=3.0f/512.0f;
embosParam.y=3.0f/512.0f;
imageHandle=LoadGraph("../lenna_orig.bmp");
shaderHandle=LoadPixelShader("shader.pso");
SetUseTextureToShader(0,imageHandle);
SetUsePixelShader(shaderHandle);
SetPSConstF(10,embosParam);
DrawPolygon2DToShader(vert,2);
WaitKey();
InitShader();
DxLib_End();
return 0;
}
struct PS_INPUT {
float4 DiffuseColor : COLOR0;
float4 SpecularColor : COLOR1;
float2 TextureCoord0 : TEXCOORD0;
float2 TextureCoord1 : TEXCOORD1;
};
struct PS_OUTPUT {
float4 Output : COLOR0;
};
float4 embosParam : register(c10);
sampler DiffuseMapTexture : register(s0);
float4 color2gray(float4 color) {
float4 result;
result.r=0.3f*color.r+0.59f*color.g+0.11f*color.b;
result.g=result.r;
result.b=result.r;
result.a=color.a;
return result;
}
PS_OUTPUT main(PS_INPUT PSInput) {
PS_OUTPUT PSOutput;
float4 nowColor;
nowColor=color2gray(tex2D(DiffuseMapTexture,PSInput.TextureCoord0));
PSOutput.Output.r=1.0-nowColor.r;
PSOutput.Output.g=1.0-nowColor.g;
PSOutput.Output.b=1.0-nowColor.b;
PSOutput.Output.a=nowColor.a;
if(PSInput.TextureCoord0.x>=embosParam.r && PSInput.TextureCoord0.y>=embosParam.g) {
float2 secondColorPos;
float4 secondColor;
secondColorPos.x=PSInput.TextureCoord0.x-embosParam.r;
secondColorPos.y=PSInput.TextureCoord0.y-embosParam.g;
secondColor=color2gray(tex2D(DiffuseMapTexture,secondColorPos));
PSOutput.Output.r=PSOutput.Output.r+secondColor.r-0.5f;
PSOutput.Output.g=PSOutput.Output.g+secondColor.g-0.5f;
PSOutput.Output.b=PSOutput.Output.b+secondColor.b-0.5f;
if(PSOutput.Output.r1.0f)PSOutput.Output.r=1.0f;
if(PSOutput.Output.g1.0f)PSOutput.Output.g=1.0f;
if(PSOutput.Output.b1.0f)PSOutput.Output.b=1.0f;
}
return PSOutput;
}
・・・さて、自分の環境でもシェーダーが使えることがわかったところで、本当に高速なのか実験してみましょう。
上のエンボス加工処理の速さを測定します。
エントリーしたのは、以下の3個のプログラム。
・シェーダーを使用
► スポイラーを表示
► スポイラーを表示
► スポイラーを表示
果たして、DXライブラリのシェーダーはこのハンデを乗り越えるほど高速に動作するのでしょうか?
検証環境
Windows Vista Home Premium SP2 32ビット
Intel(R) Core(TM)2Duo T8100 @2.10GHz 2.10GHz
RAM 4.00GB
gcc 4.7.2
最適化 -O2
DXライブラリ Ver 3.11
実験結果(表の単位:マイクロ秒)
ここでは
初期化:画像データのロード・パラメータの設定(DXライブラリの初期化は含まない)
画像生成:画像データをグレースケール化・エンボス加工したデータの作成
画像描画:作成したデータをDXライブラリの画面に描画
としています。ただし、シェーダーはその性質上画像生成と画像描画がセットになっています。
シェーダーを使用するプログラム
[table=border:1px solid #FFFFFF;border-collapse:collapse;][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;] [/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]初期化[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像生成・描画[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]合計[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]1[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]5034[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]8141[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]13175[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]5159[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]6054[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]11213[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]3[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]4816[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]6378[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]11194[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]4[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]5458[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]10365[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]15823[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]5[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]4798[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]6021[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]10819[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]平均[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]5053[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]7391.8[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]12444.8[/td]
[/tr][/table]
BMPファイルのデータに直接アクセスするプログラム
[table=border:1px solid #FFFFFF;border-collapse:collapse;][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;] [/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]初期化[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像生成[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像描画[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像生成・描画[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]合計[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]1[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2197[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3910[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]6692[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]10602[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]12799[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2021[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3615[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]5573[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]9188[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]11209[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]3[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2168[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3773[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]7430[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]11203[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]13371[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]4[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2373[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3640[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]6956[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]10596[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]12969[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]5[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2624[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3890[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]9205[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]13095[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]15719[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]平均[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2276.6[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3765.6[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]7171.2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]10936.8[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]13213.4[/td]
[/tr][/table]
SoftImage系の関数を使用するプログラム
[table=border:1px solid #FFFFFF;border-collapse:collapse;][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;] [/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]初期化[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像生成[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像描画[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]画像生成・描画[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]合計[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]1[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2291[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]49470[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]4108[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]53578[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]55869[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2123[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]43229[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3894[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]47123[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]49246[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]3[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2183[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]44743[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3977[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]48720[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]50903[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]4[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2531[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]45833[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]8715[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]54548[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]57079[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]5[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2082[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]65611[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]3746[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]69357[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]71439[/td]
[/tr][tr=]
[td=border:1px solid #FFFFFF;padding:0.2em;]平均[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]2242[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]49777.2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]4888[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]54665.2[/td]
[td=border:1px solid #FFFFFF;padding:0.2em;]56907.2[/td]
[/tr][/table]
詳しく見ていくと、以下のことがわかります。
・頂点を設定したりシェーダーをロードしたりするシェーダーの初期化に比べ、ほぼ画像のロードとメモリ確保だけのBMPやSoftImageの初期化は速い
・BMPファイルのデータの描画は、シェーダーを用いた描画と同じくらいの時間がかかる
・DXライブラリのSoftImageの操作はかなり遅いが、逆に描画は速い
このことから、実用上は、DXライブラリのファイル容量と起動時間が大きいということもあり、
一般の画像加工にはシェーダーを使う必要は無さそう、と言えそうです。
さて、試しにシェーダーを使わず、画像処理をせずに描画してみたら、どのくらいの時間がかかるのでしょうか?
► スポイラーを表示
初期化:4692 画像描画:46 合計:4738
やはり、何も加工せずただ描画するのは、かなり速いです。さすがDXライブラリですね。
しかし、LoadGraphはこんなに重いのでしょうか?そういえば、シェーダーの初期化にもLoadGraphを使っていました。
次回予告
あまり画像加工の性能が良くないことがわかったシェーダー。それでも計算処理に使用してみたらどうなるか?
遅いかもしれない。しかし、それでも一度やってみよう。