对BRDF模型的自我理解

主要是参考毛星云大佬对BRDF的解释
还有就是unity内置管线中的BRDF相关代码:
整个BRDF和PBR系列整理的很碎,主要是记录的一些自己忽略的点,
网上整体讲解BRDF的很多,但是讲到下面的知识的很少,或者说大佬已经讲了我没理解==
权当自己的笔记,谨慎参考~~
(1)BRDF公式中 分母的消失??!!!
隐式遮蔽函数:

隐式遮蔽函数 (The Implicit Masking Function)可以和Specular的分母校正因子4(n·l)(n·v)相消为1,虽然不是严格基于物理,但具有非常好的性价比。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
重要:这样在计算的时候,就通了!!!!!
在计算高光项的时候,
在这里插入图片描述
最后的公式就变成 : f(I,V) = F * V * D

(2)关于grazingTerm的理解: grazingTerm 影响间接高光的反射
(光滑度和金属度的和 =》 决定 grazingTerm的大小,而grazingTerm的大小 影响 间接高光的反射)
在这里插入图片描述

  
  --漫反射率  -- metallic: 金属度
  half oneMinusReflectivity = OneMinusReflectivityMetallic(metallic);
  
  half grazingTerm = saturate(smoothness + (1-oneMinusReflectivity));
  smoothness : 光滑度
  oneMinusReflectivity : 漫反射率

在这里插入图片描述
因此:在金属工作流的模式下,

反射率只和金属度有关: 反射率和金属度成 正比

金属度							metallic :  0				1

漫反射率 OneMinusReflectivity: 0.96 0

金属度 0, 反射率 0.04;
金属度 1, 反射率 1;

在这里插入图片描述
在这里插入图片描述
最后附上BRDF计算中用的数学模型对应的代码:

//  阴影遮蔽函数
//  Sq(x)  = x * x;
// Precompute part of lambdaV
real GetSmithJointGGXPartLambdaV2(real NdotV, real roughness)
{
    
    
    real a2 = Sq(roughness);
    return sqrt(max(0.002,-NdotV * a2 + NdotV) * NdotV + a2);
}
real V_SmithJointGGX2(real NdotL, real NdotV, real roughness, real partLambdaV)
{
    
    
    real a2 = Sq(roughness);
    real lambdaV = NdotL * partLambdaV;
    real lambdaL = NdotV * sqrt(max(0.002,(-NdotL * a2 + NdotL) * NdotL + a2));
    //return 0.5 / (NdotL + lambdaL);
    return 0.5 / max(0.002,lambdaV + lambdaL);
}

real V_SmithJointGGX2(real NdotL, real NdotV, real roughness)
{
    
    
    real partLambdaV = GetSmithJointGGXPartLambdaV2(NdotV, roughness);
    return V_SmithJointGGX2(NdotL, NdotV, roughness, partLambdaV);
}


//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//迪士尼的diffuse模型 

half StDisneyDiffuse(half NdotV, half NdotL, half LdotH, half perceptualRoughness)
{
    
    
	half fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
	// Two schlick fresnel term
	half lightScatter = (1 + (fd90 - 1) * Pow5(1 - NdotL));
	half viewScatter = (1 + (fd90 - 1) * Pow5(1 - NdotV));

	return lightScatter * viewScatter;
}



//---------------------------------------------------------------------
//---------------------------------------------------------------------
//---------------------------------------------------------------------
//  法线分布函数:
real D_GGXNoPI(real NdotH, real roughness)
{
    
    
    real a2 = Sq(roughness);
    real s = (NdotH * a2 - NdotH) * NdotH + 1.0;

    // If roughness is 0, returns (NdotH == 1 ? 1 : 0).
    // That is, it returns 1 for perfect mirror reflection, and 0 otherwise.
    return SafeDiv(a2, s * s);
}

real D_GGX(real NdotH, real roughness)
{
    
    
    return INV_PI * D_GGXNoPI(NdotH, roughness);
}

猜你喜欢

转载自blog.csdn.net/js0907/article/details/120718188
今日推荐