|
都是市面上常见的,没啥新鲜东西,是我自己的学习笔记。希望大家多多指正。
一、描边
①视线法线夹角
计算视线与法线的夹角的余弦值,太大了就是边缘。可以通过阈值或者(一维)纹理采样的方法来控制描边宽度,但是作用有限。因为在box之类的几何体上,视线法线夹角大小不一,同一个物体上可能宽度会变化很大,描边宽度不好控制。
优点:简单,就在原来的pass里加几行代码就搞定,也不用渲染纹理什么的。
缺点:描边宽度受限于模型。可能有些模型用不了这种方法。
②后处理边缘检测
在后处理中,在深度缓冲(或把法线写进一张渲染纹理)上用Sobel算子进行边缘检测。但是Sobel算子等滤波模板会大量采样,而且不谈采样它们本身的计算量也不小。所以可以只让需要的物体描边,让这些物体渲两个pass,第二个pass进行边缘检测。但是这样渲染负担会随场景复杂度提升而提升,这时候另一个做法是让想描边的几个物体写进stencil buffer,然后后处理的时候在通过模板测试的地方进行边缘检测,虽然这样就不能每个物体单独制定描边颜色了。
优点:开销固定,都是一整个屏幕。镂空的地方也可以描边,因为镂空的地方虽然在mesh上是实心的,但是它们不会写入深度缓冲。
缺点:描边宽度仍然不好控制。而且我寻思在移动平台上用后处理本身就很蛋疼了,就算是只用深度缓冲(不把法线写进一张渲染纹理),滤波模板带来的大量采样也会给移动设备的带宽造成很大的压力。只是个人猜想
③扩大背面
渲两个pass,后一个pass就正常地渲正面,前一个pass用黑色或别的深色渲背面,但是要在vertex shader里把背面撑大一点(沿法线扩张),这样边缘上会多出来一圈黑的。或者不撑大,让背面往前挪一点,边缘处会穿插出来,也看来像描边,只不过是在轮廓以内描的(撑大的方案是在轮廓以外描的)。但是往前挪的话,描边宽度受限于三角面的角度。还可以根据远近实时调整描边的宽度,也就是根据z值调整顶点扩张的距离。
优点:简单,性能友好。可以逐顶点地控制描边宽度(顶点色里存储该处的扩张距离)。
缺点:对于有内凹的模型,背面面片会遮挡正面面片。
我选③。
二、着色
漫反射方案选择:
①Tone Based Shading(渐变,类似半兰伯特光照)
计算光线和法线的余弦值,以前是会把负的也就是背光出的余弦值直接截到0,但是现在还是让它参与计算。最背光的地方(dot=-1)指定一个冷色,最向光(dot=1)的地方指定一个暖色。然后用余弦值在两个颜色之间差值。
优点:大概是不用采样纹理,漫反射颜色直接是计算出来的。不采样纹理对移动平台的带宽貌似就友好一点
缺点:太美式了(其实也谈不上缺点,风格差异而已,只是这篇的主题是日本二次元),而且留给艺术家控制的余地不大。
②Cel Shading(突变,纯色色块)
风格上来说就是明暗之间有一个很楞的交界线,是明暗是突变过去的。实现上最好是不要粗暴地把光线和法线的余弦值用阈值砍一刀,那样锯齿比较难搞,手机又不能开抗锯齿。要用smoothstep之类的东西抗锯齿又会有额外的性能消耗。而且就明暗两个阶梯还好,多了怎么办,用一串if吗,shader性能会爆的. 所以所以最好是用一个纹理来控制,用法线-光的余弦值去采样这个查找表,这样的话方便艺术家控制,想稍微要一点柔和的渐变的话在纹理上涂抹模糊一下就可以了,而且想要好几个阶梯的明暗变化也不成问题。
优点:很好很日本()。留给艺术家的发挥空间大。既然都用纹理了,纹理坐标多出来的一个维度岂不是浪费了,还不如一个维度是光线-法线夹角,另一个维度是视线-法线夹角,来做个rim light(边缘光),不过这样艺术家就有点辛苦了. 我倒是在想有没有什么机制或者插件能够把艺术家画的纹理实时体现(渲染)出来,每画一笔就能看到效果(扯远了
缺点:大概是又多了一张贴图要采样吧。这种彩色的贴图还不能跟别人合并通道(?),移动平台带宽悲鸣(心痛 所以整个16×16的贴图就可以了,大了也没意义。
我选②(
More about 日本二次元:
既然都二次元了我们就快乐地二次元到底叭,关于这个日本二次元渲染再说几句。漫反射这里还可以加上次表面散射的贴图和AO,没什么高大上的,无非是给艺术家和带宽增加一点痛苦而已,不想给带宽增加痛苦就合并颜色通道叭。
光一个漫反射肯定还不够。还有很多与视角相关的成分,rim light刚才在②的优点里已经提到过了。高光的话甚至可以继续用glossness和specular的贴图,这个意思有点类似于PBR流程里的光泽度和金属度贴图(?)。当然还是可以合并通道的啦。
三、头发的高光
可以把头发在微观层面上抽象成直径小于一个像素的圆柱体:
高光计算中,half-way向量与法线越接近,高光就越强。如果是普通的平面,法线方向是固定的,所以如果half-way向量和法线偏很多,高光就较弱。但是既然头发是圆柱体,而且这个圆柱体直径小于一个像素,那么这一个像素里可以认为这个表面有很多个朝向,哪个朝向能更好地把光线反射到我们眼睛里,哪个朝向的影响就越大。也就是说,可以认为这里的法线是能够自动适应half-way向量、自动旋转到与光线和视线共面。
接下来我们来看看这个高光项具体怎么计算。这里的法线是旋转的,不是固定值,所以就不能像传统的Blinn模型那样拿法线和half-way向量做点积。但是可以观察到,切线、half-way向量、法线在此时是共面的,且切线和法线成直角,所以想要求法线和half-way向量的点积(余弦值),直接求切线和法线的正弦值就可以了,切线是已知的是固定的。
从宏观上来看,这样计算会让高光沿着发丝的垂直方向伸展。
但是这还不够。实际的头发高光在发丝的方向是有锯齿状的扰动的。这是因为不同的头发与头发之间的切线方向是不同的,发丝的走向方向不一样,有点往头里钻,有的往头外边冒,他们不是一路都肩并肩顺顺地长下来的,这样高光就看起来“上下颤动”:
为了颤动。让切线往法线(指mesh的法线)方向偏移就可以了,可以用一张噪声控制偏移的方向和程度:
仔细观察会发现,上上图里有两条光带,一条强烈的白色的高光,和一条较弱的有颜色的高光(此处暂且称为“次高光”)。次高光的特点是带颜色,而且更向发根偏移,强度较弱。那么我们计算两个不同的高光然后叠加,其中次高光用前一段提到的方法偏移,只不过加一个向发根偏移的基础偏移量罢了。
至于怎么把这种方法转换成日本二次元的,二次元的特点是明暗是突变的。那么还是用梯度漫反射的老方法(Cel Shading)来处理高光,用高光项采样一个Ramp贴图即可。
四、边缘光
也就是前面讲到的rim light。Cel shading的Ramp贴图里,纹理坐标多出来的一个维度岂不是浪费了,还不如一个维度是光线-法线夹角,另一个维度是视线-法线夹角,来做个rim light(边缘光)。
五、杜绝脸上的硬光照
看日本二次元的人物画比较多的盆友会注意到,脸部的光一般都显得比较“平”,也就是和美国西部漫画的硬汉的阴阳脸形象相差较大:
其实就是说光源的方向不能是垂直于视线方向的,不然就会把明暗部之间的强烈对比呈现出来,那样不日本。一个解决办法是专门为脸部补一个光,光源是从观察者这边射出去的。
造成阴阳脸的除了脸的表面和光的朝向,还有各种阴影。我们常说纸片人,但是脸的实际模型肯定不可能是一个片,有几何的起伏势必会造成阴影。所以可以加一个阴影mask,由美术来指定哪里可以接受阴影,哪里不可以。
还有一个是,我们形容某个人好看的时候,会说他好像在发光。其实他可能真的在发光,这也就是自发光,或说emission,数学上只是简单地把画好的albedo色加上明暗,而不是乘上明暗(可能这个描述不太准确)。也就是说就算是在暗处也能保持一定的明度,不会有死黑。
杜绝阴阳脸,除了不能有特别暗的地方(背面暗部、阴影),还不能有特别亮的地方(边缘光、高光)。
上一节讲到边缘光,边缘光在下眼睑/颧骨上方等脸上的地方最好就是不要出现了。这个同样可以加一个mask控制。
高光也是一样,脸上就免了,况且显得油多
总结一下:
不要太暗:①面部补光;②阴影mask; ③自发光。
不要太亮:①边缘光mask;②不要高光。
六、参考
都是各位大佬智慧的结晶:
3D日式卡通人物渲染的经验分享
https://gameinstitute.qq.com/community/detail/100050
卡通渲染及其相关技术
https://zhuanlan.zhihu.com/p/26409746
简易二次元角色渲染风格(一)
http://walkingfat.com/
作者:Marcus Xie
专栏地址:https://zhuanlan.zhihu.com/p/132388004
|
|