浏览代码

Switch to Emmanuel's version of MS energy compensation

/Yibing-Project-2
Evgenii Golubev 7 年前
当前提交
7ddb7cdc
共有 6 个文件被更改,包括 22 次插入107 次删除
  1. 6
      ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl
  2. 16
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  3. 40
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  4. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl
  5. 10
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader.meta
  6. 55
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader

6
ScriptableRenderPipeline/Core/ShaderLibrary/ImageBasedLighting.hlsl


// 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} =
// F0 * y + (1 - F0) * x = lerp(x, y, F0)
// (1 - F0) * x + F0 * y = lerp(x, y, F0)
acc.x += weightOverPdf;
acc.y += weightOverPdf * pow(1 - VdotH, 5);
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

16
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


// For image based lighting
Material m_InitPreFGD;
Material m_ComputeGgxEnergyCompensationFactors;
RenderTexture m_GgxEnergyCompensationFactors;
// For area lighting - We pack all texture inside a texture array to reduce the number of resource required
Texture2DArray m_LtcData; // 0: m_LtcGGXMatrix - RGBA, 2: m_LtcDisneyDiffuseMatrix - RGBA, 3: m_LtcMultiGGXFresnelDisneyDiffuse - RGB, A unused

public override void Build(RenderPipelineResources renderPipelineResources)
{
m_InitPreFGD = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/PreIntegratedFGD");
m_ComputeGgxEnergyCompensationFactors = CoreUtils.CreateEngineMaterial("Hidden/HDRenderPipeline/ComputeGgxEnergyCompensationFactors");
// For DisneyDiffuse integration values goes from (0.5 to 1.53125). GGX need 0 to 1. Use float format.
m_PreIntegratedFGD = new RenderTexture(128, 128, 0, RenderTextureFormat.RGB111110Float, RenderTextureReadWrite.Linear);

m_PreIntegratedFGD.Create();
m_GgxEnergyCompensationFactors = new RenderTexture(128, 128, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
m_GgxEnergyCompensationFactors.filterMode = FilterMode.Bilinear;
m_GgxEnergyCompensationFactors.wrapMode = TextureWrapMode.Clamp;
m_GgxEnergyCompensationFactors.hideFlags = HideFlags.DontSave;
m_GgxEnergyCompensationFactors.Create();
m_LtcData = new Texture2DArray(k_LtcLUTResolution, k_LtcLUTResolution, 3, TextureFormat.RGBAHalf, false /*mipmap*/, true /* linear */)
{
hideFlags = HideFlags.HideAndDontSave,

public override void Cleanup()
{
CoreUtils.Destroy(m_InitPreFGD);
CoreUtils.Destroy(m_ComputeGgxEnergyCompensationFactors);
// TODO: how to delete RenderTexture ? or do we need to do it ?
m_isInit = false;

CoreUtils.DrawFullScreen(cmd, m_InitPreFGD, new RenderTargetIdentifier(m_PreIntegratedFGD));
}
using (new ProfilingSample(cmd, "Compute GGX Energy Compensation Factors"))
{
CoreUtils.DrawFullScreen(cmd, m_ComputeGgxEnergyCompensationFactors, new RenderTargetIdentifier(m_GgxEnergyCompensationFactors));
}
m_isInit = true;
}

Shader.SetGlobalTexture("_GgxEnergyCompensationFactors", m_GgxEnergyCompensationFactors);
Shader.SetGlobalTexture("_LtcData", m_LtcData);
}
}

40
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


// Area light textures
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);
TEXTURE2D(_GgxEnergyCompensationFactors);
TEXTURE2D_ARRAY(_LtcData); // We pack the 3 Ltc data inside a texture array
#define LTC_GGX_MATRIX_INDEX 0 // RGBA
#define LTC_DISNEY_DIFFUSE_MATRIX_INDEX 1 // RGBA

// 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)
{
// Pre-integrate GGX FGD
// Integral{BSDF * <N,L> dw} =

// F0 * y + (1 - F0) * x = lerp(x, y, F0)
// (1 - F0) * x + F0 * y = lerp(x, y, F0)
// Pre integrate DisneyDiffuse FGD:
// z = DisneyDiffuse
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, s_linear_clamp_sampler, float2(NdotV, perceptualRoughness), 0).xyz;

#else
diffuseFGD = preFGD.z;
#endif
reflectivity = preFGD.y;
}
void ApplyDebugToSurfaceData(inout SurfaceData surfaceData)

// GGX
float partLambdaV;
float3 energyCompensation;
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))
{

}
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION
#if 1 // Evgenii's horrible hack to match Eric's results for gold in Mitsuba
float3 cbsdfInt = preLightData.specularFGD;
float3 Kms = 1 / cbsdfInt - 1;
float3 Fms = Sqr(bsdfData.fresnel0);
preLightData.energyCompensation = (1 + Fms * Kms);
preLightData.specularFGD = lerp(Fms, 1, cbsdfInt); // Equivalent to (specularFGD * energyCompensation)
#else // Emmanuel's reference implementation for metals
float cbsdfInt = SAMPLE_TEXTURE2D_LOD(_GgxEnergyCompensationFactors, s_linear_clamp_sampler, float2(NdotV, bsdfData.perceptualRoughness), 0).r;
float Kms = 1 / cbsdfInt - 1;
float3 Fms = bsdfData.fresnel0;
preLightData.energyCompensation = (1 + Fms * Kms);
preLightData.specularFGD *= preLightData.energyCompensation;
#endif
// 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;
preLightData.energyCompensation = 1;
preLightData.energyCompensation = 0;
#endif // LIT_USE_GGX_ENERGY_COMPENSATION
// Area light

);
#endif
}
specularLighting += F * DV * preLightData.energyCompensation;
specularLighting += F * DV * (1 + bsdfData.fresnel0 * preLightData.energyCompensation);
#ifdef LIT_DIFFUSE_LAMBERT_BRDF

// 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;
}

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl


}
}
return acc * preLightData.energyCompensation / sampleCount;
return acc / sampleCount;
}

10
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader.meta


fileFormatVersion: 2
guid: c7c7d11c211eb5746b7fe3d016ae62e8
timeCreated: 1508422200
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

55
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/ComputeGgxEnergyCompensationFactors.shader


Shader "Hidden/HDRenderPipeline/ComputeGgxEnergyCompensationFactors"
{
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
#include "../../../../Core/ShaderLibrary/Common.hlsl"
#include "../../../../Core/ShaderLibrary/ImageBasedLighting.hlsl"
#include "../../../ShaderVariables.hlsl"
struct Attributes
{
uint vertexID : SV_VertexID;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float2 texCoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
output.texCoord = GetFullScreenTriangleTexCoord(input.vertexID);
return output;
}
float4 Frag(Varyings input) : SV_Target
{
// These coordinate sampling must match the decoding in GetPreIntegratedDFG in lit.hlsl, i.e here we use perceptualRoughness, must be the same in shader
float NdotV = input.texCoord.x;
float roughness = PerceptualRoughnessToRoughness(input.texCoord.y);
float3 N = float3(0, 0, 1);
float3 V = float3(sqrt(1 - NdotV * NdotV), 0, NdotV);
float cbsdfInt = IntegrateGgxWithoutFresnel(V, N, roughness);
return cbsdfInt.xxxx;
}
ENDHLSL
}
}
Fallback Off
}
正在加载...
取消
保存