浏览代码

Merge pull request #522 from EvgeniiG/multi_bounce_ggx

Implement energy compensation for metallic GGX
/Add-support-for-light-specular-color-tint
GitHub 7 年前
当前提交
8f4af1c6
共有 4 个文件被更改,包括 44 次插入25 次删除
  1. 12
      ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl
  2. 17
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  3. 1
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  4. 39
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl

12
ScriptableRenderPipeline/Core/ShaderLibrary/Fibonacci.hlsl


// Computes a point using the Fibonacci sequence of length N.
// Input: Fib[N - 1], Fib[N - 2], and the index 'i' of the point.
// Ref: Efficient Quadrature Rules for Illumination Integrals
float2 Fibonacci2dSeq(float fibN1, float fibN2, int i)
float2 Fibonacci2dSeq(float fibN1, float fibN2, uint i)
{
// 3 cycles on GCN if 'fibN1' and 'fibN2' are known at compile time.
// N.b.: According to Swinbank and Pusser [SP06], the uniformity of the distribution

#define GOLDEN_RATIO 1.6180339887498948482
// Replaces the Fibonacci sequence in Fibonacci2dSeq() with the Golden ratio.
float2 Golden2dSeq(int i, float n)
float2 Golden2dSeq(uint i, float n)
static const int k_FibonacciSeq[] = {
static const uint k_FibonacciSeq[] = {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181
};

case 89: return k_Fibonacci2dSeq89[i];
default:
{
int fibN1 = sampleCount;
int fibN2 = sampleCount;
uint fibN1 = sampleCount;
uint fibN2 = sampleCount;
for (int j = 1; j < 20; j++)
for (uint j = 1; j < 20; j++)
{
if (k_FibonacciSeq[j] == fibN1)
{

17
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


if (NdotL > 0.0)
{
// Integral is
// 1 / NumSample * \int[ L * fr * (N.L) / pdf ] with pdf = D(H) * (N.H) / (4 * (L.H)) and fr = F(H) * G(V, L) * D(H) / (4 * (N.L) * (N.V))
// This is split in two part:
// A) \int[ L * (N.L) ]
// B) \int[ F(H) * 4 * (N.L) * V(V, L) * (L.H) / (N.H) ] with V(V, L) = G(V, L) / (4 * (N.L) * (N.V))
// = \int[ F(H) * weightOverPdf ]
// Integral{BSDF * <N,L> dw} =
// Integral{(F0 + (1 - F0) * (1 - <V,H>)^5) * (BSDF / F) * <N,L> dw} =
// F0 * Integral{(BSDF / F) * <N,L> dw} +
// (1 - F0) * Integral{(1 - <V,H>)^5 * (BSDF / F) * <N,L> dw} =
// (1 - F0) * x + F0 * y = lerp(x, y, F0)
// Recombine at runtime with: ( f0 * weightOverPdf * (1 - Fc) + f90 * weightOverPdf * Fc ) with Fc =(1 - V.H)^5
float Fc = pow(1.0 - VdotH, 5.0);
acc.x += (1.0 - Fc) * weightOverPdf;
acc.y += Fc * weightOverPdf;
acc.x += weightOverPdf * pow(1 - VdotH, 5);
acc.y += weightOverPdf;
}
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table

1
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


{
CoreUtils.DrawFullScreen(cmd, m_InitPreFGD, new RenderTargetIdentifier(m_PreIntegratedFGD));
}
m_isInit = true;
}

39
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// Reference Lambert diffuse / GGX Specular for IBL and area lights
#ifdef HAS_LIGHTLOOP // Both reference define below need to be define only if LightLoop is present, else we get a compile error
//#define LIT_DISPLAY_REFERENCE_AREA
//#define LIT_DISPLAY_REFERENCE_IBL
// #define LIT_DISPLAY_REFERENCE_AREA
// #define LIT_DISPLAY_REFERENCE_IBL
#endif
// Use Lambert diffuse instead of Disney diffuse
// #define LIT_DIFFUSE_LAMBERT_BRDF

#define LIT_USE_GGX_ENERGY_COMPENSATION
// Sampler use by area light, gaussian pyramid, ambient occlusion etc...
SamplerState s_linear_clamp_sampler;

// For image based lighting, a part of the BSDF is pre-integrated.
// This is done both for specular and diffuse (in case of DisneyDiffuse)
void GetPreIntegratedFGD(float NdotV, float perceptualRoughness, float3 fresnel0, out float3 specularFGD, out float diffuseFGD)
void GetPreIntegratedFGD(float NdotV, float perceptualRoughness, float3 fresnel0, out float3 specularFGD, out float diffuseFGD, out float reflectivity)
// _PreIntegratedFGD.x = Gv * (1 - Fc) with Fc = (1 - H.L)^5
// _PreIntegratedFGD.y = Gv * Fc
// Integral{BSDF * <N,L> dw} =
// Integral{(F0 + (1 - F0) * (1 - <V,H>)^5) * (BSDF / F) * <N,L> dw} =
// F0 * Integral{(BSDF / F) * <N,L> dw} +
// (1 - F0) * Integral{(1 - <V,H>)^5 * (BSDF / F) * <N,L> dw} =
// (1 - F0) * x + F0 * y = lerp(x, y, F0)
// _PreIntegratedFGD.z = DisneyDiffuse
// z = DisneyDiffuse
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;
specularFGD = lerp(preFGD.xxx, preFGD.yyy, fresnel0);
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
diffuseFGD = 1.0;

reflectivity = preFGD.y;
}
void ApplyDebugToSurfaceData(inout SurfaceData surfaceData)

// GGX
float partLambdaV;
float energyCompensation;
float TdotV;
float BdotV;

iblR = reflect(-V, iblNormalWS);
}
float reflectivity;
GetPreIntegratedFGD(NdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD);
GetPreIntegratedFGD(NdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD, reflectivity);
if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_CLEAR_COAT))
{

preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, iblRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness);
}
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION
// Ref: Practical multiple scattering compensation for microfacet models.
// We only apply the formulation for metals.
// For dielectrics, the change of reflectance is negligible.
// We deem the intensity difference of a couple of percent for high values of roughness
// to not be worth the cost of another precomputed table.
// Note: this formulation bakes the BSDF non-symmetric!
preLightData.energyCompensation = 1 / reflectivity - 1;
#else
preLightData.energyCompensation = 0;
#endif // LIT_USE_GGX_ENERGY_COMPENSATION
// Area light
// UVs for sampling the LUTs

// envDiffuseLighting is used for refraction in this Lit material. Use the weight to balance between transmission and reflection
diffuseLighting = lerp(directDiffuseLighting + bakeDiffuseLighting, accLighting.envDiffuseLighting, accLighting.envDiffuseLightingWeight);
specularLighting = accLighting.dirSpecularLighting + accLighting.punctualSpecularLighting + accLighting.areaSpecularLighting + accLighting.envSpecularLighting;
specularLighting *= 1 + bsdfData.fresnel0 * preLightData.energyCompensation;
}
正在加载...
取消
保存