ぼかし処理の実装
ぼかし処理に必要な、重み係数を定義します。
なお、ここではすでにガウス関数より算出済みの数値を使用します。
// 背景のクリア値
float4 ClearColor = {1,1,1,0};
float ClearDepth = 1.0;
//以下を追加
//ぼかしのサンプリング数
#define SAMP_NUM 7
// ぼかし処理の重み係数:
// ガウス関数 exp( -x^2/(2*d^2) ) を d=3.5, x=0~7 について計算したのち、
// (W[7] + W[6] + … + W[1] + W[0] + W[1] + … + W[7]) が 1 になるように正規化したもの
static float Weight[SAMP_NUM+1] = {
0.11769580,
0.11298861,
0.09996679,
0.08151250,
0.06125479,
0.04242319,
0.02707784,
0.01592839,
};
次に、2つのピクセルシェーダにそれぞれX方向とY方向へとぼかす処理を加えます。
// X方向のぼかし処理
float4 PS_GaussianX(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
Color = Weight[0] * tex2D( ScnSamp, Tex );
for (int i = 1; i <= SAMP_NUM; i++) {
float4 SampColor1 = tex2D( ScnSamp, Tex-float2(SampStep.x*i,0) );
float4 SampColor2 = tex2D( ScnSamp, Tex+float2(SampStep.x*i,0) );
Color += Weight[i] * SampColor1 + Weight[i] * SampColor2;
}
return Color;
}
// Y方向のぼかし処理
float4 PS_GaussianY(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
Color = Weight[0] * tex2D( ScnSamp2, Tex );
for (int i = 1; i <= SAMP_NUM; i++) {
float4 SampColor1 = tex2D( ScnSamp2, Tex-float2(0,SampStep.y*i) );
float4 SampColor2 = tex2D( ScnSamp2, Tex+float2(0,SampStep.y*i) );
Color += Weight[i] * SampColor1 + Weight[i] * SampColor2;
}
return Color;
}
実行結果確認
以上の編集を行うと、図9のように、ぼかしフィルタができ上がります。
ここまでの編集結果は、GaussianFilter.fxという名前で収録してあります。
ディフュージョンフィルタ
ディフュージョンフィルタは、図10のように、スクリーンの中で明るい部分を周囲になじませるような効果があります。簡単に絵の見栄えをよくすることができるため、MMD動画製作者の中では人気の高いエフェクトです。
MME用のディフュージョンフィルタは、すでにそぼろ氏によって開発・配布されていますが、今回は、先のぼかしフィルタを改変することで、簡易的なディフュージョンフィルタを作成してみます。
原理
今回実装するディフュージョンフィルタは、以下の画像合成処理を行います。
- 入力: オリジナル画像
- オリジナル画像を自分自身と"乗算合成"したもの
- 1.をぼかしたもの
- 1.と2.を"スクリーン合成"したもの
- 出力: 3.とオリジナル画像を"比較(明)"で合成したもの
実装
ぼかしフィルタを改変し、まず、最初の乗算合成を行います。オリジナル画像を入力しているX方向ぼかし処理において、取得したピクセルの色を2乗します。
float4 PS_GaussianX(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
Color = Weight[0] * tex2D( ScnSamp, Tex );
for (int i = 1; i <= SAMP_NUM; i++) {
float4 SampColor1 = tex2D( ScnSamp, Tex-float2(SampStep.x*i,0) );
float4 SampColor2 = tex2D( ScnSamp, Tex+float2(SampStep.x*i,0) );
//以下を追加
SampColor1 *= SampColor1;
SampColor2 *= SampColor2;
Color += Weight[i] * SampColor1 + Weight[i] * SampColor2;
}
return Color;
}
次に、3.のスクリーン合成の処理を挿入します。挿入位置は、Y方向ぼかし処理直後のコードです。ここで、得られたぼかし後の色と、オリジナル画像のピクセル色の2乗とをスクリーン合成します。
そして最後に、この色とオリジナル画像のピクセルの色とを比較し、大きい側の値を各色成分ごとに採ることで、"比較(明)"の合成が完了します。
float4 PS_GaussianY(float2 Tex: TEXCOORD0) : COLOR
{
float4 Color;
Color = Weight[0] * tex2D( ScnSamp2, Tex );
for (int i = 1; i <= SAMP_NUM; i++) {
float4 SampColor1 = tex2D( ScnSamp2, Tex-float2(0,SampStep.y*i) );
float4 SampColor2 = tex2D( ScnSamp2, Tex+float2(0,SampStep.y*i) );
Color += Weight[i] * SampColor1 + Weight[i] * SampColor2;
}
//以下を追加
float4 ColorOrg = tex2D( ScnSamp, Tex );
float4 ColorMul = ColorOrg * ColorOrg;
//スクリーン合成
Color = Color + ColorMul - Color * ColorMul;
//比較(明)
Color = max( Color, ColorOrg );
return Color;
}
実行結果確認
以上の編集を行うと、図11のように、ディフュージョンフィルタができ上がります。ここまでの編集結果は、DiffusionFilter.fxという名前で収録してあります。
最後に
まとめ
今回は、ポストエフェクトの基本を作成と共に解説しました。最終回となる次回は、パーティクルのような、ポストエフェクトともまた異なる種類のエフェクトの作成方法について解説する予定です。
