虛幻4渲染編程(材質編輯器篇)【第二卷:自定義光照模型】
來自專欄 虛幻4渲染編程
先上專欄目錄
小IVan:專題概述及目錄還是老規矩先上效果吧:
讀過我前面一些博客的朋友對虛幻4的渲染流程有了一些大致的了解之後,那麼我們現在可以開始著手開始修改虛幻4引擎了·。我們有些時候需要實現某些效果,就需要動手自己改引擎了。這是customnode或者是純material無法做到的。有些人可能就要反駁了,「我純用材質編輯器也能實現卡通材質啊」。但是無法忽略的一點是:在材質編輯器里製作的卡通材質無法接受光影。這時候有些人就想出了騷操作,用藍圖自己實現一個光源,渲染一張depthmap的RT然後傳到material里去。這種方法其實過於麻煩,這相當於你拋棄掉了虛幻4的光照系統。這是得不償失的。
閱讀下面的內容你需要具備一下知識:
(1)C++
(2)對虛幻引擎及其渲染模塊有一定了解,如果不了解可以先讀讀我之前的一些文章。
(3)HLSL
那麼下面就以這個卡通材質為例,讓我們一步步來定製自己的渲染管線。來看一下虛幻的GBuffer的數據有哪些吧:
首先你得下載好一個源碼版引擎,我使用的是4.19版引擎。也許在未來引擎會做更新,單應該變化不大。然後打開如下的文件:
首先找到EngineTypes.h,找到EMaterialSamplerType這個枚舉。這個枚舉將會控制材質編輯器里的那個下展欄。然後我們加入我們的枚舉成員MSM_MyShadingModel UMETA(DisplayName="MyShadingModel")編譯引擎後你將會看到如下的樣子:
你將能在材質編輯器里找到自己的ShadingModel材質的枚舉類型。
這一步只是讓編輯器有了一個切換枚舉,並不會讓材質編輯的UI發生什麼變化,比如material的節點上多出幾個pin,禁用幾個pin或者別的什麼變化。現在我們需要激活幾個pin介面,讓我們能把變數「連上去」
接下來找到Material.cpp 我們找到bool UMaterial::IsPropertyActive(EMaterialProperty InProperty)這個函數。然後做如下圖所示修改
這樣就能讓材質編輯器在我們切換shadingmodel枚舉的時候,實時增加一個CustomData的pin介面給我們用啦。
有了這個東西之後,我們還要讓材質編輯器在切換瞬間告訴我們的shader:「我們應該用我們自定義的shader啦」。如何告訴shader應該跑我們MSM_MyShadingModel的shading分支邏輯呢?答案是使用宏。
打開MaterialShared.cpp,找到FMaterial::SetupMaterialEnvironment(
EShaderPlatform Platform,
const FUniformExpressionSet& InUniformExpressionSet,
FShaderCompilerEnvironment& OutEnvironment
)
這個函數我們做如下修改:添加如下代碼
case MSM_MyShadingModel: OutEnvironment.SetDefine(TEXT("MATERIAL_SHADINGMODEL_MyShadingModel"), TEXT("1")); break;
這個字元串會被壓進shader里,成為宏。
做完這些我們就可以編譯引擎了。可能會等待半小時左右。
編譯好引擎之後,我們開始對shader層進行修改。
首先打開DefferedShadingCommon.ush文件,找到下圖所示區域並做如下修改:在#define SHADINGMODELID_EYE 9後面添加#define SHADINGMODELID_MyShadingModel 10 並且把SHADINGMODELID_NUM後的數字改為11
這個宏將作為我們shader跑哪根線路的判斷依據。還是在這個文件里,翻到DefferedShadingCommon.ush的最底部,找到float3 GetShadingModelColor(uint ShadingModelID)函數,在case SHADINGMODELID_EYE: return float3(0.3f, 1.0f, 1.0f);後面添加 case SHADINGMODELID_MyShadingModel: return float3(0.4f, 0.0f, 0.8f);//紫色
如下圖所示:
做完這個修改以後,我們就能在編輯器的ShadingModle預覽模式下看到如下效果:
你能看到我們定義的顏色已經能在debug模式下看到了。說明一切順利!!
下一步來到ShadingModelsMaterial.ush 找到void SetGBufferForShadingModel函數。我們在這個函數的最後面做如下修改:
這裡的MATERIAL_SHADINGMODEL_MyShadingModel是從c++層那裡塞進來的,然後把這個ShadingModle的ID保存到GBuffer里作為後面管線使用的數據。這一步是給DefferedShadingCommon.ush使用的。
完成之後我們需要打開BassPassCommon.ush,打開CustomData的寫入許可權
這一步的目的是當我們的shadingmode為MyShadingModel的時候,將CustomData的信息寫入GBuffer。
然後來打DefferdLightingCommon.ush 找到GetDynamicLighting函數,我們對這個函數做如下修改:
當然做了這個修改之後我們還需要對SurfaceShading函數再做修改:
打開ShadingModels.ush做如下修改:
完成這一步之後,我們還要對透明模式下的代碼進行修改。打開BasePassPixelShader做如下修改:
完成這一步之後,我們還要對透明模式下的代碼進行修改。打開BasePassPixelShader做如下修改:
那麼就完成了對引擎shader的定製啦!
引擎的定製對項目還是很重要的,官方其實考慮更多的是通用和兼容,但是這往往就導致一點:用虛幻4做出來的遊戲都長得差不多。不知道大家有沒有發現這點。其實我對這點感受還是很明顯的,現在的demo或者視頻瞟一眼就知道是不是虛幻做的,因為大家的shader效果是一樣的。這就會導致大量的同質化作品的出現,無法使你的項目脫穎而出。比如超龍珠鬥士Z,那麼精美的卡通渲染,肯定對引擎進行了大量的定製。
有沒有發現,我們自己激活的哪個CustomData0 這個介面的名字在你切換成Eye的時候,它會變成其他名字。鑒於強烈的強迫症,看這個CustomData0真的很不舒服,所以我們就來自己定義一下材質輸入介面的名字吧:
我們在Engine/Source/Editor/UnrealEd/Private/MaterialGraph.cpp的529行左右找到GetCustomDataPinName函數,然後做如下修改
編譯後你將會看到:
Enjoy it!!!
推薦閱讀:
※Unity ShaderLab 模板緩存(Stencil Buffer) 基本概念
※筆記十二——動畫效果
※Shader(三)基本光照
※[OpenGL]Shader編譯流程示例
※Instagram濾鏡,影視級調色演算法實現