欢迎光临散文网 会员登陆 & 注册

【MME开发日志/配布】屏幕空间边缘光

2022-07-23 08:23 作者:三金络合物  | 我要投稿

说明:开发日志仅简单讲解原理,大家想学怎么写MME的话可以找点别的教材或者等我哪天一时兴起做个写MME的教程(?

首先我们看原神游戏内的边缘光效果

原神游戏内的边缘光

可能这样看不是很清楚,告诉大家一个小技巧

元素视野下,边缘光会变得非常清晰。

特别亮的地方就是了!

是基于屏幕空间的效果,需要X轴的视角法线线性的空间深度还有投影


这里可以发现需要的信息刚好有三个,按理来说需要三张map,不过节省资源的话可以把这些信息都整合到一张map中,分别使用RGB三个通道,省很多资源。

三个信息整合在一张map中

然后要做偏移,这里说一下游戏里描边大小是不随模型远近变换的,但边缘光始终和模型保持等宽。

可以看到边缘光粗细相对模型比例是一致的。

所以在对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相减就行。

这里注意一下这个边缘光有个特性是遮挡效果

游戏截图

就是视角边缘正常亮度,但是如果被其他材质部分挡住了就会消失或者变暗

看到有大佬是按照深度阈值的,但是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;
    }

非常简单的判断映射!

还没按权重矫正之前

算出来是这样,然后不同通道需要按不同权重加在一起。

顺便说一下眼睛那些地方之类的可以加遮罩

float inten = saturate(Color.r) + Color.g + saturate(Color.b * 1.0);
按不同权重加在一起

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

Post画上去

大概就是这些,之后就是调整颜色,强度,粗细之类的了,写个控制器全搞定!

五月份填的坑,是第一次从头写后处理MME,从AR那里偷学来很多东西,收获很多!

有点类似描边的做法了,和传统NdotV形式然后取阈值相比的边缘光有好有坏吧。对卡渲硬面材质的效果很好。

兼容ray景深的话只需要多加一个附件去掉透明通道就可以放ray前面,不过只能加算。

相关参考资料:

《Unity URP Shader 与 HLSL 自学笔记六 等宽屏幕空间边缘光》 作者:Cutano

https://zhuanlan.zhihu.com/p/365339160

《屏幕空间等距边缘光》 作者:馬鹿家郎

https://www.bilibili.com/read/cv11841147


MMD借物:

模型:miHoYo/观海

MME:Rui_cg/三金络合物

2023.4.21 开始公配!感谢帮助过我的小伙伴们!

下载地址:https://github.com/TrimetCat/SJ_RimLight

使用方法请仔细阅读readme


【MME开发日志/配布】屏幕空间边缘光的评论 (共 条)

分享到微博请遵守国家法律