LearnOpenGL.PBR.理论

判断一种PBR光照模型是否是基于物理的,必须满足以下三个条件:
1)基于微平面(Microfacet)的表面模型。Be based on the microfacet surface model.
(2)能量守恒。Be energy conserving.
(3)应用基于物理的BRDF。Use a physically based BRDF.
 
原理一 微平面模型 The microfacet model
    描述:任何表面(surface)在微观尺度下都可以描述为由一系列微小的平面(microfacet)组成,并且我们假设这些微平面都是绝对光滑的镜面,能够完美反射光线。
    粗糙度(roughness)参数:没有任何表面是绝对光滑的,但微表面已经小到没法在像素尺度上区分,因此我们在像素的尺度上引入了粗糙度的概念(rougness),用来表示与半角向量h大致对齐的microfacet的占比。 roughness是一个统计学上的近似。
    散射(scatter):材质表面越粗糙,说明其微表面的方向越不一致,那其就会将光线反射到各个不同的方向,这就是散射。越光滑的表面,其微表面反射方向越一致,那么材质表面的高光区域就越集中越锐利。
    半角向量h(halfway vector):光照向量l和视角向量v的中间值。
    越多的微表面和半角向量对齐,那这个点的高光反射就越强越锐利。 
 
原理二 能量守恒 Energy conservation
    描述:出射光的能量不能超过入射光的能量(自发光除外)。所以光滑的表面反射光区域小强度高,粗糙的表面反射光区域大(分散)但更朦胧。
    为了能量守恒,我们需要将光区分为diffuse和specular,分开处理,因为这两者是互斥的,能量来源都是入射光。
    reflection part 反射部分:specular lighting
    refraction part 折射部分:diffuse lighting,折射部分的光线会进入物体内部继续传播。
    物质可以看成是由无数个很小的particles组成(微观),光线在碰到这些particle时,一部分能量被吸收转化为热能(能量损失),一部分被反射后继续传播(方向随机的散射),直到能量损失耗尽或离开物体表面继续传播。而逃出物质表面继续传播的光线就成为了surface的diffuse color。 (light和particle碰撞时会有能量损耗)。 
  
  PBR对这个模型做了一个简化:假设所有的折射光线要么被完全吸收,要么只会从一个很小的区域(同一个像素)散射出物体表面,而忽略那些在物体内部传播然后从远离入射点的地方散射出去的光线。
    次表面散射(SubSurface Scattering):SSS技术基于PBR并考虑了较远距离散射的光线能量,显著提升了表现效果,但也会带来一些性能损耗。SSS材质一般用在皮肤、透光的大理石、蜡状物的渲染模拟上。
    金属材质(metallic):所有的refraction light都被直接吸收(转化为热能),而不会散射。所以金属材质只有reflection light,没有diffuse color。由于金属材质的特殊性,在PBR的管线中,对于metallic和dielectrics(非金属材质,电介质,绝缘体)的处理方式是不一样的。
    能量守恒的表述:reflection和refraction是互斥的,所以我们先计算reflectec/specular的光照比例,然后剩下的就是refracted/diffuse的光照部分了。这样能够保证反射光和折射光都不可能超过1。 
    float kS = calculateSpecularComponent(...); // reflection/specular fraction
    float kD = 1.0 - kS;                        // refraction/diffuse  fraction
反射率方程 The reflectance equation
    渲染方程(Render Equation):用来模拟光的视觉效果最好的模型。
    反射率方程:物理渲染所使用的特定的渲染方程: 
    辐射度量学(Radiometry):是一种用来度量电磁场辐射的手段。
    Radiation:辐射
    Radiance:辐射率,用L表示,和反射率方程有关的一种辐射度量,用来度量某一方向上发射来的光线的大小或强度。
    还有很多辐射度量(radiometric quantities)用来测量曲面在某个方向上的光,我们只关注radiance。
    辐射通量(Radiant flux):Φ,感觉叫辐射流量更好理解,表示一个光源所输出的能量,单位瓦特(Watts)。光是有多种不同波长的能量组合而成。
        函数表示:光源所包含的各种波长的一个函数。(可见光波长范围390nm-700nm)。
        简化表示:三原色RGB编码(光色)。这个编码有信息损失,但对于视觉上的影响可忽略不计。
    立体角(Solid Angle):ω,投射到单位球体上的一个截面的大小或面积。
    辐射强度(Radiant Intensity):I,单位球面上,一个光源向单位立体角所投射的辐射通量。
          辐射强度=辐射通量/立体角:
        辐射率(radiance):辐射强度Φ的光源在单位面积A、单位立体角w上辐射出的总能量: (辐射率方程The radiance euqation)
其中:float cosTheta = dot(lightDir, N);  
        辐射率(Radiance)是辐射度两学上表示一个区域平面上光线总量的物理量。
        光束对单个像素的作用:立体角w和面积A看做无限小,实际上将立体角w转变为方向向量w,面积A转为点p。
     辐照度(Irradiance):所有投射到点p上的光线的总和。
        积分(Integral)的值等于一个函数曲线的面积。
        黎曼和(Riemann sum):在半球领域Ω中按一定步长将反射率方程分散求解,然后按照步长将结果平均化。 
        半球领域(Hemisphere):反射率方程概括了半球领域Ω内,照射到点p上的所有入射方向wi上的光线的辐射率,并受到fr的约束,然后返回观察方向上反射光的Lo。
        IBL:利用一个环境贴图来测算所有入射方向上的辐射率。 
 
原理三 BRDF Bidirectional Reflective Distribution Function 双向反射分布函数
    作用:基于表面材质属性来对入射辐射率进行缩放或者加权。依据微平面理论来近似求得材质的反射与折射属性。
    输入:入射方向wi,出射方向wo,平面发现n,微平面粗糙度α。
    输出:近似的求出每束光线对一个给定了材质属性的平面上最终反射出来的光线所作出的贡献度。
    Blinn-Phong光照模型:采用wi和wo作为参数,可被认为是一个简化的BRDF,但没有遵守能量守恒。
    Cook-Torrance BRDF模型:主流BRDF,兼有漫反射和镜面反射 
    公式解析:
        kd:入射光线中被折射部分的能量所占的比率
        ks:被反射部分的比率
        漫反射部分:Lambertian漫反射,据Epic的结论,Lambertian漫反射模型已足够用: 
        镜面反射部分:
        D:Normal Distribution Funcion,正态分布函数/法线分布函数,粗糙度相关
            微表面中与半角向量对齐的微平面的比例。
        F:Fresnel Rquation,菲涅尔方程,金属度相关(通过金属度计算反射率)
            在一个反射平面上,当入射角度越“倾斜”,反射的光线越多,折射的光线越少;入射角度越“直”折射越多,反射越少。该参数描述不同角度下的光线反射比率。
        G:Geometry Function,几何函数,可见性函数,粗糙度相关
            描述了光线从入射到出射过程中,有多少比例被微平面自身的凹凸不平遮挡住了,也就是自阴影属性。根据入射和出射方向,计算出不被自身遮挡的光线的比例。
     Epic Games的Unreal Engine 4采用的套餐:
        D:Trowbridge-Reitz GGX 
    float DistributionGGX(vec3 N, vec3 H, float a)
    {
        float a2     = a*a;
        float NdotH  = max(dot(N, H), 0.0);
        float NdotH2 = NdotH*NdotH;
        
        float nom    = a2;
        float denom  = (NdotH2 * (a2 - 1.0) + 1.0);
        denom        = PI * denom * denom;
        
        return nom / denom;
    }

        F:Fresnel-Schlick近似(Fresnel-Schlick Approximation)
            Fresnel equation是一个相当复杂的公式,不过我们可以使用Fresnel-Schlick公式来近似: 
            F0表示平面的基础反射率(Base Reflectivity),可以使用IOR(Indices of Refraction,折射指数)计算得出。
            菲涅尔现象:理论上,任何表面从完美的90度(垂直于法线)看,都会完全地反射光线(很强)。越是从掠角上看菲涅尔现象就越是明显,反光就越强。
            grazing andle:掠角。
            金属材质的特殊性:对于导体,使用IOR计算出的F0并不准确。
            材质基础反射率查询网站: https://refractiveindex.info/
            电介质材质:基础反射率不会高于0.17。
            导体材质(金属):基础反射率大多在0.5-1.0之间,而且一般会带有颜色,所以 F0需要用RGB三原色表示
            由于金属与非金属的差异,所以引入了 金属工作流(metallic workflow),材质引入金属度(metalness)属性,用来表示一个材质是金属还是非金属。 
    vec3 F0 = vec3(0.04);
    F0      = mix(F0, surfaceColor.rgb, metalness);

            非金属:取0.04,多数情况下已经够用,物理可信。
            金属:取颜色纹理作为基础反射率。(金属会吸收所有折射光线,而没有漫反射)。 
    vec3 fresnelSchlick(float cosTheta, vec3 F0)
    {
        return F0 + (1.0 - F0) * pow(1.0 - cosTheta, 5.0);
    }

           cosTheta:法线n与观察方向v的点乘结果。
        G:Smith's Schlick-GGX
            Schlick-GGX:GGX与Schlick-Beckmann近似的结合体
            参数k是粗糙度α的转化,在计算直接光照和IBL光照时算法不同:
            为了有效地模拟几何遮挡,我们需要同时考虑:
                geometry obstruction:几何遮蔽,视线方向遮挡
                geometry shadowing:几何阴影,光线照射方向遮挡
            使用史密斯法(Smith's method): 
            取值范围0.0-1.0,1.0表示没有微平面阴影,0.0表示完全遮蔽。
    float GeometrySchlickGGX(float NdotV, float k)
    {
        float nom   = NdotV;
        float denom = NdotV * (1.0 - k) + k;

        return nom / denom;
    }

    float GeometrySmith(vec3 N, vec3 V, vec3 L, float k)
    {
        float NdotV = max(dot(N, V), 0.0);
        float NdotL = max(dot(N, L), 0.0);
        float ggx1 = GeometrySchlickGGX(NdotV, k);
        float ggx2 = GeometrySchlickGGX(NdotL, k);

        return ggx1 * ggx2;
    }

    基于Cook-Torrance BRDF的反射率方程:
        上面的公式并不完全正确,我们会发现其中的F表示光线在表面上的反射比率,而ks也是同样的物理意义,所以高光反射部分的DFG中已经隐式包含了这个反射比率的物理意义,那么我们的反射率方程的最终形态应该是这样:
    
        这个公式就是我们所说的PBR模型正确形态。 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

猜你喜欢

转载自www.cnblogs.com/sifenkesi/p/11924734.html
PBR