透明度测试
一种比较极端的透明方法,它无法实现半透明效果,它的透明度要么为1,要么为0,也就是要么完全透明,要么完全不透明。
透明度测试就是要判断一下,吧不满足条件的像素值剔除掉
在shaderlab中,为什么提供了一个内置的函数,clip(float x)如果传入的参数小于0 那么该像素块就会被剔除掉
Shader "Custom/AlphaTest"
{
Properties
{
_MainTex ("Albedo (RGB)", 2D) = "white" {
}
_CutOff ("Alpha CutOff",Range(0,1))=0.5
}
SubShader
{
tags{
"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
pass{
Tags{
"LightMode"="ForwardBase"}
cull off
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "Lighting.cginc"
sampler2D _MainTex;
float4 _MainTex_ST;
fixed _CutOff;
struct a2v{
float4 vertex : POSITION;
float3 normal : NORMAL;
float4 texcoord : TEXCOORD0;
};
struct v2f{
float4 pos : SV_POSITION;
float3 worldNormal : TEXCOORD0;
float3 worldPos : TEXCOORD1;
float2 uv : TEXCOORD2;
};
v2f vert(a2v i){
v2f o;
o.pos = UnityObjectToClipPos(i.vertex);
o.worldPos = mul(unity_ObjectToWorld,i.vertex);
//o.worldNormal = UnityObjectToWorldNormal(i.normal);
o.worldNormal = mul(unity_ObjectToWorld,i.normal);
o.uv = TRANSFORM_TEX(i.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i):SV_TARGET{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 worldLightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex,i.uv);
//Alpha Test
clip(texColor.w - _CutOff);
fixed3 albedo = texColor.xyz;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
fixed3 diffuse = _LightColor0.xyz * albedo * max(0,dot(worldNormal,worldLightDir));
return fixed4(ambient+diffuse, 1);
}
ENDCG
}
}
FallBack "Diffuse"
}
透明度混合
真正实现半透明效果的还是透明度混合
透明度混合实现半透明效果需要把自身的颜色和已经存在于颜色缓冲区的颜色进行混合
透明度混合要关闭深度写入,但是不需要关闭深度测试,所以当使用透明度混合渲染一个片元的时候,以旧会吧当前的的深度值和深度缓冲之中的值进行比较,如果深度值距离摄像机远,就不需要混合,意思就是当一个不透明的问题在透明物体的前面,我们先渲染了不透明的物体,他是可以遮挡住不透明的物体的因此对于透明度混合来说,深度缓冲是只读的
关于渲染顺序的问题,先渲染不透明物体,在渲染透明物体,其中透明物体按照距离摄像机的远近进行排序,先渲染距离摄像机远的,在渲染进的
unity为我们提供了5个渲染顺序
当然 由于关闭了深度写入,无法对模型进行像素级别的排序,如果模型包含了复杂的遮罩关系或者凸网格的时候,就会出现错误的透明效果
Shader "Custom/AlphaBlend"
{
Properties
{
_Color ("Color Tint", Color) = (1, 1, 1, 1)
_MainTex ("Main Tex", 2D) <