Shader学习的基础知识(八)透明度混合

上一篇中讲到在深度测试和深度写入后,色值会存放在颜色缓冲区中等待处,而我们这里就要来讲讲怎么拿它来做混合处理,从而实现真正的透明效果。由于透明混合需要关闭深度写入使用得我们要非常小心物体的渲染循序。

Blend

Blend是Unity提供给我们的的混合模式命令,有以下几种形式

名称意义
Blend Off关闭混合
Blend SrcFactor DstFactor开启混合源色会乘以SrcFactior而目标色会乘以DstFactor
Blend SrcFactor DstFactor, SrcFactorA DstFactorA和上面几乎一样,只是使用不同的因子混合
BlendOp BlendOperation并非排源色和目标色相加混合,而是使用BlendOperation对它们进行其他操作

这里用Blend SrcFactor DstFactor来进行混合,设置的同也开启了混合模式,这时候透明通道才有意义。有时候发现自己的模型没有透明效果,往往就是没有设置混合因子,或是没有打开混合模式。
混合因子:
把SrcFactor设为SrcAlpha,而目标颜色的混合因子DstFactor设为OneMinusSrcAlpha那这样的话,混合后的颜色则会是:

Blend SrcAlpha OneMinusSrcAlpha

DstColor(新的)=SrcAlpha X SrcColor + (1 - SrcAlpha) X DstColor(旧的)
新的颜色=源色透明度 X 源色颜色 + (1 - 源色透明度) X 旧的目标颜色

参数描述
One因子为1
Zero因子为0
SrcColor源因子为色值 ,当为RGB通道时返回rgb,当为A通道时返回a值
SrcAlpha源因子的A通道值
DstColor目标因子色值,当RGB通道时返回rgb,当为A通道时返回a值
DstAlpha目标色值为A通道值
OneMinusSrcColor因子为1-源颜色。当为RBG则用rgb作为分量,为A通道时则以a作业值
OneMinusSrcAlpha因子为1-源颜色的a
OneMinusDstColor因子为1-目标颜色。当为RBG则用rgb作为分量,为A通道时则以a作业值
OneMinusDstAlpha因子为1-目标颜色a

当我们需要A通道也进行混合可以使用:

Blend SrcAlpha OneMinusSrcAlpha,One zero

实例:

效果是这样的:
在这里插入图片描述
下面上代码:

Shader "Custom/TestShader15" {
	Properties{
		_Color("Color Tint",Color)=(1,1,1,1)
		_MainTex("Main Tex",2D)="white"{}
		_AlphaScale("Alpha Scale",Range(0,1))=1
	}
	SubShader{
	//"Queue"="Transparent"			队列为透明混合
	//"IgnoreProjector"="True"		不接受投影
	//"RenderType"="TransparentCutout"指明该Shader是一个用于透明测试的Shader
	Tags{"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
	
	Pass{
		Tags{"LightMode"="ForwardBase"}
		//关闭深度写入
		ZWrite off
		//源因子:透明度            目标因子:1-源因子透明度
		//最后会把源因子和目标因子相乘得到最终结果
		Blend SrcAlpha OneMinusSrcAlpha

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

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

		struct a2v{
			float4 vertex:POSITION;
			float3 normal:NORMAL;
			float4 texcoord:TEXCOORD0;
		};
		struct v2f{
			float4 pos:SV_POSITION;
			float3 worldNormal:TEXCOORD0;
			float3 worldPos:TEXCOORD1;
			float2 uv:TEXCOORD2;
		};

		v2f vert(a2v v){
			v2f o;
			o.pos=UnityObjectToClipPos(v.vertex);
			o.worldNormal=UnityObjectToWorldNormal(v.normal);
			o.worldPos=mul(unity_ObjectToWorld,v.vertex).xyz;
			o.uv=TRANSFORM_TEX(v.texcoord,_MainTex);
			return o;
		}

		float4 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;
			fixed diffuse=_LightColor0.rgb*albedo*max(0,dot(worldNormal,worldLightDir));

			//最后输的颜色设置了透明度
			return fixed4(ambient+diffuse,texColor.a*_AlphaScale);
		}
		ENDCG
	}
	}
}

开启深度写入也能半透明效果

这个需要使用两个Pass来渲染模型:
step1:第一个Pass开启深度写入,但不输出颜色,目的只是为了把深度值写入深度缓冲中。
step2:第二个是正常使用混合,由于上一个Pass已经得到了正确的深度信息,该Pass就可以按照像素级别深度排序进行透明渲染。
但这个很消耗性能!!!
使用:ColorMask 0则不会输出颜色信息
别的代码和上面的一样

Pass{
		ZWrite On
		ColorMask 0
	}

ShaderLab的混合命令

名称意义
Blend SrcFactor DstFactor开启混合,源色会乘以SrcFactior,而目标色会乘以DstFactor
Blend SrcFactor DstFactor, SrcFactorA DstFactorA和上面几乎一样,只是使用不同的因子混合

第一个重载只有一个命令来提供两个因子,也就是说RGB和Alpha通道都是用同样的方式来混合
混合因子有很多SrcColor、SrcAlpha、DstColor、One、Zero等…可以使用第二个重载来进行设置如:

Blend SrcAlpha OneMinusSrcAlpha,One Zero

常见的混合类型有:
正常:
Blend SrcAlpha OneMinusSrcAlpha
正片叠低:
Blend DstColor Zero
等等…

双面渲染透明

使用双面渲染性能的消耗会成总倍的增加。
我们可以使用Cull Back|Front|Off 来实现,但一般情况下我们不会关闭剔除功能。
在这里插入图片描述

上面透明的代码法制成两个Pass通道,差别在下面:

Pass{
		Tags{"LightMode"="ForwardBase"}
		Cull Front
		//一样的代码...
		}
Pass{
		Tags{"LightMode"="ForwardBase"}
		Cull Back
		//一样的代码...
		}
  • 2
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小盖子

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

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

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

打赏作者

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

抵扣说明:

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

余额充值