|
|
|
|
|
|
} |
|
|
|
|
|
|
|
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 12. |
|
|
|
float D_GGX_Visible(float NdotH, float NdotV, float roughness) |
|
|
|
float D_GGX_Visible(float NdotH, float NdotV, float VdotH, float roughness) |
|
|
|
} |
|
|
|
|
|
|
|
// Precompute part of lambdaV |
|
|
|
float GetSmithJointGGXPreLambdaV(float NdotV, float roughness) |
|
|
|
{ |
|
|
|
float a2 = roughness * roughness; |
|
|
|
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2); |
|
|
|
float V_SmithJointGGX(float NdotL, float NdotV, float roughness) |
|
|
|
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float preLambdaV) |
|
|
|
float a2 = roughness * roughness; |
|
|
|
|
|
|
|
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5f; |
|
|
|
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f; |
|
|
|
// G = 1 / (1 + lambda_v + lambda_l); |
|
|
|
// lambda_v = (-1 + sqrt(a2 * (1 - NdotL2) / NdotL2 + 1)) * 0.5 |
|
|
|
// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5 |
|
|
|
// G = 1 / (1 + lambda_v + lambda_l); |
|
|
|
float a = roughness; |
|
|
|
float a2 = a * a; |
|
|
|
// Reorder code to be more optimal |
|
|
|
float lambdaV = NdotL * sqrt((-NdotV * a2 + NdotV) * NdotV + a2); |
|
|
|
// Reorder code to be more optimal: |
|
|
|
float lambdaV = NdotL * preLambdaV; |
|
|
|
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2); |
|
|
|
|
|
|
|
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l)); |
|
|
|
|
|
|
// Precompute part of lambdaV |
|
|
|
float GetSmithJointGGXLambdaV(float NdotV, float roughness) |
|
|
|
float V_SmithJointGGX(float NdotL, float NdotV, float roughness) |
|
|
|
float a = roughness; |
|
|
|
float a2 = a * a; |
|
|
|
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2); |
|
|
|
float preLambdaV = GetSmithJointGGXPreLambdaV(NdotV, roughness); |
|
|
|
return V_SmithJointGGX(NdotL, NdotV, roughness, preLambdaV); |
|
|
|
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float lambdaV) |
|
|
|
// Inline D_GGX() * V_SmithJointGGX() together for better code generation. |
|
|
|
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float preLambdaV) |
|
|
|
float a = roughness; |
|
|
|
float a2 = a * a; |
|
|
|
// Reorder code to be more optimal |
|
|
|
lambdaV *= NdotL; |
|
|
|
float a2 = roughness * roughness; |
|
|
|
float f = (NdotH * a2 - NdotH) * NdotH + 1.0; |
|
|
|
float2 D = float2(a2, f * f); // Fraction without the constant (1/Pi) |
|
|
|
|
|
|
|
float lambdaV = NdotL * preLambdaV; |
|
|
|
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l)); |
|
|
|
return 0.5 / (lambdaV + lambdaL); |
|
|
|
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5) |
|
|
|
|
|
|
|
return (INV_PI * 0.5) * (D.x * G.y) / (D.y * G.y); |
|
|
|
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness) |
|
|
|
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness) |
|
|
|
float a = roughness; |
|
|
|
// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough) |
|
|
|
float lambdaV = NdotL * (NdotV * (1 - a) + a); |
|
|
|
float lambdaL = NdotV * (NdotL * (1 - a) + a); |
|
|
|
|
|
|
|
return 0.5 / (lambdaV + lambdaL); |
|
|
|
float preLambdaV = GetSmithJointGGXPreLambdaV(NdotV, roughness); |
|
|
|
return DV_SmithJointGGX(NdotH, NdotL, NdotV, roughness, preLambdaV); |
|
|
|
} |
|
|
|
|
|
|
|
// Precompute a part of LambdaV. |
|
|
|
|
|
|
float GetSmithJointGGXApproxLambdaV(float NdotV, float roughness) |
|
|
|
float GetSmithJointGGXPreLambdaVApprox(float NdotV, float roughness) |
|
|
|
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float lambdaV) |
|
|
|
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float preLambdaV) |
|
|
|
// Approximation of the above formulation (simplify the sqrt, not mathematically correct but close enough) |
|
|
|
lambdaV *= NdotL; |
|
|
|
|
|
|
|
float lambdaV = NdotL * preLambdaV; |
|
|
|
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness) |
|
|
|
{ |
|
|
|
float preLambdaV = GetSmithJointGGXPreLambdaVApprox(NdotV, roughness); |
|
|
|
return V_SmithJointGGXApprox(NdotL, NdotV, roughness, preLambdaV); |
|
|
|
} |
|
|
|
|
|
|
|
float f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH; |
|
|
|
float aT2 = roughnessT * roughnessT; |
|
|
|
float aB2 = roughnessB * roughnessB; |
|
|
|
|
|
|
|
float f = TdotH * TdotH / aT2 + BdotH * BdotH / aB2 + NdotH * NdotH; |
|
|
|
return 1.0 / (roughnessT * roughnessB * f * f); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
float GetSmithJointGGXAnisoPreLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB) |
|
|
|
{ |
|
|
|
float aT2 = roughnessT * roughnessT; |
|
|
|
float aB2 = roughnessB * roughnessB; |
|
|
|
|
|
|
|
return sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV); |
|
|
|
} |
|
|
|
|
|
|
|
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB) |
|
|
|
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float preLambdaV) |
|
|
|
float aT = roughnessT; |
|
|
|
float aT2 = aT * aT; |
|
|
|
float aB = roughnessB; |
|
|
|
float aB2 = aB * aB; |
|
|
|
float aT2 = roughnessT * roughnessT; |
|
|
|
float aB2 = roughnessB * roughnessB; |
|
|
|
float lambdaV = NdotL * sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV); |
|
|
|
float lambdaV = NdotL * preLambdaV; |
|
|
|
float GetSmithJointGGXAnisoLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB) |
|
|
|
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB) |
|
|
|
float aT = roughnessT; |
|
|
|
float aT2 = aT * aT; |
|
|
|
float aB = roughnessB; |
|
|
|
float aB2 = aB * aB; |
|
|
|
|
|
|
|
return sqrt(aT2 * TdotV * TdotV + aB2 * BdotV * BdotV + NdotV * NdotV); |
|
|
|
float preLambdaV = GetSmithJointGGXAnisoPreLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB); |
|
|
|
return V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB, preLambdaV); |
|
|
|
float V_SmithJointGGXAnisoLambdaV(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float lambdaV) |
|
|
|
// Inline D_GGXAniso() * V_SmithJointGGXAniso() together for better code generation. |
|
|
|
float DV_SmithJointGGX(float TdotH, float BdotH, float NdotH, |
|
|
|
float TdotV, float BdotV, float NdotV, |
|
|
|
float TdotL, float BdotL, float NdotL, |
|
|
|
float roughnessT, float roughnessB, float preLambdaV) |
|
|
|
float aT = roughnessT; |
|
|
|
float aT2 = aT * aT; |
|
|
|
float aB = roughnessB; |
|
|
|
float aB2 = aB * aB; |
|
|
|
float aT2 = roughnessT * roughnessT; |
|
|
|
float aB2 = roughnessB * roughnessB; |
|
|
|
|
|
|
|
float f = TdotH * TdotH / aT2 + BdotH * BdotH / aB2 + NdotH * NdotH; |
|
|
|
float2 D = float2(1, roughnessT * roughnessB * f * f); // Fraction without the constant (1/Pi) |
|
|
|
lambdaV *= NdotL; |
|
|
|
float lambdaV = NdotL * preLambdaV; |
|
|
|
return 0.5 / (lambdaV + lambdaL); |
|
|
|
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5) |
|
|
|
|
|
|
|
return (INV_PI * 0.5) * (D.x * G.y) / (D.y * G.y); |
|
|
|
} |
|
|
|
|
|
|
|
float DV_SmithJointGGX(float TdotH, float BdotH, float NdotH, |
|
|
|
float TdotV, float BdotV, float NdotV, |
|
|
|
float TdotL, float BdotL, float NdotL, |
|
|
|
float roughnessT, float roughnessB) |
|
|
|
{ |
|
|
|
float preLambdaV = GetSmithJointGGXAnisoPreLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB); |
|
|
|
return DV_SmithJointGGX(TdotH, BdotH, NdotH, |
|
|
|
TdotV, BdotV, NdotV, |
|
|
|
TdotL, BdotL, NdotL, |
|
|
|
roughnessT, roughnessB, preLambdaV); |
|
|
|
} |
|
|
|
|
|
|
|
//----------------------------------------------------------------------------- |
|
|
|