浏览代码

Merge pull request #510 from EvgeniiG/new_aniso_hack

Clean up GetPreLightData() and rename 'preLambdaV' to 'partLambdaV'
/Yibing-Project-2
GitHub 7 年前
当前提交
8acab88d
共有 3 个文件被更改,包括 54 次插入54 次删除
  1. 46
      ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl
  2. 6
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  3. 56
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

46
ScriptableRenderPipeline/Core/ShaderLibrary/BSDF.hlsl


}
// Precompute part of lambdaV
float GetSmithJointGGXPreLambdaV(float NdotV, float roughness)
float GetSmithJointGGXPartLambdaV(float NdotV, float roughness)
{
float a2 = roughness * roughness;
return sqrt((-NdotV * a2 + NdotV) * NdotV + a2);

// Ref: http://jcgt.org/published/0003/02/03/paper.pdf
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float preLambdaV)
float V_SmithJointGGX(float NdotL, float NdotV, float roughness, float partLambdaV)
{
float a2 = roughness * roughness;

// G = 1 / (1 + lambda_v + lambda_l);
// Reorder code to be more optimal:
float lambdaV = NdotL * preLambdaV;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l));

float V_SmithJointGGX(float NdotL, float NdotV, float roughness)
{
float preLambdaV = GetSmithJointGGXPreLambdaV(NdotV, roughness);
return V_SmithJointGGX(NdotL, NdotV, roughness, preLambdaV);
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
return V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float preLambdaV)
float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness, float partLambdaV)
float lambdaV = NdotL * preLambdaV;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)

float DV_SmithJointGGX(float NdotH, float NdotL, float NdotV, float roughness)
{
float preLambdaV = GetSmithJointGGXPreLambdaV(NdotV, roughness);
return DV_SmithJointGGX(NdotH, NdotL, NdotV, roughness, preLambdaV);
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
return DV_SmithJointGGX(NdotH, NdotL, NdotV, roughness, partLambdaV);
}
// Precompute a part of LambdaV.

// https://www.desmos.com/calculator/wtp8lnjutx
float GetSmithJointGGXPreLambdaVApprox(float NdotV, float roughness)
float GetSmithJointGGXPartLambdaVApprox(float NdotV, float roughness)
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float preLambdaV)
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float partLambdaV)
float lambdaV = NdotL * preLambdaV;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * (NdotL * (1 - a) + a);
return 0.5 / (lambdaV + lambdaL);

{
float preLambdaV = GetSmithJointGGXPreLambdaVApprox(NdotV, roughness);
return V_SmithJointGGXApprox(NdotL, NdotV, roughness, preLambdaV);
float partLambdaV = GetSmithJointGGXPartLambdaVApprox(NdotV, roughness);
return V_SmithJointGGXApprox(NdotL, NdotV, roughness, partLambdaV);
}
// roughnessT -> roughness in tangent direction

return INV_PI * D_GGXAnisoNoPI(TdotH, BdotH, NdotH, roughnessT, roughnessB);
}
float GetSmithJointGGXAnisoPreLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB)
float GetSmithJointGGXAnisoPartLambdaV(float TdotV, float BdotV, float NdotV, float roughnessT, float roughnessB)
{
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;

// Note: V = G / (4 * NdotL * NdotV)
// Ref: https://cedec.cesa.or.jp/2015/session/ENG/14698.html The Rendering Materials of Far Cry 4
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float preLambdaV)
float V_SmithJointGGXAniso(float TdotV, float BdotV, float NdotV, float TdotL, float BdotL, float NdotL, float roughnessT, float roughnessB, float partLambdaV)
float lambdaV = NdotL * preLambdaV;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);
return 0.5 / (lambdaV + lambdaL);

{
float preLambdaV = GetSmithJointGGXAnisoPreLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB, preLambdaV);
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
return V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB, partLambdaV);
}
// Inline D_GGXAniso() * V_SmithJointGGXAniso() together for better code generation.

float roughnessT, float roughnessB, float preLambdaV)
float roughnessT, float roughnessB, float partLambdaV)
{
float aT2 = roughnessT * roughnessT;
float aB2 = roughnessB * roughnessB;

float lambdaV = NdotL * preLambdaV;
float lambdaV = NdotL * partLambdaV;
float lambdaL = NdotV * sqrt(aT2 * TdotL * TdotL + aB2 * BdotL * BdotL + NdotL * NdotL);
float2 G = float2(1, lambdaV + lambdaL); // Fraction without the constant (0.5)

float TdotL, float BdotL, float NdotL,
float roughnessT, float roughnessB)
{
float preLambdaV = GetSmithJointGGXAnisoPreLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
float partLambdaV = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV, roughnessT, roughnessB);
roughnessT, roughnessB, preLambdaV);
roughnessT, roughnessB, partLambdaV);
}
//-----------------------------------------------------------------------------

6
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


float3x3 localToWorld = GetLocalFrame(N);
#ifndef USE_KARIS_APPROXIMATION
float NdotV = 1; // N == V
float preLambdaV = GetSmithJointGGXPreLambdaV(NdotV, roughness);
float NdotV = 1; // N == V
float partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, roughness);
#endif
float3 lightInt = float3(0.0, 0.0, 0.0);

#ifndef USE_KARIS_APPROXIMATION
// The choice of the Fresnel factor does not appear to affect the result.
float F = 1; // F_Schlick(F0, LdotH);
float V = V_SmithJointGGX(NdotL, NdotV, roughness, preLambdaV);
float V = V_SmithJointGGX(NdotL, NdotV, roughness, partLambdaV);
float G = V * NdotL * NdotV; // 4 cancels out
lightInt += F * G * val;

56
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// General
float NdotV; // Geometric version (could be negative)
// GGX iso
float ggxPreLambdaV;
// GGX Aniso
// GGX
float partLambdaV;
float anisoGGXPreLambdaV;
// Clear coat
float coatNdotV;

// In the case of IBL we want shift a bit the normal that are not toward the viewver to reduce artifact
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, preLightData.NdotV, MIN_N_DOT_V); // Use non-clamped NdotV
float3 iblR = reflect(-V, iblNormalWS);
float3 iblR;
// GGX iso
preLightData.ggxPreLambdaV = GetSmithJointGGXPreLambdaV(NdotV, bsdfData.roughness);
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference.
// We use a single fetch, and we stretch the normal to use based on various criteria.
// result are far away from the reference but better than nothing
preLightData.TdotV = 0.0;
preLightData.BdotV = 0.0;
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.anisoGGXPreLambdaV = GetSmithJointGGXAnisoPreLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference.
// We use a single fetch, and we stretch the normal to use based on various criteria.
// result are far away from the reference but better than nothing
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(grainDirWS, iblNormalWS, V, stretch);
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(grainDirWS, iblNormalWS, V, stretch);
}
else // GGX iso
{
preLightData.TdotV = 0;
preLightData.BdotV = 0;
preLightData.partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, bsdfData.roughness);
iblR = reflect(-V, iblNormalWS);
}
// IBL

}
else
{
float minRoughness, minPerceptualRoughness;
// Note: this is a ad-hoc tweak.
float iblRoughness, iblPerceptualRoughness;
minRoughness = saturate(min(bsdfData.roughnessT, bsdfData.roughnessB) + roughnessBias);
minPerceptualRoughness = RoughnessToPerceptualRoughness(minRoughness);
iblRoughness = saturate(min(bsdfData.roughnessT, bsdfData.roughnessB) + roughnessBias);
iblPerceptualRoughness = RoughnessToPerceptualRoughness(iblRoughness);
minRoughness = bsdfData.roughness;
minPerceptualRoughness = bsdfData.perceptualRoughness;
iblRoughness = bsdfData.roughness;
iblPerceptualRoughness = bsdfData.perceptualRoughness;
preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, minRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(minPerceptualRoughness);
preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, iblRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness);
}
// Area light

TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData.preLambdaV);
, preLightData.partLambdaV);
#else
);
#endif

DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughness
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData preLambdaV);
, preLightData partLambdaV);
#else
);
#endif

正在加载...
取消
保存