Unity-Shader-渲染队列

Unity-Shader-渲染队列

  • 渲染简介
  • Unity中的几种渲染队列
    • Background (1000)最早被渲染的物体的队列。
    • Geometry (2000) 不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染,也就是Unity Shader中默认的渲染队列。
    • AlphaTest (2450) 有透明通道,需要进行Alpha Test的物体的队列,比在Geomerty中更有效。
    • Transparent (3000)半透物体的渲染队列。一般是不写深度的物体,Alpha Blend等的在该队列渲染。
    • Overlay (4000)最后被渲染的物体的队列,一般是覆盖效果,比如镜头光晕,屏幕贴片之类的。
    • Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。
    • Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。
    • TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。
    • Background: 天空盒着色器。
    • Overlay: GUITexture,镜头光晕,屏幕闪光等效果使用的着色器。
    • TreeOpaque: 地形引擎中的树皮。
    • TreeTransparentCutout: 地形引擎中的树叶。
    • TreeBillboard: 地形引擎中的广告牌树。
    • Grass: 地形引擎中的草。
    • GrassBillboard: 地形引擎中的广告牌草。
  • 相同渲染队列中不透明物体的渲染顺序
  • 相同渲染队列中半透明物体的渲染顺序
  • 自定义渲染队列
    • 注意

渲染简介

在渲染阶段,引擎所做的工作是把所有场景中对象按照一定的策略(顺序)进行渲染。最早的是画家算法,顾名思义,就是像画家画画一样,先画后面的物体,如果前面还有物体,那么就用前面的物体把后面的物体覆盖,不过这种方式由于排列是针对物体来排序的,而物体之间也可能有重叠,所以效果并不好。所以目前更加常用的方式是z-buffer算法,类似颜色缓冲区缓冲颜色,z-buffer中存储的是当前的深度信息,对于每个像素存储一个深度值,这样,我们屏幕上显示的每个像素点都会进行深度排序,就可以保证绘制的遮挡关系是正确的。而控制z-buffer就是通过ZTest、和ZWrite来进行的。但是有时候需要更加精准的控制不同类型的对象的渲染顺序,所以就有了渲染队列。今天就来学习一下渲染队列,ZTest,ZWrite的基本使用以及分析一下Unity为了Early-Z所做的一些优化。

Unity中的几种渲染队列

首先看一下Unity中的几种内置渲染队列,按照渲染顺序,**从先到后进行排序,队列数越小的,越先渲染,队列数越大的,越后渲染。
**

Background (1000)最早被渲染的物体的队列。

Geometry (2000) 不透明物体的渲染队列。大多数物体都应该使用该队列进行渲染,也就是Unity Shader中默认的渲染队列。

AlphaTest (2450) 有透明通道,需要进行Alpha Test的物体的队列,比在Geomerty中更有效。

Transparent (3000)半透物体的渲染队列。一般是不写深度的物体,Alpha Blend等的在该队列渲染。

Overlay (4000)最后被渲染的物体的队列,一般是覆盖效果,比如镜头光晕,屏幕贴片之类的。

Unity中设置渲染队列也很简单,我们不需要手动创建,也不需要写任何脚本,只需要在shader中增加一个Tag就可以了,当然,如果不加,name就是默认的渲染队列Geometry。比如我们需要我们的物体在Transparent这个渲染队列中进行渲染的话,就可以这样写:
Tags{“Queue” = “Transparent”}
我们可以直接在shader的Inspector面板上看到shader的渲染队列:
在这里插入图片描述
另外,我们在写shader的时候还经常有个Tag叫RenderType,不过这个没有Render Queue那么常用,这里顺便记录一下:

Opaque: 用于大多数着色器(法线着色器、自发光着色器、反射着色器以及地形的着色器)。

Transparent:用于半透明着色器(透明着色器、粒子着色器、字体着色器、地形额外通道的着色器)。

TransparentCutout: 蒙皮透明着色器(Transparent Cutout,两个通道的植被着色器)。

Background: 天空盒着色器。

Overlay: GUITexture,镜头光晕,屏幕闪光等效果使用的着色器。

TreeOpaque: 地形引擎中的树皮。

TreeTransparentCutout: 地形引擎中的树叶。

TreeBillboard: 地形引擎中的广告牌树。

Grass: 地形引擎中的草。

GrassBillboard: 地形引擎中的广告牌草。

相同渲染队列中不透明物体的渲染顺序

在Unity,创建三个立方体,都是用默认的bump diffuse shader(渲染队列相同),分别给三个人不同材质(相同材质的小顶点数的物体引擎会动态合批),用Unity带的Frame Debug工具查看一下DrawCall。
在这里插入图片描述
可以看出,Unity中对于不透明的物体,是采用了从前到后的渲染顺序进行渲染的,这样,不透明物体在进行完vertex阶段,进行Z Test,然后就可以得到该物体最终是否在屏幕上可见了,如果前面渲染完的物体已经写好了深度,深度测试失败,那么后面渲染的物体就不会再去进行fragment阶段。(不过这里需要把三个物体之间的距离稍微拉开一些,本人在测试时发现,如果距离特别近,就会出现渲染次序比较乱的情况,因为我们不知道Unity内部距离排序时是按照什么标准来判定的哪个物体离摄像机更近,这里我也就不猜测了)

相同渲染队列中半透明物体的渲染顺序

透明物体的渲染一直是图形学方面比较蛋疼的地方,对于透明物体的渲染,就不能像渲染不透明物体那样多快好省了,因为透明物体不会写深度,也就是说透明物体之间穿插关系是没有办法判断的,所以半透明的物体在渲染的时候一般都是采用从后向前的方法进行渲染的,由于透明物体多了,透明物体不写深度,name透明物体之间就没有所谓的可以通过深度测试来剔除的优化,每个透明物体都会走像素阶段的渲染,会造成大量的over Draw。这也就是粒子特效特别耗费性能的原因。

我们实验一下Unity中渲染半透明物体的顺序,还是上面三个立方体,我们把材质的shader统一换成粒子最常用的Particle/Additive类型的shader,再用FrameDebug工具查看一下渲染的顺序:
在这里插入图片描述

自定义渲染队列

Unity支持我们自定义渲染队列,比如我们需要保证某种类型的对象需要在其他类型的对象渲染之后再渲染,就可以通过自定义队列进行渲染。而且超级方便,我们只需要在写shader的时候修改一下渲染队列中的Tag即可。比如我们希望我们的物体要在所有默认的不透明物体渲染完之后渲染,name我们就可以使用
Tag{“Queue” = “Geometry+1”}就可以让使用了这个shader的物体在这个队列中进行渲染。
还是上面的三个立方体,这次我们分别给三个不同的shader,并且渲染队列不同,通过上面的实验我们知道,默认情况下,不透明物体都是在Geometry这个队列中进行渲染的,那么不透明的三个物体就会按照cube1,cube2,cube3进行渲染。这次我们希望将渲染的顺序反过来,那么我们就可以让cube1的渲染队列最大,cube3的渲染队列最小。贴出其中一个的shader:

Shader "Custom/RenderQueue1" {SubShader{Tags { "RenderType"="Opaque" "Queue" = "Geometry+1"}Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include "UnityCG.cginc"struct v2f{float4 pos : SV_POSITION;};v2f vert(appdata_base v){v2f o;o.pos = mul(UNITY_MATRIX_MVP, v.vertex);return o;}fixed4 frag(v2f i) : SV_Target{return fixed4(0,0,1,1);}ENDCG}}//FallBack "Diffuse"
}

这里我用ASE制作的Shader跟上述是一致的。

其他的两个shader类似,只是渲染队列和输出颜色不同。

在这里插入图片描述
通过渲染队列,我们就可以自由地控制使用该shader的物体在什么时机渲染。比如某个不透明的像素阶段操作较费,我们就可以控制它的渲染队列,让其渲染更靠后,这样可以通过其他不透明物体写入的深度剔除该物体所占的一些像素。

注意

我们在修改shader的时候一般不需要什么其他操作就可以直接看到修改后的变化,但是改完渲染队列后,有时候会出现从shader的文件上能看到渲染队列的变化,但是从渲染结果以及Frame Debug工具中并没有看到渲染结果的变化,重启Unity也没有起到作用,直到我们把shader重新赋值给材质之后,变化才起了效果。**

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/378735.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MyBatis ResultMap(2)

SQL 映射XML 文件是所有sql语句放置的地方。需要定义一个workspace&#xff0c;一般定义为对应的接口类的路径。写好SQL语句映射文件后&#xff0c;需要在MyBAtis配置文件mappers标签中引用&#xff0c;例如&#xff1a; Xml代码 <mappers> <mapper resource&qu…

形态学操作——腐蚀与膨胀

预备知识 结构元&#xff08;SE&#xff09; 1、结构元的中心一般来说是放在其重心位置处&#xff0c;但原则上原点的选择是依赖于你要解决的问题的。 2、对图像操作时&#xff0c;我们要求结构元是矩形阵列。&#xff08;在结构元的基础上添加较少的背景元素实现&#xff09…

java集合转换_java各种集合的转换

内容&#xff1a;1、List转Array 2、Array转List3、String转int[],String[](对单个字符) 4、数组、List、Set、Map相互转换5、一行输入多个元素方法常用集合&#xff1a;Map、Set、List、Array、String1、List转Array&#xff…

10-礼帽与黑帽操作

cv2.morphologyEx(img,cv2.MORPH_TOPHAT,kernel) 第一个参数&#xff1a;图像对象名称 第二个参数&#xff1a;运算类型TOPHAT为礼帽运算 第三个参数&#xff1a;卷积核的大小 礼帽运算&#xff1a;原始的输入-开运算&#xff08;先腐蚀再膨胀&#xff09; 原始带刺儿&#xff…

2011 cnblogs开通--给力吧

在信息传递如此迅速的时代&#xff0c;自己慢慢的老去&#xff0c;是否要想写些什么&#xff0c;跟大家一起分享学习、工作、生活的酸甜苦辣&#xff0c;提高自己的各方面的能力;往后将慢慢记录自己的程序人生吧&#xff0c;就什么多了&#xff0c;作为自己cnblogs第一篇吧^_^转…

Android----获取activity上所有的控件

01/**02 * note 获取该activity所有view03 * author liuh04 * */05 public List<View> getAllChildViews() {06 View view this.getWindow().getDecorView();07 return getAllChildViews(view);08 }09 10 private List<View> …

微信小程序 查找兄弟节点_使用C ++程序在链接列表中查找节点

微信小程序 查找兄弟节点Given a linked list and an integer N, you need to find and return index where N is present in the Linked List. Return -1 if n is not present in the Linked List. 给定一个链表和一个整数N&#xff0c;您需要查找并返回索引&#xff0c;其中链…

形态学操作——开闭运算、顶帽底(黑)帽变换

膨胀和腐蚀运算的问题&#xff1a; 边缘形状发生了变化&#xff0c;膨胀发生了扩张&#xff0c;腐蚀发生了收缩 目标物体变形&#xff0c;对识别时的特征提取会造成影响 解决方法&#xff1a; 开操作: B对A的开操作就是先B对A腐蚀&#xff0c;紧接着用B对结果进行膨胀 先腐…

java 基础实战_Java基础实战(三)

是否是否是否是否获取字符串字符数组大写?小写?数字?非字母与数字大写字母小写字母数字i结束ii1第一步 拆分字符串为字符数组&#xff1a;static void count(String str) {// 将字符串拆分为字符数组char[] charArray str.toCharArray();}第二步 定义相关变量记录结果&…

11-图像梯度-Sobel算子

图像梯度是指图像某像素在x和y两个方向上的变化率&#xff08;与相邻像素比较&#xff09;&#xff0c;是一个二维向量&#xff0c;由2个分量组成&#xff0c;X轴的变化、Y轴的变化 。 其中X轴的变化是指当前像素右侧&#xff08;X加1&#xff09;的像素值减去当前像素左侧&…

给IE有效指定编码

<title>下一站</title> <meta http-equiv"Content-Type" content"text/html; charsetutf-8" /> IE每次打开&#xff0c;均是一片空白&#xff0c;查看右键&#xff0d;编码&#xff0c;显示是GB2312。要手功改为UTF-8后才能正常显示页面…

形态学操作——击中击不中变换

操作目的 HitMiss变换是形态检测的一个工具&#xff0c;通过定义形状模板可以在图像中获取同一形状物体的位置坐标。 算法讲解 1、用击中结构去腐蚀原始图像得到击中结果X&#xff08;这个过程可以理解为在原始图像中寻找和击中结构完全匹配的模块&#xff0c;匹配上了之后&…

stack.pop()方法_C.示例中的Stack.Pop()方法

stack.pop()方法C&#xff03;Stack.Pop()方法 (C# Stack.Pop() method) Stack.Pop() method is used to remove an object from the top of the stack. The method removes and returns the object from the top. Stack.Pop()方法用于从堆栈顶部删除对象。 该方法从顶部删除并…

java list的作用_集合框架(List集合的特有功能概述和测试)

package cn.itcast_03;import java.util.ArrayList;import java.util.List;/** List集合的特有功能&#xff1a;* A:添加功能* void add(int index,Object element):在指定位置添加元素* B:获取功能* Object get(int index):获取指定位置的元素* C:列表迭代器* ListIterator li…

12-图像梯度-Scharr算子和laplacian算子

Scharr算子 cv2.Scharr(img,cv2.CV_64F,1,0) 第一个参数&#xff1a;当前的图像对象名称 第二个参数&#xff1a;当前图像的深度&#xff0c;通常情况下指定为-1&#xff0c;表示输出和输入的深度是一样的&#xff1b;cv2.CV_64F可以存6字节的大小&#xff0c;为了方便后面的取…

新的一年新希望,百忙中继续学习

公司来了一批新同事&#xff0c;我又忙于购买设备&#xff0c;布置办公桌了。 小林建议我找一份更合适的工作&#xff0c;目前的我其实是在混日子&#xff0c;因为我并不擅长沟通与销售。 暂时还是保持这样吧&#xff0c;我还需要一定时间来积蓄力量。 转载于:https://www.cnbl…

Oracle Internal Event:10200 Consistent Read诊断事件

10200(consistent read buffer status)内部诊断事件可以用于探测一致性读CR(consistent read)块的访问情况&#xff0c;虽然cr读的统计信息可以从v$sysstat或AWR/statspack中获取&#xff0c;但是10200 event还是我们研究Consistent Read一致性读的有力工具。该事件可以通过在会…

多线程循环输出abcc++_C ++循环| 查找输出程序| 套装4

多线程循环输出abccProgram 1: 程序1&#xff1a; #include <iostream>using namespace std;int A 5;int fun(){return A--;}int main(){int A 5;while (fun()) {cout << A ::A << " ";}return 0;}Output: 输出&#xff1a; 9 8 7 6 5Explana…

Opencv——图像金字塔与图像尺寸缩放

主要讲解 1、resize()函数调用 函数定义&#xff1a; 调用方式&#xff1a; resize(srcImage, dstImage, Size(64, 128)); //对图片进行修改 resize(srcImage, dstImage, Size(), 0.5, 0.5);第6个参数的含义&#xff1a; INTER_NEAREST:最邻近插值 (放大好用) INTER_ARE…

java nature_Java中BufferedReader和scanner的对比 - nature

原地址&#xff1a;http://blog.sina.com.cn/s/blog_5fd837410100rtwk.html Scanner 和BufferedReader同样能实现将键盘输入的数据送入程序&#xff0c; import java.io.*; import java.util.Scanner; public class C { public static void main(String []args) throws IOExcep…