Cook-Torrance/ Ward反射方程

1, Cook-Torrance反射方程

Cook-Torrance反射方程
其代码如下:

float m 0.001 .3 .1
float f0 0 1 .1

float Beckmann(float m, float t)
{
    float M = m*m;
    float T = t*t;
    return exp((T-1)/(M*T)) / (M*T*T);
}

float Fresnel(float f0, float u)
{
    // from Schlick
    return f0 + (1-f0) * pow(1-u, 5);
}

vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
    // compute the half vec3
    vec3 H = normalize( L + V );

    float NdotH = dot(N, H);
    float VdotH = dot(V, H);
    float NdotL = dot(N, L);
    float NdotV = dot(N, V);
    float oneOverNdotV = 1.0 / NdotV;

    float D = Beckmann(m, NdotH);
    float F = Fresnel(f0, VdotH);

    NdotH = NdotH + NdotH;
    float G = (NdotV < NdotL) ? 
        ((NdotV*NdotH < VdotH) ?
         NdotH / VdotH :
         oneOverNdotV)
        :
        ((NdotL*NdotH < VdotH) ?
         NdotH*NdotL / (VdotH*NdotV) :
         oneOverNdotV);

    if (include_G) G = oneOverNdotV;
    float val = NdotH < 0 ? 0.0 : D * G ;

    if (include_F) val *= F;

    val = val / NdotL;
    return vec3(val);
}

2, Ward 反射方程(各向异性高光)

Ward BRDF
在这里插入图片描述
其中高光反射部分:
在这里插入图片描述
参数ρs,αx与αy。其实ρs就跟phong模型中的镜面反射系数是差不多的,而αx与αy控制了高光在x和y方向上的范围(也可以理解成表面在x和y方向上的粗糙程度)。当αx=αy的时候,该brdf描述的是一个各向同性的反射模型,其效果和phong很类似,反之则描述各向异性反射模型。

公式中的θi,θo,θh分别代表了入射向量i,出射向量o以及半角h与表面法向量的夹角,Φh则是h在物体表面上的投影与表面切向量的夹角。在这里插入图片描述
αx与αy两个参数,一般我们会在0-1之间取值,取值越大,得到的高光区域越大。如下图示:

在这里插入图片描述
考虑了metallic值的影响后的算法:

 // Ward BRDF 
 color Cs vec3(1 1 1)
color Cd  vec3(1 1 1)
float metallic 0 1.0 0.1
float alpha_x 0 1.0 0.15
float alpha_y 0 1.0 0.15

 float sqr( float x )
{
    return x*x;
}

float pbrFresnel(float VdotH, float F0)
{
	float f = 1.0 - VdotH;
	float f2 = f * f;
	return F0 + (1.0 - F0) * f2 * f2 * f;
}

// Ward BRDF
// this is the formulation specified in "Notes on the Ward BRDF" - Bruce Walter, 2005

vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
    vec3 H = normalize(L + V);
    	// Fresnel
	float F = pbrFresnel(dot(V, H), metallic);
    // specular
    float ax = alpha_x;
    float ay = isotropic ? alpha_x : alpha_y;
    float exponent = -(
        sqr( dot(H,X) / ax ) +
        sqr( dot(H,Y) / ay)
    ) / sqr( dot( H, N ) );
    float spec = 1.0 / (4.0 * 3.14159265 * ax * ay * sqrt( dot(L,N) * dot(V, N) )) * F;
    spec *= exp( exponent );
    return Cd / 3.14159265 + Cs * spec;
}

论文下载:
1, https://download.csdn.net/download/u011469662/11798234
2, https://download.csdn.net/download/u011469662/11798231

3 Disney BRDF 反射方程

在这里插入图片描述
1, 漫反射项目:
在这里插入图片描述
其中, [公式]
在这里插入图片描述

// [Burley 2012, "Physically-Based Shading at Disney"]
float3 Diffuse_Burley_Disney( float3 DiffuseColor, float Roughness, float NoV, float NoL, float VoH )
{
	float FD90 = 0.5 + 2 * VoH * VoH * Roughness;
	float FdV = 1 + (FD90 - 1) * Pow5( 1 - NoV );
	float FdL = 1 + (FD90 - 1) * Pow5( 1 - NoL );
	return DiffuseColor * ( (1 / PI) * FdV * FdL );
}

2, 法线分布项::GTR
在这里插入图片描述
Disney Principled BRDF中使用了两个固定的镜面反射波瓣(specular lobe):

主波瓣(primary lobe)
  1. 使用γ= 2的GTR(即GGX分布)
  2. 代表基础底层材质(Base Material)的反射
  3. 可为各项异性(anisotropic)或各项同性(isotropic)的金属或非金属
次级波瓣(secondary lobe)
  1. 使用γ= 1的GTR(即Berry分布)
  2. 代表基础材质上的清漆层(ClearCoat Layer)的反射
  3. 一般为各项同性(isotropic)的非金属材质,即清漆层(ClearCoat Layer)

3 菲涅尔项(Specular F):Schlick Fresnel
在这里插入图片描述
4, 几何项(Specular G):Smith-GGX
在这里插入图片描述
测试效果见下图:
在这里插入图片描述
完整的BRDF函数如下:

const float PI = 3.14159265358979323846;

float sqr(float x) { return x*x; }

float SchlickFresnel(float u)
{
    float m = clamp(1-u, 0, 1);
    float m2 = m*m;
    return m2*m2*m; // pow(m,5)
}

float GTR1(float NdotH, float a)
{
    if (a >= 1) return 1/PI;
    float a2 = a*a;
    float t = 1 + (a2-1)*NdotH*NdotH;
    return (a2-1) / (PI*log(a2)*t);
}

float GTR2(float NdotH, float a)
{
    float a2 = a*a;
    float t = 1 + (a2-1)*NdotH*NdotH;
    return a2 / (PI * t*t);
}

float GTR2_aniso(float NdotH, float HdotX, float HdotY, float ax, float ay)
{
    return 1 / (PI * ax*ay * sqr( sqr(HdotX/ax) + sqr(HdotY/ay) + NdotH*NdotH ));
}

float smithG_GGX(float NdotV, float alphaG)
{
    float a = alphaG*alphaG;
    float b = NdotV*NdotV;
    return 1 / (NdotV + sqrt(a + b - a*b));
}

float smithG_GGX_aniso(float NdotV, float VdotX, float VdotY, float ax, float ay)
{
    return 1 / (NdotV + sqrt( sqr(VdotX*ax) + sqr(VdotY*ay) + sqr(NdotV) ));
}

vec3 mon2lin(vec3 x)
{
    return vec3(pow(x[0], 2.2), pow(x[1], 2.2), pow(x[2], 2.2));
}


vec3 BRDF( vec3 L, vec3 V, vec3 N, vec3 X, vec3 Y )
{
    float NdotL = dot(N,L);
    float NdotV = dot(N,V);
    if (NdotL < 0 || NdotV < 0) return vec3(0);

    vec3 H = normalize(L+V);
    float NdotH = dot(N,H);
    float LdotH = dot(L,H);

    vec3 Cdlin = mon2lin(baseColor);
    float Cdlum = .3*Cdlin[0] + .6*Cdlin[1]  + .1*Cdlin[2]; // luminance approx.

    vec3 Ctint = Cdlum > 0 ? Cdlin/Cdlum : vec3(1); // normalize lum. to isolate hue+sat
    vec3 Cspec0 = mix(specular*.08*mix(vec3(1), Ctint, specularTint), Cdlin, metallic);
    vec3 Csheen = mix(vec3(1), Ctint, sheenTint);

    // Diffuse fresnel - go from 1 at normal incidence to .5 at grazing
    // and mix in diffuse retro-reflection based on roughness
    float FL = SchlickFresnel(NdotL), FV = SchlickFresnel(NdotV);
    float Fd90 = 0.5 + 2 * LdotH*LdotH * roughness;
    float Fd = mix(1.0, Fd90, FL) * mix(1.0, Fd90, FV);

    // Based on Hanrahan-Krueger brdf approximation of isotropic bssrdf
    // 1.25 scale is used to (roughly) preserve albedo
    // Fss90 used to "flatten" retroreflection based on roughness
    float Fss90 = LdotH*LdotH*roughness;
    float Fss = mix(1.0, Fss90, FL) * mix(1.0, Fss90, FV);
    float ss = 1.25 * (Fss * (1 / (NdotL + NdotV) - .5) + .5);

    // specular
    float aspect = sqrt(1-anisotropic*.9);
    float ax = max(.001, sqr(roughness)/aspect);
    float ay = max(.001, sqr(roughness)*aspect);
    float Ds = GTR2_aniso(NdotH, dot(H, X), dot(H, Y), ax, ay);
    float FH = SchlickFresnel(LdotH);
    vec3 Fs = mix(Cspec0, vec3(1), FH);
    float Gs;
    Gs  = smithG_GGX_aniso(NdotL, dot(L, X), dot(L, Y), ax, ay);
    Gs *= smithG_GGX_aniso(NdotV, dot(V, X), dot(V, Y), ax, ay);

    // sheen
    vec3 Fsheen = FH * sheen * Csheen;

    // clearcoat (ior = 1.5 -> F0 = 0.04)
    float Dr = GTR1(NdotH, mix(.1,.001,clearcoatGloss));
    float Fr = mix(.04, 1.0, FH);
    float Gr = smithG_GGX(NdotL, .25) * smithG_GGX(NdotV, .25);

    return ((1/PI) * mix(Fd, ss, subsurface)*Cdlin + Fsheen)
        * (1-metallic)
        + Gs*Fs*Ds + .25*clearcoat*Gr*Fr*Dr;
}

参考文章:

1, https://www.cnblogs.com/starfallen/p/3572352.html
2, https://github.com/wdas/brdf
3, http://chiakailiang.org/project_ward/#Ward92

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值