SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

MikuMikuEffectで学ぶHLSL入門

3DCGツール「MikuMikuDance」のエフェクトを拡張する「MikuMikuEffect」
ポストエフェクトの作成方法

MikuMikuEffectで学ぶHLSL入門(5)

ダウンロード sample.zip (10.5 KB)

ぼかし処理の実装

 ぼかし処理に必要な、重み係数を定義します。
なお、ここではすでにガウス関数より算出済みの数値を使用します。

重み係数追加
// 背景のクリア値
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という名前で収録してあります。

図9 ぼかしフィルタ実行結果
図9 ぼかしフィルタ実行結果

ディフュージョンフィルタ

 ディフュージョンフィルタは、図10のように、スクリーンの中で明るい部分を周囲になじませるような効果があります。簡単に絵の見栄えをよくすることができるため、MMD動画製作者の中では人気の高いエフェクトです。

図10 ディフュージョンフィルタ
図10 ディフュージョンフィルタ

 MME用のディフュージョンフィルタは、すでにそぼろ氏によって開発・配布されていますが、今回は、先のぼかしフィルタを改変することで、簡易的なディフュージョンフィルタを作成してみます。

原理

 今回実装するディフュージョンフィルタは、以下の画像合成処理を行います。

  • 入力: オリジナル画像
  1. オリジナル画像を自分自身と"乗算合成"したもの
  2. 1.をぼかしたもの
  3. 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という名前で収録してあります。

図11 ディフュージョンフフィルタ実行結果
図11 ディフュージョンフフィルタ実行結果

最後に

まとめ

 今回は、ポストエフェクトの基本を作成と共に解説しました。最終回となる次回は、パーティクルのような、ポストエフェクトともまた異なる種類のエフェクトの作成方法について解説する予定です。

参考資料

  1. ディフュージョンフィルタのススメ
  2. 【MMD】MMEでディフュージョンフィルタを実装してみた【MME】

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
MikuMikuEffectで学ぶHLSL入門連載記事一覧

もっと読む

この記事の著者

舞力介入P(ブリョクカイニュウピー)

ニコニコ動画でMMD関連のツール開発者として活動中。代表作は「MikuMikuEffect」。我流のAPI Hookを常套手段とする、邪道プログラマです。ニコニコ動画マイリスト

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/6298 2011/12/09 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー