zoukankan      html  css  js  c++  java
  • 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会判断片元着色器中的操作是否与提前测试冲突,如果有冲突就会禁用提前测试,也就造成了性能上的下降。

  • 相关阅读:
    SQliteDatabase详解
    Eclipse常用快捷键
    Android 省市区三级联动
    关于安卓9patch图片的探究
    9patch
    Day3_UI布局--FXQ
    day2-UI布局
    Day01_扩展_Genymotion模拟器的使用
    React Examples
    React项目结构
  • 原文地址:https://www.cnblogs.com/jietian331/p/7154001.html
Copyright © 2011-2022 走看看