浏览代码

Fix anisotropy.

/StackLit2
Stephane Laroche 6 年前
当前提交
27bea6de
共有 1 个文件被更改,包括 68 次插入50 次删除
  1. 118
      com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl

118
com.unity.render-pipelines.high-definition/HDRP/Material/StackLit/StackLit.hlsl


# define COAT_NB_LOBES 0
# define COAT_LOBE_IDX 0
# define BASE_LOBEA_IDX 0
# define BASE_LOBEB_IDX (BASE_LOBEA_IDX+1)
# define BASE_LOBEB_IDX (BASE_LOBEA_IDX+1) // (make sure B is always #A+1)
# define NB_NORMALS 1
# define NB_LV_DIR 1

// TODO: if dual lobe base
//#define BASE_NB_LOBES 1
#define BASE_NB_LOBES 2
#define TOTAL_NB_LOBES (BASE_NB_LOBES+COAT_NB_LOBES)
#define BASE_NB_LOBES 2 // use numeric indices for these arrays
#define TOTAL_NB_LOBES (BASE_NB_LOBES+COAT_NB_LOBES) // use *_LOBE?_IDX for these arrays.
// TODO CLEANUP and put in proper define above

// Otherwise, the calculation of these is done for each light
//
// Handle IBL + area light + multiscattering.
// Note: use the not modified by anisotropy iblPerceptualRoughness here.
// Handle FGD texture fetches for IBL + area light + multiscattering.
// Note: use the unmodified by anisotropy iblPerceptualRoughness here.
//
//
// Also note that while the fetch directions for the light samples (IBL) are the ones
// at the top interface, for the FGD terms (in fact, for all angle dependent BSDF
// parametrization data), we need to use the actual interface angle a propagated direction

preLightData.TdotV = TdotV;
preLightData.BdotV = BdotV;
#endif
// perceptualRoughness is use as input and output here
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS, bsdfData.tangentWS, N, V, preLightData.iblAnisotropy[0], preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX], iblN[BASE_LOBEA_IDX], preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX]);
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS, bsdfData.tangentWS, N, V, preLightData.iblAnisotropy[1], preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX], iblN[BASE_LOBEB_IDX], preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX]);
// Handle iblPerceptualRoughness modifications for anisotropy.
// iblPerceptualRoughness is used as input and output here:
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS,
bsdfData.tangentWS,
N[BASE_NORMAL_IDX],
V,
preLightData.iblAnisotropy[0],
preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX],
iblN[BASE_LOBEA_IDX],
preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX]);
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS,
bsdfData.tangentWS,
N[BASE_NORMAL_IDX],
V,
preLightData.iblAnisotropy[1],
preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX],
iblN[BASE_LOBEB_IDX],
preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX]);
iblN[COAT_LOBE_IDX] = N[COAT_NORMAL_IDX]; // no anisotropy for coat.
}

iblN[BASE_LOBEA_IDX] = iblN[BASE_LOBEB_IDX] = N[BASE_NORMAL_IDX];
} // anisotropy
// IBL
// Handle IBL pre calculated data + GGX multiscattering energy loss compensation term
// Handle IBL fetch direction R + GGX multiscattering energy loss compensation term
iblR[0] = reflect(-V, iblN[0]);
iblR[1] = reflect(-V, iblN[1]);

//
// Notice again that the roughness and iblR properly use the output lobe statistics, but baseLayerNdotV
// is used for the offspecular correction because the true original offspecular tilt is parametrized by
// the angle at the base layer and the correction itself is influenced by that. See comments above.

preLightData.iblPerceptualRoughness[0] = bsdfData.perceptualRoughnessA;
preLightData.iblPerceptualRoughness[1] = bsdfData.perceptualRoughnessB;
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_ANISOTROPY))
{
float TdotV = dot(bsdfData.tangentWS, V);
float BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV[0] = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV[0], preLightData.layeredRoughnessT[0], preLightData.layeredRoughnessB[0]);
preLightData.partLambdaV[1] = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV[0], preLightData.layeredRoughnessT[1], preLightData.layeredRoughnessB[1]);
// 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
// For positive anisotropy values: tangent = highlight stretch (anisotropy) direction, bitangent = grain (brush) direction.
float3 grainDirWS = (bsdfData.anisotropy >= 0.0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
// Reduce stretching for (perceptualRoughness < 0.2).
float stretch[2];
stretch[0] = abs(bsdfData.anisotropy) * saturate(5 * preLightData.iblPerceptualRoughness[0]);
stretch[1] = abs(bsdfData.anisotropy) * saturate(5 * preLightData.iblPerceptualRoughness[1]);
iblN[0] = GetAnisotropicModifiedNormal(grainDirWS, N[0], V, stretch[0]);
iblN[1] = GetAnisotropicModifiedNormal(grainDirWS, N[0], V, stretch[1]);
}
else
{
preLightData.partLambdaV[0] = GetSmithJointGGXPartLambdaV(NdotV[0], preLightData.layeredRoughnessT[0]);
preLightData.partLambdaV[1] = GetSmithJointGGXPartLambdaV(NdotV[0], preLightData.layeredRoughnessT[1]);
iblN[0] = iblN[1] = N[0];
} // ...no anisotropy
float3 f0forCalculatingFGD = bsdfData.fresnel0;
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_IRIDESCENCE))
{

}
}
// IBL
// Handle IBL pre calculated data + GGX multiscattering energy loss compensation term
// Handle FGD texture fetches for IBL + area light + multiscattering.
GetPreIntegratedFGDGGXAndDisneyDiffuse(NdotV[0],
preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX],

specularReflectivity[BASE_LOBEB_IDX]);
if (HasFlag(bsdfData.materialFeatures, MATERIALFEATUREFLAGS_STACK_LIT_ANISOTROPY))
{
float TdotV = dot(bsdfData.tangentWS, V);
float BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV[0] = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV[0], preLightData.layeredRoughnessT[0], preLightData.layeredRoughnessB[0]);
preLightData.partLambdaV[1] = GetSmithJointGGXAnisoPartLambdaV(TdotV, BdotV, NdotV[0], preLightData.layeredRoughnessT[1], preLightData.layeredRoughnessB[1]);
// Handle iblPerceptualRoughness modifications for anisotropy.
// iblPerceptualRoughness is used as input and output here:
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS,
bsdfData.tangentWS,
N[BASE_NORMAL_IDX],
V,
preLightData.iblAnisotropy[0],
preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX],
iblN[BASE_LOBEA_IDX],
preLightData.iblPerceptualRoughness[BASE_LOBEA_IDX]);
GetGGXAnisotropicModifiedNormalAndRoughness(bsdfData.bitangentWS,
bsdfData.tangentWS,
N[BASE_NORMAL_IDX],
V,
preLightData.iblAnisotropy[1],
preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX],
iblN[BASE_LOBEB_IDX],
preLightData.iblPerceptualRoughness[BASE_LOBEB_IDX]);
}
else
{
preLightData.partLambdaV[0] = GetSmithJointGGXPartLambdaV(NdotV[0], preLightData.layeredRoughnessT[0]);
preLightData.partLambdaV[1] = GetSmithJointGGXPartLambdaV(NdotV[0], preLightData.layeredRoughnessT[1]);
iblN[0] = iblN[1] = N[0];
} // ...no anisotropy
// Handle IBL fetch direction R + GGX multiscattering energy loss compensation term
// This is a ad-hoc tweak to better match reference of anisotropic GGX.
// TODO: We need a better hack.
float fact = saturate(1.2 - abs(bsdfData.anisotropy));
preLightData.iblPerceptualRoughness[0] *= fact;
preLightData.iblPerceptualRoughness[1] *= fact;
// Correction of reflected direction for better handling of rough material
preLightData.iblR[0] = GetSpecularDominantDir(N[0], iblR[0], preLightData.iblPerceptualRoughness[0], NdotV[0]);
preLightData.iblR[1] = GetSpecularDominantDir(N[0], iblR[1], preLightData.iblPerceptualRoughness[1], NdotV[0]);

// formulation. ie Compensation corresponds to using FGDinf instead of FGD.
preLightData.energyCompensationFactor[BASE_LOBEA_IDX] = GetEnergyCompensationFactor(specularReflectivity[BASE_LOBEA_IDX], bsdfData.fresnel0);
preLightData.energyCompensationFactor[BASE_LOBEB_IDX] = GetEnergyCompensationFactor(specularReflectivity[BASE_LOBEB_IDX], bsdfData.fresnel0);
#else
preLightData.energyCompensationFactor[BASE_LOBEA_IDX] =

正在加载...
取消
保存