课时70 Fragment shader - Alpha 与 blend 运算

  • 课时70 Fragment shader - Alpha 与 blend 运算

1.Zwrite:深度写入,默认是Zwrite On。如果需要绘制实心物体需要开启,如果绘制半透明物体,需要关闭深度写入。见:ShaderLab: Culling & Depth Testing 

2.Ztest:默认LEqual,当深度值小于等于深度缓冲区的值,则写入(用Zwrite)并覆盖深度缓冲区对应位置的值。但是,如果Zwrite 为off,则只会输出颜色,不会写入深度缓冲区。

3.半透明红色物体如果不关闭深度写入,某些情况下会不显示身后的其他半透明物体,原理是红色物体深度值较小,破坏了蓝色半透明物体的Alpha颜色混合计算结果。关闭深度写入之后,每次Alpha Test只比较已存在的深度值,如果小于等于则只输出颜色混合结果。

4.代码:

Shader "Custom/Lesson70_1"
{
	//课时70 Fragment shader - Alpha 与 blend 运算
	SubShader
	{
		Tags{"queue"="transparent"}
		Pass
		{
			blend srcalpha oneminussrcalpha
			Zwrite Off//半透明物体需关闭深度写入
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag 
			#include "UnityCG.cginc"

			struct v2f
			{
				float4 pos:POSITION;
			}; 
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 color = fixed4(1,0,0,0.5);
				 
				return color;
			}
			ENDCG
		}
	}
}

效果:

  • 课时71 Fragment shader 7 - 实现半透明着色 1

1.需求:要求胶囊体被墙体遮挡部分显示半透明。

2.主要用到Alpha混合,Zwrite默认。

3.如果想让下半部分显示,需要改写深度对比方式,以让深度大于墙体的被遮挡部分写入深度缓存。但是会导致上半部分消失。

4.如果显示上半部分,需要在第二个通道里面,深度对比方式改为小于等于,Alpha改为1。此时产生新的问题,第二个通道的颜色会覆盖。

5.分析原因:第一个通道的下半部分由于被写入缓冲区中,第二个通道渲染时下半部分会与上个通道渲染结果进行深度对比,因为深度值一样,且对比方式为LEqual,所以会覆盖下半部分已有的蓝色的深度值。解决方式一:关闭第一个通道的深度写入功能,只输出颜色信息。

6.解决方式二:第一个通道的深度写入功能可关可不关,第二个通道的深度对比方式改为小于。

7.代码:

Shader "Custom/Lesson71"
{
	//课时71 Fragment shader 7 - 实现半透明着色 1
	SubShader
	{
			Tags{"queue"="transparent"}
		Pass
		{
			blend srcalpha oneminussrcalpha
			ZTest Greater//关键点,覆盖前景——墙
			// Zwrite Off//可关可不关,半透明物体需关闭深度写入
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag 
			#include "UnityCG.cginc"

			struct v2f
			{
				float4 pos:POSITION;
			}; 
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 color = fixed4(0,0,1,0.5);
				 
				return color;
			}
			ENDCG
		}
		//=====================负责渲染上半部分================================
			Pass
		{
			// blend srcalpha oneminussrcalpha //可混合可不混合。上下两个通道分别渲染两个部分,没有重合部分和混合的必要
			ZTest Less //关键点,覆盖背景,但不覆盖上一通道
			// Zwrite Off//可关可不关深度写入
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag 
			#include "UnityCG.cginc"

			struct v2f
			{
				float4 pos:POSITION;
			}; 
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				return o;
			}
			
			fixed4 frag (v2f i) : SV_Target
			{
				fixed4 color = fixed4(1,0,0,1);
				 
				return color;
			}
			ENDCG
		}
	}
}

8.遗留问题:透明墙体挡在前面时,下半部分不再显示蓝色。

 

  • 课时72 Fragment shader 7 - 实现半透明着色 2

1.需求:让下面的胶囊体不论是被不透明墙还是透明墙挡在前面,上面部分显示蓝色,下半部分显示黄色。

 

2.分析原因:由于红色半透明墙体的深度关闭,导致胶囊体下半部分无法和它的深度做对比(对比方式为Greater),从而无法输出颜色信息。第二个通道的渲染顺序为背景-第二通道-墙体,它只简单输出颜色。

3.解决方式一:开启半透明墙体的深度写入,由于半透明物体的深度写入一般都要求关闭,所以不建议。

4.解决方式二:使用摄像机深度贴图(Camera’s Depth Texture),但是摄像机深度贴图只记录不透明物体渲染队列,所以不可行。

5.解决方式三:使用摄像机置换Shader(Rendering with Replaced Shaders)。

6.使用方式:①编写一个置换透明物体用的shader,"RenderType"="Transparent",用于基于RenderType来置换并记录透明物体深度信息(注:半透明墙体shader需加"RenderType"="Transparent")。

Shader "Custom/Lesson72_ReplacementShader"
{
	//课时72 Fragment shader 7 - 实现半透明着色 2
	SubShader
	{
		Tags{"RenderType"="Transparent"}//只会置换具有相同RenderType的shader
		Pass
		{
			// blend srcalpha oneminussrcalpha
			// Zwrite Off
			CGPROGRAM
			#pragma vertex vert
			#pragma fragment frag 
			#include "UnityCG.cginc"

			struct v2f
			{
				float4 pos:POSITION;
				float2 depth:TEXCOORD0;//存储深度信息
			}; 
			
			v2f vert (appdata_base v)
			{
				v2f o;
				o.pos=UnityObjectToClipPos(v.vertex);
				o.depth=o.pos.zw;
				return o;
			}
			
			fixed4 frag (v2f IN) : COLOR
			{
				float r=IN.depth.x/IN.depth.y;//得到深度信息
				r=Linear01Depth(r);//换算成0~1
				fixed4 color = fixed4(r,0,0,0.5);//只用r信息,r存储深度信息
				return color;
			}
			ENDCG
		}
	}
}

      ②在Start中调用camera.SetReplacementShader()(结束对应camera.ResetReplacementShader())。

using UnityEngine;

public class ReplacementTransparentShader : MonoBehaviour {
	void Start () {
		Camera.main.SetReplacementShader(Shader.Find("Custom/Lesson72_ReplacementShader"),"RenderType");
	} 
}

7.运行前后效果:

8.最终运行时效果:

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值