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

原神角色渲染02

2023-07-01 18:08 作者:绝剑结城  | 我要投稿

身体头发阴影

接下来开始搞身体头发的阴影,首先,所有ramp图的wrap mode改为clamp。防止像这个大佬一样出现黑线。

然后是ramp图采样,首先v方向我们都用半兰伯特采样。但是我们观察ramp图可以发现,这些ramp图的明暗交界线是位于很靠右的位置的。这里这个大佬是通过把Lambert01范围压缩,来解决这个问题(https://zhuanlan.zhihu.com/p/435005339)。

大佬做法

不过我是用另一个办法,直接把兰伯特乘以2,其实这样的方法和上面大佬的方法原理一样,只不过我的少了clamp这个步骤,在亮部实际上取到了1到2的值。不过因为我之前对ramp图的循环模式设置为了clamp钳制,所以没什么问题。

这里十分值得一提的是,https://www.bilibili.com/video/BV1h14y177bp,在这个视频里,用的半兰伯特是加了平方的,我试了之后确实加平方效果更好,暗部更暗亮部更亮了。(这其实就是power的作用)但是作者说,半兰伯特不加平方的,面试全不给过,把我吓到了。我特地去网上搜了一圈,绝大部分资料是直接*0.5+0.5,没有平方,如果搞这么严,感觉有点绝。

两种半兰伯特

然后是u方向的选择,这个我研究了半天,很多人是直接手动设置要取哪一行的ramp图的坐标。但是我看了上面那个大佬,他是直接把lightmap的a通道做v方向的采样。我便效仿了,但是效果很不对。而且我看到也有人说这样不对之后还是逐行取读。

后面我找到了原因,首先这个透明度的值是不能直接用作采样的v坐标的,否则就会像下图那样采样到不正确的边缘。而且透明度有三层值,对应的ramp也有三条(冷暖各三条),说明是对应得上的。头发那边也是同理。

唉,从写上面那一段话到写这一段话,哥们经历了诸多探索。起初我的想法是,对lightmap.a做一些运算,把它的位置映射到ramp图对应的v值上。如下图。但是做好之后,我发现我的效果不太对劲。

首先是颜色太淡了,我人力对比了下ramp图原图和引擎的效果,感觉这个颜色就是十分不对的,结果找了半天,把sRGB勾上后,就正常了些。但是很明显的又能发现,头发ramp图采样暗部竟然有个亮线。

我又研究了半天,发现ramp图的采样也不对劲。ramp图原图是只有十行的,理论上来说,只有v值在一个ramp的v坐标区间内,比如0.81-0.89,那么ramp颜色是不会改变的。但是我经过多次测试后发现,提莫的会改变,而且上面那个亮线就是在某一个值的时候出现的。然后我又经过多次尝试之后,发现把图像压缩关了就没有那个亮线了。

但但但但是,还是有问题,就是上面我说那个v值在区间内改变,ramp值也会变的问题。然后我突然发现,tnnd怎么这个图变成256*16了。在外面看明明高度是10的。

然后我去搜了一下,哦原来图片导入unity中尺寸会变成2的N次方,为的是规范化格式,不浪费空间。就好像磁盘那个簇,如果一个簇512k,那么放一个513k的文件就要两个簇,极大的浪费了空间,那么我们把513k压缩到512k,就规范了格式,不浪费空间了。大概就这个意思。然后这个ramp图被调整到16行后,进行了插值计算。计算方式如下图。所以最终,这个ramp图被模糊了。也就是我们从材质面板看到的样子。

https://blog.csdn.net/linxinfa/article/details/108827197

模糊的ramp

到这里所以谜团似乎解开了,我想着的是:好吧,你模糊就模糊吧,好在还是有一条能用的ramp。结果我又发现,这肚子的颜色不太对啊结果发现,lightmap的a通道里面,皮肤是1,然而ramp图里面,皮肤是在中间的。好吧,这下我那个方法别用了。

于是,我自己把ramp图改了过来,这下又用回我之前的办法了。

最终效果也还不错

然后,如何利用lightmap的g通道的阴影蒙版又是一个问题。g通道内,黑色是死阴影,永远是暗面,灰色是受光照影响的部分,白色是永远是亮面。我尝试了几个方法之后,最后还是使用了两层lerp,第一步,把亮面和暗面混合起来。其实在这些混合的时候会有一些问题,如果直接用lightmap.g混合,中间0.5部分的颜色就是亮暗混合,很怪异。所以我们要让lightmap.g变成非0即1。所以进行了乘2然后clmap的操作,把0.5和1全部划分为亮部。因为后续混合ramp阴影的时候可以再覆盖0.5部分,所以这样操作没问题。

然后第二层lerp,就是在前面的finalcol的基础上加上ramp阴影,也就是说,我需要把lightmap.g划分为两部分,0,1值是一部分,这部分颜色不用动,0.5值是一部分,这部分变为使用ramp阴影。所以我使用了-0.5取绝对值然后乘2的操作,成功把原来三个区域划分为01区域。然后再lerp就好了

效果

值得一提的是,我当时发现ramp阴影和死阴影颜色不一样,看上去有点突兀,然后我研究了半天怎么让它们融合,结果效果都不理想,最后去官方看了一眼,发现原来官方也没有解决这个问题。(要不是我迪希雅歪了,到现在还没有,至于找个参考都这么费劲吗QAQ)

那么总之,阴影的效果暂且就先这样了。其实后面有挺多步骤我都是自己弄明白原理后自己想的办法。因为我感觉网上这么多还原原神渲染的资料,各个都有些差别,等于说没个标准答案。既然明白了基本用法,那就按自己想法来吧,可能效果还差一些,看到最后再看吧,如果效果差很多的话,我再去寻找优化的资料。参考大佬的经验。

下面还差多少呢?描边,高光,边缘光。

法线

本来想着法线不多顺便搞的,结果也花了一番功夫,归根结底还是对urpshader不熟悉的缘故。之后好好学一下这边的基础吧。

其实也是和之前差不多,多加一个法线贴图的采样,然后输入结构加入切线信息,输出结构存在纹理里面(其实这个还有点模糊,我暂且理解为纹理)。

下面在顶点着色器里面获取切线和副切线。这里和CG差别好像挺大的,反正我看网上也有人用以前的方法,但是我用了之后,信息是错误的。后面终于找到一个简单省事的代码,而且获取来的信息是准确的,以后在URP里面就这样获取切线副切线了。

之后就是老三样,采样解码,构建TBN,转换。不过好像也有一个专门函数用来转换,但是既然这样行那就先这样吧。


原神角色渲染02的评论 (共 条)

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