UnityでのDeferred Celシェーディング

どうも,チョコです.院試おつ↓かれ↑ーい.

いつものUnityでのCelシェーディングをやっていました.しかし,シェーダを全部Cel式に変えるのはめんどい.そしてunlit shaderで照明を扱うのはどうも釈然としない.そこで,Deferredでなんとかならない?と思ったわけです.

UnityではDeferredの内部シェーダを変えられるようになっています.このように.

(Edit->Project Settings->Graphics)

Screenshot (13)

ここに自分のシェーダを突っ込めば,カメラの出力を制御できるというわけですね.

さて,これをやるにはまずbuiltin_shadersアセットをダウンロードしないといけない(ダウンロードページにあります).そして,Internal-DeferredShading.shaderを見つけます.

シェーダを中を見ると,おっと,この部分は画面に色を吐いているなと,読めばわかると思います.

half4 CalculateLight (unity_v2f_deferred i)
{
    ...
    half4 res = UNITY_BRDF_PBS (data.diffuseColor, data.specularColor, oneMinusReflectivity, data.smoothness, data.normalWorld, -eyeVec, light, ind);
    return res;
}

なるほど.つまり,ここの戻り値を変えればいいと.さて,Celシェーディングでやりたいことを確認しましょう.

deftoon

図の通り,まずは白の材質に対しての照明を得て(1),そしてCel風のカーブにし(2),最後にDiffuseを適用(3)すればいいです.上のコードを書き換えましょう.

uniform float _deferred_cutoff;
uniform float _deferred_shade;
uniform float _deferred_saturate;
half4 CalculateLight (unity_v2f_deferred i)
{
    ...
    half4 inten = UNITY_BRDF_PBS (half3(1,1,1), half3(0, 0, 0), 1, 0.5, data.normalWorld, -eyeVec, light, ind);
    float brg = clamp(ceil(inten.r - _deferred_cutoff), 0, 1);
    float shd = 1-((1-_deferred_shade) * (1-data.smoothness));
    return half4(saturate(data.diffuseColor * (brg * (1-shd) + shd), 1 + _deferred_saturate - (_deferred_saturate) * brg), 1);
}

(デフォルトシェーダの仕組みはどこにも書いていないので,関数の意味などはCGIncludesの中身を自分で読まないといけませんね)

はい.ここで,UNITY_BRDF_PBS は(1)なので,それを(2)にしたのがbrgとなって,最後にdata.diffuseColorを適用しました(3).

最後に,Inspectorでデフォルトのシェーダを変えよう.そしたら(エラーがなければ)オブジェクトのマテリアルを一切触っていないのにカメラの出力が変わります.

Screenshot (12)

これで1つのシェーダでアニメ風にできますね.スタイル変換捗りー.

(実はこの方法は,照明ごとに行われるので,光が重なるととても明るくなります.解決したらパーツ2の記事にします)

では.

Posted on