透明效果一
一、基础
要在模型中实现透明效果,可以通过两种方式来实现:透明测试和透明混合。
透明测试:这种方式其实是通过透明度来判断哪些地方需要去渲染,如果透明度低于设定的值就不去渲染。其实这里和遮罩有点相似。透明测试主要去判断一张贴图的透明通道,然后将低于该透明通道的部分取消渲染。
透明度混合:这种方式可以实现半透明效果。
二、一些关键词
深度缓冲(z-buffer):深度缓冲对应深度测试中的一环。缓冲其实是指对应内存空间的一块区域。
深度写入(z-write):是指能够写入深度缓冲区域。如果关闭则不能写入。
深度测试(z-test):深度测试是逐片元渲染中一个测试环节,每个片元需要经过不同的测试才能被最终渲染,而深度测试就是其中之一。如果开启了深度测试,那么片元会与已有的深度缓存区进行比较。深度测试流程为:
在有透明效果的渲染流程中,深度测试的设置显得尤为重要。如果一个片元没有通过深度测试,但是我们还是能够通过配置去决定是否写入到深度缓存区。
颜色缓冲(ColorBuffer):三、透明测试
在透明测试实现中,我们不需要去考虑是否需要关闭深度写入,可以按照不透明物体来设置。
代码:
// Upgrade NOTE: replaced 'mul(UNITY_MATRIX_MVP,*)' with 'UnityObjectToClipPos(*)'
Shader "Custom/4.1.1" {//渐变纹理
Properties{
_Color("Color Tint", Color) = (1, 1, 1, 1)
_MainTex("Main Tex",2D) = "white"{}
_CutOff("CutOff Value",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"
fixed4 _Color;
sampler2D _MainTex;
float4 _MainTex_ST;//一张贴图就应该对应一个_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 v) {
v2f o;
o.pos = UnityObjectToClipPos(v.vertex);//将模型空间转到剪切空间
//o.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw;//缩放后再位移
//为之后计算凹凸纹理做准备先将光线和视线方向转到切线空间
o.worldNormal = UnityObjectToWorldNormal(v.normal);
o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
o.uv = TRANSFORM_TEX(v.texcoord,_MainTex);
return o;
}
fixed4 frag(v2f i) : SV_Target{
fixed3 worldNormal = normalize(i.worldNormal);
fixed3 lightDir = normalize(UnityWorldSpaceLightDir(i.worldPos));
fixed4 texColor = tex2D(_MainTex, i.uv);
//开始剔除
clip(texColor.a - _CutOff);
fixed3 albedo = texColor.rgb * _Color;
fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;//环境光
fixed3 diffuse = _LightColor0.rgb * ambient * max(0, dot(worldNormal, lightDir));//漫反射
return fixed4(ambient + diffuse, 1.0);
}
ENDCG
}
}
FallBack "Specular"
}
与之前计算漫反射效果不同的是,这里添加了一句:clip(texColor.a - _CutOff);
这一句话决定,低于某个值的片元将会被剔除,因此才有了上图效果。相比于书上的例子,我这里添加了一句Cull Off来实现双面渲染效果。这样看起来会更好一些。
在透明效果实现的时候我们会强调关闭深度写入,注意渲染队列等