基本原理:使用Projector和Camera结合实现的动态阴影,使用Camera渲染出一张模型轮廓图,再用Projector投射到场景的接收物体上。
思路:
1、创建一个GameObject用来挂载Projector和Camera。
2、生成一张RenderTexture贴图,命名为mShadowRT。
3、创建一个单独渲染主角轮廓的相机,挂在GameObject上,为相机替换一个简单shader(ShadowCaster),只渲染模型的轮廓图, 渲染的结果targetTexture 保存到mShadowRT中。
4、创建一个投射器Projector,挂在GameObject上,为Projector设置一个投影shader(ShadowReceive), 该shader的材质贴图使用保存有相机渲染的mShadowRT。
5、GameObject随主角位置的移动而更新。
两个Shader:
ShadowCaster:
1 Shader "xj/ModelEffect/ShadowReceive" 2 { 3 Properties { 4 _ShadowTex ("ShadowTex", 2D) = "gray" {} 5 _bulerWidth ("BulerWidth", float) = 1 6 _shadowfactor ("Shadowfactor", Range(0,1)) = 0.3 7 _ShadowMask ("ShadowMask",2D) = "white"{} 8 } 9 SubShader { 10 Tags { "Queue"="AlphaTest+1" } 11 Pass { 12 ZWrite Off 13 ColorMask RGB 14 Blend DstColor Zero 15 Offset -1, -1 16 17 CGPROGRAM 18 #pragma vertex vert 19 #pragma fragment frag 20 #include "UnityCG.cginc" 21 22 struct v2f { 23 float4 pos:POSITION; 24 float4 sproj:TEXCOORD0; 25 }; 26 27 float4x4 _Projector; 28 sampler2D _ShadowTex; 29 sampler2D _ShadowMask; 30 uniform half4 _ShadowTex_TexelSize; 31 float _bulerWidth; 32 float _shadowfactor; 33 34 v2f vert(float4 vertex:POSITION){ 35 v2f o; 36 o.pos = mul(UNITY_MATRIX_MVP,vertex); 37 o.sproj = mul(_Projector, vertex); 38 return o; 39 } 40 41 float4 frag(v2f i):COLOR{ 42 43 half4 shadowCol = tex2Dproj(_ShadowTex, UNITY_PROJ_COORD(i.sproj)); 44 half maskCol = tex2Dproj(_ShadowMask, UNITY_PROJ_COORD(i.sproj)).r; 45 half a = (shadowCol * maskCol).a; 46 if(a > 0) 47 { 48 return float4(1,1,1,1) * (1 - _shadowfactor * a); 49 } 50 else 51 { 52 return float4(1,1,1,1) ; 53 } 54 } 55 56 ENDCG 57 } 58 } 59 FallBack "Diffuse" 60 }
ShadowReceive:
1 Shader "xj/ModelEffect/ShadowCaster" 2 { 3 Properties 4 { 5 _MainTex ("Texture", 2D) = "white" {} 6 _TintColor ("Tint Color", Color) = (0.5,0.5,0.5,0.5) 7 _AlphaCutoff ("Cutoff", float) = 0.5 8 } 9 Subshader 10 { 11 Tags { "RenderType"="Opaque" "Queue"="Geometry"} 12 Pass { 13 Lighting Off Fog { Mode off } 14 SetTexture [_MainTex] { 15 constantColor (1,1,1,1) 16 combine constant 17 } 18 } 19 } 20 Subshader 21 { 22 Tags { "RenderType"="TransparentCutout" "Queue"="AlphaTest"} 23 Pass { 24 Lighting Off Fog { Mode off } 25 AlphaTest Greater [_AlphaCutoff] 26 Color [_TintColor] 27 SetTexture [_MainTex] { 28 constantColor (1,1,1,1) 29 combine constant, previous * texture 30 } 31 } 32 } 33 Subshader 34 { 35 Tags { "RenderType"="TransparentAlphaBlended" "Queue"="Transparent"} 36 Pass { 37 Lighting Off Fog { Mode off } 38 ZWrite Off 39 Blend SrcAlpha OneMinusSrcAlpha 40 Color [_TintColor] 41 SetTexture [_MainTex] { 42 constantColor (1,1,1,1) 43 combine constant, previous * texture 44 } 45 } 46 } 47 Subshader 48 { 49 Tags { "RenderType"="TransparentAlphaAdditve" "Queue"="Transparent"} 50 Pass { 51 Lighting Off Fog { Mode off } 52 ZWrite Off 53 Blend SrcAlpha One 54 Color [_TintColor] 55 SetTexture [_MainTex] { 56 constantColor (1,1,1,1) 57 combine constant, previous * texture 58 } 59 } 60 } 61 }
效果图: