当前位置:   article > 正文

【Unity Shader入门精要 第8章】透明效果(二)

【Unity Shader入门精要 第8章】透明效果(二)

1. 透明度测试

透明度测试的原理是将片元的 Alpha 值与某个指定的阈值进行比较,当 Alpha 超过阈值时,该片元正常显示,若 Alpha 值低于指定的阈值,则将该片元丢弃。准确来讲,透明度测试并不是为了渲染一种半透的效果,而是为了通过片元的 Alpha 值进行筛选,确定哪些像素需要渲染哪些像素不需要渲染,跟我们之前提到过的深度测试的效果是一样的,只不过筛选条件不同。

实际上,在透明度测试中,与阈值进行比较的并不一定必须是Alpha值,我们可以用采样得到的任意通道的值——甚至是某个计算得到的值,只要是我们通过某种方式可以掌控的值——来跟阈值进行比较。其重点是通过设定的阈值对像素进行筛选,以确定像素是否需要被丢弃。

因此,透明度测试的结果要么完全不显示,要么正常显示。

【Unity Shader入门精要 第2章】渲染流水线 中我们曾经提到过,存在透明度测试时无法开启Early-Z,正是因为如果开启了 Early-Z,那么在进入片元着色器之前就已经完成了深度测试,此时像素的深度值就会被写入到深度缓冲当中。接着进入片元着色器,发现当前片元的 Alpha 值没有达到阈值,于是该片元被舍弃不会进行渲染,但已经写入深度缓冲中的深度值又不会被撤回,结果就导致深度缓存出错。

2. 示例

  • 创建 Chapter_8_AlphaTest_Mat 作为测试材质
  • 创建 Chapter_8_AlphaTest_Shader 作为测试shader,并赋给 Chapter_8_AlphaTest_Mat 材质
  • 场景中创建一个用于测试的立方体,将 Chapter_8_AlphaTest_Mat 材质赋给立方体
  • 场景中添加一盏平行光,并调整平行光角度
  • 为了便于观察效果,在立方体下方创建一个Plane

使用的测试纹理如下:
在这里插入图片描述
Shader中增加 _AlphaTest 属性,用于控制进行透明度测试的阈值

在SubShader中设置标签

Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
  • 1

在片元着色器中,使用了clip 方法进行裁剪,该方法的参数可以传入float

void clip(float _checkValue);
  • 1

此时若 _checkValue 小于0,则会舍弃当前片元的颜色输出,否则正常输出。
也可以传入float2、float3等矢量

void clip(float3 _checkValue);
  • 1

此时,若 _checkValue 中的任意一个分量小于0,均会舍弃当前片元的颜色输出,否则正常输出。

在 Inpector 面板中改变 AlphaTest属性的值,即可看到效果。
在这里插入图片描述

最终Shader如下:

Shader "MyShader/Chapter_8/Chapter_8_AlphaTest_Shader"
{
    Properties
    {
        _MainTex("MainTex", 2D) = "white"{}
        _AlphaTest("AlphaTest", range(0, 1)) = 0
    }
    
    SubShader
    {
    	Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCurout"}
    	
        Pass
        {
            Tags {"LightMode" = "ForwardBase"}
        
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
            #include "UnityCG.cginc"
            #include "Lighting.cginc"
            
            struct a2v
            {
                float4 vertex : POSITION;
                float3 normal : NORMAL;
                float2 uv : TEXCOORD0;
            };
            
            struct v2f
            {
                float4 vertex : SV_POSITION;
                float2 uv : TEXCOORD0;
                float3 worldNormal : TEXCOORD1;
            };
            
            sampler2D _MainTex;
            float4 _MainTex_ST;
            fixed _AlphaTest;
            
            v2f vert(a2v i)
            {
                v2f o;
                o.vertex = UnityObjectToClipPos(i.vertex);
                o.worldNormal = mul(i.normal, (float3x3)unity_WorldToObject);
                o.uv = TRANSFORM_TEX(i.uv, _MainTex);
                return o;
            }
            
            fixed4 frag(v2f i) : SV_Target
            {
                fixed3 _ambient = UNITY_LIGHTMODEL_AMBIENT.rgb;
                float3 _worldNormal = normalize(i.worldNormal);
                float3 _worldLight = normalize(_WorldSpaceLightPos0.xyz);
                fixed4 _sampledColor = tex2D(_MainTex, i.uv);
                clip(_sampledColor.w - _AlphaTest);
                fixed3 _diffuse = _LightColor0.rgb * _sampledColor.xyz * (0.5 * dot(_worldLight, _worldNormal) + 0.5);
                return fixed4(_ambient + _diffuse, 1);
            }
            
            ENDCG
        }
    
    }

}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67

效果如下:
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/AllinToyou/article/detail/603502
推荐阅读
相关标签
  

闽ICP备14008679号