赞
踩
透明度测试的原理是将片元的 Alpha 值与某个指定的阈值进行比较,当 Alpha 超过阈值时,该片元正常显示,若 Alpha 值低于指定的阈值,则将该片元丢弃。准确来讲,透明度测试并不是为了渲染一种半透的效果,而是为了通过片元的 Alpha 值进行筛选,确定哪些像素需要渲染哪些像素不需要渲染,跟我们之前提到过的深度测试的效果是一样的,只不过筛选条件不同。
实际上,在透明度测试中,与阈值进行比较的并不一定必须是Alpha值,我们可以用采样得到的任意通道的值——甚至是某个计算得到的值,只要是我们通过某种方式可以掌控的值——来跟阈值进行比较。其重点是通过设定的阈值对像素进行筛选,以确定像素是否需要被丢弃。
因此,透明度测试的结果要么完全不显示,要么正常显示。
在【Unity Shader入门精要 第2章】渲染流水线 中我们曾经提到过,存在透明度测试时无法开启Early-Z,正是因为如果开启了 Early-Z,那么在进入片元着色器之前就已经完成了深度测试,此时像素的深度值就会被写入到深度缓冲当中。接着进入片元着色器,发现当前片元的 Alpha 值没有达到阈值,于是该片元被舍弃不会进行渲染,但已经写入深度缓冲中的深度值又不会被撤回,结果就导致深度缓存出错。
使用的测试纹理如下:
在Shader中增加 _AlphaTest 属性,用于控制进行透明度测试的阈值
在SubShader中设置标签
Tags {"Queue" = "AlphaTest" "IgnoreProjector" = "True" "RenderType" = "TransparentCutout"}
在片元着色器中,使用了clip 方法进行裁剪,该方法的参数可以传入float
void clip(float _checkValue);
此时若 _checkValue 小于0,则会舍弃当前片元的颜色输出,否则正常输出。
也可以传入float2、float3等矢量
void clip(float3 _checkValue);
此时,若 _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 } } }
效果如下:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。