浏览代码

Improve support of transmission for Disney Diffuse

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
a88795d9
共有 1 个文件被更改,包括 37 次插入8 次删除
  1. 45
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

45
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


#define LTC_LUT_OFFSET (0.5 * rcp(LTC_LUT_SIZE))
// Subsurface scattering constant
#define SSS_WRAP_ANGLE (PI/12) // Used for wrap lighting
#define SSS_WRAP_ANGLE (PI/12) // 15 degrees
#define SSS_WRAP_LIGHT cos(PI/2 - SSS_WRAP_ANGLE)
CBUFFER_START(UnitySSSParameters)

#elif LIT_DIFFUSE_GGX_BRDF
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
#else
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
// A note on subsurface scattering.
// The correct way to handle SSS is to transmit light inside the surface, perform SSS,
// and then transmit it outside towards the viewer.
// Transmit(X) = F_Transm_Schlick(F0, F90, NdotX), where F0 = 0, F90 = 1.
// Therefore, the diffuse BSDF should be decomposed as follows:
// f_d = A / Pi * F_Transm_Schlick(0, 1, NdotL) * F_Transm_Schlick(0, 1, NdotV) + f_d_reflection,
// with F_Transm_Schlick(0, 1, NdotV) applied after the SSS pass.
// The alternative (artistic) formulation of Disney is to set F90 = 0.5:
// f_d = A / Pi * F_Transm_Schlick(0, 0.5, NdotL) * F_Transm_Schlick(0, 0.5, NdotV) + f_retro_reflection.
// That way, darkening at grading angles is reduced to 0.5.
// In practice, applying F_Transm_Schlick(F0, F90, NdotV) after the SSS pass is expensive,
// as it forces us to read the normal buffer at the end of the SSS pass.
// Separating f_retro_reflection also has a small cost (mostly due to energy compensation
// for multi-bounce GGX), and the visual difference is negligible.
// Therefore, we choose not to separate diffuse lighting into reflected and transmitted.
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
#endif
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().

[branch] if (bsdfData.enableTransmission)
{
// We apply wrapped lighting instead of the regular Lambertian diffuse
// to compensate for approximations within EvaluateTransmission().
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// Apply wrapped lighting to better handle thin objects (cards) at grazing angles.
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
illuminance = Lambert() * wrappedNdotL;
#else
float tNdotL = saturate(-NdotL);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
illuminance = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
#endif
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().

[branch] if (bsdfData.enableTransmission)
{
// We apply wrapped lighting instead of the regular Lambertian diffuse
// to compensate for approximations within EvaluateTransmission().
float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// Apply wrapped lighting to better handle thin objects (cards) at grazing angles.
float wrappedNdotL = ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
illuminance = Lambert() * wrappedNdotL;
#else
float tNdotL = saturate(-NdotL);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
illuminance = INV_PI * F_Transm_Schlick(0, 0.5, NdotV) * F_Transm_Schlick(0, 0.5, tNdotL) * wrappedNdotL;
#endif
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
// We don't multiply by 'bsdfData.diffuseColor' here. It's done only once in PostEvaluateBSDF().

正在加载...
取消
保存