あくまでも方法ですので
皆様からのアドバイスをお待ちしています
こちらの動画を参考にして、
[nico]http://www.nicovideo.jp/watch/sm12147682[/nico]
作ってみました!
↑の動画との変更点は、
・サイズを自由に変えられるようにした(2のn乗以外でも扱えるように)
・計算式を全て単純でわかりやすくした(厨房の自分でも考えつくレベルの計算です)
・色等の変更をしやすくした(まだ引数化できてませんが、色情報はできるだけ変更が簡単に)
・エフェクトの形を動画のものと違う方法でつくった(シンプルに。でもできるだけ東方に近くなるように)
これらを含めて作った結果がこちら↓
では、ソースを載せたいと思います
*実装する前の準備!*
・龍神録プログラミングの館で背景描画ができているものを、どれでも
(main関数の中のenemyやboss関連消しておくと背景に集中できていいかも)
・参考にしてある動画にある処理をコピペしてHLSLプログラミングの準備
(動画なので見えにくいかも・・・このUP主の許可がおりればコピペ貼り付けるかも)
①まずは参考動画の内容を実行してみてください。
②DxLibにある、Rippleeffect関数をvoid gunya_effect(int red,int green,int blue,double r,double x,double y);
という名前と引数に変えてください(関数名はかえなくてもいいです)
③この関数をグラフィックメイン関数の背景描画のすぐ後においてください
④引数を適当に。まだ、色情報(red,green,blue)は意味無いです。使いません
動画ではgunya_effect(255,255,255,200,ch.x,ch.y);です
⑤関数の処理を変えます コピペでもしてくださいな
void gunya_effect(int red,int green,int blue,double r,double x,double y){
//色情報、大きさ、中心点
int grhandle;//グラフィックハンドル
grhandle=MakeGraph(FMX,FMY);//スクショ分メモリ確保
GetDrawScreenGraph(FX,FY,FX+FMX,FY+FMY,grhandle);//グニャグニャさせる範囲全体を保存
RippleVertex.Vert[0].pos=VGet(float(FX),float(FY),0.0f);//2のn乗でおそらくこれよりでかいサイズは使わない
RippleVertex.Vert[1].pos=VGet(float(510+FX),float(FY),0.0f);//から左上をFX,FYにして
RippleVertex.Vert[2].pos=VGet(float(FX),float(510+FY),0.0f);//510分のテクスチャを作る
RippleVertex.Vert[3].pos=VGet(float(510+FX),float(510+FY),0.0f);
RippleVertex.Vert[4]=RippleVertex.Vert[2];
RippleVertex.Vert[5]=RippleVertex.Vert[1];
FLOAT4 vec;//引数
vec.x=x/510;//中心点Xをテクスチャ用座標に交換して渡す
SetPSConstF(0,vec);
vec.y=y/510;//中心点Yを~
SetPSConstF(0,vec);
vec.w=r/510;//大きさを~
SetPSConstF(0,vec);
vec.z=count;//カウンタを渡す
SetPSConstF(0,vec);
SetUseTextureToShader(0,grhandle);//使用するグラフィックハンドルをセット
SetUsePixelShader(RipplePShandle);//シェーダをセット
DrawPrimitive2DToShader(RippleVertex.Vert,6,DX_PRIMTYPE_TRIANGLELIST);//情報を渡す
DeleteGraph(grhandle);//イメージハンドルの削除
}
⑥エフェクトファイルを変更
float4 temp;
struct PS_INPUT{
float4 Diffuse:COLOR0;
float4 Specular:COLOR1;
float2 TexCoords0:TEXCOORD0;
};
struct PS_OUTPUT{
float4 Output:COLOR0;
};
sampler sampler0:register(s0);
PS_OUTPUT main(PS_INPUT psin){
PS_OUTPUT psout;
float2 tempcoord;
float4 texc;
int y=psin.TexCoords0.y*510+temp.z*2;//変形させる基準をスクリーン座標になおして、カウンタ分(変化おおきくするため*2)座標をプラス
float rpt=60;//変更を行うタイミング(波型の一つの波の大きさ)
float pura;//結果プラスする値
if(y%(rpt*2)<rpt){//波型が上がりなら
pura=(y%(rpt*2)-rpt/2)/510;//テクスチャ座標に直して、yが大きいほど、puraが大きくなるように
}
else{//下がりなら
pura=(rpt-y%rpt-rpt/2+1)/510;//テクスチャ ~ 小さくなるように
}
float xo=temp.x+pura/4;//新たにできる中心点X
float dx=psin.TexCoords0.x-xo;//ずらした中心点をもとに
float dy=psin.TexCoords0.y-temp.y;
float dist=sqrt(dx*dx+dy*dy);//中心との距離を
if(dist<temp.w){//半径temp.w以内なら
float epspura;//グニャグニャ濃度
if(temp.z%720<360){//グニャグニャ濃度が上がる時なら
epspura=(temp.z%720)/360;//temp.zが大きいほどepsは大きく
}
else{
epspura=(360-temp.z%360+1)/360;//~は小さく
}
float eps=epspura*(1-dist/temp.w);//濃度*(1-中心からの距離(最大は1))
tempcoord.x=((psin.TexCoords0.x-temp.x/2)-temp.w/2)*(1-eps)+temp.w/2+temp.x/2;//重みを求める
tempcoord.y=((psin.TexCoords0.y-temp.y/2)-temp.w/2)*(1-eps)+temp.w/2+temp.y/2;
//テクスチャ座標が中心点によってかわるため、-temp.y/2とかをしている(結果のぐにゃぐにゃの大きさや角度がかわるのを防ぐため)
texc=tex2D(sampler0,tempcoord);//値を保存
psout.Output.r=texc.r-(temp.w-dist)*2;//離れているほど色を+または-する
psout.Output.g=texc.g+(temp.w-dist);
psout.Output.b=texc.b-(temp.w-dist)*2;
psout.Output.a=1.0;//アルファは常に1
}
else psout.Output=tex2D(sampler0,psin.TexCoords0);//円外なら処理をしない
return psout;//返す
}
temp.w=大きさ
temp.z=カウンタ
と勝手に使っています。
これで、できるはず・・・
たりてないところがあれば追記します