unity3d技术---在2d游戏中用shader模拟阴影

在作2d游戏的时候,每每会遇到2d场景或角色阴影投射时,没法使用正常的光照投影系统,之前我通常会复制一份要投影的物体进行变换后处理颜色并给透明度就看成影子了,但最近有位朋友说到性能和实际工做效率时提出想用shader来实现这一问题,我就试着写了一个这样的shader。app

首先须要让shader绘制出第二份一样的物体,通常来说就是添加一个pass。性能

Pass {
      ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha
      CGPROGRAM
      #pragma vertex vert_offset
      #pragma fragment frag_color
      ENDCG
    }
    Pass { 
    ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha
      CGPROGRAM
      #pragma vertex vert_normal
      #pragma fragment frag_normal
      ENDCG
    }

效果是这样的,注意,这里是一个gameobject。

而后把透明遮罩加上,并把阴影部分的透明度在0.5以上的部分设置为0.5,最后在调整好位置。spa

记得把ZWrite off 加上,不然就会出现看起来是透明的底,却能把一样的物体挡住的现象。像这样:3d


说道ZWrite的问题,其实挺麻烦的,由于关闭了以后就会使得后面的物体反倒出如今前面,最直接的方法就是定义渲染顺序,直接加上code

Tags{"Queue" = "Transparent"}

最终版本的代码以下:orm

Shader "Custom/Shadow" {
  Properties {
    _MainTex ("Main Tex", 2D) = "white" {}
     _AlphaTex("AlphaTex",2D) = "white"{}
    _Offset ("Offset", vector) = (0, 0, 0, 0) 
  }
  CGINCLUDE
    #include "UnityCG.cginc"
    sampler2D _MainTex;
    float4 _Offset;
    sampler2D _AlphaTex;
    float4 _MainTex_ST;
    
    struct v2f {
      float4 pos : POSITION;
      float2 uv : TEXCOORD0;
    };
    
    v2f vert_normal(appdata_base v) { 
      v2f o;
      o.pos = mul(UNITY_MATRIX_MVP, v.vertex);
      o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
      return o;
    }
    
    v2f vert_offset(appdata_base v) {
      v2f o;
      float4 pos = mul(_Object2World, v.vertex);
      o.pos = mul(UNITY_MATRIX_VP, pos + _Offset);
      o.uv = TRANSFORM_TEX(v.texcoord, _MainTex);
      return o;
    }
    
    float4 frag_normal(v2f i) : COLOR {
      float4 texcol = tex2D (_MainTex, i.uv);
	  texcol.w = tex2D(_AlphaTex,i.uv)*texcol.w;
	  return texcol;
    }
    
    float4 frag_color(v2f i) : COLOR {
      float4 c;
      c = tex2D(_MainTex, i.uv);
      c.w = tex2D(_AlphaTex,i.uv)*c.w;
      if(c.w >= 0.5)
      {
      	 c.r =0;
   	     c.g=0;
    	 c.b=0;
    	 c.w = 0.5f;
      }

      return c;
    }
  ENDCG
  SubShader { 
  Tags{"Queue" = "Transparent"}
    Pass {
      ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha
      CGPROGRAM
      #pragma vertex vert_offset
      #pragma fragment frag_color
      ENDCG
    }
    Pass { 
    ZWrite Off
      Blend SrcAlpha OneMinusSrcAlpha
      CGPROGRAM
      #pragma vertex vert_normal
      #pragma fragment frag_normal
      ENDCG
    }
  } 
  FallBack "Diffuse"
}

最终效果图: