【MME開發(fā)日志/配布】屏幕空間邊緣光

說明:開發(fā)日志僅簡單講解原理,大家想學怎么寫MME的話可以找點別的教材或者等我哪天一時興起做個寫MME的教程(?

首先我們看原神游戲內(nèi)的邊緣光效果

可能這樣看不是很清楚,告訴大家一個小技巧
在元素視野下,邊緣光會變得非常清晰。

是基于屏幕空間的效果,需要X軸的視角法線,線性的空間深度還有投影。

這里可以發(fā)現(xiàn)需要的信息剛好有三個,按理來說需要三張map,不過節(jié)省資源的話可以把這些信息都整合到一張map中,分別使用RGB三個通道,省很多資源。

然后要做偏移,這里說一下游戲里描邊大小是不隨模型遠近變換的,但邊緣光始終和模型保持等寬。


可以看到邊緣光粗細相對模型比例是一致的。
所以在對map偏移的時候要考慮到深度,校準深度值讓偏移的比例是正確的,按視角法線方向來偏移。
coord.x = coord.x + scnmap.r * offsetThr / sqrt(scnmap.g) * (1 + SizeUp * 2.0f) * saturate(1 - SizeDown);
offsetThr是偏移程度,SizeUp&Down是控制器。
啊還有就是這個要在像素著色器做,我在頂點著色器里嘗試是不太支持會報錯。。
這串代碼中的scnmap.g就是深度信息,因為我們之前把深度信息存在g通道里了。
scnmap.r就是視角向量的X軸法線信息。
順便說一下視角向量怎么獲得,物體的世界法線和視角空間矩陣相乘就可以,
float3 normal = normalize( mul( Normal, (float3x3)WorldViewMatrix ) );
深度信息的話就是視角空間里的w軸。
然后偏移后的map和原來的map相減就行。

這里注意一下這個邊緣光有個特性是遮擋效果。

就是視角邊緣是正常亮度,但是如果被其他材質(zhì)部分擋住了就會消失或者變暗。
看到有大佬是按照深度閾值的,但是MMD算出來的深度好像不太行。。所以用的剪影算視角邊緣,法線算其他被遮擋的邊緣。
啊還有視角法線要把0.5以下的映射到0.5-1.0之間的,方向問題。
? ?if (Color.r < 0.5)
? ?{
? ? ? ?// depmap.r = 0.5 - depmap.r;
? ? ? ?Color.r = 1 - Color.r;
? ?}
? ?if (depmap.r < 0.5)
? ?{
? ? ? ?depmap.r = 1 - depmap.r;
? ? ? ?// Color.r = ?1.5 - Color.r;
? ?}
非常簡單的判斷映射!

算出來是這樣,然后不同通道需要按不同權(quán)重加在一起。
順便說一下眼睛那些地方之類的可以加遮罩。
float inten = saturate(Color.r) + Color.g + saturate(Color.b * 1.0);

最后加在按照需要的強度畫在畫面上就可以!

大概就是這些,之后就是調(diào)整顏色,強度,粗細之類的了,寫個控制器全搞定!

五月份填的坑,是第一次從頭寫后處理MME,從AR那里偷學來很多東西,收獲很多!
有點類似描邊的做法了,和傳統(tǒng)NdotV形式然后取閾值相比的邊緣光有好有壞吧。對卡渲硬面材質(zhì)的效果很好。
兼容ray景深的話只需要多加一個附件去掉透明通道就可以放ray前面,不過只能加算。

相關(guān)參考資料:
《Unity URP Shader 與 HLSL 自學筆記六 等寬屏幕空間邊緣光》 作者:Cutano
https://zhuanlan.zhihu.com/p/365339160
《屏幕空間等距邊緣光》 作者:馬鹿家郎
https://www.bilibili.com/read/cv11841147
MMD借物:
模型:miHoYo/觀海
MME:Rui_cg/三金絡(luò)合物

2023.4.21 開始公配!感謝幫助過我的小伙伴們!
下載地址:https://github.com/TrimetCat/SJ_RimLight
使用方法請仔細閱讀readme