如需转载本文,请声明作者及出处。
一 蒙特卡洛方法:
若要求这样一个积分的解,按牛顿-布来尼茨公式来求解的话,自然是先求出被积函数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中内容请搜索靠谱客的其他文章。
发表评论 取消回复