浏览代码

Merge pull request #95 from EvgeniiG/master

Improve the quality of IBL
/main
GitHub 8 年前
当前提交
55ce8087
共有 4 个文件被更改,包括 37 次插入24 次删除
  1. 11
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.hlsl
  2. 6
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  3. 6
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl
  4. 38
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl

11
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.hlsl


float anisoGGXLambdaV;
float3 iblDirWS; // Dominant specular direction, used for IBL in EvaluateBSDF_Env()
float iblMipLevel;
float3 specularFGD; // Store preconvole BRDF for both specular and diffuse
float diffuseFGD;

// We need to take into account the modified normal for faking anisotropic here.
float3 iblR = reflect(-V, iblNormalWS);
preLightData.iblDirWS = GetSpecularDominantDir(bsdfData.normalWS, iblR, bsdfData.roughness);
preLightData.iblDirWS = GetSpecularDominantDir(bsdfData.normalWS, iblR, bsdfData.roughness, preLightData.NdotV);
preLightData.iblMipLevel = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
// Area light specific
// UVs for sampling the LUTs

// TODO: we must always perform a weight calculation as due to tiled rendering we need to smooth out cubemap at boundaries.
// So goal is to split into two category and have an option to say if we parallax correct or not.
// TODO: compare current Morten version: offline cubemap with a particular remap + the bias in perceptualRoughnessToMipmapLevel
// to classic remap like unreal/Frobiste. The function GetSpecularDominantDir can result in a better matching in this case
// We let GetSpecularDominantDir currently as it still an improvement but not as good as it could be
float mip = perceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, R, mip);
float4 preLD = SampleEnv(lightLoopContext, lightData.envIndex, R, preLightData.iblMipLevel);
specularLighting = preLD.rgb * preLightData.specularFGD;
// Apply specular occlusion on it

6
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalTS = reflect(normalTS, float3(0.0, 0.0, 1.0)); // Reflect around vertex normal (in tangent space this is z)
#endif
// TODO : Test if GetOdddNegativeScale() is necessary here in case of normal map, as GetOdddNegativeScale is take into account in CreateTangentToWorld();
// TODO : Test if GetOddNegativeScale() is necessary here in case of normal map, as GetOddNegativeScale is take into account in CreateTangentToWorld();
(GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) :
(-GetOdddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
(GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) :
(-GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A

6
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl


return glstate_matrix_inv_projection;
}
float GetOdddNegativeScale()
float GetOddNegativeScale()
{
return unity_WorldTransformParams.w;
}

float3x3 CreateTangentToWorld(float3 normal, float3 tangent, float tangentSign)
{
// For odd-negative scale transforms we need to flip the sign
float sign = tangentSign * GetOdddNegativeScale();
float3 bitangent = cross(normal, tangent) * sign;
float sgn = tangentSign * GetOddNegativeScale();
float3 bitangent = cross(normal, tangent) * sgn;
return float3x3(tangent, bitangent, normal);
}

38
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// Util image based lighting
//-----------------------------------------------------------------------------
// Performs a *non-linear* remapping which improves the perceptual roughness distribution
// and adds reflection (contact) hardening. The *approximated* version.
// 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);

// Performs a *non-linear* remapping which improves the perceptual roughness distribution
// and adds reflection (contact) hardening. The *accurate* version.
// 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;
}
// Performs *linear* remapping for runtime EnvMap filtering.
// The inverse of the *approximated* version of perceptualRoughnessToMipmapLevel().
return saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
float perceptualRoughness = saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
return saturate(1.7 / 1.4 - sqrt(2.89 - 2.8 * perceptualRoughness) / 1.4);
// 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)
// Ref: "Moving Frostbite to PBR", p. 69.
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness, float NdotV)
float lerpFactor = a * (sqrt(a) + roughness);
float s = sqrt(a);
#ifdef USE_FB_DSD
// This is the original formulation.
float lerpFactor = (s + roughness) * a;
#else
// TODO: tweak this further to achieve a closer match to the reference.
float lerpFactor = (s + roughness) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
#endif
// The result is not normalized as we fetch in a cubemap
return lerp(N, R, lerpFactor);
}

// Bias samples towards the mirror direction to reduce variance.
// This will have a side effect of making the reflection sharper.
// Ref: Stochastic Screen-Space Reflections, p. 67.
const float bias = 0.2;
const float bias = 0.1 + 0.2 * roughness;
u.x = lerp(u.x, 0.0, bias);
float3 L;

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.

正在加载...
取消
保存