一、前言
前一段时间在看PBR X NPR结合的渲染,恰好前一段时间又猛猛给我推少前2 Vepley渲染的视频和文章,没玩过这个游戏,但感觉这个渲染效果挺独特的,本着效果可以烂大街,但是我不能没有 的原则,拿这个练练手。灵感来自于很久以前在Github上看到过的一个项目

madumpa/URP_StylizedLitShader: Madumpa's URP Stylized Lit Shader Repositoryhttps://github.com/madumpa/URP_StylizedLitShader
在这个项目里,作者巧妙的在URP Lit的框架下使用各种SmoothStep来形程色阶,达到了PBR和NPR结合的效果。在使用的时候,发现两个问题,一个是使用手动Ramp映射难以控制。另外一个,如果一直在Lit框架下这么改,灵活性大大受限,Lit的框架本身很冗长,中间又各种封装,想改一点就要牵一发动全身。
因此,我在URP里重写了一套Lit,保留关键部分,删掉多余部分(如ClearCoat,因为目前用不到)。然后自己使用Ramp图去控制色阶,至于融合方式,和上面的项目差不多,都是映射漫反射和高光部分。
由于少前2的模型没有类似崩铁那种ID灰度图去区分角色部位,因为这样可以一下子去采样所有部位的RampColor。我就直接图省事,每个部位单独给一张图了(实际项目这么做肯定不太好)。
二、PBR与NPR的融合方式
PBR x NPR或者说,PBR框架下的NPR,它本质上仍然是NPR,因此它就不可避免的有NPR的一些特点。比如:主观性这个东西,也就是说PBR和NPR如何结合本质上仍然是风格的问题,可能PBR占比多一点或者NPR占比多一点,或者是涂鸦风,线条风,水墨风,素描风,那就更需要一些特殊的处理。
PBR框架下的NPR好处是,提供了一个能量守恒的框架,防止某些trick失控。另外就是提供了更多样的材质表达,比如金属,在纯NPR是比较难表现的。
回归到NPR本质,我认为还是色阶的减少,因此选择了用Ramp去映射PBR中间步骤的方法。其它诸如两者lerp或其它方式,日后再细究。
如何画Ramp其实也是一个值得思考的问题,不过其实最终还是以效果为导向,想要什么样的效果就画什么样的Ramp,色阶少一点,Ramp色阶就少一点,反之多一点。

没有刻意去还原游戏里的样子,纯平感觉,反正效果还勉强算凑合吧hhh。
三、其它常见Feature
这部分都是卡渲的常见Feature,想必大伙基本上都烂熟于心了,我这里就简单罗列一下,除了一些自己的小trick,其它的跟常规做法没什么不同。
1.描边
采用平滑法线外扩模型然后剔除正面的做法,很常见的做法,没什么特殊的。
FOV的获取是用脚本传参的,据说现算会很慢,外扩在View空间,z拍扁。
其次就是Face的Zoffset加一个bias,让眼眶没描边,不然变成熊猫了。刚开始学习卡渲的时候用过一张自己画的Mask图来控制面部的眼眶描边。貌似崩铁的SDF的a通道自带一张mask也是这种做法。反正哪种都行,因人而异吧。
2.边缘光
边缘光也是常见做法,屏幕空间深度采样偏移,确定阈值step
阈值还可以作为强度细节给个小小的渐变,视角和光的夹角,菲涅尔等也可以决定RimLight的强度。
3.面部阴影
SDF阴影,光方向和脸朝向夹角计算ctrl去step那张SDF脸图。当然为了看起来柔和一点,可以用smoothstep,然后和其它计算一样去ramp就好了。
3.绒毛
就是一个普通的URP多Pass Feature,没做什么特殊的细节处理。想做更好的,这里有一个不错的参考。Multiple Pass Fair Rendering - Yoko的博客 | Yoko Bloghttps://yokowave.github.io/2020/09/08/multiple-pass-fur/
4.刘海投影和眉眼透过刘海
刘海投影和眉眼透过刘海都是用的模板。刘海投影是画了一遍刘海,又画了一遍脸,取交叉地方作为阴影。
由于第二次画的是脸,可以直接采样Face的AlbedoTex,然后和其它部位一样做Ramp和光照计算,然后取的Min让它和SDF的阴影融合的稍微好一些。光照计算这里我没有完全和其它部位一样,做了简化,所以还是会有细微的区别,但是观感上差距不大(也可能是我色弱)。
眉眼透过刘海也是用的模板。这里问题就来了,现在我们有,眼睛,脸,刘海,投影渲染第一遍的头发,投影渲染第二遍的脸。于是这5个东西的遮挡关系如何用模板测试去整理就变成了一个蛋疼的问题(当然,只是对我来说)。
首先眉毛眼睛在最上面,但是它们还是需要接收投影。脸是在最下面的,什么东西都可以挡住它。利用好深度测试和渲染队列排序,还是可以解决的。
先渲染眼眉,一律通过写入A。再渲染脸一律通过写入B。然后头发≠A通过刷0。这样眼眉透视就有了。
接着渲染头发投影≠0的通过,同样刷0。最后是脸投影 = 0通过就OK了。示意图差不多如下。
5.后处理
Bloom用了Unity自带的,因为没什么定制需求,而且也挺好用的个人感觉。
Tonemapping做了常见的GT,Simple ACES。其实测试下来感觉Unity自带的ACES效果其实也还行。



四、模型来源
模之屋【少女前线2:追放】维普蕾
【少女前线2:追放】维普蕾https://www.aplaybox.com/details/model/slAehTLupjVA