浏览代码

Update all shaders

/stochastic_alpha_test
Sebastien Lagarde 7 年前
当前提交
816098d9
共有 18 个文件被更改,包括 667 次插入646 次删除
  1. 29
      ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Editor/BaseEyeUI.cs
  2. 74
      ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Editor/EyeUI.cs
  3. 68
      ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Eye.hlsl
  4. 28
      ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Eye.shader
  5. 100
      ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/EyeData.hlsl
  6. 29
      ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Editor/BaseFabricUI.cs
  7. 74
      ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Editor/FabricUI.cs
  8. 76
      ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Fabric.hlsl
  9. 28
      ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Fabric.shader
  10. 96
      ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/FabricData.hlsl
  11. 4
      ScriptableRenderPipeline/HDRenderPipeline/Material/Hair/Hair.shader
  12. 130
      ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare1.hlsl
  13. 524
      ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare2.hlsl
  14. 11
      ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  15. 10
      ScriptableRenderPipeline/LightweightPipeline.meta
  16. 10
      Tests.meta
  17. 12
      ScriptableRenderPipeline/HDRenderPipeline/Editor/SceneSettingsManagementWindow.cs.meta
  18. 10
      Tests/GraphicsTests/RenderPipeline/HDRenderPipeline/Scenes/0xxx.meta

29
ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Editor/BaseEyeUI.cs


EditorGUI.indentLevel--;
}
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, StylesBaseLit.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0f)
{

static public void SetupBaseLitMaterialPass(Material material)
{
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
bool distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
if (distortionEnable && distortionOnly)
{
// Disable all passes except distortion (setup in BaseUnlitUI.cs) and debug passes (to visualize distortion)
material.SetShaderPassEnabled("GBuffer", false);
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
material.SetShaderPassEnabled("Meta", false);
material.SetShaderPassEnabled("ShadowCaster", false);
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("MotionVectors", false);
material.SetShaderPassEnabled("Forward", false);
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
}
else
{
// Enable all passes except distortion (setup in BaseUnlitUI.cs)
material.SetShaderPassEnabled("GBuffer", true);
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
material.SetShaderPassEnabled("Meta", true);
material.SetShaderPassEnabled("ShadowCaster", true);
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("MotionVectors", true);
material.SetShaderPassEnabled("Forward", true);
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
}
}
}
} // namespace UnityEditor

74
ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Editor/EyeUI.cs


public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC7/BC5/DXT5(nm))");
public static GUIContent normalMapOSText = new GUIContent("Normal Map OS", "Normal Map (BC7/DXT1/RGB)");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent heightMapText = new GUIContent("Height Map (R)", "Height Map");
public static GUIContent heightMapAmplitudeText = new GUIContent("Height Map Amplitude", "Height Map amplitude in world units.");
public static GUIContent heightMapCenterText = new GUIContent("Height Map Center", "Center of the heightmap in the texture (between 0 and 1)");

UseEmissiveColor,
UseEmissiveMask,
}
protected MaterialProperty UVBase = null;
protected const string kUVBase = "_UVBase";
protected MaterialProperty TexWorldScale = null;

protected void ShaderSSSInputGUI(Material material)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var sssSettings = hdPipeline.sssSettings;
if (subsurfaceProfile == null)
if (sssSettings == null)
// Attempt to load the profile from the SSS Settings.
int profileID = (int)subsurfaceProfileID.floatValue;
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null)
{
// This is a valid profile ID.
subsurfaceProfile = hdPipeline.sssSettings.profiles[profileID];
// Refresh the ID of the profile.
hdPipeline.sssSettings.OnValidate();
}
EditorGUILayout.HelpBox("No Subsurface Scattering Settings have been assigned to the render pipeline asset.", MessageType.Warning);
return;
subsurfaceProfile = EditorGUILayout.ObjectField(Styles.subsurfaceProfileText, subsurfaceProfile, typeof(SubsurfaceScatteringProfile), false) as SubsurfaceScatteringProfile;
// TODO: Optimize me
var profiles = hdPipeline.sssSettings.profiles;
var names = new GUIContent[profiles.Length + 1];
names[0] = new GUIContent("None");
bool validProfile = false;
var values = new int[names.Length];
values[0] = SssConstants.SSS_NEUTRAL_PROFILE_ID;
// Set the profile ID.
if (subsurfaceProfile != null)
for (int i = 0; i < profiles.Length; i++)
// Load the profile from the GUI field.
int profileID = subsurfaceProfile.settingsIndex;
names[i + 1] = new GUIContent(profiles[i].name);
values[i + 1] = i + 1;
}
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null &&
hdPipeline.sssSettings.profiles[profileID] == subsurfaceProfile)
using (var scope = new EditorGUI.ChangeCheckScope())
{
int profileID = (int)subsurfaceProfileID.floatValue;
using (new EditorGUILayout.HorizontalScope())
validProfile = true;
material.SetInt("_SubsurfaceProfile", profileID);
EditorGUILayout.PrefixLabel(Styles.subsurfaceProfileText);
using (new EditorGUILayout.HorizontalScope())
{
profileID = EditorGUILayout.IntPopup(profileID, names, values);
if (GUILayout.Button("Goto", EditorStyles.miniButton, GUILayout.Width(50f)))
Selection.activeObject = sssSettings;
}
else
{
subsurfaceProfile = null;
Debug.LogError("The SSS Profile assigned to the material has an invalid index. First, add the Profile to the SSS Settings, and then reassign it to the material.");
}
}
if (!validProfile)
{
// Disable SSS for this object.
material.SetInt("_SubsurfaceProfile", SssConstants.SSS_NEUTRAL_PROFILE_ID);
if (scope.changed)
subsurfaceProfileID.floatValue = profileID;
}
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);

{
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapOSText, tangentMapOS);
}
}
protected override void MaterialPropertiesGUI(Material material)

m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapSText, maskMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.specularOcclusionMapText, specularOcclusionMap);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText);
// Triplanar only work with tangent space normal

68
ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Eye.hlsl


// SurfaceData is define in Eye.cs which generate Eye.cs.hlsl
#include "Eye.cs.hlsl"
#include "../Lit/SubsurfaceScatteringProfile.cs.hlsl"
#include "../Lit/SubsurfaceScatteringSettings.cs.hlsl"
#define WANT_SSS_CODE
#include "../LightEvaluationShare1.hlsl"

float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float Vis;
float D;
// TODO: this way of handling aniso may not be efficient, or maybe with material classification, need to check perf here
// Maybe always using aniso maybe a win ?
float DV;
float3 H = (L + V) * invLenLV;
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float TdotL = dot(bsdfData.tangentWS, L);
float BdotH = dot(bsdfData.bitangentWS, H);
float BdotL = dot(bsdfData.bitangentWS, L);
float3 H = (L + V) * invLenLV;
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float TdotL = dot(bsdfData.tangentWS, L);
float BdotH = dot(bsdfData.bitangentWS, H);
float BdotL = dot(bsdfData.bitangentWS, L);
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, preLightData.anisoGGXLambdaV);
#else
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
Vis = V_SmithJointGGXAniso(preLightData.TdotV, preLightData.BdotV, NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB);
#endif
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
D = D_GGXAniso(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
preLightData.TdotV, preLightData.BdotV, preLightData.NdotV,
TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData.partLambdaV);
#else
);
#endif
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness, preLightData.ggxLambdaV);
#else
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness);
#endif
D = D_GGX(NdotH, bsdfData.roughness);
DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughness
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData partLambdaV);
#else
);
#endif
specularLighting = 10*F * (Vis * D);
specularLighting = 10 * F * DV;
float diffuseTerm = Lambert();
float diffuseTerm = Lambert();
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.perceptualRoughness);
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
diffuseLighting = bsdfData.diffuseColor * diffuseTerm;
diffuseLighting = bsdfData.diffuseColor * diffuseTerm;
}
#endif // #ifdef HAS_LIGHTLOOP

28
ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/Eye.shader


_ShiverDrag("Shiver Drag", float) = 0.2
_ShiverDirectionality("Shiver Directionality", Range(0.0, 1.0)) = 0.5
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}
// Following options are for the GUI inspector and different from the input parameters above
// These option below will cause different compilation flag.

[ToggleOff] _DistortionEnable("Enable Distortion", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Depth Test Enable", Float) = 0.0
[ToggleOff] _DepthOffsetEnable("Depth Offset View space", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

//-------------------------------------------------------------------------------------
#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT

#include "ShaderPass/EyeVelocityPass.hlsl"
#include "EyeData.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"
ENDHLSL
}
Pass
{
Name "Distortion" // Name is not used
Tags { "LightMode" = "DistortionVectors" } // This will be only for transparent object based on the RenderQueue index
Blend One One
ZTest [_ZTestMode]
ZWrite off
Cull [_CullMode]
HLSLPROGRAM
#define SHADERPASS SHADERPASS_DISTORTION
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/EyeDistortionPass.hlsl"
#include "EyeData.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"
ENDHLSL
}

100
ScriptableRenderPipeline/HDRenderPipeline/Material/Eye/EyeData.hlsl


float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;
bool isTriplanar = false;
#if defined(_PER_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)
// All variable are compile time value
ppdEnable = true;
isPlanar = layerTexCoord.base.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR;
#endif
if (ppdEnable)
{
// See comment in layered version for details
float maxHeight = GetMaxDisplacement();
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
PerPixelHeightDisplacementParam ppdParam;
float height; // final height processed
float NdotV;
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// TODO: support object space planar/triplanar ?
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
float3 viewDirTS;
float planeHeight;
int numSteps;
// Perform a POM in each direction and modify appropriate texture coordinate
ppdParam.uv = layerTexCoord.base.uvZY;
viewDirTS = float3(V.x > 0.0 ? uvZY : -uvZY, V.x);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetZY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
// Apply offset to all triplanar UVSet
layerTexCoord.base.uvZY += offsetZY;
layerTexCoord.details.uvZY += offsetZY;
height = layerTexCoord.triplanarWeights.x * planeHeight;
ppdParam.uv = layerTexCoord.base.uvXZ;
viewDirTS = float3(V.y > 0.0 ? uvXZ : -uvXZ, V.y);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXZ = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
layerTexCoord.base.uvXZ += offsetXZ;
layerTexCoord.details.uvXZ += offsetXZ;
height += layerTexCoord.triplanarWeights.y * planeHeight;
ppdParam.uv = layerTexCoord.base.uvXY;
viewDirTS = float3(V.z > 0.0 ? uvXY : -uvXY, V.z);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
layerTexCoord.base.uvXY += offsetXY;
layerTexCoord.details.uvXY += offsetXY;
height += layerTexCoord.triplanarWeights.z * planeHeight;
NdotV = 1; // TODO.
}
else
{
ppdParam.uv = layerTexCoord.base.uv; // For planar it is uv too, not uvXZ
float3x3 worldToTangent = input.worldToTangent;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surfarce that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// Apply offset to all UVSet0 / planar
layerTexCoord.base.uv += offset;
layerTexCoord.details.uv += isPlanar ? offset : _UVDetailsMappingMask.x * offset; // Only apply offset if details map use UVSet0 _UVDetailsMappingMask.x will be 1 in this case, else 0
}
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
return tilingScale * verticalDisplacement / NdotV;
}
return 0.0;
}

float2 EyeUvs(float2 uv, float irisDepth, float irisRadius, float IOR, float3 normalWS, float3 viewWS)
{
float height = irisDepth * saturate( 1.0 - 0.736 * (1-irisRadius) * (1-irisRadius) );
float height = irisDepth * saturate( 1.0 - 0.736 * (1-irisRadius) * (1-irisRadius) );
// Refraction
float w = IOR * dot( normalWS, viewWS );

float mask = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, uv).r;
float cosAlpha = dot(_frontNormalWS, -refractedW);
float dist = height / cosAlpha;
float3 offsetW = dist * refractedW;

29
ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Editor/BaseFabricUI.cs


EditorGUI.indentLevel--;
}
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, StylesBaseLit.enablePerPixelDisplacementText);
if (enablePerPixelDisplacement.floatValue > 0.0f)
{

static public void SetupBaseLitMaterialPass(Material material)
{
bool distortionEnable = material.GetFloat(kDistortionEnable) > 0.0f;
bool distortionOnly = material.GetFloat(kDistortionOnly) > 0.0f;
if (distortionEnable && distortionOnly)
{
// Disable all passes except distortion (setup in BaseUnlitUI.cs) and debug passes (to visualize distortion)
material.SetShaderPassEnabled("GBuffer", false);
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
material.SetShaderPassEnabled("Meta", false);
material.SetShaderPassEnabled("ShadowCaster", false);
material.SetShaderPassEnabled("DepthOnly", false);
material.SetShaderPassEnabled("MotionVectors", false);
material.SetShaderPassEnabled("Forward", false);
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
}
else
{
// Enable all passes except distortion (setup in BaseUnlitUI.cs)
material.SetShaderPassEnabled("GBuffer", true);
material.SetShaderPassEnabled("GBufferDisplayDebug", true);
material.SetShaderPassEnabled("Meta", true);
material.SetShaderPassEnabled("ShadowCaster", true);
material.SetShaderPassEnabled("DepthOnly", true);
material.SetShaderPassEnabled("MotionVectors", true);
material.SetShaderPassEnabled("Forward", true);
material.SetShaderPassEnabled("ForwardDisplayDebug", true);
}
}
}
} // namespace UnityEditor

74
ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Editor/FabricUI.cs


public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC7/BC5/DXT5(nm))");
public static GUIContent normalMapOSText = new GUIContent("Normal Map OS", "Normal Map (BC7/DXT1/RGB)");
public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent heightMapText = new GUIContent("Height Map (R)", "Height Map");
public static GUIContent heightMapAmplitudeText = new GUIContent("Height Map Amplitude", "Height Map amplitude in world units.");
public static GUIContent heightMapCenterText = new GUIContent("Height Map Center", "Center of the heightmap in the texture (between 0 and 1)");

public enum FabricType
{
Silk,
CottonWool,
CottonWool,
}
public enum UVBaseMapping

protected void ShaderSSSInputGUI(Material material)
{
HDRenderPipeline hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var hdPipeline = RenderPipelineManager.currentPipeline as HDRenderPipeline;
var sssSettings = hdPipeline.sssSettings;
if (subsurfaceProfile == null)
if (sssSettings == null)
// Attempt to load the profile from the SSS Settings.
int profileID = (int)subsurfaceProfileID.floatValue;
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null)
{
// This is a valid profile ID.
subsurfaceProfile = hdPipeline.sssSettings.profiles[profileID];
// Refresh the ID of the profile.
hdPipeline.sssSettings.OnValidate();
}
EditorGUILayout.HelpBox("No Subsurface Scattering Settings have been assigned to the render pipeline asset.", MessageType.Warning);
return;
subsurfaceProfile = EditorGUILayout.ObjectField(Styles.subsurfaceProfileText, subsurfaceProfile, typeof(SubsurfaceScatteringProfile), false) as SubsurfaceScatteringProfile;
// TODO: Optimize me
var profiles = hdPipeline.sssSettings.profiles;
var names = new GUIContent[profiles.Length + 1];
names[0] = new GUIContent("None");
bool validProfile = false;
var values = new int[names.Length];
values[0] = SssConstants.SSS_NEUTRAL_PROFILE_ID;
// Set the profile ID.
if (subsurfaceProfile != null)
for (int i = 0; i < profiles.Length; i++)
// Load the profile from the GUI field.
int profileID = subsurfaceProfile.settingsIndex;
names[i + 1] = new GUIContent(profiles[i].name);
values[i + 1] = i + 1;
}
if (0 <= profileID && profileID < hdPipeline.sssSettings.profiles.Length &&
hdPipeline.sssSettings.profiles[profileID] != null &&
hdPipeline.sssSettings.profiles[profileID] == subsurfaceProfile)
using (var scope = new EditorGUI.ChangeCheckScope())
{
int profileID = (int)subsurfaceProfileID.floatValue;
using (new EditorGUILayout.HorizontalScope())
validProfile = true;
material.SetInt("_SubsurfaceProfile", profileID);
EditorGUILayout.PrefixLabel(Styles.subsurfaceProfileText);
using (new EditorGUILayout.HorizontalScope())
{
profileID = EditorGUILayout.IntPopup(profileID, names, values);
if (GUILayout.Button("Goto", EditorStyles.miniButton, GUILayout.Width(50f)))
Selection.activeObject = sssSettings;
}
else
{
subsurfaceProfile = null;
Debug.LogError("The SSS Profile assigned to the material has an invalid index. First, add the Profile to the SSS Settings, and then reassign it to the material.");
}
}
if (!validProfile)
{
// Disable SSS for this object.
material.SetInt("_SubsurfaceProfile", SssConstants.SSS_NEUTRAL_PROFILE_ID);
if (scope.changed)
subsurfaceProfileID.floatValue = profileID;
}
m_MaterialEditor.ShaderProperty(subsurfaceRadius, Styles.subsurfaceRadiusText);

{
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapOSText, tangentMapOS);
}
}
protected override void MaterialPropertiesGUI(Material material)

m_MaterialEditor.TexturePropertySingleLine(Styles.maskMapSText, maskMap);
m_MaterialEditor.TexturePropertySingleLine(Styles.specularOcclusionMapText, specularOcclusionMap);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText);
// Triplanar only work with tangent space normal

76
ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Fabric.hlsl


// SurfaceData is define in Fabric.cs which generate Fabric.cs.hlsl
#include "Fabric.cs.hlsl"
#include "../Lit/SubsurfaceScatteringProfile.cs.hlsl"
#include "../Lit/SubsurfaceScatteringSettings.cs.hlsl"
#define WANT_SSS_CODE
#include "../LightEvaluationShare1.hlsl"

#endif
float NdotLwrap = sqrt(NdotL);
float diffuseTerm = Lambert();
float diffuseTerm = Lambert();
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.perceptualRoughness);
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
#endif
diffuseLighting = bsdfData.diffuseColor * diffuseTerm*lerp(1,0.5,bsdfData.roughness);

float3 F = F_Schlick(bsdfData.fresnel0, LdotH);
float Vis;
float D;
// TODO: this way of handling aniso may not be efficient, or maybe with material classification, need to check perf here
// Maybe always using aniso maybe a win ?
float DV;
float3 H = (L + V) * invLenLV;
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float TdotL = dot(bsdfData.tangentWS, L);
float BdotH = dot(bsdfData.bitangentWS, H);
float BdotL = dot(bsdfData.bitangentWS, L);
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
float3 H = (L + V) * invLenLV;
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float TdotL = dot(bsdfData.tangentWS, L);
float BdotH = dot(bsdfData.bitangentWS, H);
float BdotL = dot(bsdfData.bitangentWS, L);
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGXAnisoLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB, preLightData.anisoGGXLambdaV);
#else
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
Vis = V_SmithJointGGXAniso(preLightData.TdotV, preLightData.BdotV, NdotV, TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB);
#endif
bsdfData.roughnessT = ClampRoughnessForAnalyticalLights(bsdfData.roughnessT);
bsdfData.roughnessB = ClampRoughnessForAnalyticalLights(bsdfData.roughnessB);
D = D_GGXAniso(TdotH, BdotH, NdotH, bsdfData.roughnessT, bsdfData.roughnessB);
// TODO: Do comparison between this correct version and the one from isotropic and see if there is any visual difference
DV = DV_SmithJointGGXAniso(TdotH, BdotH, NdotH,
preLightData.TdotV, preLightData.BdotV, preLightData.NdotV,
TdotL, BdotL, NdotL,
bsdfData.roughnessT, bsdfData.roughnessB
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData.partLambdaV);
#else
);
#endif
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness, preLightData.ggxLambdaV);
#else
Vis = V_SmithJointGGX(NdotL, NdotV, bsdfData.roughness);
#endif
D = D_GGX(NdotH, bsdfData.roughness);
DV = DV_SmithJointGGX(NdotH, NdotL, NdotV, bsdfData.roughness
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
, preLightData partLambdaV);
#else
);
#endif
specularLighting = F * (Vis * D)*_FuzzTint;
specularLighting = F * DV * _FuzzTint;
float diffuseTerm = Lambert();
float diffuseTerm = Lambert();
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.perceptualRoughness);
float3 diffuseTerm = DiffuseGGX(bsdfData.diffuseColor, NdotV, NdotL, NdotH, LdotV, bsdfData.roughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float diffuseTerm = DisneyDiffuse(NdotV, NdotL, LdotV, bsdfData.perceptualRoughness);
diffuseLighting = bsdfData.diffuseColor * diffuseTerm;
diffuseLighting = bsdfData.diffuseColor * diffuseTerm;
}
#endif // #ifdef HAS_LIGHTLOOP

28
ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/Fabric.shader


_ShiverDrag("Shiver Drag", float) = 0.2
_ShiverDirectionality("Shiver Directionality", Range(0.0, 1.0)) = 0.5
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}
// Following options are for the GUI inspector and different from the input parameters above
// These option below will cause different compilation flag.

[ToggleOff] _DistortionEnable("Enable Distortion", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Depth Test Enable", Float) = 0.0
[ToggleOff] _DepthOffsetEnable("Depth Offset View space", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 1.0

//-------------------------------------------------------------------------------------
#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON
#pragma shader_feature _PER_PIXEL_DISPLACEMENT

#include "ShaderPass/FabricVelocityPass.hlsl"
#include "FabricData.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"
ENDHLSL
}
Pass
{
Name "Distortion" // Name is not used
Tags { "LightMode" = "DistortionVectors" } // This will be only for transparent object based on the RenderQueue index
Blend One One
ZTest [_ZTestMode]
ZWrite off
Cull [_CullMode]
HLSLPROGRAM
#define SHADERPASS SHADERPASS_DISTORTION
#include "../../ShaderVariables.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/FabricDistortionPass.hlsl"
#include "FabricData.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"
ENDHLSL
}

96
ScriptableRenderPipeline/HDRenderPipeline/Material/Fabric/FabricData.hlsl


float ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
bool ppdEnable = false;
bool isPlanar = false;
bool isTriplanar = false;
#if defined(_PER_PIXEL_DISPLACEMENT) && defined(_HEIGHTMAP)
// All variable are compile time value
ppdEnable = true;
isPlanar = layerTexCoord.base.mappingType == UV_MAPPING_PLANAR;
isTriplanar = layerTexCoord.base.mappingType == UV_MAPPING_TRIPLANAR;
#endif
if (ppdEnable)
{
// See comment in layered version for details
float maxHeight = GetMaxDisplacement();
float2 minUvSize = GetMinUvSize(layerTexCoord);
float lod = ComputeTextureLOD(minUvSize);
PerPixelHeightDisplacementParam ppdParam;
float height; // final height processed
float NdotV;
// planar/triplanar
float2 uvXZ;
float2 uvXY;
float2 uvZY;
GetTriplanarCoordinate(V, uvXZ, uvXY, uvZY);
// TODO: support object space planar/triplanar ?
// We need to calculate the texture space direction. It depends on the mapping.
if (isTriplanar)
{
float3 viewDirTS;
float planeHeight;
int numSteps;
// Perform a POM in each direction and modify appropriate texture coordinate
ppdParam.uv = layerTexCoord.base.uvZY;
viewDirTS = float3(V.x > 0.0 ? uvZY : -uvZY, V.x);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetZY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
// Apply offset to all triplanar UVSet
layerTexCoord.base.uvZY += offsetZY;
layerTexCoord.details.uvZY += offsetZY;
height = layerTexCoord.triplanarWeights.x * planeHeight;
ppdParam.uv = layerTexCoord.base.uvXZ;
viewDirTS = float3(V.y > 0.0 ? uvXZ : -uvXZ, V.y);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXZ = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
layerTexCoord.base.uvXZ += offsetXZ;
layerTexCoord.details.uvXZ += offsetXZ;
height += layerTexCoord.triplanarWeights.y * planeHeight;
ppdParam.uv = layerTexCoord.base.uvXY;
viewDirTS = float3(V.z > 0.0 ? uvXY : -uvXY, V.z);
numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offsetXY = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, planeHeight);
layerTexCoord.base.uvXY += offsetXY;
layerTexCoord.details.uvXY += offsetXY;
height += layerTexCoord.triplanarWeights.z * planeHeight;
NdotV = 1; // TODO.
}
else
{
ppdParam.uv = layerTexCoord.base.uv; // For planar it is uv too, not uvXZ
float3x3 worldToTangent = input.worldToTangent;
// Note: The TBN is not normalize as it is based on mikkt. We should normalize it, but POM is always use on simple enough surfarce that mean it is not required (save 2 normalize). Tag: SURFACE_GRADIENT
float3 viewDirTS = isPlanar ? float3(uvXZ, V.y) : TransformWorldToTangent(V, worldToTangent);
NdotV = viewDirTS.z;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
float2 offset = ParallaxOcclusionMapping(lod, _PPDLodThreshold, numSteps, viewDirTS, maxHeight, ppdParam, height);
// Apply offset to all UVSet0 / planar
layerTexCoord.base.uv += offset;
layerTexCoord.details.uv += isPlanar ? offset : _UVDetailsMappingMask.x * offset; // Only apply offset if details map use UVSet0 _UVDetailsMappingMask.x will be 1 in this case, else 0
}
// Since POM "pushes" geometry inwards (rather than extrude it), { height = height - 1 }.
// Since the result is used as a 'depthOffsetVS', it needs to be positive, so we flip the sign.
float verticalDisplacement = maxHeight - height * maxHeight;
// IDEA: precompute the tiling scale? MOV-MUL vs MOV-MOV-MAX-RCP-MUL.
float tilingScale = rcp(max(_BaseColorMap_ST.x, _BaseColorMap_ST.y));
return tilingScale * verticalDisplacement / NdotV;
}
return 0.0;
}

4
ScriptableRenderPipeline/HDRenderPipeline/Material/Hair/Hair.shader


//-------------------------------------------------------------------------------------
#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _DOUBLESIDED_ON

}
}
CustomEditor "Experimental.Rendering.HDPipeline.CharacterGUI"
//CustomEditor "Experimental.Rendering.HDPipeline.HairGUI"
CustomEditor "Experimental.Rendering.HDPipeline.HairGUI"
}

130
ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare1.hlsl


// Area light textures specific constant
SamplerState ltc_linear_clamp_sampler;
// Sampler use by area light, gaussian pyramid, ambient occlusion etc...
SamplerState s_linear_clamp_sampler;
SamplerState s_trilinear_clamp_sampler;
// Rough refraction texture
// Color pyramid (width, height, lodcount, Unused)
TEXTURE2D(_GaussianPyramidColorTexture);
// Depth pyramid (width, height, lodcount, Unused)
TEXTURE2D(_PyramidDepthTexture);
CBUFFER_START(UnityGaussianPyramidParameters)
float4 _GaussianPyramidColorMipSize;
float4 _PyramidDepthMipSize;
CBUFFER_END
// Ambient occlusion texture
TEXTURE2D(_AmbientOcclusionTexture);
CBUFFER_START(UnityAmbientOcclusionParameters)
float4 _AmbientOcclusionParam; // xyz occlusion color, w directLightStrenght
CBUFFER_END
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);
TEXTURE2D_ARRAY(_LtcData); // We pack the 3 Ltc data inside a texture array

// 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
// _PreIntegratedFGD.x = Gv * (1 - Fc) with Fc = (1 - H.L)^5
// _PreIntegratedFGD.y = Gv * Fc
// Pre integrate DisneyDiffuse FGD:
// _PreIntegratedFGD.z = DisneyDiffuse
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, ltc_linear_clamp_sampler, float2(NdotV, perceptualRoughness), 0).xyz;
// Pre-integrate GGX FGD
// Integral{BSDF * <N,L> dw} =
// 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} =
// (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;
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;
specularFGD = lerp(preFGD.xxx, preFGD.yyy, fresnel0);
diffuseFGD = 1.0;
diffuseFGD = 1.0;
diffuseFGD = preFGD.z;
// Remap from the [0, 1] to the [0.5, 1.5] range.
diffuseFGD = preFGD.z + 0.5;
reflectivity = preFGD.y;
}
// Precomputed lighting data to send to the various lighting functions

float NdotV; // Geometric version (could be negative)
// GGX iso
float ggxLambdaV;
// GGX Aniso
// GGX
float partLambdaV;
float energyCompensation;
float anisoGGXLambdaV;
// IBL
float3 iblDirWS; // Dominant specular direction, used for IBL in EvaluateBSDF_Env()

NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
// GGX iso
preLightData.ggxLambdaV = GetSmithJointGGXLambdaV(NdotV, bsdfData.roughness);
preLightData.TdotV = 0.0;
preLightData.BdotV = 0.0;
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.anisoGGXLambdaV = GetSmithJointGGXAnisoLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
// Tangent = highlight stretch (anisotropy) direction. Bitangent = grain (brush) direction.
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(bsdfData.bitangentWS, iblNormalWS, V, bsdfData.anisotropy);
preLightData.TdotV = dot(bsdfData.tangentWS, V);
preLightData.BdotV = dot(bsdfData.bitangentWS, V);
preLightData.partLambdaV = GetSmithJointGGXAnisoPartLambdaV(preLightData.TdotV, preLightData.BdotV, NdotV, bsdfData.roughnessT, bsdfData.roughnessB);
// For GGX aniso and IBL we have done an empirical (eye balled) approximation compare to the reference.
// We use a single fetch, and we stretch the normal to use based on various criteria.
// result are far away from the reference but better than nothing
// For positive anisotropy values: tangent = highlight stretch (anisotropy) direction, bitangent = grain (brush) direction.
float3 grainDirWS = (bsdfData.anisotropy >= 0) ? bsdfData.bitangentWS : bsdfData.tangentWS;
// Reduce stretching for (perceptualRoughness < 0.2).
float stretch = abs(bsdfData.anisotropy) * saturate(5 * bsdfData.perceptualRoughness);
float3 anisoIblNormalWS = GetAnisotropicModifiedNormal(grainDirWS, iblNormalWS, V, stretch);
else // GGX iso
{
preLightData.TdotV = 0;
preLightData.BdotV = 0;
preLightData.partLambdaV = GetSmithJointGGXPartLambdaV(NdotV, bsdfData.roughness);
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);
// Note: this is a ad-hoc tweak.
float iblRoughness, iblPerceptualRoughness;
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
// Use the min roughness, and bias it for higher values of anisotropy and roughness.
float roughnessBias = 0.075 * bsdfData.anisotropy * bsdfData.roughness;
iblRoughness = saturate(min(bsdfData.roughnessT, bsdfData.roughnessB) + roughnessBias);
iblPerceptualRoughness = RoughnessToPerceptualRoughness(iblRoughness);
}
else
{
iblRoughness = bsdfData.roughness;
iblPerceptualRoughness = bsdfData.perceptualRoughness;
}
preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, bsdfData.roughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
preLightData.iblDirWS = GetSpecularDominantDir(iblNormalWS, iblR, iblRoughness, NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(iblPerceptualRoughness);
#ifdef LIT_USE_GGX_ENERGY_COMPENSATION
// 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.0 / reflectivity - 1.0;
#else
preLightData.energyCompensation = 0.0;
#endif // LIT_USE_GGX_ENERGY_COMPENSATION
// Area light
// UVs for sampling the LUTs

// Get the inverse LTC matrix for Disney Diffuse
preLightData.ltcTransformDiffuse = 0.0;
preLightData.ltcTransformDiffuse._m22 = 1.0;
preLightData.ltcTransformDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
preLightData.ltcTransformDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
#endif
// Get the inverse LTC matrix for GGX

preLightData.ltcTransformSpecular._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
preLightData.ltcTransformSpecular._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_GGX_MATRIX_INDEX, 0);
// Construct a right-handed view-dependent orthogonal basis around the normal
preLightData.orthoBasisViewNormal[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);

float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, ltc_linear_clamp_sampler, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, s_linear_clamp_sampler, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
float ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r; // The difference of magnitudes of GGX and Fresnel
float ltcGGXFresnelMagnitude = ltcMagnitude.g;
float ltcDisneyDiffuseMagnitude = ltcMagnitude.b;

524
ScriptableRenderPipeline/HDRenderPipeline/Material/LightEvaluationShare2.hlsl


#ifdef HAS_LIGHTLOOP
//-----------------------------------------------------------------------------
// Lighting structure for light accumulation
//-----------------------------------------------------------------------------
// These structure allow to accumulate lighting accross the Lit material
// AggregateLighting is init to zero and transfer to EvaluateBSDF, but the LightLoop can't access its content.
struct DirectLighting
{
float3 diffuse;
float3 specular;
};
struct IndirectLighting
{
float3 specularReflected;
float3 specularTransmitted;
};
struct AggregateLighting
{
DirectLighting direct;
IndirectLighting indirect;
};
void AccumulateDirectLighting(DirectLighting src, inout AggregateLighting dst)
{
dst.direct.diffuse += src.diffuse;
dst.direct.specular += src.specular;
}
void AccumulateIndirectLighting(IndirectLighting src, inout AggregateLighting dst)
{
dst.indirect.specularReflected += src.specularReflected;
dst.indirect.specularTransmitted += src.specularTransmitted;
}
#ifdef WANT_SSS_CODE
// Currently, we only model diffuse transmission. Specular transmission is not yet supported.

}
else
{
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1;
isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1.0 - positionLS.z) <= 1.0;
}
// We let the sampler handle tiling or clamping to border.

cookie.a = isInBounds ? cookie.a : 0;
cookie.a = isInBounds ? cookie.a : 0.0;
void EvaluateBSDF_Directional(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
DirectLighting EvaluateBSDF_Directional( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
DirectionalLightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
float3 positionWS = posInput.positionWS;
float3 L = -lightData.forward; // Lights are pointing backward in Unity

diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float shadow = 1;
float shadow = 1.0;
#ifdef SURFACE_TYPE_TRANSPARENT
#ifdef _SURFACE_TYPE_TRANSPARENT
shadow = GetDirectionalShadowAttenuation(lightLoopContext.shadowContext, positionWS, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
#else
shadow = LOAD_TEXTURE2D(_DeferredShadowTexture, posInput.unPositionSS).x;

[branch] if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);
diffuseLighting *= illuminance * lightData.diffuseScale;
specularLighting *= illuminance * lightData.specularScale;
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
}
#ifdef WANT_SSS_CODE

float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
}
//-----------------------------------------------------------------------------

return attenuation * GetAngleAttenuation(L, -lightData.forward, lightData.angleScale, lightData.angleOffset);
}
void EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting,
out float3 specularLighting)
DirectLighting EvaluateBSDF_Punctual( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
int lightType = lightData.lightType;
int lightType = GPULightType;
// All punctual light type in the same formula, attenuation is neutral depends on light type.
// light.positionWS is the normalize light direction in case of directional light and invSqrAttenuationRadius is 0

lightData.diffuseScale *= attenuation;
lightData.specularScale *= attenuation;
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
float shadow = 1;
float shadow = 1.0;
[branch] if (lightData.shadowIndex >= 0)
{

illuminance *= shadow;
}
#ifdef VOLUMETRIC_SHADOWING_ENABLED
float volumetricShadow = Transmittance(OpticalDepthHomogeneous(preLightData.globalFogExtinction, dist));
// Premultiply.
lightData.diffuseScale *= volumetricShadow;
lightData.specularScale *= volumetricShadow;
#endif
// Projector lights always have a cookies, so we can perform clipping inside the if().
[branch] if (lightData.cookieIndex >= 0)
{

[branch] if (illuminance > 0.0)
{
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual ligth have a radius with this hack
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
bsdfData.roughness = max(bsdfData.roughness, lightData.minRoughness); // Simulate that a punctual light have a radius with this hack
BSDF(V, L, positionWS, preLightData, bsdfData, lighting.diffuse, lighting.specular);
diffuseLighting *= illuminance * lightData.diffuseScale;
specularLighting *= illuminance * lightData.specularScale;
lighting.diffuse *= illuminance * lightData.diffuseScale;
lighting.specular *= illuminance * lightData.specularScale;
}
#ifdef WANT_SSS_CODE

float illuminance = Lambert() * ComputeWrappedDiffuseLighting(-NdotL, SSS_WRAP_LIGHT);
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
lighting.diffuse += EvaluateTransmission(bsdfData, illuminance * lightData.diffuseScale, shadow);
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
#include "Lit/LitReference.hlsl"
#include "Lit\LitReference.hlsl"
void EvaluateBSDF_Line(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Line( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
diffuseLighting, specularLighting);
lighting.diffuse, lighting.specular);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float len = lightData.size.x;
float3 T = lightData.right;

axis, invAspectRatio);
// Terminate if the shaded point is too far away.
if (intensity == 0.0) return;
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;
lightData.specularScale *= intensity;

{
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcTransformDiffuse);
ltcValue *= lightData.diffuseScale;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
#ifdef WANT_SSS_CODE

ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1);
}
#endif

ltcValue *= lightData.specularScale;
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue;
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue;
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
}
//-----------------------------------------------------------------------------

// #define ELLIPSOIDAL_ATTENUATION
void EvaluateBSDF_Rect( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Rect( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData)
DirectLighting lighting;
ZERO_INITIALIZE(DirectLighting, lighting);
diffuseLighting, specularLighting);
lighting.diffuse, lighting.specular);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float3 unL = lightData.positionWS - positionWS;
[branch]

return;
return lighting;
}
// Rotate the light direction into the light space.

#endif
// Terminate if the shaded point is too far away.
if (intensity == 0.0) return;
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;
lightData.specularScale *= intensity;

// Polygon irradiance in the transformed configuration.
ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformDiffuse));
ltcValue *= lightData.diffuseScale;
diffuseLighting = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
lighting.diffuse = bsdfData.diffuseColor * (preLightData.ltcMagnitudeDiffuse * ltcValue);
}
#ifdef WANT_SSS_CODE

ltcValue *= lightData.diffuseScale;
// We use diffuse lighting for accumulation since it is going to be blurred during the SSS pass.
diffuseLighting += EvaluateTransmission(bsdfData, ltcValue, 1);
lighting.diffuse += EvaluateTransmission(bsdfData, ltcValue, 1);
}
#endif

ltcValue = PolygonIrradiance(mul(lightVerts, preLightData.ltcTransformSpecular));
ltcValue *= lightData.specularScale;
specularLighting += preLightData.ltcMagnitudeFresnel * ltcValue;
lighting.specular += preLightData.ltcMagnitudeFresnel * ltcValue;
diffuseLighting *= lightData.color;
specularLighting *= lightData.color;
lighting.diffuse *= lightData.color;
lighting.specular *= lightData.color;
return lighting;
void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType,
out float3 diffuseLighting, out float3 specularLighting)
DirectLighting EvaluateBSDF_Area( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType)
EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData);
EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData);
// EvaluateBSDF_SSLighting for screen space lighting
// ----------------------------------------------------------------------------
IndirectLighting EvaluateBSDF_SSReflection(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, BSDFData bsdfData,
inout float hierarchyWeight)
{
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
// TODO
return lighting;
}
IndirectLighting EvaluateBSDF_SSRefraction(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, BSDFData bsdfData,
inout float hierarchyWeight)
{
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
#if HAS_REFRACTION
// Refraction process:
// 1. Depending on the shape model, we calculate the refracted point in world space and the optical depth
// 2. We calculate the screen space position of the refracted point
// 3. If this point is available (ie: in color buffer and point is not in front of the object)
// a. Get the corresponding color depending on the roughness from the gaussian pyramid of the color buffer
// b. Multiply by the transmittance for absorption (depends on the optical depth)
float3 refractedBackPointWS = float3(0.0, 0.0, 0.0);
float opticalDepth = 0.0;
uint2 depthSize = uint2(_PyramidDepthMipSize.xy);
// For all refraction approximation, to calculate the refracted point in world space,
// we approximate the scene as a plane (back plane) with normal -V at the depth hit point.
// (We avoid to raymarch the depth texture to get the refracted point.)
#if defined(_REFRACTION_PLANE)
// Plane shape model:
// We approximate locally the shape of the object as a plane with normal {bsdfData.normalWS} at {bsdfData.positionWS}
// with a thickness {bsdfData.thickness}
// Refracted ray
float3 R = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
// Get the depth of the approximated back plane
float pyramidDepth = LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, posInput.positionSS * (depthSize >> 2), 2).r;
float depth = LinearEyeDepth(pyramidDepth, _ZBufferParams);
// Distance from point to the back plane
float distFromP = depth - posInput.depthVS;
// Optical depth within the thin plane
opticalDepth = bsdfData.thickness / dot(R, -bsdfData.normalWS);
// The refracted ray exiting the thin plane is the same as the incident ray (parallel interfaces and same ior)
float VoR = dot(-V, R);
float VoN = dot(V, bsdfData.normalWS);
refractedBackPointWS = posInput.positionWS + R * opticalDepth - V * (distFromP - VoR * opticalDepth);
#elif defined(_REFRACTION_SPHERE)
// Sphere shape model:
// We approximate locally the shape of the object as sphere, that is tangent to the shape.
// The sphere has a diameter of {bsdfData.thickness}
// The center of the sphere is at {bsdfData.positionWS} - {bsdfData.normalWS} * {bsdfData.thickness}
//
// So the light is refracted twice: in and out of the tangent sphere
// Get the depth of the approximated back plane
float pyramidDepth = LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, posInput.positionSS * (depthSize >> 2), 2).r;
float depth = LinearEyeDepth(pyramidDepth, _ZBufferParams);
// Distance from point to the back plane
float depthFromPosition = depth - posInput.depthVS;
// First refraction (tangent sphere in)
// Refracted ray
float3 R1 = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
// Center of the tangent sphere
float3 C = posInput.positionWS - bsdfData.normalWS * bsdfData.thickness * 0.5;
// Second refraction (tangent sphere out)
float NoR1 = dot(bsdfData.normalWS, R1);
// Optical depth within the sphere
opticalDepth = -NoR1 * bsdfData.thickness;
// Out hit point in the tangent sphere
float3 P1 = posInput.positionWS + R1 * opticalDepth;
// Out normal
float3 N1 = normalize(C - P1);
// Out refracted ray
float3 R2 = refract(R1, N1, bsdfData.ior);
float N1oR2 = dot(N1, R2);
float VoR1 = dot(V, R1);
// Refracted source point
refractedBackPointWS = P1 - R2 * (depthFromPosition - NoR1 * VoR1 * bsdfData.thickness) / N1oR2;
#endif
// Calculate screen space coordinates of refracted point in back plane
float4 refractedBackPointCS = mul(_ViewProjMatrix, float4(refractedBackPointWS, 1.0));
float2 refractedBackPointSS = ComputeScreenSpacePosition(refractedBackPointCS);
float refractedBackPointDepth = LinearEyeDepth(LOAD_TEXTURE2D_LOD(_PyramidDepthTexture, refractedBackPointSS * depthSize, 0).r, _ZBufferParams);
// Exit if texel is out of color buffer
// Or if the texel is from an object in front of the object
if (refractedBackPointDepth < posInput.depthVS
|| any(refractedBackPointSS < 0.0)
|| any(refractedBackPointSS > 1.0))
{
// Do nothing and don't update the hierarchy weight so we can fall back on refraction probe
return lighting;
}
// Map the roughness to the correct mip map level of the color pyramid
float mipLevel = PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness, uint(_GaussianPyramidColorMipSize.z));
lighting.specularTransmitted = SAMPLE_TEXTURE2D_LOD(_GaussianPyramidColorTexture, s_trilinear_clamp_sampler, refractedBackPointSS, mipLevel).rgb;
// Beer-Lamber law for absorption
float3 transmittance = exp(-bsdfData.absorptionCoefficient * opticalDepth);
lighting.specularTransmitted *= transmittance;
float weight = 1.0;
UpdateLightingHierarchyWeights(hierarchyWeight, weight); // Shouldn't be needed, but safer in case we decide to change hiearchy priority
lighting.specularTransmitted *= weight;
#else
// No refraction, no need to go further
hierarchyWeight = 1.0;
#endif
return lighting;
}
//-----------------------------------------------------------------------------
void EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting, out float2 weight)
IndirectLighting EvaluateBSDF_Env( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData, int envShapeType, int GPUImageBasedLightingType,
inout float hierarchyWeight)
IndirectLighting lighting;
ZERO_INITIALIZE(IndirectLighting, lighting);
#if !HAS_REFRACTION
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION)
return lighting;
#endif
float3 envLighting = float3(0.0, 0.0, 0.0);
float weight = 1.0;
specularLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
envLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
/*
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
diffuseLighting = IntegrateLambertIBLRef(lightData, V, bsdfData);
#else
diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
#endif
*/
diffuseLighting = float3(0.0, 0.0, 0.0);
// TODO: Do refraction reference (is it even possible ?)
// #ifdef LIT_DIFFUSE_LAMBERT_BRDF
// envLighting += IntegrateLambertIBLRef(lightData, V, bsdfData);
// #else
// envLighting += IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
// #endif
weight = float2(0.0, 1.0);
weight = 1.0;
// also think about how such a loop can handle 2 cubemap at the same time as old unity. Macro can allow to do that
// but we need to have UNITY_SAMPLE_ENV_LOD replace by a true function instead that is define by the lighting arcitecture.
// Also not sure how to deal with 2 intersection....
// Box and sphere are related to light property (but we have also distance based roughness etc...)
// In this code we redefine a bit the behavior of the reflcetion proble. We separate the projection volume (the proxy of the scene) form the influence volume (what pixel on the screen is affected)
// Guideline for reflection volume: In HDRenderPipeline we separate the projection volume (the proxy of the scene) from the influence volume (what pixel on the screen is affected)
// However we add the constrain that the shape of the projection and influence volume is the same (i.e if we have a sphere shape projection volume, we have a shape influence).
// It allow to have more coherence for the dynamic if in shader code.
// Users can also chose to not have any projection, in this case we use the property minProjectionDistance to minimize code change. minProjectionDistance is set to huge number
// that simulate effect of no shape projection
// 1. First determine the projection volume
float3 R = preLightData.iblDirWS;
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFRACTION)
{
// This is the same code than what is use in screen space refraction
// TODO: put this code into a function
#if defined(_REFRACTION_PLANE)
R = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
#elif defined(_REFRACTION_SPHERE)
float3 R1 = refract(-V, bsdfData.normalWS, 1.0 / bsdfData.ior);
// Center of the tangent sphere
float3 C = posInput.positionWS - bsdfData.normalWS * bsdfData.thickness * 0.5;
// Second refraction (tangent sphere out)
float NoR1 = dot(bsdfData.normalWS, R1);
// Optical depth within the sphere
float opticalDepth = -NoR1 * bsdfData.thickness;
// Out hit point in the tangent sphere
float3 P1 = posInput.positionWS + R1 * opticalDepth;
// Out normal
float3 N1 = normalize(C - P1);
// Out refracted ray
R = refract(R1, N1, bsdfData.ior);
#endif
}
// This mean that location and oritention matter. So after intersection of proxy volume we need to convert back to world.
// This mean that location and orientation matter. So after intersection of proxy volume we need to convert back to world.
float3 R = preLightData.iblDirWS;
if (lightData.envShapeType == ENVSHAPETYPE_SPHERE)
// Note: using envShapeType instead of lightData.envShapeType allow to make compiler optimization in case the type is know (like for sky)
if (envShapeType == ENVSHAPETYPE_SPHERE)
// 1. First process the projection
dist = max(dist, lightData.minProjectionDistance); // Setup projection to infinite if requested (mean no projection shape)
// We can reuse dist calculate in LS directly in WS as there is no scaling. Also the offset is already include in lightData.positionWS
R = (positionWS + dist * R) - lightData.positionWS;
R = (positionWS + dist * R) - lightData.positionWS;
// 2. Process the influence
float distFade = max(length(positionLS) - lightData.innerDistance.x, 0.0);
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
else if (lightData.envShapeType == ENVSHAPETYPE_BOX)
else if (envShapeType == ENVSHAPETYPE_BOX)
dist = max(dist, lightData.minProjectionDistance); // Setup projection to infinite if requested (mean no projection shape)
}
// 2. Apply the influence volume (Box volume is used for culling whatever the influence shape)
// TODO: In the future we could have an influence volume inside the projection volume (so with a different transform, in this case we will need another transform)
weight.y = 1.0;
if (lightData.envShapeType == ENVSHAPETYPE_SPHERE)
{
float distFade = max(length(positionLS) - lightData.innerDistance.x, 0.0);
weight.y = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
}
else if (lightData.envShapeType == ENVSHAPETYPE_BOX ||
lightData.envShapeType == ENVSHAPETYPE_NONE)
{
// Influence volume
weight.y = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
weight = saturate(1.0 - distFade / max(lightData.blendDistance, 0.0001)); // avoid divide by zero
weight.x = 0.0;
weight.y = Smoothstep01(weight.y);
weight = Smoothstep01(weight);
specularLighting = float3(0.0, 0.0, 0.0);
specularLighting += F * preLD.rgb * preLightData.specularFGD;
envLighting += F * preLD.rgb * preLightData.specularFGD;
#endif
diffuseLighting = float3(0.0, 0.0, 0.0);
UpdateLightingHierarchyWeights(hierarchyWeight, weight);
if (GPUImageBasedLightingType == GPUIMAGEBASEDLIGHTINGTYPE_REFLECTION)
lighting.specularReflected = envLighting * weight;
else
lighting.specularTransmitted = envLighting * weight;
#endif
return lighting;
}
//-----------------------------------------------------------------------------

void PostEvaluateBSDF( LightLoopContext lightLoopContext, PreLightData preLightData, BSDFData bsdfData, LightLoopAccumulatedLighting accLighting, float3 bakeDiffuseLighting,
void PostEvaluateBSDF( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, BSDFData bsdfData, float3 bakeDiffuseLighting, AggregateLighting lighting,
// Use GTAOMultiBounce approximation for ambient occlusion (allow to get a tint from the baseColor)
#define GTAO_MULTIBOUNCE_APPROX 1
// Note: When we ImageLoad outside of texture size, the value returned by Load is 0 (Note: On Metal maybe it clamp to value of texture which is also fine)
// We use this property to have a neutral value for AO that doesn't consume a sampler and work also with compute shader (i.e use ImageLoad)
// We store inverse AO so neutral is black. So either we sample inside or outside the texture it return 0 in case of neutral
// Ambient occlusion use for indirect lighting (reflection probe, baked diffuse lighting)
float indirectAmbientOcclusion = 1.0 - LOAD_TEXTURE2D(_AmbientOcclusionTexture, posInput.unPositionSS).x;
// Ambient occlusion use for direct lighting (directional, punctual, area)
float directAmbientOcclusion = lerp(1.0, indirectAmbientOcclusion, _AmbientOcclusionParam.w);
bakeDiffuseLighting *= GTAOMultiBounce(lightLoopContext.indirectAmbientOcclusion, bsdfData.diffuseColor);
#if GTAO_MULTIBOUNCE_APPROX
bakeDiffuseLighting *= GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor);
#else
bakeDiffuseLighting *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), indirectAmbientOcclusion);
#endif
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, lightLoopContext.indirectAmbientOcclusion, bsdfData.roughness);
float specularOcclusion = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness);
accLighting.envSpecularLighting *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0);
#if GTAO_MULTIBOUNCE_APPROX
lighting.indirect.specularReflected *= GTAOMultiBounce(min(bsdfData.specularOcclusion, specularOcclusion), bsdfData.fresnel0);
#else
lighting.indirect.specularReflected *= lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), min(bsdfData.specularOcclusion, specularOcclusion));
#endif
// envDiffuseLighting is not used in our case
diffuseLighting = (accLighting.dirDiffuseLighting + accLighting.punctualDiffuseLighting + accLighting.areaDiffuseLighting) * GTAOMultiBounce(lightLoopContext.directAmbientOcclusion, bsdfData.diffuseColor) + bakeDiffuseLighting;
specularLighting = accLighting.dirSpecularLighting + accLighting.punctualSpecularLighting + accLighting.areaSpecularLighting + accLighting.envSpecularLighting;
}
lighting.direct.diffuse *=
#if GTAO_MULTIBOUNCE_APPROX
GTAOMultiBounce(directAmbientOcclusion, bsdfData.diffuseColor);
#else
lerp(_AmbientOcclusionParam.rgb, float3(1.0, 1.0, 1.0), directAmbientOcclusion);
#endif
diffuseLighting = lighting.direct.diffuse + bakeDiffuseLighting;
// If refraction is enable we use the transmittanceMask to lerp between current diffuse lighting and refraction value
// Physically speaking, it should be transmittanceMask should be 1, but for artistic reasons, we let the value vary
#if HAS_REFRACTION
diffuseLighting = lerp(diffuseLighting, lighting.indirect.specularTransmitted, bsdfData.transmittanceMask);
#endif
specularLighting = lighting.direct.specular + lighting.indirect.specularReflected;
// Rescale the GGX to account for the multiple scattering.
specularLighting *= 1.0 + bsdfData.fresnel0 * preLightData.energyCompensation;
#ifdef DEBUG_DISPLAY
if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_OCCLUSION_FROM_SSAO)
{
diffuseLighting = indirectAmbientOcclusion;
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_OCCLUSION_FROM_SSAO)
{
diffuseLighting = GetSpecularOcclusionFromAmbientOcclusion(preLightData.NdotV, indirectAmbientOcclusion, bsdfData.roughness);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
#if GTAO_MULTIBOUNCE_APPROX
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_DIFFUSE_GTAO_FROM_SSAO)
{
diffuseLighting = GTAOMultiBounce(indirectAmbientOcclusion, bsdfData.diffuseColor);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
else if (_DebugLightingMode == DEBUGLIGHTINGMODE_INDIRECT_SPECULAR_GTAO_FROM_SSAO)
{
diffuseLighting = GTAOMultiBounce(specularOcclusion, bsdfData.fresnel0);
specularLighting = float3(0.0, 0.0, 0.0); // Disable specular lighting
}
#endif
#endif
}
#endif // #ifdef HAS_LIGHTLOOP

11
ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


}
preLightData.NdotV = dot(bsdfData.normalWS, V); // Store the unaltered (geometric) version
float NdotV = preLightData.NdotV;
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, preLightData.NdotV, MIN_N_DOT_V); // Use non-clamped NdotV
float3 iblR;
float3 iblNormalWS = GetViewShiftedNormal(bsdfData.normalWS, V, NdotV, MIN_N_DOT_V); // Use non clamped NdotV
float3 iblR = reflect(-V, iblNormalWS);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
NdotV = max(NdotV, MIN_N_DOT_V); // Use the modified (clamped) version
// GGX aniso
if (bsdfData.materialId == MATERIALID_LIT_ANISO && HasMaterialFeatureFlag(MATERIALFEATUREFLAGS_LIT_ANISO))

axis, invAspectRatio);
// Terminate if the shaded point is too far away.
if (intensity == 0.0)
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;

#endif
// Terminate if the shaded point is too far away.
if (intensity == 0.0)
if (intensity == 0.0)
return lighting;
lightData.diffuseScale *= intensity;

10
ScriptableRenderPipeline/LightweightPipeline.meta


fileFormatVersion: 2
guid: f9ca3ff6d08b48b42ae424159889f367
folderAsset: yes
timeCreated: 1509065726
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

10
Tests.meta


fileFormatVersion: 2
guid: f81d4d56cb6097e4d9f9bf7ef575ef55
folderAsset: yes
timeCreated: 1509065725
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

12
ScriptableRenderPipeline/HDRenderPipeline/Editor/SceneSettingsManagementWindow.cs.meta


fileFormatVersion: 2
guid: a6a2e8d7ee3eb2c46962c9b49ff6c8ef
timeCreated: 1485262288
licenseType: Pro
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

10
Tests/GraphicsTests/RenderPipeline/HDRenderPipeline/Scenes/0xxx.meta


fileFormatVersion: 2
guid: 405d053465ae98342849302f26ddfee0
folderAsset: yes
timeCreated: 1508423740
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存