こんにちわ、オオバです。

前回に引き続きイメージエフェクトやります。

イメージエフェクトドリル : カメラブラー

今回はBloom(ブルーム)です。

Blooming (ブルーム)とは明るい光源(例えば、閃光のような)からの光が周囲の物体に漏れるように見える光学効果である。

Unity公式より

個人的にはBloomは画作りには欠かせないエフェクトの1つだと思ってます。今回も自分で考えて実装してみようと思います。

イメージエフェクト適用前のフレームバッファ

Unityで輝度を考慮しないBloom_0

この状態からイメージエフェクトを2Pass処理していきます。

明るい所のみを取得(1Pass目)

Unityで輝度を考慮しないBloom_1

1Pass目では明るいところを取得した画像を生成します。最終的には元画像に加算するため、しきい値を越えなければ黒くしておきます。

fixed4 frag0 (v2f_img i) : SV_Target  
{
    fixed4 col = tex2D(_MainTex, i.uv);  
    // ピクセルの明るさ  
    float bright = (col.r + col.g + col.b)/3;  
    // 0 or 1  
    float tmp = step(_Threshold, bright);  
    return tex2D(_MainTex, i.uv) * tmp * _Strength;  
}

step関数は 第1引数の値 > 第2引数の値 ? 1 : 0と、0 or 1を返却するので、しきい値とピクセルの明るさを代入ししています。

ぼかして元画像と合成(2Pass目)

Unityで輝度を考慮しないBloom_2

Unityで輝度を考慮しないBloom_3

2Pass目で先の明るい所取得した画像をぼかし、もとの画像に加算合成して完成です。

fixed4 fragBlur (v2f_img i) : SV_Target  
{
    float u = 1 / _ScreenParams.x;  
    float v = 1 / _ScreenParams.y;  

    fixed4 result;  
    // ぼかし  
    for (float x = 0; x < _Blur; x++)  
    {
        float xx = i.uv.x + (x - _Blur/2) * u;  

        for (float y = 0; y < _Blur; y++)  
        {
            float yy = i.uv.y + (y - _Blur/2) * v;  
            fixed4 smp = tex2D(_Tmp, float2(xx, yy));  
            result += smp;  
        }
    }

    result /= _Blur * _Blur;  
    return tex2D(_MainTex, i.uv) + result;  
}

ハマった所

一時的に生成したRenderTextureの解放でハマりました。
RenderTexture.GetTemporary関数で生成したRenderTextureは Releaseメソッドでは解放できません。

Unityで輝度を考慮しないBloom_4

var tmp = RenderTexture.GetTemporary(100,100);  
tmp.Release();  //・・・☓ 解放されない  
var tmp = RenderTexture.GetTemporary(100,100);  
RenderTexture.ReleaseTemporary(tmp);  //・・・○ 解放される  

今回のサンプルコードはこちら
なんちゃってBloom · GitHub

期間限定 最大95%オフセール
効率UPメガバンドル開催中!最大95%オフ!!!
期間 : 11月1日午後15時59分まで
オススメ記事