09_添加PBR高光

添加PBR高光

贴图信息

金属Mask和高光遮罩在下方贴图中 金属图,G通道 注意这里的金属度图并非是非0和1,大概是64/255这个样子,应该是想表达带漆面的金属效果一类 高光Mask,B通道 光滑度信息在下方的贴图的G通道中 Smoothnesss,G通道

PBR金属高光和漫反射划分

获取对应的金属信息和高光遮罩 pbrDiffuseColor进行金属与非金属的划分,非金属的最大漫反射比例是0.96,0.96 x GammColor就是非金属的漫反射,而金属部分是只有镜面反射的没有漫反射,所以漫反射为0。pbrSpecularColor镜面反射,非金属的镜面反射比例就是1-0.96,因为非金属的镜面反射颜色不受本身颜色影响仅受材料的反射率影响,所以这里给上0.04固定颜色。而金属部分,金属的镜面反射是受颜色影响的所以反射原本的颜色

高光的一般计算方法

高光的常规计算方式是Phong和BlinnPhong

Phong BRDF

公式: K是指SpecularIntensity高光强度,R是灯光向量(-L)的反射向量,V是观察向量,这里需要指明一点这里参加计算的灯光向量是物体指向灯光的向量,也就是-L 常规计算代码:

1
2
3
float3 reflect_dir = reflect(-light_dir, normal_dir); //获取灯光反射向量
float RdotV = dot(reflect_dir, view_dir);//数值范围在-1~1所以需要限制
float3 specular = pow(max(0.0, RdotV), _Shininess) * _SpecularIntensity;

Blinn-Phong BRDF

K是指SpecularIntensity高光强度,H是半角向量是L和V之间的向量,V是观察向量,它不需要计算反射所以性能被Phong更好

1
2
half3 half_dir = normalize(light_dir + view_dir);//获得灯光与视角中间的半角向量
half NdotH = dot(normal_dir, half_dir);///数值范围在-1~1所以需要限制

PBR中 GGX BRDF高光计算

相关资料 https://community.arm.com/cfs-file/__key/communityserver-blogs-components-weblogfiles/00-00-00-20-66/siggraph2015_2D00_mmg_2D00_renaldas_2D00_notes.pdf 公式: 公式看起来太复杂了,说人话就是D是像NoH粗糙度影响然后乘上SpecularMask得到高光形状(这部分可以由我们自己调整),F是菲涅尔系数,G是物体表面的遮蔽。F和G是固定公式 GGX高光计算 不乘上面末尾的NoL就是BRDF计算的结果

Unity中URP的BRDF.hlsl文件中也有介绍,但这里是使用的优化版的减少计算量 简化方式简单来说就是将F(菲涅尔项)与G(几何遮蔽项)变成了V点乘F 将含G的这部分式子替换成V了 不需要纠结怎么简化的,反正最后优化成近似的结果,V乘F公式就变成了下面这个,L是光向量,H是半角向量

1
V * F = 1.0 / ( LoH^2 * (roughness + 0.5) )

计算公式就变成了

1
2
3
BRDFspec = (D * V * F) / 4.0

Finalspec = (D * V * F) / 4.0 * NoL

UE中对应也有节点GGXSpecular 原理和上面差不多

高光参数新增

这里对应是球形法线开关,球形高光范围缩放 卡通高光的软硬参数,高光强度 额外的高光强度参数针对物体大小调整的参数 高光染色参数

饰品类PBR卡通高光计算

计算半角向量

计算LoH

根据公式需要,这里计算LoH和LoH的平方参数,对LoH也进行重映射,因为希望保持高光一直在最暗的时候也存在

计算NoL

根据公式需要,最后需要乘上NoL,所以这里计算NoL并重映射提高暗处的亮度

计算NoH

根据公式,计算高光项NoH并进行重映射

头发和其余部分法线区分计算

头发部分使用球形法线,其余部分使用贴图法线,使用顶点位置减去球心HeadCenter位置就可以得到球状法线,使用HeadSphereRang进行控制范围计算出球形法线的一个遮罩,使用遮罩对贴图法线和球形法线混合输出 判断是否HeadSphereRang有效,无效的话说明不需要球状法线就直接输出贴图法线

头发和其余部分衰减区分计算

当HeadSphereRang有效,就使用混合过的ShapeNormal进行计算NoL衰减。反之使用贴图法线计算的衰减 上面开方和重映射都是为了调整曲线,增加高光的有效范围,开放可以使高光的衰减变平缓

最终计算

1
2
V * F = 1.0 / ( LoH^2 * (roughness + 0.5) )
Finalspec = (D * V * F) / 4.0 * NoL

回忆公式,这里VxF项中Roughness直接给1,然后直接使用公式计算 当前的高光,我调过参数所以会亮一点

衣服类的PBR高光计算

这里直接照抄GGX就行

1
2
3
 brdfData.normalizationTerm = (roughness + 0.5) * 4.0
 
 Final BRDFspec = roughness^2 / ( NoH^2 * (roughness^2 - 1) + 1 )^2 * (LoH^2 * (roughness + 0.5) * 4.0)

获取光滑度信息

对于写实类高光,需要粗糙度进行计算,这里是光滑度,先提取出来

粗糙度相关参数计算

这里计算Roughness的相关参数。光滑度转粗糙度是1-Smoothness在平方,1-Smoothness是感知粗糙度,真正参与计算的是它的平方,也就是粗糙度

计算GGX

根据公式可以计算出GGX高光 这里也可以直接使用GGX节点,计算出来实际上差不多

GGX混合参数

计算完GGX后减去光滑度,降低光滑表面的高光强度,然后乘上光照衰减,钳制到0~1。除以粗糙度这里在提高粗糙表面的高光强度。最后使用两个参数控制高光强度然后乘上高光遮罩后就得到了高光,末尾的乘法相当于提高了高光的硬度

两种高光混合

使用是否开启了球形法线为判断来混合,后面使用SpecularIntensity进行整体的强度控制,然后染色,因为高光在面部眼睛是没有的,所以使用身体开关判断 最终混合输出 高光和漫反射分别计算在相加即可

当前效果

记得开启饰品和头发的球形高光开关,这里我感觉亮度太低了所以给了0.2强度,默认是0.1


Enjoy Reading This Article?

Here are some more articles you might like to read next:

  • URP - RendererFeature :ScreenSpaceOutline
  • 平滑法线处理 - 八面体映射
  • Lv.3 Unity主线:一个简单的PBRShader
  • 理论支线:直接光漫反射与GGX高光的混合问题
  • 理论支线:PBR - 基于图像的照明( image based lighting-IBL)
  • # #