[Unity3D][Shader]PANCgShader--第二章 透明面--02透明物体Alpha混合

混合(Blending)

可编程图形管线中提到fragment shader为每一个片元(除非被discard)计算RGBA颜色(以fragment输出参数COLOR的形式)。

然后片元会按照在cg 逐片元操作中提到的过程被进一步处理。

这其中,提到了Blending阶段,该阶段会把该片元输出的颜色(称之为source color)同帧缓存中的颜色(称之为destination color)进行处理。

Blending是一个固定管线功能阶段,你只能指定其支持的操作,而不能对其进行编程处理。

Unity3D中通过Blend {code for SrcFactor} {code for DstFactor}来指定,该表达式对应的数学运算法则为:

float4 result=
SrcFactor*fragment_output+DstFactor*pixel_color;

fragment_output为fragment shader阶段的输出参数,pixel_color是当前帧缓存中已经存在的颜色。最终的result就是blending的结果。

下表展示了SrcFactor和DstFactor常用的code(更多Unity ShaderLab支持的code参见ShaderLab: Blending):

codeexpressiong
Onefloat4(1.0,1.0,1.0,1.0)
Zerofloat4(0.0,0.0,0.0,0.0)
SrcColorfragment_output
SrcAlphafragment_output.aaaa
DstColorpixel_color
DstAlphapixel_color.aaaa
OneMinusSrcColorfloat4(1.0,1.0,1.0,1.0)-fragment_output
OneMinusSrcAlphafloat4(1.0,1.0,1.0,1.0)-fragment_output.aaaa
OneMinusDstColorfloat4(1.0,1.0,1.0,1.0)-pixel_color
OneMinusDstAlphafloat4(1.0,1.0,1.0,1.0)-pixel_color.aaaa

注意这里提到的所有颜色相关的值,最终都会被限制在[0,1]这个区间内。

Alpha混合

在Unity中Alpha混合等式为Blend SrcAlpha OneMinusSrcAlpha。对应的数学表达式为:

float4 rsult=
fragment_output.aaaa*fragment_output+
(float4(1.0,1.0,1.0,1.0)-fragment_output.aaaa)*pixel_color;

该混合等式,有时候也被称之为覆盖操作,即fragment_output覆盖pixel_color。

预乘Alpha混合

对于fragment shader输出color已经处理了alpha值的,不再需要对其再次处理,可以使用混合等式Blend One OneMinusSrcAlpha。对应的数学表达式为:

float result=
flaot4(1.0,1.0,1.0,1.0)*fragment_output+
(float4(1.0,1.0,1.0,1.0)-fragment_output.aaaa)*pixel_color;

叠加混合(Additive Blending)

等式为:Blend One One
对应的数学表达式为:

float4 result=
float4(1.0,1.0,1.0,1.0)*fragment_output+
float4(1.0,1.0,1.0,1.0)*pixel_color;

该混合方式会把fragment shader的输出颜色值直接加在帧缓冲的颜色上。在粒子系统中会经常出现该混合方式。更多的讨论见Order-Independent Transparency

Shader代码

对于Alpha混合透明物体shader的实现,需要注意几个点:
1,SubShader的第一句需要增加Queue为Transparent的Tags。
Tags{"Queue"="Transparent"}
2,Pass中第一句要关闭深度缓冲ZWrite Off(注意ZWrite Off 指令也可以写在SubShader层级下,那么将会影响所有的Pass)
3,Pass中紧接着在CGPROGRAM前面,需要声明混合模式,比如:Blend SrcAlpha OneMinusSrcAlpha。

Shader "My/Transparency/SrcAlpha_OneMinusSrcAlpha"
{ 
	 
    SubShader
    {		
		Tags{"Queue"="Transparent"}	
        Pass
        {						
			ZWrite Off
			Blend SrcAlpha OneMinusSrcAlpha
		
            CGPROGRAM
            #pragma vertex vert
            #pragma fragment frag
						
			struct vertexInput{
				float4 vertex:POSITION;	 
			};

			struct vertexOutput{
				float4 pos:SV_POSITION;							
			    float4 posInObjSpace:TEXCOORD0;
			};

            vertexOutput vert (vertexInput input)
            {                			   
			   vertexOutput output;
			   output.pos=UnityObjectToClipPos(input.vertex);
			   output.posInObjSpace=input.vertex;			   
			   return output;
            }

            fixed4 frag (vertexOutput input) : COLOR
            {
				return float4(0.0,1.0,0.0,0.3);
            }			
            ENDCG
        }				 
    }
}
  • 深度缓冲会记录片元的距离,根据算法决定哪些片元会自动被discard。因为透明物体的存在,被透明物体遮挡的物体需要可见,因此需要关闭深度缓冲。
  • Tags{"Queue"="Transparent"}指定了使用该subshader的mesh在所有不透明(opaque)的mesh渲染完毕后再渲染。之所以要这样指定,部分原因是因为我们关闭了深度缓冲,这会导致一个透明物体被它后面的非透明物体遮挡。因此我们通过增加"Queue"="Transparent"的Tags来指定透明物体在非透明物体渲染完毕后再渲染(需要注意这种方式并不是经常奏效,更多参考:Order-Independent Transparency)
    Unity中预定义的Queue包含以下几个:
    Background,index为1000
    Geometry,默认值,index为2000
    AlphaTest,index为2450
    Transparent,index为3000
    Overlay,index为4000,最后渲染的物体可以使用该Queue,比如lens flares.
    更多关于Unity ShaderLab的Tags内容参考:ShaderLab: SubShader Tags
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

iningwei

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值