首页 > 代码库 > 透明度混合
透明度混合
透明度混合:这种方法可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。但是透明度混合需要关闭深度写入。
这使得我们要非常小心物体的渲染顺序。
为了进行混合,我们需要使用Unity提供的混合命令——Blend。
我们这里使用 Blend SrcAlpha OneMinusSrcAlpha
内部公式为:DstColor(new)=SrcAlpha*SrcColor+(1-SrcAlpha)*DstColor(old);
首先是关闭深度写入的代码:
1 Shader "Custom/AlphaBlend" {
2 Properties {
3 _Color ("Main Tint", Color) = (1,1,1,1)
4 _MainTex ("Albedo (RGB)", 2D) = "white" {}
5 _AlphaScale("Alpha Scale",Range(0,1))=1
6 }
7 SubShader {
8 /*
9 "Queue"="AlphaTest":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列
10 "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响
11
12 通常使用了透明度测试的shader都应该在SubShader中设置这3个标签
13 */
14 Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="TransparentCutout"}
15 Pass
16 {
17 Tags{"LightMode"="ForwardBase"}
18 Cull Off
19 ZWrite Off
20 Blend SrcAlpha OneMinusSrcAlpha
21 CGPROGRAM
22 #pragma vertex vert
23 #pragma fragment frag
24 #include"Lighting.cginc"
25
26 fixed4 _Color;
27 sampler2D _MainTex;
28 float4 _MainTex_ST;
29 fixed _AlphaScale;
30
31 struct a2v
32 {
33 float4 vertex:POSITION;
34 float3 normal:NORMAL;
35 float4 texcoord:TEXCOORD0;
36 };
37 struct v2f
38 {
39 float4 pos:SV_POSITION;
40 float3 worldNormal:TEXCOORD0;
41 float3 worldPos:TEXCOORD1;
42 float2 uv:TEXCOORD2;
43 };
44 v2f vert(a2v v)
45 {
46 v2f o;
47 o.pos=mul(UNITY_MATRIX_MVP,v.vertex);
48 o.worldNormal=UnityObjectToWorldNormal(v.normal);
49 o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
50 o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
51 return o;
52 }
53
54 fixed4 frag(v2f i):SV_Target
55 {
56 fixed3 worldNormal=normalize(i.worldNormal);
57 fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos));
58 fixed4 texColor=tex2D(_MainTex,i.uv);
59 fixed3 albedo=texColor.rgb*_Color.rgb;
60 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo;
61 fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));
62 return fixed4(ambient+diffuse,texColor.a*_AlphaScale);
63 }
64
65 ENDCG
66 }
67 }
68 FallBack "Transparent/Cutout/VertexLit"
69 }
我们可以调节材质面板上的Alpha Scale参数,以控制整体透明度。
当然,关闭深度写入有时候会带来因为排序错误而产生的错误的透明效果(模型本身有复杂的遮挡关系)。
所以我们可以采用开启深度写入进行透明度混合。原理是开启2个Pass来渲染模型。第一个Pass开启深度写入,但是不输出颜色,它的目的仅仅是为了把该模型的深度值写入深度缓冲中。第二个Pass进行透明度混合。(多使用一个Pass会对性能造成一定的影响)。在之前的代码中原有的Pass前面添加以下代码即可:
Pass { ZWrite On ColorMask 0 }
完整代码:
1 Shader "Custom/AlphaBlend" { 2 Properties { 3 _Color ("Main Tint", Color) = (1,1,1,1) 4 _MainTex ("Albedo (RGB)", 2D) = "white" {} 5 _AlphaScale("Alpha Scale",Range(0,1))=1 6 } 7 SubShader { 8 /* 9 "Queue"="AlphaTest":Unity中透明度测试使用的渲染队列是名为AlphaTest的队列 10 "IgnoreProjectors"="True":意味着这个Shader不会受到投影器的影响 11 12 通常使用了透明度测试的shader都应该在SubShader中设置这3个标签 13 */ 14 Tags{"Queue"="Transparent""IgnoreProjectors"="True""RenderType"="TransparentCutout"} 15 Pass 16 { 17 ZWrite On 18 ColorMask 0 19 } 20 Pass 21 { 22 Tags{"LightMode"="ForwardBase"} 23 ZWrite Off 24 Blend SrcAlpha OneMinusSrcAlpha 25 CGPROGRAM 26 #pragma vertex vert 27 #pragma fragment frag 28 #include"Lighting.cginc" 29 30 fixed4 _Color; 31 sampler2D _MainTex; 32 float4 _MainTex_ST; 33 fixed _AlphaScale; 34 35 struct a2v 36 { 37 float4 vertex:POSITION; 38 float3 normal:NORMAL; 39 float4 texcoord:TEXCOORD0; 40 }; 41 struct v2f 42 { 43 float4 pos:SV_POSITION; 44 float3 worldNormal:TEXCOORD0; 45 float3 worldPos:TEXCOORD1; 46 float2 uv:TEXCOORD2; 47 }; 48 v2f vert(a2v v) 49 { 50 v2f o; 51 o.pos=mul(UNITY_MATRIX_MVP,v.vertex); 52 o.worldNormal=UnityObjectToWorldNormal(v.normal); 53 o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz; 54 o.uv=TRANSFORM_TEX(v.texcoord,_MainTex); 55 return o; 56 } 57 58 fixed4 frag(v2f i):SV_Target 59 { 60 fixed3 worldNormal=normalize(i.worldNormal); 61 fixed3 worldLightDir=normalize(UnityWorldSpaceLightDir(i.worldPos)); 62 fixed4 texColor=tex2D(_MainTex,i.uv); 63 fixed3 albedo=texColor.rgb*_Color.rgb; 64 fixed3 ambient=UNITY_LIGHTMODEL_AMBIENT.xyz*albedo; 65 fixed3 diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir)); 66 return fixed4(ambient+diffuse,texColor.a*_AlphaScale); 67 } 68 69 ENDCG 70 } 71 } 72 FallBack "Transparent/Cutout/VertexLit" 73 }
透明度混合
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。