私たちのシェーダーは現在、影を受けたり投影したりすることはできません。最初に影の投影 (シャドウキャスティング) を実装しましょう。
影を投影するには、シェーダーの サブシェーダー または フォールバック のいずれかに ShadowCaster パスタイプ が必要です。ShadowCaster パスは、オブジェクトをシャドウマップにレンダリングするために使用されます。通常、このパスはかなり単純です。頂点シェーダーは頂点位置を評価するだけでよく、フラグメントシェーダーはほとんど何も行いません。シャドウマップはただの深度バッファなので、フラグメントシェーダーによる色の出力さえあまり重要ではありません。
これは、多くのシェーダーにとって、シャドウキャスターのパスはほぼ正確に同じになることを意味します (オブジェクトにカスタム頂点シェーダーに基づくデフォーメーションがある、または、アルファカットアウト/半透明部分がある場合を除く)。取り入れる最も簡単な方法は、UsePass シェーダーコマンドを使用することです。
Pass
{
// regular lighting pass
}
// pull in shadow caster from VertexLit built-in shader
UsePass "Legacy Shaders/VertexLit/SHADOWCASTER"
ですが、今は学習の途中なので、同じことをいわゆる “手動で” 行いましょう。コードを短くするために、ライティングパス (“ForwardBase”) を、テクスチャを使わないアンビエントのみのコードに置き換えました。その下に、オブジェクトがシャドウキャスティングできるようにするための “ShadowCaster” パスがあります。
Shader "Lit/Shadow Casting"
{
SubShader
{
// very simple lighting pass, that only does non-textured ambient
Pass
{
Tags {"LightMode"="ForwardBase"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct v2f
{
fixed4 diff : COLOR0;
float4 vertex : SV_POSITION;
};
v2f vert (appdata_base v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
half3 worldNormal = UnityObjectToWorldNormal(v.normal);
// only evaluate ambient
o.diff.rgb = ShadeSH9(half4(worldNormal,1));
o.diff.a = 1;
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return i.diff;
}
ENDCG
}
// shadow caster rendering pass, implemented manually
// using macros from UnityCG.cginc
Pass
{
Tags {"LightMode"="ShadowCaster"}
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#pragma multi_compile_shadowcaster
#include "UnityCG.cginc"
struct v2f {
V2F_SHADOW_CASTER;
};
v2f vert(appdata_base v)
{
v2f o;
TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)
return o;
}
float4 frag(v2f i) : SV_Target
{
SHADOW_CASTER_FRAGMENT(i)
}
ENDCG
}
}
}
さて、下の方に平面があります。標準ビルトインディフューズシェーダーを使用しているので、影が実行されているのがわかります (現在使用しているシェーダーは、シャドウを 受けること をまだサポートしていないことに注意してください)。
#pragma multi_compile_shadowcaster ディレクティブを使用しました。これにより、シェーダーは、それぞれに定義された異なるプリプロセッサーマクロを持つ複数のバリアントにコンパイルされます (詳細は、複数のシェーダーバリアント のページを参照してください)。シャドウマップにレンダリングするとき、「ポイントライト」対「他のライトタイプ」の場合は、少し違うシェーダーコードが必要です。そのため、このディレクティブが必要です。