原神角色渲染01
三渲二相关
首先看了这个大佬的视频https://www.bilibili.com/video/BV1Je4y1K74i,对三渲二学习更多一些。我现在构思的角色部分最终作品,就是在一个很动漫风的场景里面放一个卡通渲染的人物。而且不是原神那种风格的卡通渲染,是更偏向日本动漫那种风格的,比如这个大佬的视频https://www.bilibili.com/video/BV1Fe4y1D7Pb/。
三渲二相比二维优势:细节可以更丰富,对于二维动画来说,更复杂的细节(比如各种衣服装饰,明暗阴影)对画师来说工作量是十分庞大的。例如宝石之国的头发,如果靠手绘在动画中体现这种效果,很难,但是用三渲二技术,只需要做出模型和材质。劣势:二维动画一些效果,比如一些夸张的形变(还是可以看上面那个muro大佬的视频)实现起来很难。

三渲二相比三维优势:其实那个大佬说得有点抽象,我感觉这就是风格上的一种选择的差距。三渲二属于NPR下的一个分支,你选择了这个风格,那这就是它的优势。非要说的话反而劣势还更多,三渲二流程会比纯三维复杂很多。
我想到原神的三渲二,它渲的是谁的二呢,就是米哈游自己画风的二,可以看原神里面角色邀约的照片那种画风。不过好像也不对,说不定是画风根据游戏来画而不是游戏根据画风来渲染。但总之原神现在已经有一套自己的渲染风格而且哪怕和星穹铁道和绝区零都不一样。
视频后面大佬从模型,动画,合成等等方面介绍了一些工业流程上三渲二会遇到的问题和解决方案,不过我就不做笔记了,要是以后碰到再回来看吧。
信息了解:效果很好的三渲二工具:https://www.bilibili.com/video/BV1AA411A7RR
价值数万元的三渲二技术,这应该算是行业顶级了吧:https://www.bilibili.com/video/BV1mm4y1w78s
SDF面部阴影
看了半天终于悟了。先抛开这个SDF,看一下这个阴影贴图。他其实是一个阈值图。用来判断面部哪些区域为阴影与非阴影。求出当前面部方向与光方向的夹角,比如36度,映射为0.2,那么用了这个贴图的脸上,贴图值小于0.2的地方就是阴影,大于0.2的地方就是非阴影。具体可以看这个:https://blog.csdn.net/qjh5606/article/details/119958786。说得非常清楚。

所以在应用阶段其实和SDF没什么关系,但是为什么叫基于SDF的面部阴影呢?(这里插一句,我发现我写笔记确实很容易写成科普文章一样的感觉,不过就这样吧,因为我总是怕以后的我看不懂,所以还是越详细越好)首先SDF是什么?Signed Distance Field有向距离场,有2D和3D,但概念都是共通的。说到场,一开始我还觉得很抽象,但是你回忆一下电场,磁场,可能就对场这个词有点理解了。
首先,SDF是用来反映一个物体的。它的定义,其实就是把空间中每一点,给它一个值,这个值等于该点到该物体的最短距离。在物体外的点是正值,在物体内的点是负值。那么,这个SDF图应该很好理解了,有一圈刚好到纯黑的地方即值为0的地方就是物体表面,外面扩散这些就是该点到物体表面的距离。

那么它有什么用呢?和上面那个阴影图有什么关系呢?可以观看Games202的P5(不给链接了)它其实就是可以给出移动的阴影贴图之间的插值。比如下面,A阴影到B阴影是一个移动的过程,我们想求A到B的一个中间时刻的阴影状态,怎么求?如果直接加起来平均,就得不到正确的结果,但是如果使用他们的SDF来加起来平均,就可以得到正确的插值。真是太妙了。

而SDF在这个贴图里的应用,就是用来生成上面那个图的。通过事先绘制不同过程的阴影图,然后用它们的SDF来融合成那一张图。这个方法确实妙啊。

贴图的原理理解了,那么就是使用了。
首先吐槽一下,之前我采样贴图不知道为什么这里一直报错,结果今天再打开,突然就没问题了。。。。明明啥也没改。

然后明明可以这样采样贴图,但是不懂为什么刚刚又一直报错。好无语。

总而言之,我们先对两种贴图采样,然后准备好后面要用的向量。面部朝向其实应该实时取读模型面部朝向,但是这个好像要通过脚本传递,所以现在我先直接设置为默认的z轴方向。阴影颜色我先暂时是直接把基础色变暗,后面再改。

首先我试了半天,发现网上其他大佬的代码都不太符合直觉,而且我也已经理解原理了,所以我按我自己的想法来搞吧。首先解释一下step函数。我看有大佬是吧lightmap放在a的位置,但是我感觉有点反直觉。

如果把lightmap放在a的位置,是以lightmap为阈值划分a,当然这确实就是最开始说的想法,但是这样划分出来的结果,黑色部分是光照区域,白色部分是阴影区域,有点怪,所以我反了过来。

然后我要解释一下,光方向向量其实不是从光源指出来而是指向光源的向量。lightmap图的范围是(0,1),如果光侧面90度打过来,那么光点积正面朝向,结果是0。然后以0为step的lightmap图是下面那样的,很显然不是我们要的。

我去,我之前就在纠结这个lightmap图的方向是什么情况,因为理论上我想的是只有正背面才是完全阴影,然后光源从侧后方转过来到侧面的时候伦勃朗光开始出现,然后一直到正面。但是按那些大佬的写法,都是光源从侧面照的时候才出现亮光,然后几乎到很正面了才出现伦勃朗光。这还是很反直觉,我甚至去搜了伦勃朗光的出现角度。
最终我找到了问题所在,其实一开始我是有想到的,但没想到会导致这种错误。首先刚开始我们用的是三维的光方向,而我们在想要它和正面方向的点乘结果的时候,想要的是光方向的二维方向和正面的点乘。但是我们没考虑到第三维的存在,所以即使在xz平面上光的投影已经和正面方向重合了,但是他们的点积还不是1,所以结果也是错误的。同时仍需要极度注意的一点是,投影之后如果不进行归一化,光向量的长度不对,也会导致结果出问题,所以投影后要进行归一化。


最后,根据光照贴图是从左侧还是右侧打过来,判断光照贴图的正反。


但是这里还有一个问题,也是我上面思考的那个角度问题。最终为了求证,我直接登录游戏观察。可以注意到,即使是背光,面部也是有一点亮的,然后经过测试,我得出结论,原神游戏里面的SDF映射,不是简单的直接从侧面90度开始,而是和我想的一样,从背面180度开始。我发现这一点的时候还是很开心的,因为我看的那些大佬的参考全都是从侧面90度开始,我经过自己的观察和思考,得出自己的结论,而不是生搬硬套,这是一种快乐的过程。

明白了正确的表现后,想要实现其实也很简单。光线向量从背面180度到正面180度,它与正面点积的值是(-1到1),想把它映射成(0到1),想到什么没有?很熟悉的映射了吧。

其实后面还有一种阴影mask图,不过目前我还暂时不懂怎么用,所以先不用先。调一下阴影颜色后,面部阴影部分到此告一段落。
