【UnrealEngine4】從虛幻四的著色模型到NPR

本文主要分享虛幻四中著色器的使用技巧與如何添加自己的著色模型的方式。

(正在設計的一個像素風格的渲染流程,同樣採用本文的方法,對引擎的著色模型進行了改造,可以接受天光/點光等的自定義照明效果)

鄙人消失了一個月左右,又回來了,對此深感抱歉。之前因為學業/事業/身體/等各種原因,之前的系列文章也中斷了一段時間~之前應該是講到了流體的部分,由於數學性/圖形學性較強,鄙人也還在準備當中。

本周先插播一小段技巧,同樣也是實用的技巧,希望能夠分享給大家。

一.【UnrealEngine4】距離場的使用技巧與應用

二.材質中的偽體素

1.【UnrealEngine4】材質系統中的偽三維紋理

2.【UnrealEngine4】體渲染和Tri-Planar Mapping

三.在虛幻四中基於NS方程的流體模擬

1.【UnrealEngine4】藍圖-材質的數據傳輸與偽ComputePipeline

2.NS方程的解析和實際模擬

四.metaball 的原理與在材質中的實現

五.在虛幻四中 path tracing

1.相機內參、簡單物體變換信息的處理

2.path tracing的解析,temporal的思路

3.在材質中進行path tracing

六、透明物體的渲染/造假技巧

特別篇目:

一、NPR與虛幻四的著色模型(本文)

二、一些後期處理的原理與解析

本文的目標:在虛幻四中插入自定義的著色模型,理解虛幻四中延遲渲染的流程。鄙人僅僅分享一種簡單的做法,不代表最優做法/官方做法,分享僅此為了讓一些很多人都存在的疑問得以解決。

(Cel Shading,對全部光源都適用的(而不是在材質編輯器里只能通過藍圖手動傳入的那種。。。))

文章結構:

一.GBuffer的結構

二.虛幻中Shader.usf的內部關聯

三.插入自定義著色模型

一.GBuffer的結構

虛幻四大多時候使用延遲渲染,而前向/延遲渲染的最大區別,可能就是GBuffer的使用與否。

GBuffer,全稱Geometry Buffer,事實上這個定義很早被定下,而實際上如今的意思已經遠超原本的意思(雖然這個東西不重要,還是稍微提一下)

這裡將解析一下虛幻四默認的GBuffer的結構。

首先,需要了解虛幻四延遲渲染的流程。

GBuffer的本質是送信者,將信息傳遞給最終的著色部分。而實際上信息提供者是Mesh,把信息給送信者的是材質,也就是說,材質是中介的中介(可能有點繞了)。

換句話說,虛幻的普通域的材質實際上寫入的是GBuffer,而不是最終結果。

其次,再整理一下各種東西之前的關係。

A:場景物體

B:材質/材質編輯器輸出

C:BassPixelPass(後面會提到

D:GBuffer

E:FinalPixelPass(最終根據各種著色模型輸出到屏幕的Pass

渲染順序一般為

A->B->C->D->E

最後,稍微提一下虛幻四中默認的GBuffer的排布.

本文旨在插入「新的」著色模型,基本的DiffuseColor/SpecularColor/Metalic/Specular/AO/WorldNormal什麼的不再具體闡述(畢竟需要修改的地方很少,默認的即可。)

在不知道什麼版本更新了Cloth/Eye/ClearCoat 的著色模型之後,GBuffer里多了一個八位四通道的的CustomData,也就是說,這個CustomData是可以被使用而不影響原有的渲染流程的。接下來,鄙人將分享一下,怎麼插入自定義的著色模型,和利用這個插槽來增加參數。

GBuffer.CustomData

(他在shader里的出現形式是這樣的)

虛幻四自帶的Cloth/Hair/Eye/ClearCoat等著色模型均使用了該CustomData,來儲存切線或者其他參數。

二.虛幻中Shader.usf的內部關聯

前面做了一些鋪墊,虛幻的材質系統在內部是有很大關聯的。鄙人將介紹幾個常用的usf文件,理解文件結構,也為後面增加著色模型提供了一些理論基礎。

首先打開引擎源目錄,找到Engine/Shaders文件夾(建議備份一份)

(4.18左右的版本裡面還分了Private/Public/StandaloneRenderer的文件夾)

裡面有很多文件,選幾個解析一下其作用與各種關聯。

這裡需要有一點點編程基礎(#include什麼的,#if什麼的指令需要清楚)

下面正文

1.BRDF.usf(BRDF.ush)

裡面儲存了大部分常用的brdf函數(大霧:抄過的人都說好)

因為裡面應有盡有,只有想不到的,沒有找不到的,在寫著色模型的時候也能很輕鬆地調用,因此不詳細解說了。

(其中一個Diffuse的BRDF,很方便shader學習者借鑒,因為上面有論文出處)

2.BasePassPixelShader.usf

控制寫入GBuffer的著色器。可以讀取材質編輯器里輸出的參數,可以控制GBuffer里應該寫入什麼。

比如材質編輯器里指定了著色模型A,這個Pass可以控制把材質中的diffusecolor寫入到normal里,把specular寫入到ao里,大概就是這個意思。也就是說,這裡再次說明了材質只是中介的中介,不管材質的輸出是怎麼連的,最後決定怎麼寫入GBuffer的都是這個shader。

3.DeferredLightingCommon.usf(DeferredLightingCommon.ush)

這個文件顧名思義,就是控制光照的。其中最重要的函數是GetDynamicLighting,這裡控制了對於每種光源/每種表面,著色器應該怎麼處理。添加著色模型也應該從這裡入手。

4.ShadingModels.usf(ShadingModels.ush)

被3. include了。主要函數是SurfaceShading 等一系列決定最終光照的函數。

裡面根據GBuffer里儲存的ShadingModel,在case SHADINGMODELID_XXXXXX 里進行了著色模型的選擇。

同時,這個文件里是最終決定著色方式的著色器。

他們的執行順序(按理來說)應該是:2->3->4->1

三.插入自定義著色模型

首先來一個簡單的例子:

ShadingModels.usf(ShadingModels.ush)中找到StandardShading函數,這個函數被SurfaceShading 當著色模型為默認時調用。

其中有三行:

float3 Diffuse = Diffuse_Lambert( DiffuseColor );

//float3 Diffuse = Diffuse_Burley( DiffuseColor, LobeRoughness[1], NoV, NoL, VoH );

//float3 Diffuse = Diffuse_OrenNayar( DiffuseColor, LobeRoughness[1], NoV, NoL, VoH );

可以通過注釋更改默認的Diffuse的BRDF。

對於高光也可以進行一樣的操作,當然前提是讀者對shader十分熟悉了,自然替換起來也可以得心應手。

關於添加/插入自己的著色模型。

提供兩種方案

1.通過C++增加材質編輯器里的著色模型選項,然後再通過shader增加真正的shadingmodel

2.直接去掉虛幻默認的shadingmodel,更改為自己的。

拿ClearCoat舉例,在材質中選擇ClearCoat可以開多三個口:

透明圖層,透明圖層粗糙度,還有最後的BottomNormal。

先從BasePassPixelShader.usf 開始

找到#elif MATERIAL_SHADINGMODEL_CLEAR_COAT

然後就可以決定這些介面將怎麼被寫入GBuffer中。

GBuffer.CustomData.xy = ClearCoatBottomNormal0(MaterialParameters).xy;

GBuffer.CustomData.z = GetMaterialCustomData0(MaterialParameters);

GBuffer.CustomData.w = GetMaterialCustomData1(MaterialParameters);

就像這樣,寫入到Custom的xy就是BottomNormal的xy值,寫入到Custom的z的就是材質輸出的透明圖層,以此類推。

然後到ShadingModels.usf(ShadingModels.ush) 中找到SurfaceShading ,可以看到類似的根據著色模型ID選擇著色模型的代碼。新建一個函數XX(FGBufferData GBuffer)

case SHADINGMODELID_CLEAR_COAT:

後調用自己的函數。

XX(GBuffer);

然後就可以在這個函數里為所欲為了。

關於NPR的著色器可以參考底下:

candycat1992/NPR_Lab

這裡我給出一個自己改進過的經驗模型,也就是題圖的著色模型的Diffuse部分:

alpha=Steps*NoL-0.5

eta=2(alpha-floor(alpha))-1

gamma=eta^{2Hardness+1}

Final =maxleft{ frac{(0.5gamma+floor(alpha))}{Steps},0.0 
ight}

(暫且命名為Diffuse_YCZ函數)

這個函數是基於CelShading的,加入了一個Hardness這個參數,來控制分界邊的軟硬。

註:Hardness需要為整數。這種辦法可以使CelShading退化至普通的Lambert,對於邊界的鋸齒也能更好地去除。

(將GBuffer里除了法線之外的插槽全部改為了自定義的參數,如控制多顏色的Instance,控制陰影,等)

使用這種辦法可以快速加入自己需要的著色模型,相當於定製自己的引擎,比修改源碼重新編譯應該要來得更靠譜一點,從成功幾率上看。

本期文章要分享的東西也寫完了~希望能幫到各位虛幻四的用戶和讀者。

下一期將會簡單地介紹一下一些後期處理在虛幻四中的實現方法。

包括NPR的Hatching,描邊,還有水面分界特效的簡單實現方法。

(Hatching與描邊)

(動態水面分界)

https://www.zhihu.com/video/913096339934576640

大家的點贊才是我最大的前進的動力~所以 閱讀完之後記得點贊哦(???ω?? ?)

文章僅僅為了分享經驗交流心得,拋磚引玉,見笑大方了。如有紕漏,望斧正。

參考文獻/項目:

candycat1992/NPR_Lab


推薦閱讀:

TAG:UnrealEngine4 | 计算机图形学 | 渲染 |