Unity Shader用RenderTexture+Projector生成实时动态阴影

前言

实时动态阴影有好多种生成方法,通过考虑设备支持,性能等因素来选择方法。这篇文章就介绍了多种用Unity实现移动端动态阴影的方法,我选取了其中目前比较常用的RenderTexture加Projector的方法实现了一下。在移动端通常使用这种方法给主要角色添加阴影,非主要角色的阴影就用简单的黑色面片表示。

具体实现

实现起来很简单,就是让一个拥有Camra和Projector组件的Object选择合适的方向和位置来生成阴影。Camera组件用来渲染投射阴影的物体到RenderTexture,然后Projector采样RT在接收阴影的物体上生成阴影。需要注意的一点是RenderTexture可以设定成只有R通道的格式,这样可以减少空间的占用,而且可以用SetReplacementShader来为“投射阴影”使用特定的Shader来减少小性能消耗。具体代码如下:

public class ProjectorShadow : MonoBehaviour
{
    Projector mProjector;
    Camera mCamera;
    Shader mShader;

    void Start()
    {
        mProjector = GetComponent<Projector>();
        mCamera = GetComponent<Camera>();
        mShader = Shader.Find("Custom/ShadowCaster");
        mCamera.SetReplacementShader(mShader, "");
    }
}
//生成RenderTexture用的Shader
Shader "MyShader/ShadowCaster"
{
    SubShader
    {
        Tags { "RenderType"="Opaque" }
		Pass
		{
			 CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			struct a2v
			{
				float4 vertex : POSITION;      
			};

			struct v2f
			{
				float4 pos : SV_POSITION;
			};

			v2f vert(a2v v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				return fixed4(1, 1, 1, 1);
			}
			ENDCG
		}      
    }
    FallBack "Diffuse"
}
//Projector用的Shader
Shader "MyShader/ProjectorShader"
{
	Properties
	{
		_ShadowTex("Shadow Tex", 2D) = "white"{}
		_Intensity("Intensity", Range(0, 1)) = 0.5
	}
    SubShader
    {
        Tags { "RenderType"="Transparent" }
		Pass
		{
			Zwrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			Offset -1, -1

			 CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			struct a2v
			{
				float4 vertex : POSITION;        
			};

			struct v2f
			{
				float4 pos : SV_POSITION;
				float4 sproj : TEXCOORD0;
			};

			sampler2D _ShadowTex;
			float _Intensity;
			float4x4 unity_Projector;

			v2f vert(a2v v)
			{
				v2f o;
				o.pos = UnityObjectToClipPos(v.vertex);
				o.sproj = mul(unity_Projector, v.vertex);

				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed shadowCol = tex2Dproj(_ShadowTex, UNITY_PROJ_COORD(i.sproj));
				fixed alpha = shadowCol * _Intensity;
				return fixed4(0, 0, 0, alpha);
			}
			ENDCG
		}      
    }
    FallBack "Diffuse"
}

Unity Shader用RenderTexture+Projector生成实时动态阴影_第1张图片
通过设定RT的大小可以控制阴影的质量,还可以通过Mask或者其它方式来制作阴影渐变效果或者是软化阴影。最终效果图如下:
Unity Shader用RenderTexture+Projector生成实时动态阴影_第2张图片

你可能感兴趣的:(Unity,Shader学习笔记,Unity3D)