UnityShader纹理特效(一) 图片添加阴影

两天前有个朋友想要弄个给图片加阴影的效果找我帮忙,刚开始比较纳闷图片加阴影,怎么个加法,当他发了张图瞬间就懂了,效果是这样的:

UnityShader纹理特效(一) 图片添加阴影_第1张图片

原理就是简单的一个UV小幅度的偏移采样得到影子然后和原始UV采样的结果叠加在一起(影子在后面原图在前面)就OK了.(纹理的wrapMode需要设置为Clamp)

完整的Shader:

Shader "Custom/ImageShadow"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}

		_OffsetX ("Offset X", range(-0.2,0.2)) = 0 
		_OffsetY ("Offset Y", range(-0.2,0.2)) = 0 
		_ShadowColor ("Shadow Color", COLOR) = (0,0,0,1)
		_ThresholdAlpha("Threshold Alpha", Range(0,0.5)) = 0.1
	}
	SubShader
	{
		Tags
        {
            "Queue"="Transparent"
            "IgnoreProjector"="True"
            "RenderType"="Transparent"
            "PreviewType"="Plane"
            "CanUseSpriteAtlas"="True"
        }

		Cull Off
        Lighting Off
        ZWrite Off
        Blend SrcAlpha OneMinusSrcAlpha

		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "UnityCG.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;

			half _OffsetX;
			half _OffsetY;
			fixed4 _ShadowColor;
			half _ThresholdAlpha;
			
			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				
				fixed shadowAlpha = tex2D(_MainTex, i.uv + half2(_OffsetX,_OffsetY)).a;

				fixed4 shadowColor = fixed4(_ShadowColor.rgb, _ShadowColor.a * shadowAlpha);

				fixed4 finalColor = shadowColor;

				fixed stepVal = step(_ThresholdAlpha, col.a);
				finalColor = stepVal * col + (1 - stepVal) * shadowColor;

				return finalColor;
			}
			ENDCG
		}
	}
}

VertShader中就是常规的MVP变换与UV值的计算,主要来看下FragmentShader,

 

影子的颜色值做为可调参数,采样过程中就只用关心Alpha的值,如下:

fixed shadowAlpha = tex2D(_MainTex, i.uv + half2(_OffsetX,_OffsetY)).a;
fixed4 shadowColor = fixed4(_ShadowColor.rgb, _ShadowColor.a * shadowAlpha);

_OffsetX 与 _OffsetY的作用就是对UV进行偏移计算,然后采样得到影子的alpha的值,在与_ShadowColor影子颜色参数作用在一起得到最终影子的颜色值.

 

原图的采样结果和阴影的采样结果都准备好了,接下来就叠加在一起就完成了.

fixed stepVal = step(_ThresholdAlpha, col.a);
finalColor = stepVal * col + (1 - stepVal) * shadowColor;

这一步就是找到原图的Alpha值大于阈值_ThresholdAlpha的范围,在这个区域内显示原图颜色值,超过这个区域的则显示阴影颜色值.大功告成.

 

这里是step方法其实写成if(col.a > _ThresholdAlpha)的可读性更高,因为shader中需要尽量避免条件分支的写法,在老点的GUP上会不支持或影响效率,但是现在的GPU貌似没有这个限制了(这点不是很清楚),不过可以肯定的是用step除了可读性比if稍微低了点而已其他方面都是没有问题的.

 

这个_ThresholdAlpha的作用就是处理一些图片边缘切的不干净的情况,比如

 UnityShader纹理特效(一) 图片添加阴影_第2张图片

则可以在不麻烦美术大大的情况下,通过参数调节得到比较满意的效果:

 UnityShader纹理特效(一) 图片添加阴影_第3张图片

 

最终效果:

UnityShader纹理特效(一) 图片添加阴影_第4张图片 

 

 

你可能感兴趣的:(Shader,Unity)