Unity shader學習之Alpha Test


可以在fragment中使用cg的函數--clip來進行透明度測試。

函數定義如下:

void clip(float4 x);

void clip(float3 x);

void clip(float2 x);

void clip(float1 x);

void clip(float x);

參數:裁剪時使用的標量或矢量條件。

描述:如果給定參數的任何一個分量是負數,就會舍棄當前像素的輸出顏色。等同於:

            void clip(float4 x)
            {
                if (any(x < 0))
                    discard;
            }                

轉載請注明出處:http://www.cnblogs.com/jietian331/p/7154001.html

 

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會判斷片元着色器中的操作是否與提前測試沖突,如果有沖突就會禁用提前測試,也就造成了性能上的下降。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM