浏览代码

HDRenderLoop: Fix anisotropy + rename BSDF with NoPI

- Rename DividePI to nothing and use NoPI instead
- Update UI + code to handle anisotropy correctly
/main
Sebastien Lagarde 8 年前
当前提交
84c14eca
共有 6 个文件被更改,包括 142 次插入43 次删除
  1. 53
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl
  2. 25
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/LitUI.cs
  3. 24
      Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl
  4. 2
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  5. 73
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/anisoTest.mat
  6. 8
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/anisoTest.mat.meta

53
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/Lit.hlsl


// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;
#if DIFFUSE_LAMBERT_BRDF
#ifdef DIFFUSE_LAMBERT_BRDF
diffuseFGD = 1.0;
#else
diffuseFGD = preFGD.z;

bsdfData.fresnel0 = lerp(float3(specular, specular, specular), baseColor, metallic);
bsdfData.tangentWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
// TODO: Do we need to orthonormalize here, IIRC Eric say that we should
bsdfData.bitangentWS = cross(bsdfData.normalWS, bsdfData.tangentWS);
ConvertAnisotropyToRoughness(bsdfData.roughness, anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
bsdfData.anisotropy = anisotropy;

#ifdef USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV( preLightData.TdotV, preLightData.BdotV, preLightData.NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, preLightData.anisoGGXlambdaV);
bsdfData.roughnessT, bsdfData.roughnessB, preLightData.anisoGGXLambdaV);
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
float TdotH = saturate(dot(bsdfData.tangentWS, H));
float BdotH = saturate(dot(bsdfData.bitangentWS, H));
D = D_GGXAnisoDividePI(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float BdotH = dot(bsdfData.bitangentWS, H);
D = D_GGXAniso(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
}
else
{

Vis = V_SmithJointGGX(NdotL, preLightData.NdotV, bsdfData.roughness);
#endif
D = D_GGXDividePI(NdotH, bsdfData.roughness);
D = D_GGX(NdotH, bsdfData.roughness);
float diffuseTerm = LambertDividePI();
float diffuseTerm = Lambert();
float diffuseTerm = DisneyDiffuseDividePI(preLightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuse(preLightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
#endif
diffuseLighting.rgb = bsdfData.diffuseColor * diffuseTerm;
}

diffuseLighting = float4(0.0, 0.0, 0.0, 1.0);
specularLighting = float4(0.0, 0.0, 0.0, 1.0);
// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0
// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0
[branch] if (lightData.cookieIndex && illuminance > 0.0f)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
illuminance *= SampleCookie(lightData.cookieIndex, lightToWorld, L);
}
[branch] if (lightData.cookieIndex && illuminance > 0.0f)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
illuminance *= SampleCookie(lightData.cookieIndex, lightToWorld, L);
}
[branch] if (lightData.IESIndex >= 0 && illuminance > 0.0f)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
[branch] if (lightData.IESIndex >= 0 && illuminance > 0.0f)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
}
}
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0f)
{
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0f)
{
float3 offset = float3(0.0, 0.0, 0.0); // GetShadowPosOffset(nDotL, normal);
shadowAttenuation = lerp(1.0, shadowAttenuation, lightData.shadowDimmer);
shadowAttenuation = lerp(1.0, shadowAttenuation, lightData.shadowDimmer);
illuminance *= shadowAttenuation;
}
illuminance *= shadowAttenuation;
}
[branch] if (illuminance > 0.0f)
{

float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += bsdfData.diffuseColor * Lambert() * weightOverPdf * val.rgb;
acc += bsdfData.diffuseColor * LambertNoPI() * weightOverPdf * val.rgb;
}
}

25
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders/Material/Lit/LitUI.cs


public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC5) - DXT5 for test");
public static GUIContent normalMapSpaceText = new GUIContent("Normal Map space", "");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
// public static GUIContent diffuseLightingMapText = new GUIContent("DiffuseLightingMap", "Lightmap/Lightprobe data (fill by system is not done");
public static GUIContent tangentMapText = new GUIContent("Tangent Map", "Tangent Map (BC5) - DXT5 for test");
public static GUIContent anisotropyText = new GUIContent("Anisotropy", "Anisotropy scale factor");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map", "Anisotropy (R)");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");

MaterialProperty heightMap = null;
MaterialProperty heightScale = null;
MaterialProperty heightBias = null;
MaterialProperty tangentMap = null;
MaterialProperty anisotropy = null;
MaterialProperty anisotropyMap = null;
// MaterialProperty diffuseLightingMap = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;

protected const string kspecularOcclusionMap = "_SpecularOcclusionMap";
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected const string kHeightMap = "_HeightMap";
protected const string kTangentMap = "_TangentMap";
protected const string kAnisotropyMap = "_AnisotropyMap";
public void FindOptionProperties(MaterialProperty[] props)
{

heightMap = FindProperty(kHeightMap, props);
heightScale = FindProperty("_HeightScale", props);
heightBias = FindProperty("_HeightBias", props);
// diffuseLightingMap = FindProperty("_DiffuseLightingMap", props);
tangentMap = FindProperty("_TangentMap", props);
anisotropy = FindProperty("_Anisotropy", props);
anisotropyMap = FindProperty("_AnisotropyMap", props);
emissiveColor = FindProperty("_EmissiveColor", props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);

m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightScale, heightBias);
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapText, tangentMap);
m_MaterialEditor.ShaderProperty(anisotropy, Styles.anisotropyText);
m_MaterialEditor.TexturePropertySingleLine(Styles.anisotropyMapText, anisotropyMap, anisotropy);
if (!useEmissiveMask)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);

SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
SetKeyword(material, "_TANGENTMAP", material.GetTexture(kTangentMap));
SetKeyword(material, "_ANISOTROPYMAP", material.GetTexture(kAnisotropyMap));
}
protected void SetupMaterial(Material material)

24
Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl


// With analytical light (not image based light) we clamp the minimun roughness in the NDF to avoid numerical instability.
#define UNITY_MIN_ROUGHNESS 0.002
float D_GGX(float NdotH, float roughness)
float D_GGXNoPI(float NdotH, float roughness)
{
roughness = max(roughness, UNITY_MIN_ROUGHNESS);

}
float D_GGXDividePI(float NdotH, float roughness)
float D_GGX(float NdotH, float roughness)
return INV_PI * D_GGX(NdotH, roughness);
return INV_PI * D_GGXNoPI(NdotH, roughness);
}
// Ref: http://jcgt.org/published/0003/02/03/paper.pdf

float GetSmithJointGGXApproxLambdaV(float NdotV, float roughness)
{
float a = roughness;
return (NdotV * (1 - a) + a);
return NdotV * (1 - a) + a;
}
float V_SmithJointGGXApprox(float NdotL, float NdotV, float roughness, float lambdaV)

// roughnessT -> roughness in tangent direction
// roughnessB -> roughness in bitangent direction
float D_GGXAniso(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
float D_GGXAnisoNoPI(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
{
roughnessT = max(roughnessT, UNITY_MIN_ROUGHNESS);
roughnessB = max(roughnessB, UNITY_MIN_ROUGHNESS);

}
float D_GGXAnisoDividePI(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
float D_GGXAniso(float TdotH, float BdotH, float NdotH, float roughnessT, float roughnessB)
return INV_PI * D_GGXAniso(TdotH, BdotH, NdotH, roughnessT, roughnessB);
return INV_PI * D_GGXAnisoNoPI(TdotH, BdotH, NdotH, roughnessT, roughnessB);
}
// Ref: https://cedec.cesa.or.jp/2015/session/ENG/14698.html The Rendering Materials of Far Cry 4

// Diffuse BRDF - diffuseColor is expected to be multiply by the caller
//-----------------------------------------------------------------------------
float Lambert()
float LambertNoPI()
float LambertDividePI()
float Lambert()
float DisneyDiffuse(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
float DisneyDiffuseNoPI(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
{
float fd90 = 0.5 + 2 * LdotH * LdotH * perceptualRoughness;
// Two schlick fresnel term

return lightScatter * viewScatter;
}
float DisneyDiffuseDividePI(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
float DisneyDiffuse(float NdotV, float NdotL, float LdotH, float perceptualRoughness)
return INV_PI * DisneyDiffuse(NdotV, NdotL, LdotH, perceptualRoughness);
return INV_PI * DisneyDiffuseNoPI(NdotV, NdotL, LdotH, perceptualRoughness);
}

2
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// - OmegaS : Solid angle associated to a sample
// - OmegaP : Solid angle associated to a pixel of the cubemap
float pdf = D_GGXDividePI(NdotH, roughness) * NdotH / (4.0 * LdotH);
float pdf = D_GGXNoPI(NdotH, roughness) * NdotH / (4.0 * LdotH); // TODO: Check if divide PI is required here
float omegaS = 1.0 / (sampleCount * pdf); // Solid angle associated to a sample
// invOmegaP is precomputed on CPU and provide as a parameter of the function
// float omegaP = FOUR_PI / (6.0f * cubemapWidth * cubemapWidth); // Solid angle associated to a pixel of the cubemap

73
Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/anisoTest.mat


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: anisoTest
m_Shader: {fileID: 46, guid: 0000000000000000f000000000000000, type: 0}
m_ShaderKeywords: _EMISSION
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _BumpScale: 1
- _Cutoff: 0.5
- _DetailNormalMapScale: 1
- _DstBlend: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _Metallic: 0
- _Mode: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}

8
Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/anisoTest.mat.meta


fileFormatVersion: 2
guid: eaec57fbf2cf08c4e8f4b6322cb0a015
timeCreated: 1478226940
licenseType: Pro
NativeFormatImporter:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存