Gregory Igehy

Dancing at hemisphere coordinate

Note of GGX specular shading

About

  • パストレーシングで GGX を使いたくなったので, いくつかの資料から GGX について復習

Note

http://www.shlyaev.com/images/stories/ggx/ggx_vs_the_rest.jpg

  • f : The general Cook-Torrance microfacet specular shading model (クックトランスのマイクロファセットのスペキュラシェーディングモデル)
  • D : GGX Distribution ( GGX の NDF )
  • F : Schlick-Fresnel (フレネルのシュリック近似 )
  • V : Schlick approximation of Smith solved with GGX ( スミスのシュリック近似を GGX 向けに解いたもの )

f:id:gregory-igehy:20150226150315j:plain
f:id:gregory-igehy:20150226150320j:plain
f:id:gregory-igehy:20150226150330j:plain
f:id:gregory-igehy:20150226150326j:plain

// V を計算するための便利関数
float G1V( float dotNV, float k )
{
    return 1.0f / ( dotNV * ( 1.0f - k ) + k );
}

// GGX を使ったスペキュラシェーディングの値を返す関数
float LightingFuncGGX_REF( float3 N, float3 V, float3 L,
                           // ラフネス
                           float roughness,
                           // フレネル反射率 F(0°)
                           float F0 )
{
    // α = ラフネス^2
    float alpha = roughness * roughness;

    // ハーフベクトル
    float3 H = normalize(V+L);

    // ベクトルの内積関連
    float dotNL = saturate( dot( N , L ) );
    float dotNV = saturate( dot( N , V ) );
    float dotNH = saturate( dot( N , H ) );
    float dotLH = saturate( dot( L , H ) );

    float F, D, vis;

    // D
    float alphaSqr = alpha * alpha;
    float pi       = 3.14159f;
    float denom    = dotNH * dotNH * ( alphaSqr - 1.0 ) + 1.0f;
    D              = alphaSqr / ( pi * denom * denom );

    // F
    float dotLH5   = pow( 1.0f - dotLH, 5 );
    F              = F0 + ( 1.0 - F0 ) * ( dotLH5 );

    // V
    float k        = alpha / 2.0f;
    vis            = G1V( dotNL, k ) * G1V( dotNV, k);

    float specular = dotNL * D * F * vis;

    return specular;
}