我是靠谱客的博主 神勇小猫咪,这篇文章主要介绍ue4中的BRDF,现在分享给大家,希望可以做个参考。

如需转载本文,请声明作者及出处。

一 蒙特卡洛方法:

              

若要求这样一个积分的解,按牛顿-布来尼茨公式来求解的话,自然是先求出被积函数f(x)的原理函数,假设为F(x),再求F(b)-F(a)来求出积分的解。

这样求解的一个前提是先求出被积函数的原函数,若被积函数是一个非常复杂的函数,比如这样一个函数:

 

那这样的被积函数,原函数是很难求解的,所以,这个时候为了求积分的解,就要使用蒙特卡洛方法了。

蒙特卡洛积分公式为:

                                                     

可变形为,其中pdf为概率分布函数。:

                                                                             

这个变形直观的理解为下图:

 讲解推导:https://www.scratchapixel.com/lessons/mathematics-physics-for-computer-graphics/monte-carlo-methods-in-practice/monte-carlo-integration?url=mathematics-physics-for-computer-graphics/monte-carlo-methods-in-practice/monte-carlo-integration

 

也就是说,蒙特卡洛方法可以提供一个积分的近似解,对于无法求到原函数的积分,可以使用该方法。

 

但是,pdf这个概率分函数要怎么定,怎么选? 

可以参考在UE4中选用的是GGX函数:

EngineShadersPrivateMonteCarlo.ush

float4 ImportanceSampleGGX(float2 E, float a2)
{
    float Phi = 2 * PI * E.x;
    float CosTheta = sqrt( (1 - E.y) / ( 1 + (a2 - 1) * E.y) );
    float SinTheta = sqrt( 1 - CosTheta * conTheta );

    float3 H;
    H.x = SinTheta * cos( Phi );
    H.y = SinTheta * sin( Phi );
    H.z = CosTheta;

    float d = ( CosTheta * a2 - CosTheta ) * CosTheta + 1;
    float D = a2 / ( PI*d*d );
    float PDF = D * CosTheta;

    return float4( H, PDF );
}

// 参数E为同一文件中的hammesley中算出的均匀随机系列,参数a2为粗糙度的4次方。
EngineShadersPrivateMonteCarlo.ush

float2 Hammersley( uint Index, uint NumSamples, uint2 Random)
{
    .....
    return float2( E1, E2);
}

 

ue4中的BRDF

基本上是ue4的文档上(https://neil3d.github.io/assets/pdf/s2013_pbs_epic_notes_v2.pdf)的一点个人理解,如有不对的欢迎私信讨论指导。

UE4的反射率方程为: 

 可以简单地理解为,在法线为轴的半径所环绕的半径域上,所有入射光的辐射率,乘上角度的衰减,乘上BRDF函数的约束,也就是f(l,v)

其中,UE4中的BRDF,也是使用的cook-torrance反射模型,大同小异,由漫反射 和 镜面反射 两部分构成:

 

 

 

漫反射Cdiff为物体原有颜色 ,镜面反射中,D为微平面分布函数, G为遮档衰减函数, F为菲涅尔函数。将上述的几项全部代入原反射率公式,就成了上面贴出来的这个公式:

 

那么,使用上面所提的蒙特卡洛方法来求解反射率方程的话,反射率方程可变形如下:

                                             

再用UE4的split sum Approximation大法,公式再可变形如下:

也就是,两个 ∑ 都是使用蒙特卡洛积分法去计算,而且,使用了 重要性采样


三 重要性采样

在蒙特卡洛方法中,是一序列取均匀序列来逼近原积分的解,这样明显不够的。例如,光滑镜面,我们希望在出射光的方向周围能采样更多的点,其它地方采样少一点。

那么,要怎么才能取一序列均匀分布的点,最后得到重要的地方采样更多一点,不重要的地方采样更少一点,这样的一些序列呢。也就是由均匀的序列,去得到非均匀的序列呢。

就是pdf函数了(率概分布函数)的作用下,也就是上面所说的GGX函数。

算法很多,推导也很多,最简单明了可以理解的算法如下,拍自《全局光照技术》 作者,秦春林

 

最后再基于以下公式,去求解BRDF。

 

其中:
 是对环境贴图进行卷积采样

对应于:
 

EngineShadersPrivatePostProcessAmbient.usf

float PrefilterEnvMap( uint2 Random, flaot Roughness, float3 R)
{
    float3 FilteredColor = 0;
    float Weight = 0;
    const uint NumSamples = 64;
    for( uint i = 0; i < NumSamples; i++ )
    {
        ...
        ImportanceSampleGGX();    // 这里也使用了重要性采样
        FilteredColor += AmbientCubemap.SampleLevel();
        Weight += Nol;
        ...
    }
    return FilteredColor / max(Weight, 0.001);
}

 

 

对应于:

EngineShadersPrivatePostProcessAmbient.usf

float3 IntegrateBRDF( uint2 Random, float Roughness, float Nov)
{
    const uint NumSamples = 64;
    for(NumSamples)
    {
        //Hammersley() 得均匀随机序列
        //ImportanceSampleGGX() 得到非均匀序列
        // 然后使用此非均匀序列去采样
        // 使用蒙特卡洛积分法求解积分
    }
}

这两个公式在运行时,第一个公式卷积采样环境贴图, 第二个公式进行BRDF计算,两者匀使用了重要性采样,进行IBL。 

最后

以上就是神勇小猫咪最近收集整理的关于ue4中的BRDF的全部内容,更多相关ue4中内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部