US3S3L5——透明度混合
US3S3L5——透明度混合
透明度混合
透明度测试,并不能用于实现半透明效果,
它只存在看得见和完全看不见两种状态,一般用来处理镂空效果
而透明度混合,主要就是用来实现半透明效果的
透明度混合的基本原理
基本原理:关闭深度写入,开启混合,让片元颜色和颜色缓冲区中颜色进行混合计算
具体实现:
-
采用半透明的混合因子进行混合,以
Blend SrcAlpha OneMinusSrcAlpha
为例:因此:
-
声明一个 0~1 区间的
_AlphaScale
用于控制对象整体透明度
透明度混合实现
值得一提的是,一般透明材质的 Shader 的名字后面会跟随一个 _Transparent
的后缀
-
复用 颜色纹理结合光照模型 的Shader
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
68
69
70Shader "TeachShader/Lesson57_Transparent"
{
Properties
{
_MainTex("MainTex", 2D) = ""{} // 纹理贴图
_MainColor("MainColor", Color) = (1, 1, 1, 1) // 漫反射颜色
_SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) // 高光反射颜色
_SpecularNum("SpecularNum", Range(0, 20)) = 15 // 光泽度
}
SubShader
{
Pass
{
Tags { "LightMode" = "ForwardBase" }
CGPROGRAM
// 贴图纹理对应的映射成员
sampler2D _MainTex;
float4 _MainTex_ST;
// 漫反射颜色、高光反射颜色、光泽度
fixed4 _MainColor;
fixed4 _SpecularColor;
float _SpecularNum;
struct v2f
{
float4 pos: SV_POSITION; // 裁剪空间下的顶点坐标
float2 uv: TEXCOORD0; // 纹理UV坐标
float3 wNormal: NORMAL; // 世界空间下的法线
float3 wPos: TEXCOORD1; // 世界空间下的顶点坐标
};
v2f vert (appdata_base v)
{
v2f data;
data.pos = UnityObjectToClipPos(v.vertex); // 将模型空间下的法线转换到世界空间下
data.uv = v.texcoord.xy * _MainTex_ST.xy + _MainTex_ST.zw; // 计算UV
data.wNormal = UnityObjectToWorldNormal(v.normal); // 法线转换到世界空间
data.wPos = mul(unity_ObjectToWorld, v.vertex); // 顶点转换到世界空间
return data;
}
fixed4 frag (v2f i) : SV_Target
{
fixed3 albedo = tex2D(_MainTex, i.uv).rgb * _MainColor.rgb; // 反射率,即纹理颜色和漫反射材质颜色乘法叠加共同决定的颜色
// 漫反射颜色
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 指向光源的方向
fixed3 lambertColor = _LightColor0.rgb * albedo.rgb * max(0, dot(i.wNormal, lightDir));
// 高光反射颜色
float3 viewDir = normalize(UnityWorldSpaceViewDir(i.wPos)); // 视角方向
float3 halfA = normalize(viewDir + lightDir); // 半角向量
fixed3 specularColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(i.wNormal, halfA)), _SpecularNum);
// 最终颜色 = 环境光 * 反射颜色 + 漫反射颜色 + 高光反射颜色
fixed3 color = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo + lambertColor + specularColor;
return fixed4(color.rgb, 1);
}
ENDCG
}
}
} -
在属性中加一个透明值
_AlphaScale
,取值范围为 0~1,用来设定对象整体透明度。并在CG中添加属性的映射成员(使用fixed
)1
2
3
4
5
6
7
8Properties
{
_MainTex("MainTex", 2D) = ""{} // 纹理贴图
_MainColor("MainColor", Color) = (1, 1, 1, 1) // 漫反射颜色
_SpecularColor("SpecularColor", Color) = (1, 1, 1, 1) // 高光反射颜色
_SpecularNum("SpecularNum", Range(0, 20)) = 15 // 光泽度
_AlphaScale("AlphaScale", Range(0, 1)) = 1 // 对象总体透明度
}1
2
3
4
5
6
7
8
9// 贴图纹理对应的映射成员
sampler2D _MainTex;
float4 _MainTex_ST;
// 漫反射颜色、高光反射颜色、光泽度
fixed4 _MainColor;
fixed4 _SpecularColor;
float _SpecularNum;
// 对象整体透明度
fixed _AlphaScale; -
将渲染队列设置为
Transparent
,并配合IgnoreProjector
和RenderType
一起设置1
2
3
4
5SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Pass { /*...*/ }
} -
关闭深度写入
Zwrite off
,设置混合因子Blend SrcAlpha OneMinusSrcAlpha
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15SubShader
{
Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
Pass
{
Tags { "LightMode" = "ForwardBase" }
ZWrite Off //半透明效果关闭深度写入
Blend SrcAlpha OneMinusSrcAlpha //设置混合因子
CGPROGRAM
// ...
ENDCG
}
} -
在片元着色器中获取了颜色贴图颜色后,修改最后返回颜色的 A 值为:
纹理.a * _AlphaScale
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19fixed4 frag (v2f i) : SV_Target
{
fixed4 texColor = tex2D(_MainTex, i.uv); // 取出纹理的颜色
fixed3 albedo = texColor.rgb * _MainColor.rgb; // 反射率,即纹理颜色和漫反射材质颜色乘法叠加共同决定的颜色
// 漫反射颜色
float3 lightDir = normalize(_WorldSpaceLightPos0.xyz); // 指向光源的方向
fixed3 lambertColor = _LightColor0.rgb * albedo.rgb * max(0, dot(i.wNormal, lightDir));
// 高光反射颜色
float3 viewDir = normalize(UnityWorldSpaceViewDir(i.wPos)); // 视角方向
float3 halfA = normalize(viewDir + lightDir); // 半角向量
fixed3 specularColor = _LightColor0.rgb * _SpecularColor.rgb * pow(max(0, dot(i.wNormal, halfA)), _SpecularNum);
// 最终颜色 = 环境光 * 反射颜色 + 漫反射颜色 + 高光反射颜色
fixed3 color = UNITY_LIGHTMODEL_AMBIENT.rgb * albedo + lambertColor + specularColor;
// 最终透明度 = A通道值 * 整体透明度
return fixed4(color.rgb, texColor.a * _AlphaScale);
}
完整 Shader 实现如下:
1 | Shader "TeachShader/Lesson57_Transparent" |
效果展示:
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 文KRIFE齐的博客!