zoukankan      html  css  js  c++  java
  • PBR-实践(二)

    函数

    // Main Physically Based BRDF
    // Derived from Disney work and based on Torrance-Sparrow micro-facet model
    //
    //   BRDF = kD / pi + kS * (D * V * F) / 4
    //   I = BRDF * NdotL
    //
    // * NDF (depending on UNITY_BRDF_GGX):
    //  a) Normalized BlinnPhong
    //  b) GGX
    // * Smith for Visiblity term
    // * Schlick approximation for Fresnel
    half4 BRDF1_Unity_PBS (
    half3 diffColor, 
    half3 specColor, 
    half oneMinusReflectivity, 
    half smoothness,
    half3 normal, 
    half3 viewDir,
    UnityLight light, 
    UnityIndirect gi)
    
    

    D 分布函数


    在这里h表示用来与平面上微平面做比较用的中间向量,而a表示表面粗糙度。

    G 遮蔽函数

    F 涅菲尔:

    上面一种是Fresnel-Schlick近似法求得的常用版本,下面一种是虚幻引擎用的拟合版本,后面一种由于exp2函数的高效率算起来会快一些。

    其次,方程中的F0理论上是平面的基础反射率,但实际实现时需要考虑另一个情况,即菲涅尔方程只对非金属有效,在表面为金属时需要用到跟金属表面颜色相关的另一个方程。为了能够用同一个材质表示金属和非金属的不同属性,将材料的金属性参数整合到F0的计算中,实际F0计算的代码如下:

    float3 F0 = lerp(unity_ColorSpaceDielectricSpec.rgb, Albedo, _Metallic);

    漫反射 - 间接漫反射

    //漫反射系数 =  折射率(漫)* 非金属率
    float3 kd = (1 - F)*(1 - _Metallic);
    

    根据粗糙度对以上这张贴图进行三次线性采样,采样得到的颜色就是方程左边括号内的结果。

    Unity自然也给了这张图,就存储在unity_SpecCube0这个变量里。
    存储的是场景和天空盒的反射探针数据(还有一个变量叫unity_SpecCube1,存储的离物体最近的反射探针的数据)。

    有了图我们就开始采样,采样代码如下:

    float mip_roughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
    float3 reflectVec = reflect(-viewDir, i.normal);
    
    half mip = mip_roughness * UNITY_SPECCUBE_LOD_STEPS;
    half4 rgbm = UNITY_SAMPLE_TEXCUBE_LOD(unity_SpecCube0, reflectVec, mip); 
    
    float3 iblSpecular = DecodeHDR(rgbm, unity_SpecCube0_HDR);
    

    第二行好说,就是根据视线方向和法线求出个反射向量留着以后用。

    第三行是用从0到1之间的mip_roughness函数换算出用于实际采样的mip层级,UNITY_SPECCUBE_LOD_STEPS是一个定义在UnityStandardConfig.cginc文件中的常量,没改的话就是6。

    第四行的UNITY_SAMPLE_TEXCUBE_LOD是一个采样函数,粗糙度越高采样出的结果就越模糊。cubemap的采样使用三线性插值,即从两张最近的mipmap层级上各做一次二次线性插值再将结果插值。

    最后一行使用DecodeHDR将颜色从HDR编码下解码。可以看到采样出的rgbm是一个4通道的值,最后一个m存的是一个参数,解码时将前三个通道表示的颜色乘上xM^y,x和y都是由环境贴图定义的系数,存储在unity_SpecCube0_HDR这个结构中。

    于是我们得到了iblSpeclar,也就是上面间接高光的方程里左边括号的值。

  • 相关阅读:
    程序员的自我修养---------一个程序员应该懂点什么
    Duilib的圆环形 进度条 实现(网易云信版本)
    位定义,用于判断是否包含某属性
    Duilib的圆角矩形 抗锯齿优化 弥补RoundRect不足(网易云信borderround版本)
    exe、msi、dos、bat等静默运行,后台运行,不弹窗的解决办法
    删除桌面上有文件但提示项目不存在的方法
    MyBatis插入语句返回主键值
    django学习之Model(二)
    TCP三四次握手
    django学习之Model(一)
  • 原文地址:https://www.cnblogs.com/Jaysonhome/p/14109106.html
Copyright © 2011-2022 走看看