zoukankan      html  css  js  c++  java
  • 【Unity Shaders】Transparency —— 使用渲染队列进行深度排序

    本系列主要參考《Unity Shaders and Effects Cookbook》一书(感谢原书作者),同一时候会加上一点个人理解或拓展。

    这里是本书全部的插图。这里是本书所需的代码和资源(当然你也能够从官网下载)。

    ========================================== 切割线 ==========================================



    写在前面


    为了让我们真正明确透明度。我们须要了解一下深度排序。或者说,对象的绘制顺序。Unity同意我们控制一个特定对象绘制到屏幕上的顺序,因此我们能够更好地控制哪些对象应该覆盖在其它对象上。你能够把绘制顺序理解成Photoshop中的图层的概念。

    在处理透明度或者相似界面对象的元素时。绘制顺序尤其重要。


    本篇将会解说怎样使用Unity内置的标签(tags)来利用这个分层化的方法去渲染你的对象。这是非常重要的,由于你将会更好地控制你的对象是怎样被绘制到游戏界面的。



    准备工作



    1. 创建一个新的场景,以及两个球体。而且让它们排在一条线上。我们的目标是(没有蛀牙!

      )。不管它们在3D空间中的实际坐标是什么。我们能够随你所欲地安排它们的绘制顺序。即谁在谁的上面。

    2. 为了能够看出改动绘制顺序发生的变化,我们还须要至少两个Shaders。所以,我们创建两个新的Shaders,并能够分别分别命名为Depth001和Depth002。
    3. 你的场景应该看起来和以下图片相似。




    实现



    Shader部分的代码实际上非常easy;它只须要两行新代码就能够了。

    1. 首先我们须要生命这个对象将会被绘制到那个渲染队列中。为了做到这一点,我们须要改动Tags{}块。也就是在SubShader{}的内部:
      Tags { "Queue"="Geometry-20" }
    2. 然后,我们须要告诉Unity,我们想要自己控制这个对象的渲染顺序,而不想写到深度缓存中。在上一步代码的以下加入例如以下代码:
      ZWrite Off
    3. 保存。返回Unity查看。你将会发现当中一个球体出如今全部对象的后面,甚至当它的3D空间中的实际坐标在全部对象前面时也是一样。例如以下图所看到的:


    最后,完整代码例如以下:
    Shader "Custom/Depth001" {
    	Properties {
    		_MainTex ("Base (RGB)", 2D) = "white" {}
    	}
    	SubShader {
    		Tags { "Queue"="Geometry-20" }
    		
    		ZWrite Off
    		
    		LOD 200
    		
    		CGPROGRAM
    		#pragma surface surf Lambert
    
    		sampler2D _MainTex;
    
    		struct Input {
    			float2 uv_MainTex;
    		};
    
    		void surf (Input IN, inout SurfaceOutput o) {
    			half4 c = tex2D (_MainTex, IN.uv_MainTex);
    			o.Albedo = c.rgb;
    			o.Alpha = c.a;
    		}
    		ENDCG
    	} 
    	FallBack "Diffuse"
    }
    



    解释


    默认情况下,Unity会基于对象距离摄像机的远近来排序你的对象。因此。当一个对象离摄像机越近,它就会优先绘制在其它更远的对象上面。

    对于大多数情况这是有效并合适的,可是在一些特殊情况下。你可能想要自己控制对象的绘制顺序。

    而使用Tags{}我们就能够得到这种控制。


    Unity提供给我们一些默认的渲染队列。每个相应一个唯一的值,来指导Unity绘制对象到屏幕上。这些内置的渲染队列被称为Background, Geometry, AlphaTest, Transparent, Qverlay。这些队列不是随便创建的。它们是为了让我们更easy地编写Shader并处理实时渲染的。以下的表格描写叙述了这些渲染队列的使用方法:

    渲染队列渲染队列描写叙述渲染队列值
    Background这个队列通常被最先渲染。1000
    Geometry这是默认的渲染队列。它被用于绝大多数对象。

    不透明几何体使用该队列。

    2000
    AlphaTest通道检查的几何体使用该队列。它和Geometry队列不同,对于在全部立体物体绘制后渲染的通道检查的对象,它更有效。2450
    Transparent该渲染队列在Geometry和AlphaTest队列后被渲染。

    不论什么通道混合的(也就是说。那些不写入深度缓存的Shaders)对象使用该队列。比如玻璃和粒子效果。

    3000
    Overlay该渲染队列是为覆盖物效果服务的。不论什么最后被渲染的对象使用该队列,比如镜头光晕。4000

    因此,一旦你知道你的对象属于哪一个渲染队列。你就能够指定它的内置渲染队列标签。我们的Shader使用了Geometry队列。因此我们这样写:Tags { "Queue"="Geometry" }

    可是,我们希望告诉我们的对象在我们的Geometry队列中的全部对象后面、Background队列对象的前面被绘制,因此我们改动为Tags { "Queue"="Geometry-20" }

    这样就告诉Unity。我们想要把这个对象当成一个立体物体,可是请在全部其它不透明对象后面渲染。


    注意:Geometry相应的队列值是2000,所以"Geometry-20"意味着使用队列值为1980的队列。而数值越小意味着越先被渲染,也就会被后面渲染的对象遮挡。

    最后,我们还要在SubShader块中声明ZWrite标签。

    这告诉Unity,我们想要重写对象的深度排序。而且我们将会为它指定一个新的渲染队列。

    因此。我们就简单的把ZWrite值设为Off。(不设就没有效果)



    1. 相关阅读:
      (转) qt: usb热插拔(linux);
      Qt: usb热插拔检测(windows);
      C++: 模板函数定义与声明分离;
      bootstrap: 内联表单;
      thinkphp5: 循环输出表格,并固定表格单元宽度(过长省略号)
      响应式菜单栏: bootstrap + jQuery
      Qt: 数据库操作;
      qt: 获取sql数据表的所有的字段;
      Qt: 非阻塞时间延迟;
      egg中使用jwt
    2. 原文地址:https://www.cnblogs.com/claireyuancy/p/7080033.html
    Copyright © 2011-2022 走看看