文章目录
- 前言
- 一、回顾一下上一篇的结尾
- 在这里插入图片描述
- 二、我们来解析一下 UNITY_PBS_USE_BRDF1(高配)
- 1、迪士尼BRDF原则
- 2、迪士尼的漫反射函数
- 3、参数:perceptualRoughness(感性的粗糙度)
- 4、参数:halfDir (半角向量)
- 5、参数:nv(法线向量 点积 视线向量)
- 6、参数:nl、nh、lv、lh
前言
我们在这篇文章中,继续来继续解析BRDF中的高配置情况( UNITY_PBS_USE_BRDF1)下,迪士尼的漫反射计算
- Unity中Shader的BRDF解析(一)
一、回顾一下上一篇的结尾
- 在上篇文章中,我们解析到了BRDF的具体计算
二、我们来解析一下 UNITY_PBS_USE_BRDF1(高配)
1、迪士尼BRDF原则
我们在该函数的最后能找到与迪士尼BRDF原则对应的程序:
2、迪士尼的漫反射函数
// Specular term
// HACK: theoretically we should divide diffuseTerm by Pi and not multiply specularTerm!
// 理论上漫反射项中应该除以 PI,但是由于以下两个原因没有这样做
// BUT 1) that will make shader look significantly darker than Legacy ones
//原因一:这样会导致最终效果偏暗
// and 2) on engine side “Non-important” lights have to be divided by Pi too in cases when they are injected into ambient SH
//原因二:当引擎光照为 不重要光照 时,进行球谐光照计算,会再除以一个 PI。所以,在Unity计算迪士尼漫反射时,不除以PI
我们主要来看,他用到的参数是什么
3、参数:perceptualRoughness(感性的粗糙度)
//感性的粗糙的 = 1 - smoothness
float perceptualRoughness = SmoothnessToPerceptualRoughness (smoothness);
4、参数:halfDir (半角向量)
//半角向量(一般用 H 表示): H = 光线向量 + 视线向量(此处的 光线向量 和 视线向量 为单位向量,根据向量相加的四边形法则得出半角向量)
float3 halfDir = Unity_SafeNormalize1 (float3(light.dir) + viewDir);
5、参数:nv(法线向量 点积 视线向量)
//法线 与 视线的点积在可见像素上不应该出现负值,但是他有可能发生在 投影 与 法线 映射 时
//所以,可以通过某些方式来修正,但是会产生额外的指令运算
//替代方案采用abs的形式,同样可以工作只是正确性少一些
// NdotV should not be negative for visible pixels, but it can happen due to perspective projection and normal mapping
// In this case normal should be modified to become valid (i.e facing camera) and not cause weird artifacts.
// but this operation adds few ALU and users may not want it. Alternative is to simply take the abs of NdotV (less correct but works too).
// Following define allow to control this. Set it to 0 if ALU is critical on your platform.
// This correction is interesting for GGX with SmithJoint visibility function because artifacts are more visible in this case due to highlight edge of rough surface
// Edit: Disable this code by default for now as it is not compatible with two sided lighting used in SpeedTree.
#define UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV 0
#if UNITY_HANDLE_CORRECTLY_NEGATIVE_NDOTV
// The amount we shift the normal toward the view vector is defined by the dot product.
half shiftAmount = dot(normal, viewDir);
normal = shiftAmount < 0.0f ? normal + viewDir * (-shiftAmount + 1e-5f) : normal;
// A re-normalization should be applied here but as the shift is small we don't do it to save ALU.
//normal = normalize(normal);
float nv = saturate(dot(normal, viewDir)); // TODO: this saturate should no be necessary here
#else
half nv = abs(dot(normal, viewDir)); // This abs allow to limit artifact
#endif
6、参数:nl、nh、lv、lh
//其他向量之间的点积
float nl = saturate(dot(normal, light.dir));//法线 点积 光线
float nh = saturate(dot(normal, halfDir));//法线 点积 半角
half lv = saturate(dot(light.dir, viewDir));//光线 点积 视线
half lh = saturate(dot(light.dir, halfDir));//光线 点积 半角