赞
踩
目录
1、BlendOp Sub,Alpha为0.7,混合因子不变情况
四、关于Queue为Transparent时,是否默认关闭深度写入的问题再次进行探讨和说明。
混合操作
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 中支持
混合因子
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
- }
- }
- }
很明显变暗了,因为先削弱源颜色0.3倍,再减去目标颜色削弱0.7倍后的颜色值,整体上RGBA都会变小。(其他情况自行测试),用的最普遍的情况还是BlendOp Add,混合因子也是SrcAlpha OneMinusSrcAlpha。
结论:深度写入默认是开启的,不因其他因素而影响!途中发现一些比较好复习以前透明章节的内容,下面来说明。
两个透明物体,一个红色和一个原色,并【开启了深度写入】有如下两种情况:
物体相交并穿插,按照透明物体是根据离摄像机越远的越先渲染原则,红色的箱子先渲染,原色箱子后渲染,因此红色部分渲染出来了,再到原色前半部分渲染~即这一部分会渲染,后半部分因为无法通过深度测试,无法渲染出来。
物体相交并穿插,但很明显,原色离摄像机最远,先渲染原色,再渲染红色,注意!!注意!!是开启了深度写入的!
此时,原色最靠近摄像机的前端,如下圈出来的部分,这部分的深度先进行写入了深度缓冲区!导致红色被遮挡的部分无法渲染,从而出现了看似两个物体属于不透明物体的遮挡情况,实际上它们是透明物体。
下图能够更加清晰地证明它们是一个透明物体,
这一部分的原色箱子的深度先写入,导致红色部分无法渲染。
但不影响上方这部分,即使是先渲染了原色箱子,但是由于原色箱子这部分的深度值,比红色箱子更大(我理解深度值为与摄像机的距离,只要有比深度缓冲区的深度值小,就能够渲染这个片元),所以红色箱子这部分(深度值更小)能够正常渲染出来并混合原色箱子,呈现出透明效果!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。