写実的なリアルなグラフィックをフォトリアルといいますが
その反対のアニメ的なグラフィックをノンフォトリアル NPRといいます
今回は NPRの基本のトゥーンシェーダーを
トゥーンシェーダーとは
アニメでは色の塗りをなめらかにグラデーションさせず、光、影を塗り分けます
それを カートゥーン、トゥーン と呼びます
その中の手法の1つの ランプシェーダを作ります
ランプシェーダ
プロパティーは今回は2個。ランプテクスチャと そのかかり具合
_RampTex ("RampTexture", 2D) = "white" {}
_ToonPower("ToonPower", Range(0.0, 1.0)) = 0.5
計算ですが、ここは今は適当にして、動くことだけを確認します
ランプシェーダの基本は、陰の強さ(diffuse)により通常はなめらかに変化する陰の色を
2値などに離散させるためにテクスチャを使います
たとえば このようなテクスチャを考えます
diffuseが0=光源から90度側面 のときは左端の真っ黒で
diffuseが1=光源に面しているときは真っ白
その間は なめらかではなくテクスチャのように離散する
というのを表現させるには 単純に
diffuseの値を テクスチャのu座標としてマッピングすればいいですね!
また 今回はテクスチャは1次元しかつかってないけど
t座標に スペキュラ入れたり、外部パラメータを入れて複雑な表現も可能だし
場合によっては 輪郭線を書くことも出来ます
Rampの計算は 今回は標準のブレンドにしてみます
ランプテクスチャが白黒なので 計算式にあってませんけどね・・
float4 tex = tex2D(_MainTex, i.uv);
// Diffuse(HalfLambert)
float NdotL = dot(N, L);
float diffuse = (NdotL*0.5 + 0.5);
float4 ramp = tex2D(_RampTex, float2(diffuse, 0));
return float4(saturate( (tex*(1 - _ToonPower) + ramp*_ToonPower ) ), 1.0);
diffuseをランプテクスチャのu座標にマッピングすれば
わかりにくい&ゾンビ だけど、ちゃんとトゥーンになったのがわかると思います
トゥーンシェーダ
ランプテクスチャ以外にもいろんな方法があるが
その中でもメジャーな方法として
陰色をパラメータで設定行い、シェーダーで2階調にわけます
具体的には、陰色と スレッショルドを入力し
diffuseの値が スレッショルドを超えたら陰だと判断し陰色にします
今回は2階調だが、とうぜんコードを改良すれば3階調やn階調にすることも出来る
パラメータは2つ
_ToonColor("ToonColor", Color) = (0.0, 0.0, 0.0, 0.0)
_ToonThreshold("ToonThreshold", Range(0.0,1.0)) = 1.0
計算式はとりあえず参考までに・・
今回は スレッショルドのパラメータにより2値にするので三項演算子で 白とトゥーン色に離散させます
そのあとは何となく計算
float4 ramp2 = (diffuse.x >= _ToonThreshold) ? float4(1.0, 1.0, 1.0, 1.0): float4(_ToonColor.xyz, 1.0);
return float4(saturate( (tex*(1 - _ToonPower) + ramp*_ToonPower ) * shadowTex * ramp2 ), 1.0);
これでRampテクスチャを設定もできるし、陰色を指定し スレッショルドで2値にすることも可能になった