透明度混合:这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是透明度混合需要关闭深度写入。
这使得我们要非常小心物体的渲染顺序。
为了进行混合,我们需要使用Unity提供的混合命令——Blend。
我们这里使用 Blend SrcAlpha OneMinusSrcAlpha
内部公式为:DstColor(new)=SrcAlpha*SrcColor+(1-SrcAlpha)*DstColor(old);
首先是关闭深度写入的代码:
1 Shader "Custom/AlphaBlend" { 2 Properties { 3 _Color ("Main Tint", Color) = (1,1,1,1) 4 _MainTex ("Albedo (RGB)", 2D) = "white" {} 5 _AlphaScale("Alpha Scale",Range(0,1))=1 6 } 7 SubShader { 8 /* 9 "Queue"="Transparent":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列 10 "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响 11 RenderType标签可以让Unity把这个Shader归入到提前定义的组(这里就是Transparent组) 12 */ 13 Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="Transparent"} 14 Pass 15 { 16 Tags{"LightMode"="ForwardBase"} 17 ZWrite Off//关闭深度写入 18 Blend SrcAlpha OneMinusSrcAlpha 19 CGPROGRAM 20 #pragma vertex vert 21 #pragma fragment frag 22 #include"Lighting.cginc" 23 24 fixed4 _Color; 25 sampler2D _MainTex; 26 float4 _MainTex_ST; 27 fixed _AlphaScale; 28 29 struct a2v 30 { 31 float4 vertex:POSITION; 32 float3 normal:NORMAL; 33 float4 texcoord:TEXCOORD0; 34 }; 35 struct v2f 36 { 37 float4 pos:SV_POSITION; 38 float3 worldNormal:TEXCOORD0; 39 float3 worldPos:TEXCOORD1; 40 float2 uv:TEXCOORD2; 41 }; 42 v2f vert(a2v v) 43 { 44 v2f o; 45 o.pos=mul(UNITY_MATRIX_MVP,v.vertex); 46 o.worldNormal=UnityObjectToWorldNormal(v.normal); 47 o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz; 48 o.uv=TRANSFORM_TEX(v.texcoord,_MainTex); 49 return o; 50 } 51 52 fixed4 frag(v2f i):SV_Target 53 { 54 fixed3 worldNormal=normalize(i.worldNormal); 55 fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos)); 56 fixed4 texColor=tex2D(_MainTex,i.uv); 57 fixed3 albedo=texColor.rgb*_Color.rgb; 58 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo; 59 fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir)); 60 return fixed4(ambient+diffuse,texColor.a*_AlphaScale);//颜色乘以透明程度 61 } 62 63 ENDCG 64 } 65 } 66 FallBack "Transparent/Cutout/VertexLit" 67 }