スポンサーサイト

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

DXライブラリでグロー効果シェーダ

こんにちは
今は夜なのでこんばんは

どうでも良い事に拘る拘りのペチコです
柔軟性がないとも言います


今回はグローとかグレアとか言われるアレをシェーダでやります
何言ってるのかさっぱりですね


グロー効果
こんな感じで輝くような効果です。
これはどうみてもやりすぎですね。


流れとしてはこんな感じ
レベル補正ぼかし
元画像にレベル補正をかけ
明暗をはっきりさせて
ぼかしたものを元画像とスクリーン合成すると
Afterの画像になります



まず、MakeScreenで3つの作業画面を作っておいて、一つ目のスクリーンに普通にレンダリングします

通常レンダリング
帆の左側は太陽のつもりで、光の方向と位置がおかしいのは気にしてはなりませぬ

そのスクリーンをテクスチャとしてレベル補正をかけます

// 2D描画用の頂点データを予め作っておきます
VERTEX2DSHADER Vert[6] ;
{
Vert[ 0 ].pos = VGet( 0.0f-0.5f, 0.0f-0.5f, 0.0f-0.5f ) ;
Vert[ 1 ].pos = VGet( 1024.0f-0.5f, 0.0f-0.5f, 0.0f-0.5f ) ;
Vert[ 2 ].pos = VGet( 0.0f-0.5f, 768.0f-0.5f, 0.0f-0.5f ) ;
Vert[ 3 ].pos = VGet( 1024.0f-0.5f, 768.0f-0.5f, 0.0f-0.5f ) ;
Vert[ 0 ].dif = GetColorU8( 255,255,255,255 ) ;
Vert[ 0 ].spc = GetColorU8( 0,0,0,0 ) ;
Vert[ 0 ].u = 0.0f ; Vert[ 0 ].v = 0.0f ;
Vert[ 1 ].u = 1.0f ; Vert[ 1 ].v = 0.0f ;
Vert[ 2 ].u = 0.0f ; Vert[ 2 ].v = 1.0f ;
Vert[ 3 ].u = 1.0f ; Vert[ 3 ].v = 1.0f ;
Vert[ 0 ].su = 0.0f ; Vert[ 0 ].sv = 0.0f ;
Vert[ 1 ].su = 1.0f ; Vert[ 1 ].sv = 0.0f ;
Vert[ 2 ].su = 0.0f ; Vert[ 2 ].sv = 1.0f ;
Vert[ 3 ].su = 1.0f ; Vert[ 3 ].sv = 1.0f ;
Vert[ 0 ].rhw = 1.0f ;
Vert[ 1 ].rhw = 1.0f ;
Vert[ 2 ].rhw = 1.0f ;
Vert[ 3 ].rhw = 1.0f ;
Vert[ 4 ] = Vert[ 2 ] ;
Vert[ 5 ] = Vert[ 1 ] ;
}

//レベル補正
// 描画先を2にする
SetDrawScreen( ScreenHandle2 ) ;
// 使用するピクセルシェーダーをセット
SetUseTextureToShader( 0, ScreenHandle1 ) ;//レジスタ0に通常描画した画面をセット
//レベル補正用ピクセルシェーダ
SetUsePixelShader( Handle_LevelsPS ) ;
//DrawPrimitive2DToShaderでシェーダ描画
DrawPrimitive2DToShader( Vert, 6, DX_PRIMTYPE_TRIANGLELIST ) ;
//レジスタにセットしたテクスチャを解除
SetUseTextureToShader( 0, -1 ) ;

はしょりすぎてますが、画面サイズは1024*768を想定、ハンドルとかの名前は適当に合わせてください
頂点データを-0.5fしているのはズレを防ぐため、どうせぼかすのでズレてもいいのですけどね

こちらがレベル補正用ピクセルシェーダ

LevelsPS.pso
// ディフューズマップテクスチャ
sampler DiffuseMapTexture : register( s0 ) ;
// main関数
float4 main( float2 Tex : TEXCOORD0) : COLOR0
{
//(元の色*255-黒)/(白-黒)
return (tex2D(DiffuseMapTexture, Tex)* 255.0f - 110.0f) / (155.0f - 110.0f);
}

ガンマ補正を考慮してない、数値決め打ちの手抜き似非レベル補正シェーダです
コメントで黒、白となっている所が閾値で、ここをいじれば色合いが変わります
ここでは黒110、白155で直接コードに書いてる柔軟性のなさです

レベル補正
輝度の高い部分が輝くようになるので、シーンにあった数値を見つけないといけません

めんどくさいのでRGBを一括で補正してますが、各値を別個に補正すれば空の青は輝かないけど太陽の黄色は光る、みたいにできるかもしれません


次にこのスクリーンをぼかします
ここはDXライブラリさんの「ブルーム効果基本」を参考にされた方が楽です
スクリーンを縮小して、それにブラーをかけて、バイリニア(拡大するとぼける)で元の大きさにします

ライブラリさんにあるので必要ありませんが、一応のぼかしシェーダです

GaussianH_PS.pso
static const float2 PixelKernel[13] = 
{
{ -6,0 },
{ -5,0 },
{ -4,0 },
{ -3,0 },
{ -2,0 },
{ -1,0 },
{ 0,0 },
{ 1,0 },
{ 2,0 },
{ 3,0 },
{ 4,0 },
{ 5,0 },
{ 6,0 },
};

static const float BlurWeights[13] =
{
0.002216,
0.008764,
0.026995,
0.064759,
0.120985,
0.176033,
0.199471,
0.176033,
0.120985,
0.064759,
0.026995,
0.008764,
0.002216,
};

sampler DiffuseMapTexture : register( s0 ) ; // ディフューズマップテクスチャ

// main関数
float4 main( float2 Tex : TEXCOORD0) : COLOR0
{
float4 colour = 0;
float2 TexSize = float2(1.0f/1024.0f, 1.0f/768.0f);

for (int p = 0; p < 13; p++)
{
colour += tex2D( DiffuseMapTexture, Tex + (PixelKernel[p].xy * TexSize) ) * BlurWeights[p];
}

return colour;
}

ぼかしシェーダは二つ必要です
こちらはホリゾンタル。水平方向にぼかします
これはまた手抜きで決め打ちしてるので説明は省きます
詳しく知りたい方は"ガウスフィルタ hlsl"等でお調べいただければ幸いです
color用の変数がcolourになってますが、イギリス英語での通例だそうで、格好いいので使いました

この後にバーティカル(垂直)方向にぼかしをかけます
そちらのシェーダは上のPixelKernel[13]の中身を{-6,0}→{0,-6}のようにxy交換するだけなので省きます

Screen1に通常描画→Screen2に1をレベル補正して描画→Screen3に2を水平ぼかしして描画→Screen2に3を垂直ぼかしして描画、という流れです
この流れですと今のところの最終作業画像はScreen2になります
私自身が把握できなくなるので改めて書きました。ペチコのメモ帳なのですここ

最後にScreen2の画像をScreen1の元画像にスクリーン合成します

ScreenFilterPS.pso
sampler  DiffuseMapTexture        : register( s0 ) ;		// ディフューズマップテクスチャ
sampler DecalMapTexture : register( s1 ) ; // デカールテクスチャ

// main関数
float4 main( float2 Tex : TEXCOORD0) : COLOR0
{
float4 D = tex2D(DiffuseMapTexture, Tex);
float4 C = tex2D(DecalMapTexture, Tex);
//1.0f - ( ( 1.0f - GrHandleの色 ) * ( 1.0f - BlendGrHandleの色 ) );
return ( 1.0f - ( (1.0f-D)*( 1.0f-(C*0.8f) ) ) );
}

ここでは、描画画面を裏画面にし
SetUseTextureToShader( 0, ScreenHandle1 ) ;
SetUseTextureToShader( 1, ScreenHandle2 ) ;
として、元画像をディフィーズテクスチャ、レベル補正後ぼかした画像をデカールテクスチャとして合成しています
そのままのスクリーン合成だとデカールの主張が激しかったので0.8掛けて少し抑えています

できた最終結果がこちら

90_006.jpg
うーん…

シーンが悪かったのとわかりやすいようにちょっと派手目に輝かせたせいかもしれませんが、イマイチですね
でも光が回り込んできて輝いて、疑似HDRになるところが気に入っています
もう少し輝きを抑えればちょっとしたアクセントに効果的なのではないでしょうか

画面ピクセル分、数回レンダリングするため決して軽いエフェクトではありませんが、
言い換えればどんなに頂点の多いシーンでも負荷は一定ということなので、最近のグラフィックボード向けとしてならわりと効果のあるエフェクトなのかもしれません

ちゃんとグローを維持したまま、動かす事もできます



横着して縮小ぼかしをせずに、10回ぼかしフィルタを回してるのでかなり重かったのは秘密です

コメントの投稿

非公開コメント

プロフィール

ペチコートさん

Author:ペチコートさん
大航海時代オンライン
Zephyros、Eurosサーバーに潜伏中

偽ペチコ1号・2号
ペチコの手下達
Zephyrosサーバーに潜伏中

最新記事
月別アーカイブ
カテゴリ
リンク
最新コメント
検索フォーム
QRコード
QR
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。