浏览代码

Merge pull request #396 from Unity-Technologies/specular-occlusion

Specular occlusion - draft
/main
GitHub 7 年前
当前提交
465a57d0
共有 12 个文件被更改,包括 192 次插入15 次删除
  1. 33
      ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl
  2. 23
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  3. 3
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  4. 3
      ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader
  5. 21
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  6. 3
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  7. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader
  8. 22
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl
  9. 8
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  10. 2
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader
  11. 10
      SampleScenes/HDTest/HDRenderLoopTest.meta
  12. 77
      SampleScenes/HDTest/HDRenderLoopTest/ReflectionProbe-0.exr.meta

33
ScriptableRenderPipeline/Core/ShaderLibrary/CommonLighting.hlsl


// Ref: Moving Frostbite to PBR - Gotanda siggraph 2011
// Return specular occlusion based on ambient occlusion (usually get from SSAO) and view/roughness info
float SpecularOcclusionFromAmbientOcclusion(float NdotV, float ambientOcclusion, float roughness)
float GetSpecularOcclusionFromAmbientOcclusion(float NdotV, float ambientOcclusion, float roughness)
{
return saturate(PositivePow(NdotV + ambientOcclusion, exp2(-16.0 * roughness - 1.0)) - 1.0 + ambientOcclusion);
}

float x = visibility;
return max(x, ((x * a + b) * x + c) * x);
}
// Based on Oat and Sander's 2008 technique
// Area/solidAngle of intersection of two cone
float SphericalCapIntersectionSolidArea(float cosC1, float cosC2, float cosB)
{
float r1 = FastACos(cosC1);
float r2 = FastACos(cosC2);
float rd = FastACos(cosB);
float area = 0.0;
if (rd <= max(r1, r2) - min(r1, r2))
{
// One cap is completely inside the other
area = TWO_PI - TWO_PI * max(cosC1, cosC2);
}
else if (rd >= r1 + r2)
{
// No intersection exists
area = 0.0;
}
else
{
float diff = abs(r1 - r2);
float den = r1 + r2 - diff;
float x = 1.0 - saturate((rd - diff) / den);
area = smoothstep(0.0, 1.0, x);
area *= TWO_PI - TWO_PI * max(cosC1, cosC2);
}
return area;
}
//-----------------------------------------------------------------------------

23
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


{
string propertyName = ShaderUtil.GetPropertyName(layerShader, i);
string layerPropertyName = propertyName + layerIndex;
if (!exclusionList.Contains(propertyName) || !excludeUVMappingProperties)
{
if (material.HasProperty(layerPropertyName))

}
bool DoMaterialReferencesGUI(AssetImporter materialImporter)
{
{
EditorGUILayout.LabelField(styles.materialReferencesText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;

}
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_ENABLESPECULAROCCLUSION", material.GetFloat(kEnableSpecularOcclusion) > 0.0f);
SetKeyword(material, "_MAIN_LAYER_INFLUENCE_MODE", material.GetFloat(kkUseMainLayerInfluence) != 0.0f);

}
SetKeyword(material, "_DENSITY_MODE", useDensityModeEnable);
}
private void DoEmissiveGUI(Material material)
{
EditorGUILayout.Space();
EditorGUILayout.LabelField(Styles.lightingText, EditorStyles.boldLabel);
m_MaterialEditor.ShaderProperty(enableSpecularOcclusion, Styles.enableSpecularOcclusionText);
// TODO: display warning if we don't have bent normal (either OS or TS) and ambient occlusion
//if (enableSpecularOcclusion.floatValue > 0.0f)
{
// EditorGUILayout.HelpBox(Styles.specularOcclusionWarning.text, MessageType.Error);
}
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.ShaderProperty(albedoAffectEmissive, Styles.albedoAffectEmissiveText);
EditorGUI.indentLevel--;
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)
{

}
bool layerChanged = DoLayersGUI(materialImporter);
DoEmissiveGUI();
DoEmissiveGUI(material);
DoEmissionArea(material);
EditorGUI.indentLevel--;
m_MaterialEditor.EnableInstancingField();

3
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_ShiverDrag("Shiver Drag", float) = 0.2
_ShiverDirectionality("Shiver Directionality", Range(0.0, 1.0)) = 0.5
[ToggleOff] _EnableSpecularOcclusion("Enable specular occlusion", Float) = 0.0
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}
_EmissiveIntensity("EmissiveIntensity", Float) = 0

#pragma shader_feature _BENTNORMALMAP2
#pragma shader_feature _BENTNORMALMAP3
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _ENABLESPECULAROCCLUSION
#pragma shader_feature _HEIGHTMAP0
#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2

3
ScriptableRenderPipeline/HDRenderPipeline/Material/LayeredLit/LayeredLitTessellation.shader


_ShiverDrag("Shiver Drag", float) = 0.2
_ShiverDirectionality("Shiver Directionality", Range(0.0, 1.0)) = 0.5
[ToggleOff] _EnableSpecularOcclusion("Enable specular occlusion", Float) = 0.0
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}
_EmissiveIntensity("EmissiveIntensity", Float) = 0

#pragma shader_feature _BENTNORMALMAP2
#pragma shader_feature _BENTNORMALMAP3
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _ENABLESPECULAROCCLUSION
#pragma shader_feature _HEIGHTMAP0
#pragma shader_feature _HEIGHTMAP1
#pragma shader_feature _HEIGHTMAP2

21
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


// Specular color
public static GUIContent specularColorText = new GUIContent("Specular Color", "Specular color (RGB)");
// Specular occlusion
public static GUIContent enableSpecularOcclusionText = new GUIContent("Enable Specular Occlusion from Bent normal", "Require cosine weighted bent normal and cosine weighted ambient occlusion. Specular occlusion for reflection probe");
public static GUIContent specularOcclusionWarning = new GUIContent("Require a cosine weighted bent normal and ambient occlusion maps");
// Emissive
public static string lightingText = "Lighting Inputs";
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");

protected const string kEmissiveIntensity = "_EmissiveIntensity";
protected MaterialProperty albedoAffectEmissive = null;
protected const string kAlbedoAffectEmissive = "_AlbedoAffectEmissive";
protected MaterialProperty enableSpecularOcclusion = null;
protected const string kEnableSpecularOcclusion = "_EnableSpecularOcclusion";
protected void FindMaterialLayerProperties(MaterialProperty[] props)
{

emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty(kEmissiveIntensity, props);
albedoAffectEmissive = FindProperty(kAlbedoAffectEmissive, props);
enableSpecularOcclusion = FindProperty(kEnableSpecularOcclusion, props);
}
protected override void FindMaterialProperties(MaterialProperty[] props)

EditorGUI.indentLevel--;
}
protected void DoEmissiveGUI()
private void DoEmissiveGUI(Material material)
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(enableSpecularOcclusion, Styles.enableSpecularOcclusionText);
// TODO: display warning if we don't have bent normal (either OS or TS) and ambient occlusion
//if (enableSpecularOcclusion.floatValue > 0.0f)
{
//EditorGUILayout.HelpBox(Styles.specularOcclusionWarning.text, MessageType.Error);
}
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);
m_MaterialEditor.ShaderProperty(emissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.ShaderProperty(albedoAffectEmissive, Styles.albedoAffectEmissiveText);

protected override void MaterialPropertiesGUI(Material material)
{
DoLayerGUI(material, 0);
DoEmissiveGUI();
DoEmissiveGUI(material);
// The parent Base.ShaderPropertiesGUI will call DoEmissionArea
}

}
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_ENABLESPECULAROCCLUSION", material.GetFloat(kEnableSpecularOcclusion) > 0.0f);
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
SetKeyword(material, "_ANISOTROPYMAP", material.GetTexture(kAnisotropyMap));
SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap));

3
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, lightLoopContext.indirectAmbientOcclusion, bsdfData.roughness);
// Try to mimic multibounce with specular color. Not the point of the original formula but ok result.
accLighting.envSpecularLighting *= bsdfData.specularOcclusion * GTAOMultiBounce(specularOcclusion, bsdfData.fresnel0);
// Take the min of screenspace specular occlusion and visibility cone specular occlusion
accLighting.envSpecularLighting *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0);
// TODO: we could call a function like PostBSDF that will apply albedo and divide by PI once for the loop

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.shader


// Following options are for the GUI inspector and different from the input parameters above
// These option below will cause different compilation flag.
[ToggleOff] _EnableSpecularOcclusion("Enable specular occlusion", Float) = 0.0
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}

#pragma shader_feature _MASKMAP
#pragma shader_feature _BENTNORMALMAP
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _ENABLESPECULAROCCLUSION
#pragma shader_feature _HEIGHTMAP
#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP

22
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitData.hlsl


#include "../../../Core/ShaderLibrary/SampleUVMapping.hlsl"
#include "../MaterialUtilities.hlsl"
// TODO: move this function to commonLighting.hlsl once validated it work correctly
float GetSpecularOcclusionFromBentAO(float3 V, float3 bentNormalWS, SurfaceData surfaceData)
{
// Retrieve cone angle
// Ambient occlusion is cosine weighted, thus use following equation. See slide 129
float cosAv = sqrt(1.0 - surfaceData.ambientOcclusion);
float roughness = max(PerceptualSmoothnessToRoughness(surfaceData.perceptualSmoothness), 0.01); // Clamp to 0.01 to avoid edge cases
float cosAs = exp2(-3.32193 * Sqr(roughness));
float cosB = dot(bentNormalWS, reflect(-V, surfaceData.normalWS));
return SphericalCapIntersectionSolidArea(cosAv, cosAs, cosB) / (TWO_PI * (1.0 - cosAs));
}
void GetBuiltinData(FragInputs input, SurfaceData surfaceData, float alpha, float3 bentNormalWS, float depthOffset, out BuiltinData builtinData)
{

surfaceData.specularOcclusion = 1.0;
#ifdef _BENTNORMALMAP
GetNormalWS(input, V, bentNormalTS, bentNormalWS);
#ifdef _ENABLESPECULAROCCLUSION
surfaceData.specularOcclusion = 1.0; // TODO
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData);
#endif
#else
bentNormalWS = surfaceData.normalWS;
#endif

mappingType = UV_MAPPING_TRIPLANAR;
#endif
// Note: Blend mask have its dedicated mapping and tiling.
// Note: Blend mask have its dedicated mapping and tiling.
// To share code, we simply call the regular code from the main layer for it then save the result, then do regular call for all layers.
ComputeLayerTexCoord0( texCoord0, texCoord1, texCoord2, texCoord3, _UVMappingMaskBlendMask, _UVMappingMaskBlendMask,
positionWS, mappingType, _TexWorldScaleBlendMask, layerTexCoord, _LayerTilingBlendMask);

surfaceData.specularOcclusion = 1.0;
#if defined(_BENTNORMALMAP0) || defined(_BENTNORMALMAP1) || defined(_BENTNORMALMAP2) || defined(_BENTNORMALMAP3)
GetNormalWS(input, V, bentNormalTS, bentNormalWS);
#ifdef _ENABLESPECULAROCCLUSION
surfaceData.specularOcclusion = 1.0; // TODO
surfaceData.specularOcclusion = GetSpecularOcclusionFromBentAO(V, bentNormalWS, surfaceData);
#endif
#else // if no bent normal are available at all just keep the calculation fully
bentNormalWS = surfaceData.normalWS;
#endif

8
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitProperties.hlsl


TEXTURE2D(_MaskMap);
SAMPLER2D(sampler_MaskMap);
TEXTURE2D(_SpecularOcclusionMap);
SAMPLER2D(sampler_SpecularOcclusionMap);
TEXTURE2D(_BentNormalMap); // Reuse sampler from normal map
SAMPLER2D(sampler_BentNormalMap);
TEXTURE2D(_NormalMap);
SAMPLER2D(sampler_NormalMap);

PROP_DECL_TEX2D(_BaseColorMap);
PROP_DECL_TEX2D(_MaskMap);
PROP_DECL_TEX2D(_SpecularOcclusionMap);
PROP_DECL_TEX2D(_BentNormalMap);
PROP_DECL_TEX2D(_NormalMap);
PROP_DECL_TEX2D(_NormalMapOS);
PROP_DECL_TEX2D(_HeightMap);

float3 _EmissiveColor;
float _EmissiveIntensity;
float _AlbedoAffectEmissive;
float _EnableSpecularOcclusion;
// Caution: C# code in BaseLitUI.cs call LightmapEmissionFlagsProperty() which assume that there is an existing "_EmissionColor"
// value that exist to identify if the GI emission need to be enabled.

2
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.shader


// Following options are for the GUI inspector and different from the input parameters above
// These option below will cause different compilation flag.
[ToggleOff] _EnableSpecularOcclusion("Enable specular occlusion", Float) = 0.0
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}

#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _EMISSIVE_COLOR_MAP
#pragma shader_feature _ENABLESPECULAROCCLUSION
#pragma shader_feature _HEIGHTMAP
#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP

10
SampleScenes/HDTest/HDRenderLoopTest.meta


fileFormatVersion: 2
guid: 030c34355b9969e4e9185afe200a7b9c
folderAsset: yes
timeCreated: 1504524294
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

77
SampleScenes/HDTest/HDRenderLoopTest/ReflectionProbe-0.exr.meta


fileFormatVersion: 2
guid: 8a71c17fe204c99479b1bae8ef21b003
timeCreated: 1504524398
licenseType: Pro
TextureImporter:
fileIDToRecycleName: {}
externalObjects: {}
serializedVersion: 4
mipmaps:
mipMapMode: 0
enableMipMap: 1
sRGBTexture: 1
linearTexture: 0
fadeOut: 0
borderMipMap: 0
mipMapsPreserveCoverage: 0
alphaTestReferenceValue: 0.5
mipMapFadeDistanceStart: 1
mipMapFadeDistanceEnd: 3
bumpmap:
convertToNormalMap: 0
externalNormalMap: 0
heightScale: 0.25
normalMapFilter: 0
isReadable: 0
grayScaleToAlpha: 0
generateCubemap: 6
cubemapConvolution: 0
seamlessCubemap: 0
textureFormat: 1
maxTextureSize: 2048
textureSettings:
serializedVersion: 2
filterMode: -1
aniso: -1
mipBias: -1
wrapU: -1
wrapV: -1
wrapW: -1
nPOTScale: 1
lightmap: 0
compressionQuality: 50
spriteMode: 0
spriteExtrude: 1
spriteMeshType: 1
alignment: 0
spritePivot: {x: 0.5, y: 0.5}
spriteBorder: {x: 0, y: 0, z: 0, w: 0}
spritePixelsToUnits: 100
alphaUsage: 1
alphaIsTransparency: 0
spriteTessellationDetail: -1
textureType: 0
textureShape: 1
maxTextureSizeSet: 0
compressionQualitySet: 0
textureFormatSet: 0
platformSettings:
- buildTarget: DefaultTexturePlatform
maxTextureSize: 2048
resizeAlgorithm: 0
textureFormat: -1
textureCompression: 1
compressionQuality: 50
crunchedCompression: 0
allowsAlphaSplitting: 0
overridden: 0
androidETC2FallbackOverride: 0
spriteSheet:
serializedVersion: 2
sprites: []
outline: []
physicsShape: []
spritePackingTag:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存