【Shader进阶】常见的渲染状态RenderSetup——Blend

121 篇文章 2 订阅
24 篇文章 3 订阅

目录

一、BlendOp混合操作

二、Blend混合因子

三、实战

1、BlendOp Sub,Alpha为0.7,混合因子不变情况

四、关于Queue为Transparent时,是否默认关闭深度写入的问题再次进行探讨和说明。

(如有误解,请私信或评论留言,吐槽什么的都可以~)


一、BlendOp混合操作

混合操作
Add    
将混合后的源颜色和混合后的目标颜色相加。默认的混合操作。使用的混合等式是:

O(rgb) = SrcFactor * S(rgb) + DstFactor * D(rgb)

O(a) = SrcFactorA * S(a) + DstFactorA * D(a)

Sub    
用混合后的源颜色值减去混合后的目标颜色。使用的混合等式是:

O(rgb) = SrcFactor * S(rgb) - DstFactor * D(rgb)

O(a) = SrcFactorA * S(a) - DstFactorA * D(a)

RevSub    
用混合后的目标颜色值减去混合后的源颜色。使用的混合等式是:

O(rgb) = DstFactor * D(rgb) - SrcFactor * S(rgb)

O(a) = DstFactorA * D(a) - SrcFactorA * S(a)

Min    
使用源颜色和目标颜色中较小的值,是逐分量比较的。使用的混合等式是:

O(rgba) = ( min( S(r), D(r) ), min(S(g),D(g)), min(S(b),D(b)), min(S(a),D(a)) )

Max    
使用源颜色和目标颜色中较大的值,是逐分量比较的。使用的混合等式是:

O(rgba) = ( max( S(r), D(r) ), max(S(g),D(g)), max(S(b),D(b)), max(S(a),D(a)) )

其他逻辑操作    仅在DirectX 11.1 中支持

二、Blend混合因子

混合因子
One    1
Zero    0
SrcColor    源颜色值(RGBA):当用于混合RGB通道时,混合因子为SrcColor.rgb;当混合A通道时,混合因子为SrcColor.a
SrcAlpha    源颜色的透明度值(A通道)
DstColor    目标颜色值(RGBA):当用于混合RGB通道时,混合因子为DstColor.rgb;当混合A通道时,混合因子为DstColor.a
DstAlpha    目标颜色的透明度值(A通道)
OneMinusSrcScolor    (1 - 源颜色值(RGBA)):当用于混合RGB通道时,混合因子为(1 - 源颜色值(RGBA)).rgb;当混合A通道时,混合因子为(1 - 源颜色值(RGBA)).a
OneMinusSrcAlpha    1 - 源颜色的透明度值(A通道)
OneMinusDstScolor    
(1 - 目标颜色值(RGBA)):当用于混合RGB通道时,混合因子为(1 - 目标颜色值(RGBA)).rgb;当混合A通道时,混合因子为(1 - 目标颜色值(RGBA)).a 

OneMinusDstAlpha    1 - 目标颜色的透明度值(A通道)

三、实战

(Alpha为0.7)

Shader "Unlit/BlendShaderTest"
{
	Properties
	{
		_MainTex("Texture", 2D) = "white" {}
		_Alpha("Alpha", Range(0,1)) = 1
	}
	SubShader
	{
		Tags{
			"Queue" = "Transparent" //必須是透明通道才可混合
		}
		BlendOp Add //相加混合
		Blend SrcAlpha OneMinusSrcAlpha //RGB和A通道混合因子均为源Alpha、1-源Alpha 
		//BlendOp Add相加混合对应如下两个公式分别为RGB混合公式和A混合公式
		//
		//O(rgb) = SrcFactor * S(rgb) + DstFactor * D(rgb)
		//代入因子为 输出RGB = 源Alpha值 * 源RGB值 - (1-源Alpha值) * 目标RGB值 [源是指当前片元着色器输出的颜色值、目标是指颜色缓冲区本身存在的值]
		//假如_Alpha为0.3,片元着色器输出(1,0,0,0.3),目标颜色值为(1,1,1,1)
		//公式为 输出RGB = (1,0,0) * 0.3  + (1-0.3) * (1,1,1) = (0.3+0.7, 0.7, 0.7) = (1, 0.7, 0.7)
		//简单理解为削弱0.7倍片元着色器输出颜色值,削弱0.3倍颜色缓冲区颜色值,再将相加混合,形成新的RGB值,至此完成RGB混合

		//O(a) = SrcFactorA * S(a) + DstFactorA * D(a) [Alpha值混合同理]
		//输出Alpha值 = 源Alpha值 * 源Alpha值 - (1-源Alpha值) * 目标Alpha值

		//其实,当没有Alpha混合因子时,可以直接用 O(rgba) = SrcFactor * S(rgba) + DstFactor * D(rgba) 来运算混合后的RGBA
		//假如我混合因子为:Blend SrcAlpha OneMinusSrcAlpha 1 0
		//此时后两个数值显式指明Alpha混合因子为1和0,代入公式可得知是为了忽略目标Alpha值对混合的影响
		Pass
		{
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag		

			#include "UnityCG.cginc"

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

			struct v2f
			{
				float2 uv : TEXCOORD0;
				float4 vertex : SV_POSITION;
			};

			sampler2D _MainTex;
			float4 _MainTex_ST;
			fixed _Alpha;

			v2f vert(appdata v)
			{
				v2f o;
				o.vertex = UnityObjectToClipPos(v.vertex);
				o.uv = TRANSFORM_TEX(v.uv, _MainTex);
				return o;
			}

			fixed4 frag(v2f i) : SV_Target
			{
				fixed4 col = tex2D(_MainTex, i.uv);
				col.a = _Alpha; //片元着色器输出即为源颜色
				return col;
			}
			ENDCG
		}
	}
}

1、BlendOp Sub,Alpha为0.7,混合因子不变情况

很明显变暗了,因为先削弱源颜色0.3倍,再减去目标颜色削弱0.7倍后的颜色值,整体上RGBA都会变小。(其他情况自行测试),用的最普遍的情况还是BlendOp Add,混合因子也是SrcAlpha OneMinusSrcAlpha。

四、关于Queue为Transparent时,是否默认关闭深度写入的问题再次进行探讨和说明。

结论:深度写入默认是开启的,不因其他因素而影响!途中发现一些比较好复习以前透明章节的内容,下面来说明。

两个透明物体,一个红色和一个原色,并【开启了深度写入】有如下两种情况:

物体相交并穿插,按照透明物体是根据离摄像机越远的越先渲染原则,红色的箱子先渲染,原色箱子后渲染,因此红色部分渲染出来了,再到原色前半部分渲染~即这一部分会渲染,后半部分因为无法通过深度测试,无法渲染出来。

物体相交并穿插,但很明显,原色离摄像机最远,先渲染原色,再渲染红色,注意!!注意!!是开启了深度写入的!

此时,原色最靠近摄像机的前端,如下圈出来的部分,这部分的深度先进行写入了深度缓冲区!导致红色被遮挡的部分无法渲染,从而出现了看似两个物体属于不透明物体的遮挡情况,实际上它们是透明物体。

下图能够更加清晰地证明它们是一个透明物体,

这一部分的原色箱子的深度先写入,导致红色部分无法渲染。

但不影响上方这部分,即使是先渲染了原色箱子,但是由于原色箱子这部分的深度值,比红色箱子更大(我理解深度值为与摄像机的距离,只要有比深度缓冲区的深度值小,就能够渲染这个片元),所以红色箱子这部分(深度值更小)能够正常渲染出来并混合原色箱子,呈现出透明效果!

(如有误解,请私信或评论留言,吐槽什么的都可以~)

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值