影をベタ塗りするシェーダー [Unity]
Unityのシェーダーのしくみを理解しようと思いまして、練習として影をグラデーションではなく1色のベタ塗りで表現するシェーダーを作ってみました。
上記はキャラや地面に今回作ったシェーダーを当てています。
コードは以下の感じです。
ライティングの部分はこちらの記事を参考にさせていただきました。ありがとうございます!
・シェーダー入門したくないけど書いてみたい その6 ライティング編 - 波打際のブログさん
Shader "Custom/SolidColor" { Properties{ _Color("Color", Color) = (1,1,1,1) _MainTex("Albedo (RGB)", 2D) = "white" {} _Parting("Shade Parting", Range(0,1)) = 0.5 } SubShader{ Pass{ Tags{ "RenderType" = "Opaque" "LightMode" = "ForwardBase" } CGPROGRAM #pragma vertex vert #pragma fragment frag #pragma multi_compile_fwdbase #include "UnityCG.cginc" #include "AutoLight.cginc" fixed4 _Color; sampler2D _MainTex; half _Parting; uniform fixed4 _LightColor0; struct v2f { float4 pos : SV_POSITION; float3 lightDir : TEXCOORD0; float3 normal : TEXCOORD1; float2 uv:TEXCOORD2; LIGHTING_COORDS(3, 4) }; v2f vert(appdata_base v, float2 uv : TEXCOORD2) { v2f o; o.pos = mul(UNITY_MATRIX_MVP, v.vertex); o.lightDir = normalize(ObjSpaceLightDir(v.vertex)); o.normal = normalize(v.normal).xyz; o.uv = uv; TRANSFER_VERTEX_TO_FRAGMENT(o); TRANSFER_SHADOW(o); return o; } fixed4 frag(v2f i) : SV_Target{ fixed atten = LIGHT_ATTENUATION(i); fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT; fixed4 lightColor = _LightColor0 * saturate(dot(i.lightDir, i.normal)); fixed4 c = tex2D (_MainTex, i.uv) * _Color; fixed3 shade = (0.5 * lightColor * atten) + ambient; fixed f = (shade.r < _Parting) ? -0.08 : 0; c.rgb = c+ fixed3(f, f, f); return c; } ENDCG } } Fallback "Diffuse" }
球体を使った方が分かりやすいので、団子のモデルで解説しようと思います。
上記はUnity5のデフォルトで用意されている「Standard」シェーダーです。
今回作ったシェーダーに変更すると上記のようになります。
どんな処理を行っているかといいますと
まずは裏で、モデルにグレーの色を塗って影がどんな感じにでるのかを調べます。(ここは実際には描画しません。)
一定の明るさに達しない箇所がベタ塗りの影になります。
次に、上記のような影がまったく付いてない状態のものに、先ほど計算したベタ塗りの影を足してあげるということを今回のシェーダーで行っています。
後、影の割合を個別調整できるように、上記の「Shade Parting」をインスペクタでいじれるようにしています。
今回シェーダーのことを調べてみて、裏でこんな処理をやってたのかと(なんとなく)分かってスッキリしました。