能夠在fragment中使用cg的函數--clip來進行透明度測試。html
函數定義以下:app
void clip(float4 x);函數
void clip(float3 x);性能
void clip(float2 x);測試
void clip(float1 x);spa
void clip(float x);code
參數:裁剪時使用的標量或矢量條件。orm
描述:若是給定參數的任何一個份量是負數,就會捨棄當前像素的輸出顏色。等同於:htm
void clip(float4 x) { if (any(x < 0)) discard; }
轉載請註明出處:http://www.cnblogs.com/jietian331/p/7154001.htmlblog
shader以下:
1 // Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)' 2 3 Shader "Custom/Alpha Test" 4 { 5 Properties 6 { 7 _MainTex("Main Texture", 2D) = "white" {} 8 _Specular("Specular", Color) = (1,1,1,1) 9 _Gloss("Gloss", Range(8, 256)) = 8 10 _CutOff("Cut Off", Range(0, 1)) = 0 11 } 12 13 SubShader 14 { 15 Pass 16 { 17 Tags 18 { 19 "LightMode" = "ForwardBase" 20 } 21 22 CGPROGRAM 23 #pragma vertex vert 24 #pragma fragment frag 25 26 #include "UnityCg.cginc" 27 #include "Lighting.cginc" 28 29 sampler2D _MainTex; 30 float4 _MainTex_ST; 31 fixed4 _Specular; 32 float _Gloss; 33 float _CutOff; 34 35 struct appdata 36 { 37 float4 vertex : POSITION; 38 float3 normal : NORMAL; 39 fixed4 color : COLOR; 40 float2 uv : TEXCOORD0; 41 }; 42 43 struct v2f 44 { 45 float4 pos : SV_POSITION; 46 fixed4 color : COLOR; 47 float2 uv : TEXCOORD0; 48 float3 worldNormal : TEXCOORD1; 49 float3 worldLight : TEXCOORD2; 50 float3 worldView : TEXCOORD3; 51 }; 52 53 v2f vert(appdata v) 54 { 55 v2f o; 56 o.pos = UnityObjectToClipPos(v.vertex); 57 o.color = v.color; 58 o.uv = TRANSFORM_TEX(v.uv, _MainTex); 59 o.worldNormal = UnityObjectToWorldNormal(v.normal); 60 o.worldLight = normalize(WorldSpaceLightDir(v.vertex)); 61 o.worldView = normalize(WorldSpaceViewDir(v.vertex)); 62 return o; 63 } 64 65 fixed4 frag(v2f i) : SV_TARGET 66 { 67 fixed4 albedo = tex2D(_MainTex, i.uv) * i.color; 68 69 // alpha test 70 clip(albedo.a - _CutOff); 71 // equals to: 72 //if(albedo.a - _CutOff < 0) 73 // discard; 74 75 fixed3 ambient = albedo.rgb * UNITY_LIGHTMODEL_AMBIENT.rgb; 76 fixed3 diff = albedo.rgb * _LightColor0.rgb * max(0, dot(i.worldNormal, i.worldLight)); 77 fixed3 halfDir = normalize(i.worldLight + i.worldView); 78 fixed3 spec = albedo.rgb * _Specular.rgb * pow(max(0, dot(halfDir, i.worldNormal)), _Gloss); 79 fixed3 col = ambient + diff + spec; 80 return fixed4(col, 1); 81 } 82 83 ENDCG 84 } 85 } 86 87 Fallback "Diffuse" 88 }
效果以下:
資源以下:
http://files.cnblogs.com/files/jietian331/transparent_texture.rar
有2個問題:
1. 從效果圖中可看出,alpha test 獲得的透明效果很「極端」——要麼徹底透明,要麼徹底不透明,並且在邊緣上良莠不齊,有鋸齒,這是由於在邊界處紋理的透明度變化精度問題。
2. 在片元着色器中discard操做會形成性能的降低。爲何?
由於Unity採用了Early-Z技術來提升GPU的性能,即把深度測試提早,先進行深度測試,再進行片元着色器的着色,這樣被捨棄的片元便不須要再進行片元着色器的處理了,這樣有利於提高GPU的性能。
而這種技術與片元着色器的discard操做是衝突的,所以現代的GPU會判斷片元着色器中的操做是否與提早測試衝突,若是有衝突就會禁用提早測試,也就形成了性能上的降低。