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.pswp.cn/news/378735.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378735.shtml
英文地址,請注明出處:http://en.pswp.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…