|
点击下面链接,B站上传了实际Game窗口效果,视频有压缩,实际运行效果更好些~
系列一共5篇:
【01】Unity URP 卡通渲染 原神角色记录-Diffuse: Ramp + AO + Double Shadow
【02 | 当前浏览】Unity URP 卡通渲染 原神角色记录-Specular: Metal + Non-Metal
【03】Unity URP 卡通渲染 原神角色记录-Function-Based Light and Shadow: Emission + SDF脸部阴影
【04】Unity URP 卡通渲染 原神角色记录-Depth-Based Effect: 7Spaces + 屏幕空间等距深度边缘光Rim Light
【05】Unity URP 卡通渲染 原神角色记录-Double Pass Effect: Render Feature + 平滑法线Outline
1. 高光的种类
在上一篇中,我们记录了漫反射Diffuse相关的内容,这次来聊聊高光相关的东西。简单说,我们所关注的高光,可以分成2个大类:
- 基于视角的简单高亮,也就是说高亮部分随视角的变化而变化,用数学去表达这个视角变化就是 N dot V,与之对应高亮的变化,可以用贴图来控制。
需要注意的是,只有视角足够靠近法线时,才有高亮,这种类型的数学表达通常是:
step(1 - someLayerValue, NdotV) * someSpecularIntensity //靠近时才有高亮
- Blinn-Phong经验模型的高光, 这个高光主要是视角V和反射光R,之间的夹角,再加上expoential power形成的,但实际中,反射光线R不太好求,我们一般使用半程向量H来完成余弦夹角的求解,即N dot H。
一般来说,用N dot H来求高光的视角
半程向量H的求解
Blinn-Phong Specular
2. 原神里的高光分析
原神的高光大致可以分成2种,一个是金属类的高光Metal,一个是非金属类的高光Non-Metal。
首先我们来回顾一下,和高光相关的3个贴图:
金属图(可用于非金属高亮),随着视角变化,控制高光强弱,Metalmap.b(三通道值一样,用哪个都行)
Lightmap.r,区分金属和非金属高光
Lightmap.b,高光的强度
处理这3张贴图的基本思路,我们先用lightmap.r,来拆分出来金属和非金属,接着拆分非金属里面的层级。
金属部分,我分成了3个区间:
1.身体的项链
2.衣服的金属条
3. 头发的头饰
接下来,我们可以写一个函数,把lightmap.b里边定义的roughness转成高光指数exponent,然后使用Blinn-Phong Specular作为强度。这里使用金属贴图Metalmap.b,来控制视角变化带来的高光强弱变化,结合以上Blinn-Phong高光一起使用。
非金属部分,我也分成了3个区间:
1.衣服的花纹边
2. 衣服的图案
3.头发
这些部分,直接用lightmap.b, roughness作为强度,应该就可以。这里使用NdotV,来控制视角变化带来的高光强弱变化,结合以上lightmap.b高亮强度一起使用。
3. 高光的代码准备
前面提到Blinn-Phong高亮的指数p, 这个p怎么求呢?我使用了下面的等式进行转换。
roughness to shininess(power p)
//获得高光指数p
float RoughnessToSpecularExponent(float roughness){
return sqrt(2 / (roughness + 2));
}
//高光系数
float specularPow = pow(ndotH, RoughnessToSpecularExponent(lightMap.b));
//衣服材质,高光区间
half strokeVMask = step(1 - _StrokeRange, ndotV);
half patternVMask = step(1 - _PatternRange, ndotV);
//头部,高光区间
half hairMask = step(_HairRange, lightMap.r);
half hairViewMask = step(_HairViewSpecularThreshold, ndotV);
half hairSpecAreaMask = step(_HairSpecAreaBaseline, lightMap.b);
half hairAccGroveMask = step(_HairAccGroveBaseline, lightMap.r);4. 视角高亮的实际效果
视角高亮总的来说,当视角靠近的时候的,会发亮;视角远离的时候会变暗。注意看视频里肩部花纹随视角的明暗变化。游戏里这个变化,请自行观察,很细微,抠出来很麻烦,就不弄了。(视频在PC端应该可以看,APP好像不展示)
注意观察肩部花纹的明暗变化
https://www.zhihu.com/video/1541402999582167040
额外需要说明的是,头发的高光处理,有些特殊,我们平视时是看不到高光的,只有俯视角,且非阴影中,才能看到。
平视无高光
俯视非阴影,高光
俯视阴影,无高光
接下来看看头发还原的效果:先阴影,后无阴影 (视频在PC端应该可以看,APP好像不展示)
阴影中,平视,俯视都无高光
https://www.zhihu.com/video/1541417589461168128
为了接近游戏效果,高亮的强度,我调的比较低,游戏里也比较低。(视频在PC端应该可以看,APP好像不展示)
非阴影,平视无高光,俯视有高光
https://www.zhihu.com/video/1541418135961296897
额外说明的是,脸部无高光。
5. 视角金属高光的实际效果
游戏里的效果,可以自行对比,我就单独扣了,比较麻烦。注意看脖子,蝴蝶项链的高光变化。(视频在PC端应该可以看,APP好像不展示)
注意看蝴蝶项链的高光变化
https://www.zhihu.com/video/1541413267272036353
6. 高光部分的计算代码
//高光specular: Metal+Non-metal
//身体ILM的R通道,视角高亮
half strokeMask = step(0.001, lightMap.r) - step(_StrokeRange, lightMap.r);
half3 strokeSpecular = lightMap.b * strokeVMask * strokeMask;
half patternMask = step(_StrokeRange, lightMap.r) - step(_PatternRange, lightMap.r);
half3 patternSpecular = lightMap.b * patternVMask * patternMask;
// 金属高光, Blinn-Phong
half metalMask = step(_PatternRange, lightMap.r);
half3 metalSpecular = 2 * metalMap.b * specularPow * metalMask;
//最终高光
specular = (strokeSpecular + patternSpecular + metalSpecular) * baseColor;
//高光部分: 头发顶视角高亮
float shadowUpperBound = step(ndotLRaw, _HairShadowSmooth) ;
float isHair = step(0.11, lightMap.r) - step(0.9, lightMap.r);
float litHair = step(0.0, ndotLRaw);
specular = _HairViewSpecularIntensity * metalMap.b * hairViewMask * hairMask;
specular *= hairSpecAreaMask * baseColor * litHair;
specular += metalMap.b * ndotV * hairAccGroveMask * baseColor;
specular += hairAccGroveMask * baseColor;7. 整体效果
三种不同的高光效果:
1.衣服图案的高亮 2. 头发的特定视角高亮 3. 蝴蝶项链的金属高光 (视频在PC端应该可以看,APP好像不展示)
高亮展示,看脖子上的项链
https://www.zhihu.com/video/1541539737130545152
下次预告:【03】Unity URP 卡通渲染 原神角色记录-Function-Based Light and Shadow: Emission + SDF脸部阴影。
下一篇,会讲一下有向距离场,Signed Distance Field,脸部阴影和自发光【硬核警告】
8. 参考链接
感谢各位知乎大佬的分享,列表如下:
世界:【Unity技术美术】 原神Shader渲染还原解析
T.yz:[卡通渲染]二、原神角色渲染还原 - Specular-2
雪羽:原神角色渲染Shader分析还原
清清:从仿原神角色渲染到MMD制作(小记)
2173:【03】从零开始的卡通渲染-着色篇2 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
×
|