UnityShader初级篇——透明度混合

1.透明度混合必须关闭深度写入,开启混合模式

Shader"Unity Shaders Book/Chapter 8/Alpha Blend"
{
	Properties
	{
		_Color ("Color Tint", Color) = (1,1,1,1)
		_MainTex("MainTex", 2D) = "White" {}
		//在透明纹理的基础上控制整体的透明度
		_AlphaScale("Alpha Scale", Range(0,1)) = 1
	}
	SubShader
	{
	       //透明度混合使用Tranparent渲染队列;
	       //IgnoreProject是否忽视投影器(Project)的影响;
	       //RenderType指明此shader使用了透明度混合
	       //通常使用了透明度测试的shader都应该设置这三个标签
	        Tags{"Queue" = "Transparent" "IgnoreProject" = "True" "RenderType" = "Transparent"}

		Pass
		{
		        Tags{"LightMode" = "ForwardBase"}
		        		       
		        //关闭深度写入
		        zWrite off
		         //为透明度混合进行合适的混合状态设置
		         //SrcAlpha是源颜色(该片元着色器产生的颜色)的混合因子
		         //OneMinusSrcAlpha是目标颜色(已经存在于颜色缓冲中的颜色)的混合因子
		        Blend SrcAlpha OneMinusSrcAlpha
                        
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "LIghting.cginc"

			fixed4 _Color;
			sampler2D _MainTex;
			//需要用 “纹理名_ST” 的方式定义纹理的属性,S是缩放(scale),T是平移(transform)
			//_MainTex_ST.xy获取缩放值,_MainTex_ST.zw获取偏移值
			float4 _MainTex_ST;
			fixed _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;
			}


			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 * saturate(dot(worldNormal,worldLightDir));

				//设置返回值中的透明通道
				return fixed4(ambient + diffuse,texColor.a * _AlphaScale);
;			}
			ENDCG
		}
	}

	Fallback"Transparent/Vertexlit"
}


2.开启深度写入

当复杂模型本身有遮挡关系时,上述shader会产生错误排序,可在shader中添加一个pass,开启深度写入,但不输出颜色,就可以得到正确的深度信息

Shader"Unity Shaders Book/Chapter 8/Alpha Blending ZWrite"
{
	Properties
	{
		_Color ("Color Tint", Color) = (1,1,1,1)
		_MainTex("MainTex", 2D) = "White" {}
		//在透明纹理的基础上控制整体的透明度
		_AlphaScale("Alpha Scale", Range(0,1)) = 1
	}
	SubShader
	{
	       //透明度混合使用Tranparent渲染队列;
	       //IgnoreProject是否忽视投影器(Project)的影响;
	       //RenderType指明此shader使用了透明度混合
	       //通常使用了透明度测试的shader都应该设置这三个标签
	        Tags{"Queue" = "Transparent" "IgnoreProject" = "True" "RenderType" = "Transparent"}

	        //添加一个pass开启深度写入,但不输出颜色
	        Pass
	        {
	               //开启深度写入
	                ZWrite on
	                //ColorMask用于设置颜色通道的写掩码,设置为0时,该pass不写入任何颜色通道
	                ColorMask 0

	        }

		Pass
		{
		        Tags{"LightMode" = "ForwardBase"}
		        		       
		        //关闭深度写入
		        zWrite off
		         //为透明度混合进行合适的混合状态设置
		         //SrcAlpha是源颜色(该片元着色器产生的颜色)的混合因子
		         //OneMinusSrcAlpha是目标颜色(已经存在于颜色缓冲中的颜色)的混合因子
		        Blend SrcAlpha OneMinusSrcAlpha
                        
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag

			#include "LIghting.cginc"

			fixed4 _Color;
			sampler2D _MainTex;
			//需要用 “纹理名_ST” 的方式定义纹理的属性,S是缩放(scale),T是平移(transform)
			//_MainTex_ST.xy获取缩放值,_MainTex_ST.zw获取偏移值
			float4 _MainTex_ST;
			fixed _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;
			}


			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 * saturate(dot(worldNormal,worldLightDir));

				//设置返回值中的透明通道
				return fixed4(ambient + diffuse,texColor.a * _AlphaScale);
;			}
			ENDCG
		}
	}

	Fallback"Transparent/Vertexlit"
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值