【节点思路详细介绍】在blender中还原米哈游风格的三渲二效果

前言:
这篇文章主要阐述工程中节点的构建思路,建议配合blender工程一起使用
前两部分视频
【工程预设分享与使用教程】BV1Nh411K7nj
【大致节点构成速览与贴图部分详解】 BV1tc411u7y2
分别包括三大部分,整体shader节点组内部构造、合成节点中眉毛半透头发的遮罩设置、几何节点中制作动态描边的思路。最后dlc中记录了两个未采纳的边缘光方案
· 结尾放了度盘和模之屋的工程下载链接
· 学习参考的来源也放在文末

整体shader节点组内部构造
整体的shader节点组主要有两部分构成。一部分是需要准备的输入与输出数据,另一部分是渲染管线。
输入数据有需要准备的向量信息与灯光信息、各贴图通道数据;输出数据有aov通道输出。
渲染管线由这几部分依次构成,分别是:阴影设置、制作指针并使用ramp图给阴影染色、混合灯光的基础色、高光设置、丝袜材质设置、自发光基础色、鼻尖的正面描边、混合环境光影响的基础色贴图、matcap边缘光。
输入数据
输入数据中,本篇文章只详细阐述准备的向量信息与灯光信息,贴图的各通道输入与封装逻辑在前一个视频中已经进行讲解。

人物头的方向向量用于确定人物头部的前方向,右方向与上方向三个向量,可实时跟随模型的改变而改变。
制作方法是,分别在头的位置,前方的位置、右方的位置、分别设立三个空物体,绑定到人物头部的骨骼上。
再使用驱动器,将物体的位置信息输入到节点,此时我们有了空间中三个点的位置。

前方和右方的点分别减去原点位置,得到前方与右方的向量,最后由于blender是右手坐标系前方与右方向量叉乘可得出上方向向量,同时加以规格化输出长度为1的向量数据。


这样我们就获得了人物头前,上,右三个方向的向量。
2.摄像机向量
摄像机向量,我们有摄像机数据的视图矢量进行反转之后,由摄像机坐标改为世界坐标再规格化之后得出(这里后面的规格化节点疑似可以优化,在矢量变换第三个翻译为法向的选项中,疑似翻译错误,应该是整合了规格化节点的作用,可以直接输出一个长度一的向量,但最后保险起见也出于直观没有使用,在后面单独加了个规格化)。


3.物体法线向量
直接由物体几何数据的法相连出。

4.灯光方向
设置了一个(0,0,1)的向量,并使用驱动器复制灯光的旋转来对其进行旋转,这样获得了一个与光照方向相反的灯光方向向量。

5.灯光颜色与强度
这里直接使用驱动器获取灯光rgb三个通道的值,并与驱动器获得的光强相乘,由此获得了灯光的颜色与亮度信息。

至此前期准备工作已经完成,我们可以来详细看看各个部分的渲染管线了。
渲染管线各部分介绍
一、阴影设置

阴影设置主要分为三部分:分别有身体的阴影,脸部的阴影,与叠加ao细节。
1.身体部分阴影
身体部分阴影我们首先使用兰博特光照模型制作身体的漫反射。使用法线向量点成灯光方向来得出cosθ(θ等于物体表面法向与灯光方向的夹角),接下来不必再将cosθ转换为角度,因为其与灯光夹角角度从90°到0°的变化正好输出的是一个0到1的值。
而90°到180°度的值都小于0输出的通道都是黑色,因此不必再加以钳制。
此后我们加一个,先乘后加节点,来平滑它的阴影过度。由此我们获得了一个最基本的阴影模型。


接下来我们需要给这最基本的过渡阴影增加光照图中绿通道阴影细节。
首先我们将贴图的通道信息反转一下进行矫正,接下来将其分别相加,相减一个固定数值使边缘有一定柔和范围。
最后使用渐变映射,设置其从最小值和从最大值的范围,来设置边缘过度的平滑。


ps:这里同样可以使用相乘并使用颜色渐变来叠加阴影细节并设置过渡。
但由于颜色渐变比较难操控,不能直接调整阴影偏移与平滑等级,需要通过两个滑块的位置与相对距离来设置,较难操作,于是采用了映射范围的方案。

2.脸部sdf阴影

脸部的sdf图阴影主要是通过灯光与脸部前向量的夹角变化,来控制sdf图通道在脸上的呈现。
整体思路原理与使用兰伯特光照模型相近(节点注释中写兰伯特制作阴影其实不太对,应该改成兰伯特制作阴影的原理),不过是将模型的法向数据,拆分成了前向量与sdf图数据,由此可以达到呈现手绘sdf图阴影的效果。
ps:同理,如果不使用sdf图阴影与前向量,直接在脸上进行法线方向的编辑,也可以获得人为的阴影效果

不过也正因为将模型法线数据换成了前向量与灯光夹角并映射sdf图,我们对于灯光数据也要需要进行z方向的矫正处理,我们使用灯光向量减去其于头上向量上的投影,由此我们去除了灯光向亮在z轴方向上数据的干扰。

与此同时,脸部的sdf图只有一个方向的阴影渐变。因此我们需要判断灯光在脸部左右方向,从而翻转uv使sdf图映正确。
这里我们使用矫正后的灯光向量与头部右方向向量点成后获得夹角cos值,由此获得了一个-1到1的变化区间。
这里我们使用运算的“符号”,来这个区间二值化,也就是大于0的部分和小于0的部分分别显示0或者1,接下来与uv的向量相乘设置通道。
这边发现0和1于uv映射反了,在x轴上乘上-1进行反转。
至此我们将矫正左右方向后的sdf图作为值连入映射范围,就可以获得正确的脸部过渡阴影了。

但此时还没结束,在脸部映射阴影时,我们使用的是与前方向向量的夹角,光线在正对的时候脸部全亮是没有错的,但光线在正背面时由于向量夹角同样是0,会导致脸部呈现与灯光在正面时相同。这里我们整体偏移一点sdf图通道阈值就可以避免这个状况。

3.叠加AO细节

接下来我们给简单的应变化通道,增加亮暗面的AO细节。
对于身体,就算在灯光亮面也是有许多闭塞不能被灯光点亮的,这里我们直接使用身体的AO通道与其相乘叠加即可。

而对于脸部,在全部处于阴影时,也不要出现一片死黑的通道。正如前面贴图讲解时说过,我们对于红通道和绿通道的贴图信息进行处理,便可分开眼睛,眉毛与口腔内部三个部分。
不过这里我们让眼睛和眉毛统一根据阴影变化,单独分出嘴巴作为常暗区域。
具体操作是将红通道用小于0.5来单独分割出脸部眼眉口以外的区域跟随sdf图变化而变化。
接下来将绿通道连到最小值上,让绿通道的眼和眉部分单独成为常亮不受sdf图变化的影响;同时剔除了嘴部,使其成为常暗,也不受sdf图变化影响。

至此我们就做好了全身的阴影设置。
二、制作指针并使用ramp图给阴影染色
ramp图就像一个取色器,将一个颜色信息限制在了一个像素内。
X轴方向用来设定同一个材质,在不同亮度的阴影通道上显示的颜色。
Y轴方向用来设定不同材质类型。

1.X轴方向的指针定位

X轴方向的指针制作十分方便,前面我们已经设置好了全身的阴影,并且获得了一个从0到1的通道,因此可以直接映射到x轴上,不过在此为了增加调控性,设置了一个数值作为偏移量,来调控阴影通道在x轴上的映射范围(同理可以使用颜色渐变钳制,这里同样为了能单独提取出一个变换值,使用了运算的方式)。
2.Y轴方向的指针定位
Y轴的信息我们需要对身体头发光照图的阿尔法通道进行反向解读,由于alpha通道本身是作为高光的金属度而设置的灰度值,因此面对其固定的灰度值我们需要再进行数学上的处理来变成我们Y轴上的编号值。

这其中的运算由贴图作者自己定义,我们后期解读需要对灰度值进行处理,来找出其中作者设置的规律。在这里我直接照搬了养乐多大佬的结论:首先所有数值加0.0425再除以0.0625,这样子我们获得了让首个灰度值变成一,同时整体为有小数点的2K+1的数列。接下来用四舍五入去掉小数点后的数据后减1除以2得到k。但此时只有偶数行的序号是正确的,奇数行后半的两个应与前半的两个互换位置,因此这里我们将序号限位八个之后让奇数行后移四个单位,让位置正确。
至此已经获得了身体8行的正确Y轴指针,接下来我们限定脸部与头发的特殊情况,因为脸部不用使用ramp图染色,而头发的ramp图只有一行。
3.整合身体与头发的Y轴指针

接下来为了让头发0和1的值能够控制指针的最大值为8或者1,身体的k我们先还原回2K+1,也就是1到17的奇数,而头发0或1的值我们再用映射范围和运算将其分别输出为1/16与1/2,接下来将其与身体2K+1的编号值相乘,便可正确获得头发与身体两张ramp图正确的y轴指针(这里主要是为了整合到一个节点组中,使用是否为头发输入0和1的值判断而做的操作,如果自己在设置时本来就分开制作,那也没必要多此一举了)。
最后我们使用灯光的z轴向量,加平滑后,来作为冷暖色调两张贴图的切换开关。
至此我们使用ramp图给阴影染色的操作也就做完了。
三、混合灯光的基础色

这个制作起来就很简单了,主要就是获取灯光的颜色和强度,并且与基础色使用正片叠底相混合就完事了。
这里需要提一嘴的是,灯光使用rgb来控制颜色。但是rgb信息是包含了灯光强度值的,也就是说同样红黄蓝的三个颜色,其明都值是不一样的,因此我们需要从rgb通道中矫正明度信息,这里我们直接加一个rgb转灰度的心理学公式:gray=r*0.299+g*0.587+b*0.114,这样子分出正确的色相饱和度信息来对原始的灯光进行矫正,之后就可以正确混合了。

四、高光设置
高光设置由这几步组成,布林冯制作最基础的高光模型,然后分别设置金属与非金属的高光,调用金属度参数,最后设置混合。
1.基础高光模型制作
布林冯的高光模型是在兰伯特的基础上,将光照向量替换为了光照向量与摄像机向量相加后规格化的值,由此视角的变化也能影响模型上的亮部位置。
这里我们将布林冯做一个0到1的钳制之后,用乘方来缩减一下其边缘,同时引入光照图南通道的高光遮罩,将布林冯高光效果限制在我们遮罩指定区域,这样基础高光就做完了。

2.金属与非金属反射的设置
接下来分别设置一下金属与非金属两种材质的反射效果。
非金属的反射率为0.04,因此我们将其与基础高光进行相乘。同时在高光遮罩上我们收缩一点基础高光的阈值,来防止其溢出我们图像设置的通道。
金属的反射率为一,同时会染上上物体本来的颜色,所以我们直接正片叠底设置遮罩之后不变就是乘1,然后用颜色的正片叠底混合它的基础色贴图,这样子金属的高光效果也做完了。
下一步是混合金属与非金属的效果,并通过光照图alpha通道灰度值设置的金属度信息,给不同的材质加上不同的高光。

3.调用金属度参数

在光照图alpha通道的灰度信息中,金属的灰度值正好设置在了0.52。所以这里我们整体减去0.52来提取遮罩,此时其他物体材质的灰度信息分别有大于和小于0.52的,这里我们取绝对值,并使用映射范围,这样子距离0.52灰度值越近的材质,其金属度也越高,同时在映射范围中调小了“从最大值”的数值,来增大金属与非金属之间变换的差别。
4.给各个材质上正确的高光
接下来就是将金属度作为系数,使用颜色混合来合并所有材质,此后还使用正片叠底引入一点灯光染色的变化,最后再使用正片叠底乘一个大于一的明度值来提亮整个高光的亮度。
然后再不忘去掉脸部的高光,在确定是脸部时用全黑遮罩替代所有高光。

至此,高光也设置完成。需要注意,高光的信息需要使用颜色混合的相加来添加到前面的图片信息上。
五、丝袜材质设置

嗨丝大家懂得都懂,总的来说还是加个菲涅尔效果,然后设置通道和过渡颜色,最后叠加在基础色上就完事了。
1.制作基础菲涅尔通道

所以这里我们拿法线点乘摄像机向量,得到物体法线与视线夹角,夹角越大时,呈现丝袜颜色,夹角越小时呈现丝袜中肉的颜色。我们钳制一下cosθ之后使用乘方来设置一下过渡位置,呈现在视觉上可以认为是“丝袜厚度”。
后面还加了一个颜色渐变,用来控制过度的柔和程度(其实前面乘方的也是能合并到这个颜色渐变之中的,不过会变得很难调整因此还是分了个节点单独调整)。
2.叠加细节纹理

然后接下来需要叠加上丝袜图蓝通道中的丝袜纹理了。丝袜图也分上下半身,所以加个上下半身体的组输入判定,然后一张纹理显然太大,我们加入个数值进行缩放,此后同样是使用乘方加颜色渐变的方案来设置纹理黑白边缘过渡。
3.设置材质渐变与遮罩
至此混合菲涅尔与丝袜纹理细节之后,我们再加上丝袜图中绿通道的纹理厚度细节,并使用颜色渐变来设置过度颜色,这里颜色渐变中白色的明度值我设置了大于1的值用于显露出肉色,同理可以分到后面使用颜色渐变正片叠底一个大于1的值来把它整体提亮。
丝袜图的红通道标明了在哪些部分使用丝袜叠加。同时要引入是否为脸部与是否为头发的判断信息来确定是否开启通道。最后使用颜色混合的遮罩来应用通道就OK啦。

六、眼睛高光的自发光效果
为什么要加这样的效果,我也不知道,因为它就是有个通道信息在这

这部分的节点构成也十分简单,就是调用脸部基础色贴图的alpha通道信息之后,再用RGB混合加个是否开启自发光的判断就好了。
后面输出使用相加的方式叠加在前面的渲染上。
七、鼻尖正面描边
就是实体化描边的时候正对模型会让模型显示不出鼻描边而失去“鼻子”,因此加了这一步。

1.设置显示范围
首先是设置正面的范围判定,使用相机向量点乘人物头的前方向,接下来使用乘方收缩一下它的判定范围。接下来与脸部蓝通道的鼻子尖描边遮罩相乘,应用一下在前面限定的角度才能出现遮罩内容通道。


2.柔化通道边缘并叠加颜色
接下来使用颜色渐变来设置一下遮罩的边缘平滑过渡,接下来再适应映射范围加入一个脸部判定,在脸部是一的时候通道才会启用。
这边使用颜色混合的遮罩与前面相混合,我们设置的通道连为系数,下面通道设置我们描边的颜色。

至此鼻尖正面描边也设置完成。
八、混合环境光影响的基础色贴图
这个在前面各部分展示的视频里漏掉了。主要作用是,让人物也会受到除了主灯光以外其他光源颜色的影响。
其中主要三部分组成分别是:设置基础色、获取环境光颜色、获取主灯光颜色。
1.获取在环境光影响下的贴图颜色

这里获取环境光颜色用的是漫射bsdf着色器,去除其粗糙度的散射,同时将法线细节去除。因为我们这边只需要获取其接收环境光染色之后的颜色数据,无需阴影之类的影响。
这里去除法线细节,我们直接使用法线输入缩放成零,归零就好。
2.设置初始颜色

对于初始颜色的设置,我们需要使用基础色贴图叠加之后的效果,来作为我们的初始颜色。
AO区域我们分脸部与身体头发两部分,分别提取通道然后进行压暗处理。脸部的AO同样是单独提取眼睛,眉毛,剔除了嘴巴的通道,方法与阴影里的操作相同。
两个AO 通道设置完后同样加入一个是否为脸部的判定,接下来就是说过的压暗处理,再和基础色混合就得到我们的初始颜色了。
3.获取只在灯光影响下的贴图颜色

环境光颜色是使用相加叠再我们之前贴图上的,因此这里需要减去原本灯光颜色,排除影响。
这里使用兰伯特除以π做灯光的遮罩。为什么不用漫射再shader to rgb是因为这里本就要剔除环境光只留灯光影响,所以直接获取向量夹角值更为方便。多了个除以π是对应上面漫射粗糙度0用的。有了通道乘上灯光颜色,再乘上前面初始颜色,就获得了初始颜色在灯光下所呈现的颜色值。
4.获取排除灯光后只受环境光影响的初始颜色

最后我们用上面漫射着色器用shader to rgb转的颜色信息,减去初始颜色在单单灯光照耀下的颜色信息,就获得了初始颜色在单单环境光照耀下的颜色信息。
到这我们再相加到前面的渲染上,就成功将环境光颜色加入了。
九、matcap边缘光

matcap边缘光是使用贴图制作的假灯光。
1.设置受视角影响的边缘光位置

首先拿到一张matcap贴图,将其映射的矢量与法线相连,这样我们就获得了单边的“边缘光”。这时我们将其法线的坐标系更改为我们相机的坐标系,于是“边缘光”便会与视线方向相关联。
2.调整边缘光呈现的细节效果

接下来加一个菲涅尔,将其限制在模型边缘,IOR值较难调整,于是在后面分了个相乘来控制“边缘光的厚度”。同时边缘光的在模型边缘的位置可以用前面可以用映射的z轴旋转来控制。
然后边缘光与模型的柔和度使用颜色渐变来设置,最后是使用混合rgb乘一个大于或小于1的值来提高或降低亮度。
至此,matcap边缘光也设置完成
十、大功告成!
最后,我们使用自发光转换为着色器,前面可以加个伽马调高点强度。后面与透明着色器混合上alpha为系数的混合着色器,整体的shader就做完了。


合成节点中眉毛半透头发的遮罩设置
这里我们要的效果是在脸处于镜头时,眉毛能半透过头发,在背面没有后脑勺的部分,能被头发挡住或者消失。

一、增加输出信息
此处我们需要增加几个aov通道,分别是头发,眉毛,还有人物面对相机夹角。


头发和眉毛分别好理解分别是两个材质的遮罩,我们分两个视图层,第二个眉毛视图层去掉头发在身体上加上阻隔(不进行渲染但提供遮挡),主体图层输出头发遮罩,眉毛图层输出眉毛遮罩。
二、制作交叠部分半透明的眉毛

人物面对相机夹角用于将半透效果限制在正面,原理与鼻尖正面描边一样,接下来有了通道明都随视角变化的值,我们直接设置给眉毛,然后设置给头发的时候需要反向一下,接下来混合眉毛与头发就能做到二者交叠部分的半透效果了。
三、设置无交叠部分正常显示的眉毛

最后我们将遮罩使用眉毛和头发相乘,分离出无交叠部分,将原主体图层使用用遮罩与刚刚制作的半透眉毛相叠加,这样在未交叠部分使用原图层,交叠部分则使用半透眉毛显示。
至此做完了眉毛半透头发的遮罩设置。

几何节点中制作动态描边的思路
最后讲讲描边实现逻辑,原理是使用实体化的逻辑沿着法相挤出模型再剔除背面制作。
一、平滑模型法线并在描边用完后还原

需要注意就是这个法线的方向,前面的焊接与加权法向修改器就是先焊接那些模型中重合的顶点再根据合并后的顶点对法向进行角度平滑,这样挤出的描边就没有断边了,不过合并之后,原本渲染的边缘光线也会被扭曲,所以在描边之后又用拆边变回来(不过拆边是根据角度限制简单做的,不能完全还原,试下来59°比较能还原)。
法线方向做完后我们就有了平滑的挤出描边了,接下来说说描边根据相机与模型距离变化的动态宽度。
二、几何节点制作可切换的动态描边

其实也很简单,几何节点中可以引入相机与网格物体的位置数据,接下来加个距离就能得出值,可以和法向相乘出动态的偏移量了。
不过此时描边宽度是0到无限大,所以加了个钳制设置了一下描边宽度的最大最小值。
然后加了个布尔值用来切换是手动输入的固定数值宽度还是根据距离的动态宽度,差不多就这么简单。由于描边宽度数值太小难调整,于是在输入宽度后加了个除以500让调整舒适一点。
至此,描边也讲完啦!

到这就是预设中所有节点思路的讲解
也感谢你看到这里,辛苦啦!
后面的DLC我简单讲讲两个没有被最终采用的边缘光方案
DLC:合成节点未使用的边缘光方案
合成里做原理差不多是在渲染完图像后在模型的区域内再画一层图叠上去当做边缘光
一、使用偏移屏幕像素制作的边缘光
这里用到两个shader里引用的aov通道,一个是屏幕法向(法线变换为摄像机左边后连出),一个是灯光颜色与强度信息。然后这里视图层属性中需要勾上z通道。

首先我们制作根据屏幕法向的x轴将像素往角色内偏移。先屏幕法向的数据连给分离xyz,只取x轴,用符号设置向左还是向右,接下来加个相乘设置宽度,然后除以我们的z通道深度设置近大远小的动态宽度,深度可以加一个数值来继续最大值的钳制。
至此我们连到后面合并xyz再连给置换把uv偏移变换为像素偏移,这里法线偏移方向反了是向外偏移,所以填入负的像素值加以矫正。
再用这偏移数据减去剔除过内部细节的z通道就得到物体边缘的一层“边缘光”了,不过此时需要限制一下边缘光生成的范围,屏幕外的部分不会在继续偏移判定,所以加了个最大最小值进行限制
这就是x轴像素偏移的制作,同理也能加上y轴的进一步丰富效果不再赘述。


后面就是给这个画出来的边缘光通道继续染色
我们加上灯光颜色与强度的输入继续混合,让他也能被灯光所影响,后面再设置了二次染色和光强控制。

最后加个抗锯齿让像素直接过渡稍微平滑一点再叠加上图像就大功告成了。

二、收缩alpha遮罩的边缘光

这是一拍脑袋想出来的,不用什么输入,勾上渲染胶片的透明,然后直接用膨胀腐蚀节点向内制作了一层边缘光通道。
后面同样可以加个灯光颜色强度数据染色什么的,不过由于缺点太明显就没用了。
因为此时图层的内容只能有人物,然后单纯向内腐蚀的通道看上去也太像后期合成了,单独一个个图层调整也过于麻烦,就没有继续深入了。

不过有腐蚀做边缘光当然也有膨胀做描边,相同逻辑。

到这可算全写完了,也谢谢屏幕前的你,只要脚步不停,学习的道路就好不断延伸。。。所以加油啦!

blender预设工程下载 度盘分享:https://pan.baidu.com/s/1T76VQa_RZHuq0ISJVtgqBA?pwd=2333 提取码:2333
模之屋分享:https://www.aplaybox.com/details/model/vCROO7vsUEbA

参考来源
[1]给你柠檬椰果养乐多你会跟我玩吗【Unity/虚幻5/Blender】3种引擎 崩坏: 星穹铁道风格 卡通渲染 从球谐光照到眉毛透过刘海 完整流程 BV1CN411C7qx 学习节点大体思路与贴图资源获取
[2]小儿今天吃啥啊 [录播] 从零开始渲染一个小草神 BV1nV4y1S7HR 部分节点思路参考
[3]葉丶樱 [Unity URP] 原神人物渲染还原简单流程 BV1sK411D7d5 部分思路参考
[4]投投投投手 【Blender】使用几何节点实现宽度更可控的描边 BV1PS4y1q7e6 用几何节点制作动态描边的点子
[5] Yisacode【blender三渲二】使用等高线贴图为面部卡通渲染提供平滑阴影(教程+节点分享)BV1764y1r7fV 脸部sdf图制作阴影原理
特别感谢:Merlin251003 大佬详细的答疑解惑,提供了关于边缘钳制与混合的节点优化思路与matcap边缘光思路
模型:神帝宇 版权所属miHoYo
模之屋配布地址:https://www.aplaybox.com/details/model/JeXKhs3UppyD