Unity Shader入门精要笔记(十八):透明度混合

本系列文章由Aimar_Johnny编写,欢迎转载,转载请标明出处,谢谢。

https://blog.csdn.net/lzhq1982/article/details/82861186

 

前面章节介绍过,透明度混合是实现了真正的半透效果。它会以当前片元透明度作为混合因子,与已经存储在颜色缓冲区中的颜色进行混合,得到新的颜色。同时要关掉深度写入,小心物体的渲染顺序。

为了进行混合,我们用Unity提供的混合命令——Blend。如下表:

本节用Blend SrcFactor DstFactor来进行混合。这个命令在设置混合因子的同时也开启了混合模式,否则不会有混合效果,因为开启了混合模式,片元的透明通道才有意义。我们把源颜色的混合因子设为SrcAlpha,目标的设为OneMinusSrcAlpha。则混合后的新颜色为:

DstColor = SrcAlpha * SrcColor + (1 - SrcAlpha) * DstColor

在上代码之前,我们先看看要实现的效果:

我们用上一章提供的纹理,配合立方体实现如上效果,代码如下:

Shader "CustomShader/Transparent/AlphaBlendShader"
{
	Properties
	{
		_MainTex ("Texture", 2D) = "white" {}
		_Color ("Color Tint", Color) = (1, 1, 1, 1)
		_AlphaScale ("Alpha Scale", Range(0, 1)) = 1
	}
	SubShader
	{
		Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}

		Pass
		{
			Tags {"LightMode" = "ForwardBase"}

			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha

			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag
			
			#include "Lighting.cginc"

			struct appdata
			{
				float4 vertex : POSITION;
				float2 uv : TEXCOORD0;
				float3 normal : NORMAL;
			};

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
				float3 worldNormal : TEXCOORD1;
				float3 worldPos : TEXCOORD2;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed4 _Color;
			float _AlphaScale;

			v2f vert (appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				o.worldNormal = UnityObjectToWorldNormal(v.normal);
				o.worldPos = mul(unity_ObjectToWorld, v.vertex).xyz;
				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);
				fixed3 albedo = texColor.rgb * _Color.rgb;

				fixed3 ambient = UNITY_LIGHTMODEL_AMBIENT.xyz * albedo;
				fixed3 diffuse = _LightColor0.rgb * albedo * max(0, dot(worldNormal, worldLightDir));

				return fixed4(ambient + diffuse, texColor.a * _AlphaScale);
			}
			ENDCG
		}
	}

	FallBack "Transparent/VertexLit"
}

上面的代码去掉光照和纹理采样部分,剩下的透明处理部分其实很少,我们着重看一下。

首先要注意的是标签,我们用了如下标签:

Tags {"Queue" = "Transparent" "RenderType" = "Transparent" "IgnoreProjector" = "True"}

Queue渲染队列用Transparent表明透明混合队列,RenderType也用Transparent把这个Shader归入到提前定义的组(Transparent)中,用来指明该Shader是一个使用了透明度混合的shader。IgnoreProjector设为True来不受到投影器的影响。

然后Pass里我们关闭了深度写入:

ZWrite Off

打开并设置混合模式:

Blend SrcAlpha OneMinusSrcAlpha

最后我们在片元着色器中设置了透明通道

return fixed4(ambient + diffuse, texColor.a * _AlphaScale);

_AlphaScale可以用来调节透明的强度。

这样就可以用纹理的alpha和我们自定义的AlphaScale叠加控制最后的透明效果了。

 

上面我们只是用最常见的方法实现了透明效果,下面要重点讲一下透明参数的各种设置。

当进行混合时,我们需要两个混合等式,一个用于混合RGB通道,一个用于混合A通道。当设置混合状态时,我们实际上设置的是混合等式中的操作因子。默认情况下,混合等式使用的操作都是加操作(当然也可以使用其他操作),我们可以不用管,大多数情况我们只设置混合因子就可以了。由于需要两个等式,每个等式有两个因子(一个和源颜色相乘,一个和目标颜色相乘),所以一共需要4个因子。下表给出了ShaderLab设置混合因子的命令:

第一个命令只提供了两个因子,这意味着使用SrcFactor代替SrcFactorA,DstFactor代替DstFactorA。下面就是混合公式:

下表是ShaderLab提供的几种混合因子:

上面提到过,混合操作默认是加法,如果我们有其他需求,可以用ShaderLab的BlendOp BlendOperation设置混合操作,下表是ShaderLab支持的混合操作:

需要注意的是,当使用Min或Max时,混合因子是不起作用的,它只会判断源颜色和目标颜色的比较结果。

最后我们列举出几种常见的混合类型,得到类似Photoshop混合模式中的效果:

//正常(Normal)

Blend SrcAlpha OneMinusSrcAlpha

//柔和相加(Soft Addtive)

Blend OneMinusDstAlpha One

//正片叠底(Multiply),即相乘

Blend DstColor Zero

//两倍相乘(2x Multiply)

Blend DstColor SrcColor

//变暗(Darken)

BlendOp Min

Blend One One

//变亮(Lighten)

BlendOp Max

Blend One One

//滤色(Screen)

Blend OneMinusDstColor One

//等同于

Blend One OneMinusSrcColor

//线性减淡(Linear Dodge)

Blend One One

下图是上面得到的效果:

 

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值