Unity Shader 学习笔记(11) 渲染队列、透明效果

44 篇文章 5 订阅
36 篇文章 5 订阅

Unity Shader 学习笔记(11) 渲染队列、透明效果

参考书籍:《Unity Shader 入门精要》
【浅墨Unity3D Shader编程】之四 热带雨林篇: 剔除、深度测试、Alpha测试以及基本雾效合辑
3D数学 学习笔记(10) 背面剔除(Clipping)、裁切(Backface Culling)、光栅化(Rasterzation)
官网API:ShaderLab: SubShader Tags

透明测试所在步骤:


渲染队列(render queue)

用SubShader的Queue标签来觉得模型归于那个渲染队列。索引号越小,越早被渲染。
在这里插入图片描述


半透明物体的渲染顺序

常用顺序:

  1. 先渲染所有不透明物体,开启深度测试和深度写入。
  2. 半透明物体按离摄像机距离远近排序,从后往前渲染,开启深度测试,关闭深度写入。

部分相互重叠的物体不适用,解决方法是分割网格。

A为半透明,B为不透明

  • 正确:先渲染B,后渲染A。
  • 错误:先渲染A,后渲染B。A不写入深度缓冲,B发现深度缓冲没有东西,就会直接覆盖A的颜色。
    在这里插入图片描述

A和B都为半透明

  • 正确:先渲染B,后渲染A。
  • 错误:先渲染A,后渲染B。A先写入颜色缓冲,B再和A混合,结果相反,使B看起来在A前面。
    在这里插入图片描述

透明度测试

在这里插入图片描述

把一个片元透明度不满足条件(小于某个阈值)的舍弃掉,否则进行深度测试、深度写入等。CG中用clip(float x)函数进行透明度测试,如果给定任一分量为负,则舍弃当前像素的输出颜色。等价下面代码:

void clip(float4 x)
{
	if (any(x < 0))
		disacard;
}
Shader "Custom/AlphaTest" {
	Properties {
		...
		_Cutoff ("Alpha Cutoff", Range(0,1)) = 0.5			// 透明测试阈值
	}
	SubShader {
		// 渲染队列:透明测试;不受投影器影响;指名这个Shader提前归入TransparentCutout组(指明Shader使用了透明测试)。
		Tags { "Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout" }

		Pass {
			...
			
			fixed4 frag(v2f i) : SV_TARGET {
				...

				fixed4 texColor = tex2D(_MainTex,i.uv);

				// 透明测试(小于阈值就discard,丢掉片元,类似直接return)。等价下面的判断。
				clip(texColor.a - _Cutoff);					
				//if ((texColor.a - _Cutoff) < 0.0) { discard; }

				...
				// 计算光照等。
			}
			...
		}
	}
	// 保证使用透明度测试的物体可以正确地向其他物体投射阴影。
	FallBack "Transparent/Cutout/VertexLit"
}

透明度混合

在这里插入图片描述

将当前片元的透明度与已在颜色缓冲中的颜色值进行混合。需要关闭深度写入(不影响在其背后的物体),但不关闭深度测试(在不透明物体后面时,同样会被去掉)。
Unity提供混合命令:Blend,自动打开混合模式,源颜色的混合因子SrcFactor设为SrcAlpha,目标颜色的混合因子DstFactor设为OneMinusSrcAlpha(1 - SrcAlpha),混合后的颜色:
DstColornew = SrcAlpha × SrcColor + ( 1 - SrcAlpha ) × DstColorold
在这里插入图片描述

Properties {
	...
	_AlphaScale ("Alpha Scale", Range(0,1)) = 1		// 整体透明度
}
SubShader {
	// RenderType选择Transparent用来指名这个Shader使用了透明度混合。
	Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }

	Pass {
		Tags { "LightMode"="ForwardBase" }

		ZWrite Off							// 关闭深度写入
		Blend SrcAlpha OneMinusSrcAlpha		// 开启混合模式。SrcAlpha:源颜色混合因子,OneMinusSrcAlpha:已存在颜色混合因子
	
		...
		
		fixed4 frag(v2f i) : SV_TARGET {
			...
			//clip(texColor.a - _Cutoff);					// 没有使用透明测试。
			...
			// 透明通道乘于材质参数,即最后颜色乘于透明度
			return fixed4(ambient + diffuse,texColor.a * _AlphaScale);		
		}
		...
	}
}

开启深度写入的半透明效果

只使用透明度混合 和 开启深度写入与透明度混合对比:
在这里插入图片描述

使用两个Pass:

  1. 开启深度写入,但不输出颜色。
  2. 进行正常的透明度混合,按照像素级别的深度顺序进行透明渲染。

在透明度混合的代码中添加一个Pass即可。ColorMask用于射着颜色通道的写掩码(write mask),可以是RGBA或其他组合,0为不输出任何颜色。

// 新加一个Pass块,先把深度信息写入深度缓冲,剔除掉了被自身遮挡的片元。
Pass {
	ZWrite On
	ColorMask 0			// 颜色通道掩码。为0:不写入任何颜色通道,不输出任何颜色。
}

// 下一个Pass和上面的透明度混合代码相同
Pass {
	Tags { "LightMode"="ForwardBase" }

	ZWrite Off
	Blend SrcAlpha OneMinusSrcAlpha
	...
}

双面渲染的透明效果

直接透明混合物体 和 双面渲染的透明物体对比:
在这里插入图片描述

使用两个Pass:

  1. 第一个Pass只渲染背面。
  2. 第二个Pass只渲染正面。
SubShader {
		Tags { "Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent" }
		
		Pass {
			Tags { "LightMode"="ForwardBase" }

			Cull Front		// 剔除正面(只渲染背面)

			// 透明混合代码一样
		}

		Pass {
			Tags { "LightMode"="ForwardBase" }
			
			Cull Back		// 剔除背面

			// 同上一个Pass
		}
	}

常见混合类型

类似Photoshop的混合模式。
在这里插入图片描述


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值