Unity輕量級渲染管線LWRP源碼及案例解析(上)

Unity輕量級渲染管線LWRP源碼及案例解析(上)

原創: 張黎明 Unity官方平臺 今天git

收錄:白袍扶心 (之前、當前、將來筆記都在GIT了-嘿嘿)github

GIT: https://github.com/daozhangXDZ/DaoZhang_ProgramNote/tree/master/Unity/ScriptRenderPipelineweb

小道說一個LWRP(這裏和原來Shader的寫法有區別,不過這樣更對應GLSL和HLSL,OPENGL和DX你懂的):
CBUFFER_START(UnityPerMaterial)
float _Outline;
float4 _OutlineColor;
CBUFFER_END算法

原創: 張黎明 [Unity官方平臺]編程

今天本文將分享Unity大中華區技術總監張黎明在Unite 2019上的技術演講-Unity輕量級渲染管線LWRP源碼及案例解析。緩存

受篇幅限制,本次演講將分享二篇內容。本文將介紹可編程渲染管線SRP和輕量級渲染管線LWRP、LWRP與Built-in內置渲染管線區別、LWRP源碼解析Core RP和Lightweight RP。編輯器


演講內容函數

你們好,個人演講題目是《Unity輕量級渲染管線LWRP源碼及案例解析》。性能

你們可能發現技術分享一般去講使用爲主,講源碼的很是少,爲何我會選擇講源碼?學習

這是出於有二個緣由:

  • 第一個緣由是輕量級渲染管線LWRP實在是太新了,根本就找不到太多文檔。我原本想找文檔給你們講解一下,結果發現沒有。我本身學習也只能經過查看源碼的方式,咱們內部也沒有文檔。

  • 第二個緣由是咱們發現一些客戶已經開始使用了,並且他們每一個遊戲都有一些特殊的需求,有的遊戲可能須要對Unity輕量級渲染管線LWRP進行一些定製。這樣就必需要查看源碼,從而在遊戲中達到更好的效果。

下面是我本次分享的主要內容,首先會簡單介紹什麼是Unity的可編程渲染管線SRP以及輕量級渲染管線LWRP。


可編程渲染管線SRP

首先,簡單介紹一下Unity的可編程渲染管線SRP。


過去,咱們有一套內置渲染管線的Render Pipeline,渲染管線所有寫在引擎的源碼裏,使用C#代碼編寫。你們基本上不能改動,除非是買了Unity的源碼客戶,固然大部分開發者是不會去改源碼,因此過去的管線對開發者來講,很難進行定製。

對於咱們來講也有負擔,由於咱們要在一個渲染管線裏面支持全部的二十多個平臺,包括很是高端的PC平臺,主機平臺,也包括很是低端的平臺,很老的手機也要支持。

因而,這套代碼會變得愈來愈臃腫,很難作到使效率和效果作到最佳,因此咱們如今有一套新的基於腳本的渲染管線。

它主要把渲染管線拆分紅二層:

  • 一層是比較底層的渲染API那層,像OpenGL,D3D等相關的都封裝起來。
  • 另外一層是渲染管線比較上層的描述,上層代碼使用C#來編寫。在C#這層不須要關注底層在不一樣平臺上渲染API的差異,也不須要關注具體如何作一個Draw Call。

咱們在C#這邊會一批對象一批對象的畫,這樣性能也會更好一些。

Unity官方基於Scriptable Render Pipeline可編程渲染管線提供了二套模板:一個是輕量級渲染管線LWRP,一個是高清晰渲染管線HDRP。

高清渲染管線HDRP是所有基於Compute Shader,基於最新的硬件來開發的,能夠達到頂尖的渲染效果。例如Unity的官方演示項目《異教徒》,它的效果很是驚豔。

輕量級渲染管線LWRP

另一個渲染管線是輕量級渲染管線LWRP,主要是爲了移動平臺設計,也就是最流行的手機遊戲平臺,它能夠達到更高的效率,而後可定製性也更好。

這二個模板都是開源的,你們均可以在Github下載,也能夠本身進行修改。

img

高清晰渲染管線HDRP只支持最高端的平臺,即目前比較好的PC和主機平臺,但輕量級渲染管線LWRP支持全部的平臺。

咱們的目標是輕量級渲染管線LWRP在性能方面比過去內置的管線更好。在Unity 2019.1中,輕量級渲染管線LWRP已經成爲正式版本,可用於正式的項目製做。

LWRP與內置渲染管線對比

咱們和不少客戶有過溝通,發現其實你們對輕量級渲染管線LWRP不是很理解。不少人一聽到輕量級管線LWRP就以爲有點LOW,以爲如今你們製做移動遊戲都開始作AAA級,畫面都要PBR,都要超大世界,各類特效,後處理都加上。

不少人可能尚未去了解輕量級渲染管線LWRP,就以爲是否是趕不上目前的主流畫面。因此,我先給你們對比一下輕量級渲染管線LWRP和老的渲染管線有什麼差異。

img

如上圖所示,最重要一點就是第一行,老的渲染管線使用Multi-Pass的Forward Rendering,就是多Pass的正向渲染。最大的問題是若是要在場景裏要加不少動態光的話,每個動態光都有可能會增長一個Pass,這個動態光所影響的物體要多畫一遍。

這就致使若是遊戲裏想要有多個動態光的話,可能這個場景會被畫不少遍,性能會不好。它帶來的問題是全部的遊戲幾乎都不會用多個動態光,由於實在太費性能了。

在過去製做移動的遊戲的過程當中,你們的標準作法都是烘焙Lightmap。若是能夠用多個動態光,咱們其實能夠作出更酷的效果。

例如,製做一個有魔法的遊戲,遊戲中每一個人都釋放一個魔法球出來,咱們徹底能夠給它加一個動態的燈光,跟着它一塊兒飛出去,這樣的效果很是酷。可是由於過去每增長一個動態光都會致使渲染Pass增多,因此你們就不敢使用。

如今輕量級渲染管線LWRP就解決了這個問題。咱們實現了一個單PASS的正向渲染。咱們能夠支持多盞動態光,可是所有動態燈光都會放在一個Pass裏渲染,這樣帶來的問題是咱們要限制燈光的數量,由於每次Draw Call去畫的時候,傳給GPU的參數是有限的。

若是燈光數量特別多,參數太多,那就會沒法在一次Draw Call裏完成不少個燈光。因此咱們有一些限制,在輕量級渲染管線LWRP裏,目前是支持1盞平行光,每一個對象可能只能接受4個動態光。每一個攝像機也有一些限制,這是爲了咱們能夠把全部的計算放在一個Pass裏面。

Unity2019.2,Unity 2019.3可能會把這個限制再提升一些。相信大部分的遊戲也不太會在一個場景里加太多動態光,若是能夠作到8盞動態光,可能對於大部分遊戲來講也足夠了,這樣在一個Pass裏的渲染性能會更好。

另外,輕量級渲染管線LWRP還有新加入的功能,包括Scriptable Render Pass,還有SRP的Batcher合批。合批會比過去好一些,輕量級渲染管線LWRP仍會支持靜態合批和動態合批。咱們還會提供可經過腳本定製的Render Pass以及Custom Renderers。

不少客戶給咱們反饋,如今使用輕量級渲染管線LWRP,最欠缺的是二個功能:

  • 首先是目前還未支持的Shadow Mask,這在老的內置渲染管線裏已經有了。咱們計劃在Unity 2019.3提供Shadow Mask的功能。
  • 其次是延遲渲染Deferred Rendering,它在老的管線有,新渲染管線沒有,它也會在Unity 2019.3提供。

關於PBR,你能夠認爲它徹底不比內置渲染管線差,它也是使用了移動平臺上的最好光照模型。若是再往上提高的話,就是HD渲染管線的PBR光照算法,這樣的話就太費性能了,可能不適合你們作移動遊戲了。

在PBR這方面,它基本和內置渲染管線是保持一致的。若是你們仍是不滿意的話,能夠修改輕量級渲染管線的Shader,修改光照模型就能夠了。

img

如上圖所示,這是咱們本身進行了一些測試結果,基本上在各個方面的性能都是比內置渲染管線要好。

img

上圖顯示的是新增功能Custom Render Pass,主要是爲了提供可擴展性。咱們仍是但願你們不改源碼就能夠進行擴展,因此提供了這種方式。若是這樣還不夠的話,你們再去考慮改源碼。

咱們推薦你們,能夠不改源碼實現,就儘可能不改源碼,由於改了源碼後,升級會很麻煩,本身要升級修改過的代碼到新的版本,要避免衝突,增長你們的工做量。

img

如上圖所示,在Unity開發路線圖裏,除了如今提供的Forward Renderer,Unity 2019.2會提供一個2D的Renderer,它主要提供2D的光照和2D的陰影效果。Unity 2019.3會增長Deferred Renderer,一個延遲渲染的Renderer。

LWRP源碼解析-Core PR

若是要使用輕量級渲染管線LWRP,你須要在Package Manager裏導入二個Package:Core RP和Lightweight RP。

Core RP是高清晰渲染管線HDRP和輕量級渲染管線LWRP共同依賴的包,由於有一些代碼須要共用,因此咱們把這部分代碼拆到Core RP中。

img

以下圖所示,咱們看一看Core RP文件夾的結構。

img

Editor文件夾中是編輯器腳本,作一些Inspector裏顯示參數的代碼。Runtime文件夾中是主要代碼,有一些共用的Shader Library,共用的Shader代碼放在這裏,其它還有一些測試代碼。

img

在Runtime > Common文件夾中有一個CommandBufferPool,輕量級渲染管線LWRP和高清晰渲染管線HDRP都要用到它。

若是你要用一個CommandBuffer的話,不要本身New一個,而是在Pool裏拿一個,由於它會緩存下來,等下一幀須要用的時候,能夠在庫裏拿出來直接用,而不是每次New一個,Delete一個,這樣性能會比較差。

img

Volume文件夾是實際上相似於Post-Processing Stack後處理棧裏面的PostProcessVolume,這是一個通用的Volume,能夠調一些渲染管線的參數,它能夠在進入一個體積後調一些參數。

img

Core RP其實很簡單,我主要但願讓你們知道,沒有必要花太多的時間看這些東西,由於它裏面沒有太多的內容。

LWRP源碼解析-Lightweight PR

咱們的重點是另外一個Package,即Lightweight RP裏面有哪些東西。

img

本次重點會講下圖中這些類,這是源碼中的一些類,我要介紹這些類的用途是什麼?

img

咱們先作一點輕鬆的事情,我製做了一個很簡單的Demo,簡單說一下輕量級渲染管線LWRP怎麼使用?

img

第一步要在Package Manager裏面導入package,導入以後須要Create一個Light Weight Render Pipeline Asset。建立後咱們有Graphics Settings。

咱們要把Asset拖到Scriptable Render Pipeline Settings這個位置,而後引擎會把當前渲染管線改爲剛剛建立的Asset這種類型的渲染管線,老的內置渲染管線就開始不執行了。建立的輕量級渲染管線LWRP在Asset上有一些參數設置。

首先有Renderer,而後有二個選項Depth Texture和Opaque Texture。Render Pipeline Asset上會保存輕量級渲染管線LWRP的一些參數。

img

這裏有一個剛剛提到的Opaque Texture選項,它對應的代碼就是LightweightRenderPipelineAsset類。

咱們寫了這個類以後,就能夠在Editor裏右鍵新建一個這種類型的Asset,它繼承自RenderPipelineAsset這個類。

img

LightweightRenderPipelineAsset類中聲明瞭一些變量,這些變量就是在Inspector看到的Render Pipeline Asset上的參數,它們都是在這個類裏面定義。也就是說,這個類是用於序列化Lightweight Pipeline上全部的參數。

若是你們之後自定義輕量級渲染管線LWRP,但願增長本身的參數,找到LightweightRenderPipelineAsset這個類,並添加參數就能夠了。

img

RenderPipelineAsset繼承自ScriptableObject,你們應該知道,ScriptableObject這個類是專門用於序列化數據的,因此它在這裏序列化輕量級渲染管線LWRP的數據。

而後看一看Opaque Texture選項,這是輕量級渲染管線LWRP提供的一個功能。

在內置渲染管線Pipeline中,若是想作一個折射的效果,例如水的效果,過去的作法是用GrabPass,在Shader裏寫一個GrabPass,它會抓取當前的屏幕畫面,而後對畫面作扭曲和水的擾動等效果。

GrabPass的問題是它的性能不太好,並且在不一樣手機硬件上,不一樣渲染API上的實現方式不同,有的硬件上性能特別差,致使幀率降得特別厲害。

如今咱們在輕量級渲染管線LWRP中,能夠直接在不透明物體畫完後,勾上Opaque Texture選項後,它就會把當前畫面抓取到RenderTexture裏。若是要作折射效果或是水的效果,或者是玻璃的折射的話,直接用該選項便可。


再看一下這個Demo,勾選Opaque Texture後,它用起來很是簡單。在Shader中,咱們須要去定義一個CameraOpaqueTexture的變量,定義了後就能夠直接在後面的Fragment Pixel Shader去採樣。

咱們直接能夠採樣貼圖的Sampler,能夠作一些擾動效果,很是方便。咱們沒必要像過去那樣使用GrabPass,致使一些性能問題。


最主要的渲染管線的執行是在LightweightRenderPipeline類中,它繼承自RenderPipeline基類。這個基類實際上是一個Interface,裏面其實沒有作什麼實現,全部實現都在這個輕量級渲染管線腳本里。

如上圖所示,這個主的渲染函數也很簡單,就是For循環全部相機,而後調用RenderSingleCamera,渲染每一個相機的函數,邏輯比較簡單。


如上圖所示,在RenderSingleCamera中有幾行比較重要的代碼。上面這行會進行判斷,如今在SRP裏能夠有一個額外的數據。在Lightweight Render Pipeline和HD Render Pipeline上的參數都不同,HD的參數會多不少。它會把這些不同的參數拆出來並進行判斷。

這裏有一個if判斷,用來判斷相機上的參數有沒有設置Renderer。若是有,就優先用相機上的Renderer。若是沒有設置,就用Render Pipeline Asset上設置的Renderer。

在LightweightRenderPipelineAsset上能夠選擇Renderer,上面有Custom和Forward Renderer二個選項,它本質上也是Forward Renderer。

在相機上也能夠選擇Renderer Type,能夠選擇使用剛剛Asset中的設置,也能夠選擇在每一個相機用不一樣的Renderer。代碼裏會優先使用相機上的設置,若是相機沒有設置,它會使用Asset設置的Renderer。

最下面的代碼會調用Renderer.Setup進行配置和渲染執行。

小結

在本篇中,張黎明介紹可編程渲染管線SRP,LWRP與內置渲染管線區別,LWRP源碼解析Core RP和Lightweight RP。在下一篇中,他將分享如何定製輕量級渲染管線LWRP。

更多Unite大會精彩演講內容分享,盡在Unity Connect平臺(Connect.unity.com)。

下載Unity Connect APP,請點擊此處。 觀看部分Unity官方視頻,請關注B站賬戶:Unity官方

相關文章
相關標籤/搜索