UNITYで影を受け取る
前回は影を落としましたがまだこのシェーダでは影を受け取れません
地面(Plane)メッシュのシェーダーを 今使ってる yUnitに変えると影はおちないし、セルフシャドウもありません
今回は影を受け取るようにします
https://github.com/YukiMiyatake/UnityLesson/tree/Shadow_2github.com
仕組み
UNITYではシャドウマップを使っています
シャドウマップの具体的な説明は他のサイトにお願いして
ライトからみたデプス値を事前に別のテクスチャに書き込んでおきます
レンダリング時に、ライトからみたデプス値と比較をして、ライトのほうが近い場合は、そのポイントは影になる
という仕組みです
その ライトからみたデプステクスチャを作るパスが、前回つくった ShadowCasterパスになります
今度は、そのデプステクスチャを参照して影を作るのですが
以前のUNITYではShadowReceiveパスで影を処理していたようですが、今は通常のカラーパスにて行うことができます
具体的には、SHADOW_ATTENUATIONマクロを使えば、影は0、表は1で、その間を補完した値が手に入ります
ので そのままカラーに乗算すれば影は黒くなります
pragma
今回は ShadowのON/OFFがあるので、その両方のシェーダをコンパイルする必要があるので下記のpragmaが必要です
本当は 各種ライトに対するシェーダも必要なので もっとたくさん必要ですが、今回は最低限
#pragma multi_compile_fwdbase
構造体
フラグメントシェーダにて SHADOW_ATTENUATIONマクロを使いますが、そのために必要な入力値があるので追加
v2fにSHADOW_COORDS(n) を追加し、影用のテクスチャを追加します。今回はテクスチャ2番まで使ったので3を割り当て
あと、私が少しハマったのが、ポジションを posという名前にしなければ計算できないようです・・・
ので 以前 vertexとしていたメンバ名を posに変える
影の取得
SHADOW_ATTENUATIONに、入力構造体の中身を渡せば 0.0~1.0の範囲で取得できます
今回は単純にそれをdiffuseに乗算します
float3 diffuse = (NdotL*0.5 + 0.5) * lightCol * SHADOW_ATTENUATION(i);
完成コード(ForwardBaseパスのみ)
Pass{ Tags{ "LightMode" = "ForwardBase" } Cull Back CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" #include "Lighting.cginc" #include "AutoLight.cginc" #pragma multi_compile_fwdbase struct appdata { float4 vertex : POSITION; float3 normal : NORMAL; float2 texcoord : TEXCOORD0; }; struct v2f { float4 pos : SV_POSITION; float4 vertexW: TEXCOORD0; float2 uv : TEXCOORD1; float3 normalWorld : TEXCOORD2; SHADOW_COORDS(3) }; uniform sampler2D _MainTex; uniform float4 _MainTex_ST; uniform float _Spec1Power; uniform float4 _Spec1Color; v2f vert(appdata_full v){ v2f o; o.pos = UnityObjectToClipPos(v.vertex); o.vertexW = mul(unity_ObjectToWorld, v.vertex); o.uv = TRANSFORM_TEX(v.texcoord, _MainTex); o.normalWorld = UnityObjectToWorldNormal(v.normal); half3 eyeVec = normalize(o.vertexW.xyz - _WorldSpaceCameraPos); TRANSFER_SHADOW(o); return o; } float4 frag(v2f i) : SV_Target{ float3 L = normalize(_WorldSpaceLightPos0.xyz); float3 V = normalize(_WorldSpaceCameraPos - i.vertexW.xyz); float3 N = i.normalWorld; float3 H = normalize(L + V); //LightColor float3 lightCol = _LightColor0.rgb * LIGHT_ATTENUATION(i); //Ambient float3 ambient = UNITY_LIGHTMODEL_AMBIENT.rgb; // texture albedo float4 tex = tex2D(_MainTex, i.uv); // Diffuse(HalfLambert) float3 NdotL = dot(N, L); float3 diffuse = (NdotL*0.5 + 0.5) * lightCol * SHADOW_ATTENUATION(i); // Speculer // float3 specular = pow(max(0.0, dot(reflect(-L, N), V)), _Spec1Power) * _Spec1Color.xyz; // reflection float3 specular = pow(max(0.0, dot(H, N)), _Spec1Power) * _Spec1Color.xyz * lightCol; // Half vector return float4( (ambient + diffuse) * tex + specular, 1.0); } ENDCG }
影ができた(でもアクネがあるね)