|
|
|
|
|
|
// Util image based lighting |
|
|
|
//----------------------------------------------------------------------------- |
|
|
|
|
|
|
|
// The *approximated* version of the non-linear remapping which improves |
|
|
|
// the perceptual roughness distribution and adds reflection (contact) hardening. |
|
|
|
// The *approximated* version of the non-linear remapping. It works by |
|
|
|
// approximating the cone of the specular lobe, and then computing the MIP map level |
|
|
|
// which (approximately) covers the footprint of the lobe with a single texel. |
|
|
|
// Improves the perceptual roughness distribution. |
|
|
|
float perceptualRoughnessToMipmapLevel(float perceptualRoughness) |
|
|
|
{ |
|
|
|
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness); |
|
|
|
|
|
|
|
|
|
|
// The *accurate* version of the non-linear remapping which improves |
|
|
|
// the perceptual roughness distribution and adds reflection (contact) hardening. |
|
|
|
// The *accurate* version of the non-linear remapping. It works by |
|
|
|
// approximating the cone of the specular lobe, and then computing the MIP map level |
|
|
|
// which (approximately) covers the footprint of the lobe with a single texel. |
|
|
|
// Improves the perceptual roughness distribution and adds reflection (contact) hardening. |
|
|
|
// TODO: optimize! |
|
|
|
float perceptualRoughnessToMipmapLevel(float perceptualRoughness, float NdotR) |
|
|
|
{ |
|
|
|
|
|
|
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS; |
|
|
|
} |
|
|
|
|
|
|
|
// The *approximated* version of the non-linear remapping which improves |
|
|
|
// the perceptual roughness distribution and adds reflection (contact) hardening. |
|
|
|
// The inverse of perceptualRoughnessToMipmapLevel(). |
|
|
|
float mipmapLevelToPerceptualRoughness(float mipmapLevel) |
|
|
|
{ |
|
|
|
float perceptualRoughness = saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS); |
|
|
|
|
|
|
|
|
|
|
// Ref: See "Moving Frostbite to PBR" Listing 22 |
|
|
|
// This formulation is for GGX only (with smith joint visibility or regular) |
|
|
|
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness) |
|
|
|
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness, float NdotV) |
|
|
|
// TODO: we could bias this further (and use 'NdotV') to better match the reference. |
|
|
|
float lerpFactor = a * (sqrt(a) + roughness); |
|
|
|
// The result is not normalized as we fetch in a cubemap |
|
|
|
return lerp(N, R, lerpFactor); |
|
|
|
|
|
|
float omegaS = rcp(sampleCount) * invPdf; |
|
|
|
// invOmegaP is precomputed on CPU and provide as a parameter of the function |
|
|
|
// float omegaP = FOUR_PI / (6.0f * cubemapWidth * cubemapWidth); |
|
|
|
mipLevel = 0.5 * log2(omegaS * invOmegaP); |
|
|
|
mipLevel = 0.5 * log2(omegaS * invOmegaP + 1.0); |
|
|
|
|
|
|
|
// Bias the MIP map level to compensate for the importance sampling bias. |
|
|
|
// This will blur the reflection. |
|
|
|