一、基本概念  
在Unity中通常使用两种方法来实现透明效果 
  透明度测试(无法达到真正的半透明效果) 透明度混合(关闭了深度写入)      
 透明度测试  
基本原理:设置一个阈值,只要片元的透明度小于阈值,就会被舍弃(不会进行任何处理,也不会对颜色缓冲造成影响);否则,就会按照普通的不透明物体来处理(进行深度测试、深度写入等) 效果极端,要么透明,要么完全不透明   
 透明度混合  
基本原理:使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色 需要关闭深度写入,但没有关闭深度测试——深度缓冲是只读的  
  为什么关闭深度写入 :如果开启,半透明物体在不透明物体前面时,半透明物体会挡住不透明物体,实现不了半透明效果   可以实现半透明效果   
 二、渲染顺序  
对于半透明物体和不透明物体 ,因为关闭了深度写入,所以应该在不透明物体渲染完后再渲染半透明物体  对于两个半透明物体,应该先渲染远处的,再渲染近处的 (不准确)   
 1.渲染引擎的方法  
先渲染所有不透明物体,并开启他们的深度测试和深度写入 把半透明物体按他们的距离摄像机的远近进行排序,再按照从后往前的顺序渲染,开启深度测试,关闭深度写入 
      
 2.Unity的渲染顺序  
使用SubShader的 Queue  标签来决定我们的模型将归于哪个渲染队列,使用整数索引来表示每个渲染队列,号小的越早被渲染   如果想要通过透明度测试来实现效果,代码:   
SubShader{ 
	Tags{  "Queue"  =  "AlphaTest" } 
	Pass{ .. . } 
	} 
  
 
SubShader{ 
	Tags{  "Queue"  =  "Transparent" } 
	Pass{ 
		ZWrite Off 
		.. . } 
	} 
  
 三、透明度测试  
基本原理:设置一个阈值,只要片元的透明度小于阈值,就会被舍弃(不会进行任何处理,也不会对颜色缓冲造成影响);否则,就会按照普通的不透明物体来处理(进行深度测试、深度写入等) 通常会在片元着色器 中使用 clip函数  进行透明度测试 
  如果给定参数的任何一个分量是负数,则会舍弃当前像素的输出颜色      
Shader "Custom/Chapter8-AlphaTest" 
{ 
   Properties
   { 
		_Color ( "Main Tint" ,  Color)  =  ( 1, 1, 1, 1)  
		_MainTex ( "Main Tex" ,  2D )  =  "white" { } 
		_Cutoff ( "Alpha Cutoff" ,  Range ( 0 , 1 ) )  =  0.5 
   } 
   SubShader
   { 
		Tags { "Queue"  =  "AlphaTest"  "IgnoreProjector"  =  "True"  "RenderType"  =  "TransparentCutoff" } 
		Pass
		{ 
			Tags{ "LightMode"  =  "ForwardBase" } 
				CGPROGRAM
				#pragma  vertex vert  
				#pragma  fragment frag 
				#include  "Lighting.cginc" 
				fixed4  _Color; 
				sampler2D  _MainTex; 
				float4  _MainTex_ST; 
				fixed  _Cutoff; 
				struct  a2v 
				{ 
					float4  vertex :  POSITION; 
					float3  normal :  NORMAL; 
					float4  texcoord :  TEXCOORD0; 
				} ; 
				struct  v2f 
				{ 
					float4  pos :  SV_POSITION; 
					float3  worldNormal :  TEXCOORD0; 
					float3  worldPos :  TEXCOORD1; 
					float2  uv :  TEXCOORD2; 
				} ; 
				v2f  vert ( a2v  v) 
				{ 
					v2f  o; 
					o. pos =  UnityObjectToClipPos ( v. vertex) ; 
					o. worldNormal =  UnityObjectToWorldNormal ( v. normal) ; 
					o. worldPos =  mul ( unity_ObjectToWorld,  v. vertex) . xyz; 
					o. uv =  TRANSFORM_TEX ( v. texcoord,  _MainTex) ; 
					return  o; 
				} 
				fixed4  frag ( v2f  i)  :  SV_Target 
				{ 
					fixed3  worldNormal =  normalize ( i. worldNormal) ; 
					fixed3  worldLightDir =  normalize ( UnityWorldSpaceLightDir ( i. worldPos) ) ; 
					fixed4  texColor =  tex2D ( _MainTex,  i. uv) ; 
					
					clip ( texColor. a -  _Cutoff) ; 
					fixed3  albedo =  texColor. rgb *  _Color. rgb; 
					fixed3  ambient =  UNITY_LIGHTMODEL_AMBIENT. xyz *  albedo; 
					fixed3  diffuse =  _LightColor0. rgb *  albedo *  max ( 0 ,  dot ( worldNormal, worldLightDir) ) ; 
					return  fixed4 ( ambient +  diffuse,  1.0 ) ; 
				} 
				ENDCG
		} 
   } 
   FallBack "Transparent/Cutout/VertexLit" 
} 
  
_Cutoff (“Alpha Cutoff”, Range(0,1)) = 0.5 用于决定我们调用clip进行透明度测试时使用的判决条件 clip(texColor.a - _Cutoff); 做透明度测试,判断texColor.a - _Cutoff是否为负数,负数的纹理颜色为全透明     
 四、透明度混合  
基本原理:使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色 需要使用Unity提供的混合命令 Blend    本节中使用的是Blend SrcFactor DstFactor来进行混合,将源颜色混合因子SrcFactor设为SrcAlpha,目标颜色混合因子设为OneMinusSrcAlpha 
  即混合后的新颜色为  
        
         
          
          
            D 
           
          
            s 
           
          
            t 
           
          
            C 
           
          
            o 
           
          
            l 
           
          
            o 
           
           
           
             r 
            
            
            
              n 
             
            
              e 
             
            
              w 
             
            
           
          
         
           DstColor_{new} 
          
         
        Ds tC o l o r n e w    = SrcAlpha × SrcColor + (1-SrcAlpha) ×   
        
         
          
          
            D 
           
          
            s 
           
          
            t 
           
          
            C 
           
          
            o 
           
          
            l 
           
          
            o 
           
           
           
             r 
            
            
            
              o 
             
            
              l 
             
            
              d 
             
            
           
          
         
           DstColor_{old} 
          
         
        Ds tC o l o r o l d     ZWrite Off 关闭深度写入   
Shader "Custom/Chapter8-AlphaBlend" 
{ 
	Properties
	{ 
		_Color ( "Main Tint" ,  Color)  =  ( 1, 1, 1, 1)  
		_MainTex ( "Main Tex" ,  2D )  =  "white" { } 
		_AlphaScale ( "Alpha Scale" ,  Range ( 0 , 1 ) )  =  1 
	} 
	SubShader
	{ 
		Tags { "Queue"  =  "Transparent"  "IgnoreProjector"  =  "True"  "RenderType"  =  "Transparent" } 
		Pass
		{ 
			Tags { "LightMode"  =  "ForwardBase" } 
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma  vertex vert  
			#pragma  fragment frag  
			#include  "Lighting.cginc" 
			
			fixed4  _Color; 
			sampler2D  _MainTex; 
			float4  _MainTex_ST; 
			fixed  _AlphaScale; 
				struct  a2v 
				{ 
					float4  vertex :  POSITION; 
					float3  normal :  NORMAL; 
					float4  texcoord :  TEXCOORD0; 
				} ; 
				struct  v2f 
				{ 
					float4  pos :  SV_POSITION; 
					float3  worldNormal :  TEXCOORD0; 
					float3  worldPos :  TEXCOORD1; 
					float2  uv :  TEXCOORD2; 
				} ; 
				v2f  vert ( a2v  v) 
				{ 
					v2f  o; 
					o. pos =  UnityObjectToClipPos ( v. vertex) ; 
					o. worldNormal =  UnityObjectToWorldNormal ( v. normal) ; 
					o. worldPos =  mul ( unity_ObjectToWorld,  v. vertex) . xyz; 
					o. uv =  TRANSFORM_TEX ( v. texcoord,  _MainTex) ; 
					return  o; 
				} 
				fixed4  frag ( v2f  i)  :  SV_Target 
				{ 
					fixed3  worldNormal =  normalize ( i. worldNormal) ; 
					fixed3  worldLightDir =  normalize ( UnityWorldSpaceLightDir ( i. worldPos) ) ; 
					fixed4  texColor =  tex2D ( _MainTex,  i. uv) ; 
					
					fixed3  albedo =  texColor. rgb *  _Color. rgb; 
					fixed3  ambient =  UNITY_LIGHTMODEL_AMBIENT. xyz *  albedo; 
					fixed3  diffuse =  _LightColor0. rgb *  albedo *  max ( 0 ,  dot ( worldNormal, worldLightDir) ) ; 
					return  fixed4 ( ambient +  diffuse,  texColor. a *  _AlphaScale) ; 
				} 
			ENDCG
		} 
	} 
	FallBack "Transparent/VertexLit" 
} 
  
 
 五、开启深度写入的半透明效果  
对于复杂网格的半透明处理,避免错误排序 方法:使用 两个Pass  来渲染模型 
  第一个开启深度写入,但不输出颜色,仅仅为了把该模型的深度值写入深度缓存中 第二个Pass 进行正常的透明度混合,根据第一个Pass,可以进行像素级别的深度排序  缺点是 多个Pass会造成性能的影响      
Shader "Custom/Chapter8-AlphaBlend" 
{ 
	Properties
	{ 
		_Color ( "Main Tint" ,  Color)  =  ( 1, 1, 1, 1)  
		_MainTex ( "Main Tex" ,  2D )  =  "white" { } 
		_AlphaScale ( "Alpha Scale" ,  Range ( 0 , 1 ) )  =  1 
	} 
	SubShader
	{ 
		Tags { "Queue"  =  "Transparent"  "IgnoreProjector"  =  "True"  "RenderType"  =  "Transparent" } 
		Pass
		{ 
			ZWrite On 
			ColorMask 0 
		} 
		Pass
		{ 
			Tags { "LightMode"  =  "ForwardBase" } 
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
			CGPROGRAM
			#pragma  vertex vert  
			#pragma  fragment frag  
			#include  "Lighting.cginc" 
			
			fixed4  _Color; 
			sampler2D  _MainTex; 
			float4  _MainTex_ST; 
			fixed  _AlphaScale; 
				struct  a2v 
				{ 
					float4  vertex :  POSITION; 
					float3  normal :  NORMAL; 
					float4  texcoord :  TEXCOORD0; 
				} ; 
				struct  v2f 
				{ 
					float4  pos :  SV_POSITION; 
					float3  worldNormal :  TEXCOORD0; 
					float3  worldPos :  TEXCOORD1; 
					float2  uv :  TEXCOORD2; 
				} ; 
				v2f  vert ( a2v  v) 
				{ 
					v2f  o; 
					o. pos =  UnityObjectToClipPos ( v. vertex) ; 
					o. worldNormal =  UnityObjectToWorldNormal ( v. normal) ; 
					o. worldPos =  mul ( unity_ObjectToWorld,  v. vertex) . xyz; 
					o. uv =  TRANSFORM_TEX ( v. texcoord,  _MainTex) ; 
					return  o; 
				} 
				fixed4  frag ( v2f  i)  :  SV_Target 
				{ 
					fixed3  worldNormal =  normalize ( i. worldNormal) ; 
					fixed3  worldLightDir =  normalize ( UnityWorldSpaceLightDir ( i. worldPos) ) ; 
					fixed4  texColor =  tex2D ( _MainTex,  i. uv) ; 
					
					fixed3  albedo =  texColor. rgb *  _Color. rgb; 
					fixed3  ambient =  UNITY_LIGHTMODEL_AMBIENT. xyz *  albedo; 
					fixed3  diffuse =  _LightColor0. rgb *  albedo *  max ( 0 ,  dot ( worldNormal, worldLightDir) ) ; 
					return  fixed4 ( ambient +  diffuse,  texColor. a *  _AlphaScale) ; 
				} 
			ENDCG
		} 
	} 
	FallBack "Transparent/VertexLit" 
} 
  
 
Pass
		{ 
			ZWrite On 
			ColorMask 0 
		} 
  
ZWrite On 打开深度写入,ColorMask 0 意味着Pass不写入任何颜色通道,不会输出任何颜色     
 六、ShaderLab的混合命令  
混合与两个操作数有关:源颜色(SourceColor)和目标颜色(DestinationColor) 
  源颜色指片元着色器产生的颜色 S 目标颜色指从颜色缓冲中读取到的颜色值 D 混合后的颜色 O 包含了 RGBA四个颜色通道       
 1.混合等式和参数  
将S和D进行混合的等式——混合等式,需要两个,一个用于混合RGB,一个用于混合A 设置混合状态时,即设置等式中的 “操作” 和 “因子” 
  一共有两个等式(分别用于混合RGB和A) 一个等式里有两个因子(一个与S相乘,一个与D相乘)      
 
第一个命令中只有两个因子——RGB和A通道用相同的两个因子    混合因子可以是哪些值呢?     
 2.混合操作  
可以使用 BlendOp BlendOperation命令     当使用Min和Max操作时,混合因子不起作用的   
 3.常见的混合类型(效果)  
 
 七、双面渲染的透明效果  
观察到其内部结构 可以使用Cull指令来控制需要剔除哪个面的渲染图元 
  Back:背对相机的渲染图元不会被渲染  Front:朝向相机的渲染图元不会被渲染 Off:关闭剔除功能      
Cull Back |  Front |  Off
  
 1.透明度测试的双面渲染  
在Pass中使用 Cull Off 来关闭剔除功能即可 只在 AlphaTest.shader 里Pass中加一句 Cull Off     
 2.透明度混合的双面渲染  
因为关闭了深度写入,如果直接加 Cull Off 的话会造成前后面混乱 所以,写了两个Pass (与AlphaBlend.shader一样) 
  只在Pass中,第一个Pass只渲染背面 ,添加了Cull Front;第二个只渲染正面 添加了Cull Back SubShader是会按照顺序执行Pass