第八章 透明效果

在渲染模型中控制透明通道。透明度为1,完全不透明;透明度为0,完全不会显示。

两种方法:

(1)透明度测试

(2)透明度混合

深度缓冲(z-buffer)用于解决可见性问题。可以决定哪个物体的哪些部分被渲染到前面,哪些部分会被其他物体遮掩。根据深度缓存中的值来判断该片元距离摄像机的距离,当渲染一个片元时,需要把它的深度值和已经存在于深度缓冲中的值进行比较,如果它的值距离摄像机更远,那么说明这个片元不应被渲染到屏幕上;否则,这个片元应该覆盖掉此时颜色缓冲中的像素值,并把它的深度值更新到深度缓冲中(如果开启了深度写入)。可以不关心物体渲染顺序。

基本原理

(1)透明度测试

只要一个片元的透明度不满足条件,那么它对应的片元就会被舍弃。被舍弃的片元不会再进行任何处理,也不会对颜色缓冲产生任何影响;否则,就会按照普通的不透明物体来处理,即深度测试、深度写入。透明度测试不需要关闭深度写入,它会根据透明度来舍弃一些片元,效果极端,要么完全透明,要么完全不透明。

(2)透明度混合

可以得到真正的半透明效果。它会使用当前片元的透明度作为混合因子,与已经存储在颜色缓冲中的颜色值进行混合,得到新的颜色。透明度混合需要关闭深度写入,要小心物体的渲染顺序。透明度混合只关闭了深度写入,没有关闭深度测试。当使用透明度混合渲染一个片元时,还是会比较它的深度值和当前深度缓冲中的深度值。如果它的深度值距离摄像机更远,那么就不会再进行混合操作。当一个不透明物体出现在一个透明物体前面,而我们先渲染了不透明物体,它仍然可以正常地遮挡住透明物体。对于透明度混合来说,深度缓冲是只读的。

为什么渲染顺序很重要

应该在不透明物体渲染完之后再渲染半透明物体。半透明物体之间也要符合渲染顺序。

渲染引擎一般都会对物体先排序再渲染,常用方法是

(1)先渲染所有不透明物体,并开启它们的深度测试和深度写入

(2)把半透明按它们距离摄像机的远近进行排序,然后按照从后往前的顺序渲染这些半透明物体,并开启它们的深度测试,但关闭深度写入。

为了减少错误排序,我们尽可能让模型是凸面体,并考虑将复杂模型拆分成可以独立排序的多个子模型。

Unity Shader的渲染顺序

Unity提供了渲染队列来解决渲染顺序问题。可以使用SubShader的Queue标签来决定我们的模型将归于哪个渲染队列。Unity在内部使用一系列整数索引来表示每个渲染队列,且索引号越小越早被渲染。

透明度测试

透明度测试:只要一个片元的透明度不满足条件,那么它对应的片元就会被舍弃。被舍弃的片元将不会再进行任何处理,也不会对颜色缓冲产生任何影响;否则,就会按照普通的不透明方式去处理。

通常,在片元着色器中使用clip函数进行透明度测试。clip是一个Cg函数

函数:void clip(float4 x); void clip(float3 x); void clip(float2 x); void clip(float1 x); void clip(float x);

参数:裁剪时使用的标量或矢量条件

描述:如果给定参数的任何一个分量是负数,就会舍弃当前像素的颜色。它等同于下面的代码

void clip(float4 x)
{
  	if (any(x < 0))
      discard;
}
Shader "Unity Shaders Book/Chapter 8/Alpha Test"{
	Properties {
		_Color		("Main Tint", Color) = (1, 1, 1, 1)
		_MainTex	("Main Tex", 2D) = "white"{}
		//_Cutoff用于决定我们调用clip进行透明度测试时使用的判断条件。范围是[0,1]
		_Cutoff		("Alpha Cutoff", Range(0, 1)) = 0.5
	}
	SubShader{
		//透明度测试使用的渲染队列是AlphaTest
		//把IgnoreProjector设为True,不受投影器的影响
		//RenderType可以让Unity把Shader归入提前定义的组TransparentCutout
		//指明该Shader是一个使用了透明度测试的Shader,RenderType通常被用于着色器的替换功能
		//使用了透明度测试的Shader都应该设置这三个标签
		Tags{	
				"Queue"="AlphaTest"
				"IgnoreProjector"="True"
				"RenderType"="TransparentCutout"
			}

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

			CGPROGRAM

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

			fixed4 _Color;
			sampler2D _MainTex; float4 _MainTex_ST;
			fixed _Cutoff;

			struct a2v{
				float4 vertex : POSITION;
				float3 normal : NORMAL;
				float4 texcoord : TEXCOORD0;
			};

			struct v2f{
				float4 pos : SV_POSITION;
				float3 worldNormal : TEXCOORD0;
				float3 worldPos : TEXCO
  • 40
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值