浏览代码

Merge branch 'master' into batch_rendering

# Conflicts:
#	Assets/TestScenes/HDTest/GlobalIlluminationTest.unity
#	Assets/TestScenes/HDTest/GlobalIlluminationTest/LightingData.asset
#	Assets/TestScenes/HDTest/GlobalIlluminationTest/LightingData.asset.meta
#	Assets/TestScenes/HDTest/HDRI.meta
#	ProjectSettings/GraphicsSettings.asset
#	ProjectSettings/ProjectSettings.asset
/batch_rendering
Arnaud Carre 8 年前
当前提交
2cdff1ec
共有 318 个文件被更改,包括 2855 次插入1851 次删除
  1. 5
      Assets/BasicRenderLoopTutorial/BasicRenderLoop.cs
  2. 7
      Assets/Editor/Tests/RenderloopTests/RenderloopTestFixture.cs
  3. 2
      Assets/Editor/Tests/ShaderGeneratorTests/ShaderGeneratorTests.cs
  4. 10
      Assets/ScriptableRenderLoop/AdditionalLightData.cs
  5. 5
      Assets/ScriptableRenderLoop/Editor/MaterialUpgrader.cs
  6. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/DebugViewMaterial.cs
  7. 6
      Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/DebugViewMaterial.cs.hlsl
  8. 11
      Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/Resources/DebugViewMaterialGBuffer.shader
  9. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/Resources/DebugViewTiles.shader
  10. 10
      Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  11. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs
  12. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/UpgradeStandardShaderMaterials.cs
  13. 1
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.asset
  14. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.asset.meta
  15. 211
      Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs
  16. 5
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/Forward.hlsl
  17. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightDefinition.cs
  18. 22
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl
  19. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightLoop.cs
  20. 5
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/Resources/Deferred.shader
  21. 7
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute
  22. 105
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  23. 16
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl
  24. 25
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl
  25. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  26. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.cs
  27. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.cs.hlsl
  28. 7
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.hlsl
  29. 284
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs
  30. 180
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader
  31. 169
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs
  32. 76
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs
  33. 3
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/StandardSpecularToHDLitMaterialUpgrader.cs
  34. 6
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/StandardToHDLitMaterialUpgrader.cs
  35. 82
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.cs
  36. 12
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  37. 162
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.hlsl
  38. 97
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader
  39. 447
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl
  40. 61
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl
  41. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LtcData.DisneyDiffuse.cs
  42. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LtcData.GGX.cs
  43. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/PreIntegratedFGD.shader
  44. 268
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  45. 29
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/MaterialUtilities.hlsl
  46. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs
  47. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs
  48. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.cs
  49. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.cs.hlsl
  50. 156
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.shader
  51. 7
      Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/UnlitData.hlsl
  52. 207
      Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/FinalPass.shader
  53. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/CommonSettings.cs
  54. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/Editor/CommonSettingsEditor.cs
  55. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs
  56. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl
  57. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs
  58. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl
  59. 26
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDebugViewMaterial.hlsl
  60. 28
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl
  61. 26
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl
  62. 37
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
  63. 26
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl
  64. 34
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl
  65. 53
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl
  66. 126
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl
  67. 32
      Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl
  68. 4
      Assets/ScriptableRenderLoop/HDRenderPipeline/Shadow/FixedSizePCF/FixedSizePCF.cs
  69. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Shadow/Shadow.hlsl
  70. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs
  71. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/HDRISkyParameters.cs
  72. 20
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/HDRISkyRenderer.cs
  73. 113
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/Resources/SkyHDRI.shader
  74. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Editor/ProceduralSkyEditor.cs
  75. 32
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyParameters.cs
  76. 77
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyRenderer.cs
  77. 35
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Resources/AtmosphericScattering.hlsl
  78. 40
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Resources/SkyProcedural.shader
  79. 30
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/GGXConvolve.shader
  80. 134
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs
  81. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs.hlsl
  82. 2
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyParameters.cs
  83. 8
      Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyRenderer.cs
  84. 21
      Assets/ScriptableRenderLoop/HDRenderPipeline/Utilities.cs
  85. 4
      Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs
  86. 9
      Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl
  87. 11
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  88. 38
      Assets/ScriptableRenderLoop/ShaderLibrary/BSDF.hlsl
  89. 88
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  90. 33
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl
  91. 22
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl
  92. 62
      Assets/ScriptableRenderLoop/ShaderLibrary/EntityLighting.hlsl
  93. 4
      Assets/ScriptableRenderLoop/ShaderLibrary/Fibonacci.hlsl
  94. 343
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  95. 42
      Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl
  96. 2
      Assets/ScriptableRenderLoop/common/TextureCache.cs
  97. 2
      Assets/ScriptableRenderLoop/common/TextureSettings.cs
  98. 4
      Assets/ScriptableRenderLoop/core/RenderPipeline.cs
  99. 10
      Assets/ScriptableRenderLoop/fptl/FptlLighting.cs
  100. 292
      Assets/ScriptableRenderLoop/fptl/Internal-DeferredComputeShading.compute

5
Assets/BasicRenderLoopTutorial/BasicRenderLoop.cs


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.ScriptableRenderPipeline;
// Very basic scriptable rendering loop example:
// - Use with BasicRenderLoopShader.shader (the loop expects "BasicPass" pass type to exist)

var settings = new DrawRendererSettings(cull, camera, new ShaderPassName("BasicPass"));
settings.sorting.flags = SortFlags.CommonOpaque;
settings.inputFilter.SetQueuesOpaque();
context.DrawRenderers(ref settings);
context.DrawRenderers(settings);
// Draw skybox
context.DrawSkybox(camera);

settings.inputFilter.SetQueuesTransparent();
context.DrawRenderers(ref settings);
context.DrawRenderers(settings);
context.Submit();
}

7
Assets/Editor/Tests/RenderloopTests/RenderloopTestFixture.cs


using System;
using System.Collections.Generic;
using UnityEngine.ScriptableRenderPipeline;
[ExecuteInEditMode]
public class RenderLoopTestFixture : RenderPipelineAsset

var sceneCamera = Camera.main;
var camObject = sceneCamera.gameObject;
GraphicsSettings.renderPipeline = m_Instance;
GraphicsSettings.renderPipelineAsset = m_Instance;
s_Callback = renderCallback;
Transform t = camObject.transform;

SceneView.lastActiveSceneView.LookAtDirect(t.position + t.forward * camDist, t.rotation, size);
sceneCamera.Render();
GraphicsSettings.renderPipeline = null;
GraphicsSettings.renderPipelineAsset = null;
}
}

2
Assets/Editor/Tests/ShaderGeneratorTests/ShaderGeneratorTests.cs


using UnityEngine;
using UnityEditor;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.ScriptableRenderLoop;
using UnityEditor.Experimental.Rendering;
[TestFixture]
public class ShaderGeneratorTests

10
Assets/ScriptableRenderLoop/AdditionalLightData.cs


namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering
{
public enum LightArchetype {Punctual, Rectangle, Line};

return DefaultShadowResolution;
}
[RangeAttribute(0.0F, 100.0F)]
[Range(0.0F, 100.0F)]
private float m_innerSpotPercent = 0.0F;
public float GetInnerSpotPercent01()

[RangeAttribute(0.0F, 1.0F)]
[Range(0.0F, 1.0F)]
public float shadowDimmer = 1.0f;
public bool affectDiffuse = true;

public bool isDoubleSided = false;
[RangeAttribute(0.0f, 20.0f)]
[Range(0.0f, 20.0f)]
[RangeAttribute(0.0f, 20.0f)]
[Range(0.0f, 20.0f)]
public float areaLightWidth = 0.0f;
}
}

5
Assets/ScriptableRenderLoop/Editor/MaterialUpgrader.cs


using System.Collections;
using System.Collections.Generic;
using System.Collections.Generic;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering
{
public class MaterialUpgrader
{

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/DebugViewMaterial.cs


using UnityEngine;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Attributes
{

public enum DebugViewGbuffer
{
Depth = DebugViewVarying.VertexColorAlpha + 1,
BakeDiffuseLighting,
BakeDiffuseLightingWithAlbedoPlusEmissive,
} // namespace UnityEngine.Experimental.ScriptableRenderLoop
}

6
Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/DebugViewMaterial.cs.hlsl


#ifndef DEBUGVIEWMATERIAL_CS_HLSL
#define DEBUGVIEWMATERIAL_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.Attributes.DebugViewVarying: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewVarying: static fields
//
#define DEBUGVIEWVARYING_TEXCOORD0 (1)
#define DEBUGVIEWVARYING_TEXCOORD1 (2)

#define DEBUGVIEWVARYING_VERTEX_COLOR_ALPHA (9)
//
// UnityEngine.Experimental.ScriptableRenderLoop.Attributes.DebugViewGbuffer: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewGbuffer: static fields
#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING (11)
#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE (11)
#endif

11
Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/Resources/DebugViewMaterialGBuffer.shader


Blend SrcAlpha OneMinusSrcAlpha // We will lerp only the values that are valid
HLSLPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma vertex Vert
#pragma fragment Frag

float linearDepth = frac(posInput.depthVS * 0.1);
result = linearDepth.xxx;
}
else if (_DebugViewMaterial == DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING)
// Caution: This value is not the same than the builtin data bakeDiffuseLighting. It also include emissive and multiply by the albedo
else if (_DebugViewMaterial == DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE)
result = bakeDiffuseLighting;
// TODO: require a remap
// TODO: we should not gamma correct, but easier to debug for now without correct high range value
result = bakeDiffuseLighting; needLinearToSRGB = true;
}
GetBSDFDataDebug(_DebugViewMaterial, bsdfData, result, needLinearToSRGB);

20
Assets/ScriptableRenderLoop/HDRenderPipeline/Debug/Resources/DebugViewTiles.shader


Blend SrcAlpha OneMinusSrcAlpha
HLSLPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#define LIGHTLOOP_TILE_PASS 1
#define LIGHTLOOP_TILE_ALL 1
#define LIGHTLOOP_TILE_PASS
#define LIGHTLOOP_TILE_ALL
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST

float depthMouse = LOAD_TEXTURE2D(_CameraDepthTexture, mousePosInput.unPositionSS).x;
UpdatePositionInput(depthMouse, _InvViewProjMatrix, _ViewProjMatrix, mousePosInput);
int category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
int start;
int count;
uint category = (LIGHTCATEGORY_COUNT - 1) - tileCoord.y;
uint start;
uint count;
GetCountAndStart(mousePosInput, category, start, count);
float4 result2 = float4(.1,.1,.1,.9);

int n = -1;
if(tileCoord.x == 0)
{
n = count;
n = (int)count;
else if(lightListIndex >= 0 && lightListIndex < count)
else if(lightListIndex >= 0 && lightListIndex < (int)count)
{
n = FetchIndex(start, lightListIndex);
}

}
}
Fallback Off
}
}

10
Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


//using EditorGUIUtility=UnityEditor.EditorGUIUtility;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[CustomEditor(typeof(HDRenderPipeline))]
public class HDRenderPipelineInspector : Editor

public readonly GUIContent displayOpaqueObjects = new GUIContent("Display Opaque Objects", "Toggle opaque objects rendering on and off.");
public readonly GUIContent displayTransparentObjects = new GUIContent("Display Transparent Objects", "Toggle transparent objects rendering on and off.");
public readonly GUIContent enableTonemap = new GUIContent("Enable Tonemap");
public readonly GUIContent exposure = new GUIContent("Exposure");
public readonly GUIContent useForwardRenderingOnly = new GUIContent("Use Forward Rendering Only");
public readonly GUIContent useDepthPrepass = new GUIContent("Use Depth Prepass");

debugParameters.debugViewMaterial = EditorGUILayout.IntPopup(styles.debugViewMaterial, (int)debugParameters.debugViewMaterial, styles.debugViewMaterialStrings, styles.debugViewMaterialValues);
EditorGUILayout.Space();
debugParameters.enableTonemap = EditorGUILayout.Toggle(styles.enableTonemap, debugParameters.enableTonemap);
debugParameters.exposure = Mathf.Max(Mathf.Min(EditorGUILayout.FloatField(styles.exposure, debugParameters.exposure), k_MaxExposure), -k_MaxExposure);
EditorGUILayout.Space();
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(renderContext); // Repaint

20
Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/HDRenderPipelineMenuItems.cs


using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine.Experimental.ScriptableRenderLoop;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
[UnityEditor.MenuItem("HDRenderPipeline/Create Scene Settings")]
[MenuItem("HDRenderPipeline/Create Scene Settings")]
CommonSettings[] settings = Object.FindObjectsOfType(typeof(CommonSettings)) as CommonSettings[];
CommonSettings[] settings = Object.FindObjectsOfType<CommonSettings>();
GameObject go = new GameObject();
go.name = "SceneSettings";
go.AddComponent(typeof(CommonSettings));
GameObject go = new GameObject { name = "SceneSettings" };
go.AddComponent<CommonSettings>();
go.AddComponent<PostProcessing>();
}
else
{

[UnityEditor.MenuItem("HDRenderPipeline/Synchronize all Layered materials")]
[MenuItem("HDRenderPipeline/Synchronize all Layered materials")]
static void SynchronizeAllLayeredMaterial()
{
Object[] materials = Resources.FindObjectsOfTypeAll<Material>();

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Editor/UpgradeStandardShaderMaterials.cs


using System.Collections;
using UnityEditor;
using System;
using NUnit.Framework;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
public class UpgradeStandardShaderMaterials
public class UpgradeStandardShaderMaterials
{
static List<MaterialUpgrader> GetHDUpgraders()
{

1
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.asset


m_Script: {fileID: 11500000, guid: d440c0deec24a2f478b3e9021cb66c29, type: 3}
m_Name: HDRenderPipeline
m_EditorClassIdentifier:
m_setup: {fileID: 11400000, guid: c90ada6c2ed7b4e4b85a303678826111, type: 2}
m_ShadowSettings:
enabled: 1
shadowAtlasWidth: 4096

2
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.asset.meta


fileFormatVersion: 2
guid: e185fecca3c73cd47a09f1092663ef32
timeCreated: 1483606455
timeCreated: 1484329328
licenseType: Pro
NativeFormatImporter:
userData:

211
Assets/ScriptableRenderLoop/HDRenderPipeline/HDRenderPipeline.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.ScriptableRenderPipeline;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class HDRenderPipelineInstance : RenderPipeline
{

if (m_Owner != null)
m_Owner.Build();
}
public override void Dispose()
{
base.Dispose();

public override void Render(ScriptableRenderContext renderContext, Camera[] cameras)
{

{
var instance = ScriptableObject.CreateInstance<HDRenderPipeline>();
UnityEditor.AssetDatabase.CreateAsset(instance, k_HDRenderPipelinePath);
instance.m_setup = UnityEditor.AssetDatabase.LoadAssetAtPath<HDRenderPipelineSetup>("Assets/HDRenderPipelineSetup.asset");
}
[UnityEditor.MenuItem("RenderPipeline/UpdateHDLoop")]
static void UpdateHDLoop()
{
var guids = AssetDatabase.FindAssets("t:HDRenderPipeline");
foreach (var guid in guids)
{
string path = AssetDatabase.GUIDToAssetPath(guid);
var loop = AssetDatabase.LoadAssetAtPath<HDRenderPipeline>(path);
loop.m_setup = AssetDatabase.LoadAssetAtPath<HDRenderPipelineSetup>("Assets/HDRenderPipelineSetup.asset");
EditorUtility.SetDirty(loop);
}
}
[UnityEditor.MenuItem("HDRenderPipeline/Add \"Additional Light Data\" (if not present)")]

}
#endif
HDRenderPipeline()
{
m_lightLoop = new TilePass.LightLoop(this);
}
[SerializeField]
private HDRenderPipelineSetup m_setup;
public HDRenderPipelineSetup renderPipelineSetup
{
get { return m_setup; }
}
SkyManager m_SkyManager = new SkyManager();
public SkyManager skyManager
{

public bool useDepthPrepass = false;
public bool useDistortion = true;
public bool enableTonemap = true;
public float exposure = 0;
// we have to fallback to forward-only rendering when scene view is using wireframe rendering mode --
// as rendering everything in wireframe + deferred do not play well together
public bool ShouldUseForwardRenderingOnly () { return useForwardRenderingOnly || GL.wireframe; }
}
DebugParameters m_DebugParameters = new DebugParameters();

}
// Various set of material use in render loop
Material m_FinalPassMaterial;
Material m_DebugViewMaterialGBuffer;
// Various buffer

// Keep these settings safe to recover when leaving the render pipeline
bool previousLightsUseLinearIntensity;
bool previousLightsUseCCT;
bool previousLightsUseColorTemperature;
BaseLightLoop m_lightLoop = new TilePass.LightLoop();
BaseLightLoop m_lightLoop;
public BaseLightLoop lightLoop
{

#endif
previousLightsUseLinearIntensity = UnityEngine.Rendering.GraphicsSettings.lightsUseLinearIntensity;
previousLightsUseCCT = UnityEngine.Rendering.GraphicsSettings.lightsUseCCT;
previousLightsUseColorTemperature = UnityEngine.Rendering.GraphicsSettings.lightsUseColorTemperature;
UnityEngine.Rendering.GraphicsSettings.lightsUseCCT = true;
UnityEngine.Rendering.GraphicsSettings.lightsUseColorTemperature = true;
m_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
m_CameraDepthBuffer = Shader.PropertyToID("_CameraDepthTexture");

m_SkyManager.Build();
m_FinalPassMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/FinalPass");
m_DebugViewMaterialGBuffer = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/DebugViewMaterialGBuffer");
m_ShadowPass = new ShadowRenderPass(m_ShadowSettings);

{
m_lightLoop.Cleanup();
m_LitRenderLoop.Cleanup();
Utilities.Destroy(m_FinalPassMaterial);
Utilities.Destroy(m_DebugViewMaterialGBuffer);
m_SkyManager.Cleanup();

#endif
UnityEngine.Rendering.GraphicsSettings.lightsUseLinearIntensity = previousLightsUseLinearIntensity;
UnityEngine.Rendering.GraphicsSettings.lightsUseCCT = previousLightsUseCCT;
UnityEngine.Rendering.GraphicsSettings.lightsUseColorTemperature = previousLightsUseColorTemperature;
}
void InitAndClearBuffer(Camera camera, ScriptableRenderContext renderContext)

cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear, 1, true); // Enable UAV
cmd.GetTemporaryRT(m_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
if (!debugParameters.useForwardRenderingOnly)
if (!debugParameters.ShouldUseForwardRenderingOnly())
{
m_gbufferManager.InitGBuffers(w, h, cmd);
}

// Clear GBuffers
using (new Utilities.ProfilingSample("Clear GBuffer", renderContext))
if (!debugParameters.ShouldUseForwardRenderingOnly())
Utilities.SetRenderTarget(renderContext, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
using (new Utilities.ProfilingSample("Clear GBuffer", renderContext))
{
Utilities.SetRenderTarget(renderContext, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
}
// END TEMP
}
}

sorting = { flags = SortFlags.CommonOpaque }
};
settings.inputFilter.SetQueuesOpaque();
renderContext.DrawRenderers(ref settings);
renderContext.DrawRenderers(settings);
}
void RenderTransparentRenderList(CullResults cull, Camera camera, ScriptableRenderContext renderContext, string passName, RendererConfiguration rendererConfiguration = 0)

sorting = { flags = SortFlags.CommonTransparent }
};
settings.inputFilter.SetQueuesTransparent();
renderContext.DrawRenderers(ref settings);
renderContext.DrawRenderers(settings);
}
void RenderDepthPrepass(CullResults cull, Camera camera, ScriptableRenderContext renderContext)

void RenderGBuffer(CullResults cull, Camera camera, ScriptableRenderContext renderContext)
{
if (debugParameters.useForwardRenderingOnly)
if (debugParameters.ShouldUseForwardRenderingOnly())
{
return ;
}

}
// This pass is use in case of forward opaque and deferred rendering. We need to render forward objects before tile lighting pass
void RenderForwardOnlyDepthPrepass(CullResults cull, Camera camera, ScriptableRenderContext renderContext)
void RenderForwardOnlyOpaqueDepthPrepass(CullResults cull, Camera camera, ScriptableRenderContext renderContext)
// If we are forward only we don't need to render ForwardOpaqueDepth object
// If we are forward only we don't need to render ForwardOnlyOpaqueDepthOnly object
if (debugParameters.useForwardRenderingOnly && !debugParameters.useDepthPrepass)
if (debugParameters.ShouldUseForwardRenderingOnly() && !debugParameters.useDepthPrepass)
RenderOpaqueRenderList(cull, camera, renderContext, "ForwardOnlyDepthOnly");
RenderOpaqueRenderList(cull, camera, renderContext, "ForwardOnlyOpaqueDepthOnly");
}
}

Shader.SetGlobalInt("_DebugViewMaterial", (int)debugParameters.debugViewMaterial);
RenderOpaqueRenderList(cull, hdCamera.camera, renderContext, "DebugViewMaterial");
RenderOpaqueRenderList(cull, hdCamera.camera, renderContext, "DebugViewMaterial", Utilities.kRendererConfigurationBakedLighting);
if (!debugParameters.useForwardRenderingOnly)
if (!debugParameters.ShouldUseForwardRenderingOnly())
{
Utilities.SetupMaterialHDCamera(hdCamera, m_DebugViewMaterialGBuffer);
m_DebugViewMaterialGBuffer.SetFloat("_DebugViewMaterial", (float)debugParameters.debugViewMaterial);

// Render forward transparent
{
RenderTransparentRenderList(cull, hdCamera.camera, renderContext, "DebugViewMaterial");
RenderTransparentRenderList(cull, hdCamera.camera, renderContext, "DebugViewMaterial", Utilities.kRendererConfigurationBakedLighting);
}
// Last blit

void RenderDeferredLighting(HDCamera hdCamera, ScriptableRenderContext renderContext)
{
if (debugParameters.useForwardRenderingOnly)
if (debugParameters.ShouldUseForwardRenderingOnly())
// Bind material data
m_LitRenderLoop.Bind();
m_lightLoop.RenderDeferredLighting(hdCamera, renderContext, m_CameraColorBuffer);
}

{
m_SkyManager.RenderSky(hdCamera, m_lightLoop.GetCurrentSunLight(), m_CameraColorBufferRT, m_CameraDepthBufferRT, renderContext);
}
if (!debugParameters.useForwardRenderingOnly && renderOpaque)
if (!debugParameters.ShouldUseForwardRenderingOnly() && renderOpaque)
// Bind material data
m_LitRenderLoop.Bind();
Utilities.SetRenderTarget(renderContext, m_CameraColorBufferRT, m_CameraDepthBufferRT);
m_lightLoop.RenderForward(camera, renderContext, renderOpaque);

RenderOpaqueRenderList(cullResults, camera, renderContext, "Forward");
RenderOpaqueRenderList(cullResults, camera, renderContext, "Forward", Utilities.kRendererConfigurationBakedLighting);
}
else
{

}
// Render material that are forward opaque only (like eye)
// TODO: Think about hair that could be render both as opaque and transparent...
void RenderForwardOnly(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext)
// Render material that are forward opaque only (like eye), this include unlit material
void RenderForwardOnlyOpaque(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext)
// Bind material data
m_LitRenderLoop.Bind();
RenderOpaqueRenderList(cullResults, camera, renderContext, "ForwardOnly");
}
}
void RenderForwardUnlit(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext)
{
using (new Utilities.ProfilingSample("Forward Unlit Pass", renderContext))
{
// Bind material data
m_LitRenderLoop.Bind();
Utilities.SetRenderTarget(renderContext, m_CameraColorBufferRT, m_CameraDepthBufferRT);
RenderOpaqueRenderList(cullResults, camera, renderContext, "ForwardUnlit");
RenderTransparentRenderList(cullResults, camera, renderContext, "ForwardUnlit");
RenderOpaqueRenderList(cullResults, camera, renderContext, "ForwardOnlyOpaque", Utilities.kRendererConfigurationBakedLighting);
}
}

{
// If opaque velocity have been render during GBuffer no need to render it here
if ((ShaderConfig.s_VelocityInGbuffer == 0) || debugParameters.useForwardRenderingOnly)
if ((ShaderConfig.s_VelocityInGbuffer == 1) || debugParameters.ShouldUseForwardRenderingOnly())
return ;
int w = camera.pixelWidth;

}
}
void FinalPass(ScriptableRenderContext renderContext)
void FinalPass(Camera camera, ScriptableRenderContext renderContext)
// Those could be tweakable for the neutral tonemapper, but in the case of the LookDev we don't need that
const float blackIn = 0.02f;
const float whiteIn = 10.0f;
const float blackOut = 0.0f;
const float whiteOut = 10.0f;
const float whiteLevel = 5.3f;
const float whiteClip = 10.0f;
const float dialUnits = 20.0f;
const float halfDialUnits = dialUnits * 0.5f;
// All of this is temporary, sub-optimal and quickly hacked together but is necessary
// for artists to do lighting work until the fully-featured framework is ready
// converting from artist dial units to easy shader-lerps (0-1)
var tonemapCoeff1 = new Vector4((blackIn * dialUnits) + 1.0f, (blackOut * halfDialUnits) + 1.0f, (whiteIn / dialUnits), (1.0f - (whiteOut / dialUnits)));
var tonemapCoeff2 = new Vector4(0.0f, 0.0f, whiteLevel, whiteClip / halfDialUnits);
var localPostProcess = camera.GetComponent<PostProcessing>();
var globalPostProcess = commonSettings == null
? null
: commonSettings.GetComponent<PostProcessing>();
m_FinalPassMaterial.SetVector("_ToneMapCoeffs1", tonemapCoeff1);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs2", tonemapCoeff2);
bool localActive = localPostProcess != null && localPostProcess.enabled;
bool globalActive = globalPostProcess != null && globalPostProcess.enabled;
m_FinalPassMaterial.SetFloat("_EnableToneMap", debugParameters.enableTonemap ? 1.0f : 0.0f);
m_FinalPassMaterial.SetFloat("_Exposure", debugParameters.exposure);
if (!localActive && !globalActive)
{
var cmd = new CommandBuffer { name = "" };
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
return;
}
var cmd = new CommandBuffer { name = "" };
// Resolve our HDR texture to CameraTarget.
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget, m_FinalPassMaterial, 0);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
var target = localActive ? localPostProcess : globalPostProcess;
target.Render(camera, renderContext, m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget);
}
}

// TODO: This is the wrong way to handle resize/allocation. We can have several different camera here, mean that the loop on camera will allocate and deallocate
// the below buffer which is bad. Best is to have a set of buffer for each camera that is persistent and reallocate resource if need
// For now consider we have only one camera that go to this code, the main one.
m_SkyManager.Resize(); // TODO: Also a bad naming, here we just want to realloc texture if skyparameters change (usefull for lookdev)
m_SkyManager.Resize(camera.nearClipPlane, camera.farClipPlane); // TODO: Also a bad naming, here we just want to realloc texture if skyparameters change (usefull for lookdev)
if (camera.pixelWidth != m_currentWidth || camera.pixelHeight != m_currentHeight || m_lightLoop.NeedResize())
{

m_ShadowSettings.maxShadowDistance = m_CommonSettings.shadowMaxDistance;
}
}
public void Render(ScriptableRenderContext renderContext, IEnumerable<Camera> cameras)
{
if (!m_LitRenderLoop.isInit)

InitAndClearBuffer(camera, renderContext);
// TODO: Find a correct place to bind these material textures
// We have to bind the material specific global parameters in this mode
m_LitRenderLoop.Bind();
RenderForwardOnlyDepthPrepass(cullResults, camera, renderContext);
RenderForwardOnlyOpaqueDepthPrepass(cullResults, camera, renderContext);
RenderGBuffer(cullResults, camera, renderContext);
if (debugParameters.debugViewMaterial != 0)

using (new Utilities.ProfilingSample("Shadow Pass", renderContext))
{
m_ShadowPass.Render(renderContext, cullResults, out shadows);
}
}
m_lightLoop.BuildGPULightLists(camera, renderContext, m_CameraDepthBufferRT);
m_lightLoop.BuildGPULightLists(camera, renderContext, m_CameraDepthBufferRT); // TODO: Use async compute here to run light culling during shadow
}
PushGlobalParams(hdCamera, renderContext);
}
UpdateSkyEnvironment(hdCamera, renderContext);
PushGlobalParams(hdCamera, renderContext);
// Caution: We require sun light here as some sky use the sun light to render, mean UpdateSkyEnvironment
// must be call after BuildGPULightLists.
// TODO: Try to arrange code so we can trigger this call earlier and use async compute here to run sky convolution during other passes (once we move convolution shader to compute).
UpdateSkyEnvironment(hdCamera, renderContext);
RenderForward(cullResults, camera, renderContext, true);
RenderForwardOnly(cullResults, camera, renderContext);
// For opaque forward we have split rendering in two categories
// Material that are always forward and material that can be deferred or forward depends on render pipeline options (like switch to rendering forward only mode)
// Material that are always forward are unlit and complex (Like Hair) and don't require sorting, so it is ok to split them.
RenderForward(cullResults, camera, renderContext, true); // Render deferred or forward opaque
RenderForwardOnlyOpaque(cullResults, camera, renderContext);
// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForwardUnlit(cullResults, camera, renderContext);
RenderVelocity(cullResults, camera, renderContext); // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?
// TODO: Check with VFX team.

RenderDistortion(cullResults, camera, renderContext);
FinalPass(renderContext);
FinalPass(camera, renderContext);
}
// bind depth surface for editor grid/gizmo/selection rendering

renderContext.Submit();
}
// Post effects
}
}
}

5
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/Forward.hlsl


// Must match name in GetKeyword() method of forward lighting architecture .cs file
// #pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS -> can't use a pragma from include... (for now)
// #pragma multi_compile SHADOWFILTERING_FIXED_SIZE_PCF -> can't use a pragma from include... (for now)
// No USE_FPTL_LIGHTLIST as we are in forward and this use the cluster path (but cluster path can use the tile light list for opaque)
#define USE_CLUSTERED_LIGHTLIST
#define LIGHTLOOP_TILE_ALL

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightDefinition.cs


using UnityEngine;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
//-----------------------------------------------------------------------------
// structure definition

public Vector3 offsetLS;
public float unused2;
};
} // namespace UnityEngine.Experimental.ScriptableRenderLoop
}

22
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl


#ifndef LIGHTDEFINITION_CS_HLSL
#define LIGHTDEFINITION_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.GPULightType: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.GPULightType: static fields
//
#define GPULIGHTTYPE_DIRECTIONAL (0)
#define GPULIGHTTYPE_SPOT (1)

#define GPULIGHTTYPE_CYLINDER (10)
//
// UnityEngine.Experimental.ScriptableRenderLoop.EnvShapeType: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.EnvShapeType: static fields
//
#define ENVSHAPETYPE_NONE (0)
#define ENVSHAPETYPE_BOX (1)

//
// UnityEngine.Experimental.ScriptableRenderLoop.EnvConstants: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.EnvConstants: static fields
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.LightData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.LightData
// PackingRules = Exact
struct LightData
{

bool twoSided;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.DirectionalLightData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
// PackingRules = Exact
struct DirectionalLightData
{

int cookieIndex;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.ShadowData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.ShadowData
// PackingRules = Exact
struct ShadowData
{

float4 invResolution;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.EnvLightData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.EnvLightData
// PackingRules = Exact
struct EnvLightData
{

};
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.LightData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.LightData
//
float3 GetPositionWS(LightData value)
{

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.DirectionalLightData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.DirectionalLightData
//
float3 GetForward(DirectionalLightData value)
{

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.ShadowData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.ShadowData
//
float4x4 GetWorldToShadow(ShadowData value)
{

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.EnvLightData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.EnvLightData
//
float3 GetPositionWS(EnvLightData value)
{

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/LightLoop.cs


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class BaseLightLoop
{

5
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/Resources/Deferred.shader


Blend[_SrcBlend][_DstBlend]
HLSLPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma vertex Vert
#pragma fragment Frag

//#pragma multi_compile SHADOWFILTERING_FIXED_SIZE_PCF
// TODO: Workflow problem here, I would like to only generate variant for the LIGHTLOOP_TILE_PASS case, not the LIGHTLOOP_SINGLE_PASS case. This must be on lightloop side and include here.... (Can we codition
#pragma multi_compile LIGHTLOOP_TILE_DIRECT LIGHTLOOP_TILE_INDIRECT LIGHTLOOP_TILE_ALL

7
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute


#include "common.hlsl"
#include "../TilePass.cs.hlsl"
#include "../LightingConvexHullUtils.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#if !defined(SHADER_API_XBOXONE)
#include "../SortingComputeUtils.hlsl"
#endif

for(int l=0; l<iNrCoarseLights; l++)
{
const uint idxCoarse = lightsListLDS[l];
[branch]if (idxCoarse<(uint)g_iNrVisibLights && _LightVolumeData[idxCoarse].lightVolume != LIGHTVOLUMETYPE_SPHERE) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
bool canEnter = idxCoarse<(uint)g_iNrVisibLights;
if(canEnter) canEnter = _LightVolumeData[idxCoarse].lightVolume != LIGHTVOLUMETYPE_SPHERE; // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
[branch]if(canEnter)
{
SFiniteLightBound lgtDat = g_data[idxCoarse];

105
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace TilePass
{

public static float VIEWPORT_SCALE_Z = 1.0f;
// enable unity's original left-hand shader camera space (right-hand internally in unity).
public static int USE_LEFTHAND_CAMERASPACE = 0;
public static int USE_LEFTHAND_CAMERASPACE = 1;
// flags
public static int IS_CIRCULAR_SPOT_SHAPE = 1;

int m_areaLightCount = 0;
int m_lightCount = 0;
static ComputeShader buildScreenAABBShader = null;
static ComputeShader buildPerTileLightListShader = null; // FPTL
static ComputeShader buildPerBigTileLightListShader = null;
static ComputeShader buildPerVoxelLightListShader = null; // clustered
static ComputeShader shadeOpaqueShader = null;
private ComputeShader buildScreenAABBShader { get { return m_Parent.renderPipelineSetup.buildScreenAABBShader; } }
private ComputeShader buildPerTileLightListShader { get { return m_Parent.renderPipelineSetup.buildPerTileLightListShader; } }
private ComputeShader buildPerBigTileLightListShader { get { return m_Parent.renderPipelineSetup.buildPerBigTileLightListShader; } }
private ComputeShader buildPerVoxelLightListShader { get { return m_Parent.renderPipelineSetup.buildPerVoxelLightListShader; } }
private ComputeShader shadeOpaqueShader { get { return m_Parent.renderPipelineSetup.shadeOpaqueShader; } }
static int s_GenAABBKernel;
static int s_GenListPerTileKernel;

static int s_GenListPerBigTileKernel;
public bool enableDrawLightBoundsDebug = false;
public bool disableTileAndCluster = true; // For debug / test
public bool disableTileAndCluster = false; // For debug / test
public bool disableDeferredShadingInCompute = true;
public bool enableSplitLightEvaluation = true;
public bool enableComputeLightEvaluation = false;

public bool enableClustered = false;
public bool disableFptlWhenClustered = true; // still useful on opaques. Should be false by default to force tile on opaque.
public bool enableBigTilePrepass = false;
public bool enableClustered = true;
public bool disableFptlWhenClustered = false; // still useful on opaques. Should be false by default to force tile on opaque.
public bool enableBigTilePrepass = true;
const bool k_UseDepthBuffer = true; // only has an impact when EnableClustered is true (requires a depth-prepass)
const bool k_UseAsyncCompute = true; // should not use on mobile

static ComputeBuffer s_GlobalLightListAtomic = null;
// clustered light list specific buffers and data end
private static GameObject s_DefaultAdditionalLightDataGameObject;
private static AdditionalLightData s_DefaultAdditionalLightData;
bool usingFptl
{
get

}
}
private static AdditionalLightData DefaultAdditionalLightData
{
get
{
if (s_DefaultAdditionalLightDataGameObject == null)
{
s_DefaultAdditionalLightDataGameObject = new GameObject("Default Light Data");
s_DefaultAdditionalLightDataGameObject.hideFlags = HideFlags.HideAndDontSave;
s_DefaultAdditionalLightData = s_DefaultAdditionalLightDataGameObject.AddComponent<AdditionalLightData>();
}
return s_DefaultAdditionalLightData;
}
}
Material m_DeferredDirectMaterial = null;
Material m_DeferredIndirectMaterial = null;
Material m_DeferredAllMaterial = null;

const int k_TileSize = 16;
private readonly HDRenderPipeline m_Parent;
int GetNumTileX(Camera camera)
{

return (camera.pixelHeight + (k_TileSize - 1)) / k_TileSize;
}
public LightLoop(HDRenderPipeline hdRenderPipeline)
{
m_Parent = hdRenderPipeline;
}
public override void Build(TextureSettings textureSettings)
{
m_lightList = new LightList();

m_CubeReflTexArray = new TextureCacheCubemap();
m_CubeReflTexArray.AllocTextureArray(32, textureSettings.reflectionCubemapSize, TextureFormat.BC6H, true);
buildScreenAABBShader = Resources.Load<ComputeShader>("scrbound");
buildPerTileLightListShader = Resources.Load<ComputeShader>("lightlistbuild");
buildPerBigTileLightListShader = Resources.Load<ComputeShader>("lightlistbuild-bigtile");
buildPerVoxelLightListShader = Resources.Load<ComputeShader>("lightlistbuild-clustered");
shadeOpaqueShader = Resources.Load<ComputeShader>("shadeopaque");
s_GenAABBKernel = buildScreenAABBShader.FindKernel("ScreenBoundsAABB");
s_GenListPerTileKernel = buildPerTileLightListShader.FindKernel(enableBigTilePrepass ? "TileLightListGen_SrcBigTile" : "TileLightListGen");
s_AABBBoundsBuffer = new ComputeBuffer(2 * k_MaxLightsOnScreen, 3 * sizeof(float));

Utilities.Destroy(m_DebugViewTilesMaterial);
Utilities.Destroy(m_SingleDeferredMaterial);
GameObject.DestroyImmediate(s_DefaultAdditionalLightDataGameObject);
s_DefaultAdditionalLightDataGameObject = null;
s_DefaultAdditionalLightData = null;
}
public override void NewFrame()

{
m_lightList.Clear();
if (cullResults.visibleLights.Length == 0)
if (cullResults.visibleLights.Length == 0 && cullResults.visibleReflectionProbes.Length == 0)
return;
// 1. Count the number of lights and sort all light by category, type and volume

if (additionalData == null)
{
Debug.LogWarning("Light entity detected without additional data, will not be taken into account " + light.light.name);
continue;
Debug.LogWarningFormat("Light entity {0} has no additional data, will be rendered using default values.", light.light.name);
additionalData = DefaultAdditionalLightData;
}
LightCategory lightCategory = LightCategory.Count;

int lightIndex = (int)(sortKey & 0xFFFF);
var light = cullResults.visibleLights[lightIndex];
var additionalData = light.light.GetComponent<AdditionalLightData>();
var additionalData = light.light.GetComponent<AdditionalLightData>() ?? DefaultAdditionalLightData;
// Directional rendering side, it is separated as it is always visible so no volume to handle here
if (gpuLightType == GPULightType.Directional)

for (int n = 0; n < numVectors; n++)
{
for (int i = 0; i < 4; i++)
{
{
data[4 * n + i] = values[n][i];
}
}

#if UNITY_EDITOR
private Vector2 m_mousePosition = Vector2.zero;
private void OnSceneGUI(UnityEditor.SceneView sceneview)
{
m_mousePosition = Event.current.mousePosition;

SetGlobalBuffer("g_vLightListGlobal", bUseClusteredForDeferred ? s_PerVoxelLightLists : s_LightList); // opaques list (unless MSAA possibly)
SetGlobalPropertyRedirect(shadeOpaqueShader, usingFptl ? s_shadeOpaqueFptlKernel : s_shadeOpaqueClusteredKernel, cmd);
SetGlobalBuffer("g_vLightListGlobal", bUseClusteredForDeferred ? s_PerVoxelLightLists : s_LightList); // opaques list (unless MSAA possibly)
// In case of bUseClusteredForDeferred disable toggle option since we're using m_perVoxelLightLists as opposed to lightList
if (bUseClusteredForDeferred)

if (disableTileAndCluster)
{
// This is a debug brute force renderer to debug tile/cluster which render all the lights
Utilities.SetupMaterialHDCamera(hdCamera, m_SingleDeferredMaterial);
m_SingleDeferredMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
m_SingleDeferredMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);

cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "uavOutput", cameraColorBufferRT);
cmd.DispatchCompute(shadeOpaqueShader, kernel, numTilesX, numTilesY, 1);
}
else
{
// Pixel shader evaluation
if (enableSplitLightEvaluation)
}
else
// Pixel shader evaluation
if (enableSplitLightEvaluation)
{
Utilities.SetupMaterialHDCamera(hdCamera, m_DeferredDirectMaterial);
m_DeferredDirectMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
m_DeferredDirectMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);

m_DeferredIndirectMaterial.EnableKeyword(bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");
m_DeferredIndirectMaterial.DisableKeyword(!bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");
cmd.Blit(null, cameraColorBufferRT, m_DeferredDirectMaterial, 0);
cmd.Blit(null, cameraColorBufferRT, m_DeferredIndirectMaterial, 0);
}
else
{
cmd.Blit(null, cameraColorBufferRT, m_DeferredDirectMaterial, 0);
cmd.Blit(null, cameraColorBufferRT, m_DeferredIndirectMaterial, 0);
}
else
{
Utilities.SetupMaterialHDCamera(hdCamera, m_DeferredAllMaterial);
m_DeferredAllMaterial.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
m_DeferredAllMaterial.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);

cmd.Blit(null, cameraColorBufferRT, m_DeferredAllMaterial, 0);
}
cmd.Blit(null, cameraColorBufferRT, m_DeferredAllMaterial, 0);
}
}
// Draw tile debugging

}
SetGlobalPropertyRedirect(null, 0, null);
//}
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();

public override void RenderForward(Camera camera, ScriptableRenderContext renderContext, bool renderOpaque)
{
// Note: if we use render opaque with deferred tiling we need to render a opque depth pass for these opaque objects
// Note: if we use render opaque with deferred tiling we need to render a opaque depth pass for these opaque objects
bool useFptl = renderOpaque && usingFptl;
var cmd = new CommandBuffer();

else
{
cmd.name = useFptl ? "Forward Tiled pass" : "Forward Clustered pass";
// say that we want to use tile of single loop
cmd.SetGlobalFloat("g_isOpaquesOnlyEnabled", useFptl ? 1 : 0); // leaving this as a dynamic toggle for now for forward opaques to keep shader variants down.
cmd.SetGlobalFloat("_UseTileLightList", useFptl ? 1 : 0); // leaving this as a dynamic toggle for now for forward opaques to keep shader variants down.
cmd.SetGlobalBuffer("g_vLightListGlobal", useFptl ? s_LightList : s_PerVoxelLightLists);
}

16
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl


#ifndef TILEPASS_CS_HLSL
#define TILEPASS_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeType: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightVolumeType: static fields
//
#define LIGHTVOLUMETYPE_CONE (0)
#define LIGHTVOLUMETYPE_SPHERE (1)

//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightCategory: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightCategory: static fields
//
#define LIGHTCATEGORY_PUNCTUAL (0)
#define LIGHTCATEGORY_AREA (1)

//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightDefinitions: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightDefinitions: static fields
#define USE_LEFTHAND_CAMERASPACE (0)
#define USE_LEFTHAND_CAMERASPACE (1)
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.TilePass.SFiniteLightBound
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.TilePass.SFiniteLightBound
// PackingRules = Exact
struct SFiniteLightBound
{

float radius;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightVolumeData
// PackingRules = Exact
struct LightVolumeData
{

};
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.TilePass.SFiniteLightBound
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.TilePass.SFiniteLightBound
//
float3 GetBoxAxisX(SFiniteLightBound value)
{

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeData
// Accessors for UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightVolumeData
//
float3 GetLightPos(LightVolumeData value)
{

25
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePass.hlsl


SAMPLER2D_SHADOW(samplerg_tShadowBuffer);
// Use texture array for IES
TEXTURE2D_ARRAY(_IESArray);
SAMPLER2D(sampler_IESArray);
//TEXTURE2D_ARRAY(_IESArray);
//SAMPLER2D(sampler_IESArray);
// Used by directional and spot lights
TEXTURE2D_ARRAY(_CookieTextures);

TEXTURECUBE_ARRAY(_CookieCubeTextures);
SAMPLERCUBE(sampler_CookieCubeTextures);
// Use texture array for reflection
// Use texture array for reflection (or LatLong 2D array for mobile)
#ifdef CUBE_ARRAY_NOT_SUPPORTED
TEXTURE2D_ARRAY(_EnvTextures);
SAMPLER2D(sampler_EnvTextures);
#else
#endif
TEXTURECUBE(_SkyTexture);
SAMPLERCUBE(sampler_SkyTexture); // NOTE: Sampler could be share here with _EnvTextures. Don't know if the shader compiler will complain...

// ----------------------------------------------------------------------------
// sphericalTexCoord is theta and phi spherical coordinate
float4 SampleIES(LightLoopContext lightLoopContext, int index, float2 sphericalTexCoord, float lod)
{
return SAMPLE_TEXTURE2D_ARRAY_LOD(_IESArray, sampler_IESArray, sphericalTexCoord, index, 0);
}
//float4 SampleIES(LightLoopContext lightLoopContext, int index, float2 sphericalTexCoord, float lod)
//{
// return SAMPLE_TEXTURE2D_ARRAY_LOD(_IESArray, sampler_IESArray, sphericalTexCoord, index, 0);
//}
//-----------------------------------------------------------------------------
// Reflection proble / Sky sampling function

// EnvIndex can also be use to fetch in another array of struct (to atlas information etc...).
float4 SampleEnv(LightLoopContext lightLoopContext, int index, float3 texCoord, float lod)
{
lod = min(lod, UNITY_SPECCUBE_LOD_STEPS);
#ifdef CUBE_ARRAY_NOT_SUPPORTED
return SAMPLE_TEXTURE2D_ARRAY_LOD(_EnvTextures, sampler_EnvTextures, DirectionToLatLongCoordinate(texCoord), index, lod);
#else
#endif
}
else // SINGLE_PASS_SAMPLE_SKY
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


return FetchIndexTile(tileOffset, lightIndex);
}
#else
#elif defined(USE_CLUSTERED_LIGHTLIST)
#include "ClusteredUtils.hlsl"

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.cs


//-----------------------------------------------------------------------------
// structure definition
//-----------------------------------------------------------------------------
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Builtin
{

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.cs.hlsl


#ifndef BUILTINDATA_CS_HLSL
#define BUILTINDATA_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.Builtin.BuiltinData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Builtin.BuiltinData: static fields
//
#define DEBUGVIEW_BUILTIN_BUILTINDATA_OPACITY (100)
#define DEBUGVIEW_BUILTIN_BUILTINDATA_BAKE_DIFFUSE_LIGHTING (101)

#define DEBUGVIEW_BUILTIN_BUILTINDATA_DEPTH_OFFSET (107)
//
// UnityEngine.Experimental.ScriptableRenderLoop.Builtin.LighTransportData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Builtin.LighTransportData: static fields
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Builtin.BuiltinData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Builtin.BuiltinData
// PackingRules = Exact
struct BuiltinData
{

float depthOffset;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Builtin.LighTransportData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Builtin.LighTransportData
// PackingRules = Exact
struct LighTransportData
{

7
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.hlsl


// Note: These parameters can be store in GBuffer if the writer wants
//-----------------------------------------------------------------------------
#include "BuiltinData.cs.hlsl"
//TODO: return this original relative path include after fixing a bug in Unity side
//#include "BuiltinData.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Builtin/BuiltinData.cs.hlsl"
//-----------------------------------------------------------------------------
// common Encode/Decode functions

break;
case DEBUGVIEW_BUILTIN_BUILTINDATA_BAKE_DIFFUSE_LIGHTING:
// TODO: require a remap
result = builtinData.bakeDiffuseLighting;
// TODO: we should not gamma correct, but easier to debug for now without correct high range value
result = builtinData.bakeDiffuseLighting; needLinearToSRGB = true;
break;
case DEBUGVIEW_BUILTIN_BUILTINDATA_EMISSIVE_COLOR:
// emissiveColor is premultiply by emissive intensity

284
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/Editor/LayeredLitUI.cs


using System.Linq;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
internal class LayeredLitGUI : LitGUI
{

UV3,
Planar,
Triplanar,
}
public enum VertexColorMode
{
None,
Multiply,
Add
}
private class StylesLayer

new GUIContent("Layer 0"),
new GUIContent("Main layer"),
public readonly GUIStyle[] layerLabelColors =
{
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label),
new GUIStyle(EditorStyles.label)
};
public readonly GUIContent layerMapMaskText = new GUIContent("Layer Mask", "Layer mask (multiplied by vertex color if enabled)");
public readonly GUIContent layerMapVertexColorText = new GUIContent("Use Vertex Color", "Layer mask (multiplied by layer mask if enabled)");
public readonly GUIContent layerMapMaskText = new GUIContent("Layer Mask", "Layer mask");
public readonly GUIContent vertexColorModeText = new GUIContent("Vertex Color Mode", "Mode multiply: vertex color is multiply with the mask. Mode additive: vertex color values are remapped between -1 and 1 and added to the mask (neutral at 0.5 vertex color).");
public readonly GUIContent layerTilingText = new GUIContent("Tiling", "Tiling factor applied to UVSet");
public readonly GUIContent MainLayerInfluenceText = new GUIContent("Main layer influence", "Main layer influence.");
public readonly GUIContent DensityOpacityInfluenceText = new GUIContent("Density / Opacity", "Density / Opacity");
public readonly GUIContent heightOffsetText = new GUIContent("HeightOffset", "Height offset from the previous layer.");
public readonly GUIContent useMainLayerInfluenceModeText = new GUIContent("Main Layer Influence", "Switch between regular layers mode and base/layers mode");
public readonly GUIContent heightOffsetText = new GUIContent("Height Offset", "Height offset from the previous layer.");
public readonly GUIContent heightControlText = new GUIContent("Height control");
public readonly GUIContent heightCenterOffsetText = new GUIContent("Height Center Offset", "Offset applied to the center of the height of the layer.");
public readonly GUIContent useHeightBasedBlendV2Text = new GUIContent("Use V2", "Layer will be blended with the underlying layer based on the height.");
public readonly GUIContent blendUsingHeight = new GUIContent("Blend Using Height", "Blend Layers using height.");
public readonly GUIContent inheritBaseColorThresholdText = new GUIContent("Threshold", "Inherit the base color from the base layer.");
public readonly GUIContent minimumOpacityText = new GUIContent("Minimum Opacity", "Minimum Opacity.");
public readonly GUIContent opacityAsDensityText = new GUIContent("Use Opacity as Density", "Use Opacity as Density.");
public readonly GUIContent inheritBaseNormalText = new GUIContent("Normal influence", "Inherit the normal from the base layer.");
public readonly GUIContent inheritBaseHeightText = new GUIContent("Heightmap influence", "Inherit the height from the base layer.");
public readonly GUIContent inheritBaseColorText = new GUIContent("BaseColor influence", "Inherit the base color from the base layer.");
public StylesLayer()
{
layerLabelColors[0].normal.textColor = Color.white;
layerLabelColors[1].normal.textColor = Color.red;
layerLabelColors[2].normal.textColor = Color.green;
layerLabelColors[3].normal.textColor = Color.blue;
}
}

MaterialProperty layerMaskMap = null;
const string kLayerMaskMap = "_LayerMaskMap";
MaterialProperty layerMaskVertexColor = null;
const string kLayerMaskVertexColor = "_LayerMaskVertexColor";
MaterialProperty vertexColorMode = null;
const string kVertexColorMode = "_VertexColorMode";
MaterialProperty layerCount = null;
const string kLayerCount = "_LayerCount";
MaterialProperty[] layerTexWorldScale = new MaterialProperty[kMaxLayerCount];

MaterialProperty[] layerUVDetail = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerUVDetailsMappingMask = new MaterialProperty[kMaxLayerCount];
const string kLayerTiling = "_LayerTiling";
MaterialProperty[] layerTiling = new MaterialProperty[kMaxLayerCount];
const string kkUseMainLayerInfluence = "_UseMainLayerInfluence";
MaterialProperty useMainLayerInfluence = null;
const string kUseHeightBasedBlendV2 = "_UseHeightBasedBlendV2";
MaterialProperty useHeightBasedBlendV2 = null;
const string kBlendUsingHeight = "_BlendUsingHeight";
MaterialProperty[] blendUsingHeight = new MaterialProperty[kMaxLayerCount - 1];
const string kHeightCenterOffset = "_HeightCenterOffset";
MaterialProperty[] heightCenterOffset = new MaterialProperty[kMaxLayerCount - 1];
// Height blend V2
const string kInheritBaseNormal = "_InheritBaseNormal";
MaterialProperty[] inheritBaseNormal = new MaterialProperty[kMaxLayerCount - 1];
const string kInheritBaseHeight = "_InheritBaseHeight";
MaterialProperty[] inheritBaseHeight = new MaterialProperty[kMaxLayerCount - 1];
const string kInheritBaseColor = "_InheritBaseColor";
MaterialProperty[] inheritBaseColor = new MaterialProperty[kMaxLayerCount - 1];
const string kInheritBaseColorThreshold = "_InheritBaseColorThreshold";
MaterialProperty[] inheritBaseColorThreshold = new MaterialProperty[kMaxLayerCount - 1];
const string kOpacityAsDensity = "_OpacityAsDensity";
MaterialProperty[] opacityAsDensity = new MaterialProperty[kMaxLayerCount - 1];
const string kMinimumOpacity = "_MinimumOpacity";
MaterialProperty[] minimumOpacity = new MaterialProperty[kMaxLayerCount - 1];
MaterialProperty layerEmissiveColor = null;
MaterialProperty layerEmissiveColorMap = null;
MaterialProperty layerEmissiveIntensity = null;

FindMaterialOptionProperties(props);
layerMaskMap = FindProperty(kLayerMaskMap, props);
layerMaskVertexColor = FindProperty(kLayerMaskVertexColor, props);
vertexColorMode = FindProperty(kVertexColorMode, props);
useMainLayerInfluence = FindProperty(kkUseMainLayerInfluence, props);
useHeightBasedBlendV2 = FindProperty(kUseHeightBasedBlendV2, props);
for (int i = 0; i < kMaxLayerCount; ++i)
{

layerUVMappingPlanar[i] = FindProperty(string.Format("{0}{1}", kUVMappingPlanar, i), props);
layerUVDetail[i] = FindProperty(string.Format("{0}{1}", kUVDetail, i), props);
layerUVDetailsMappingMask[i] = FindProperty(string.Format("{0}{1}", kUVDetailsMappingMask, i), props);
layerTiling[i] = FindProperty(string.Format("{0}{1}", kLayerTiling, i), props);
if(i != 0)
{

heightCenterOffset[i - 1] = FindProperty(string.Format("{0}{1}", kHeightCenterOffset, i), props);
blendUsingHeight[i - 1] = FindProperty(string.Format("{0}{1}", kBlendUsingHeight, i), props);
inheritBaseNormal[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseNormal, i), props);
inheritBaseHeight[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseHeight, i), props);
inheritBaseColor[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseColor, i), props);
inheritBaseColorThreshold[i - 1] = FindProperty(string.Format("{0}{1}", kInheritBaseColorThreshold, i), props);
minimumOpacity[i - 1] = FindProperty(string.Format("{0}{1}", kMinimumOpacity, i), props);
opacityAsDensity[i - 1] = FindProperty(string.Format("{0}{1}", kOpacityAsDensity, i), props);
}
}

return result;
}
bool CheckInputFloatOptionConsistency(string optionName, ref string outValueNames)
{
bool result = true;
outValueNames = "";
for (int i = 0; i < numLayer; ++i)
{
Material layer = m_MaterialLayers[i];
if (layer != null)
{
float currentValue = layer.GetFloat(optionName);
for (int j = i + 1; j < numLayer; ++j)
{
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)
{
if (currentValue != otherLayer.GetFloat(optionName))
{
result = false;
}
}
}
}
else
{
outValueNames += "X ";
}
}
return result;
}
bool CheckInputMapConsistency(string mapName, ref string outValueNames)
{
bool result = true;

// Input options consistency
string[] smoothnessSourceShortNames = { "Mask", "Albedo" };
string[] normalMapShortNames = { "Tan", "Obj" };
string[] heightMapShortNames = { "Parallax", "Disp" };
string[] detailModeShortNames = { "DNormal", "DAOHeight" };
string warningInputOptions = "";

{
warningInputOptions += "Normal Map Space: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kHeightMapMode, heightMapShortNames, ref optionValueNames))
if (!CheckInputFloatOptionConsistency(kEnablePerPixelDisplacement, ref optionValueNames))
warningInputOptions += "Height Map Mode: " + optionValueNames + "\n";
warningInputOptions += "Per pixel displacement: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kDetailMapMode, detailModeShortNames, ref optionValueNames))
{

{
material.SetFloat(kSmoothnessTextureChannel, firstLayer.GetFloat(kSmoothnessTextureChannel));
material.SetFloat(kNormalMapSpace, firstLayer.GetFloat(kNormalMapSpace));
material.SetFloat(kHeightMapMode, firstLayer.GetFloat(kHeightMapMode));
material.SetFloat(kEnablePerPixelDisplacement, firstLayer.GetFloat(kEnablePerPixelDisplacement));
// Force emissive to be emissive color
material.SetFloat(kEmissiveColorMode, (float)EmissiveColorMode.UseEmissiveColor);
}

Material material = m_MaterialEditor.target as Material;
EditorGUILayout.LabelField(styles.layerLabels[layerIndex]);
bool baseLayerModeEnable = useMainLayerInfluence.floatValue > 0.0f;
EditorGUILayout.LabelField(styles.layerLabels[layerIndex], styles.layerLabelColors[layerIndex]);
EditorGUI.indentLevel++;

SynchronizeLayerProperties(material, m_MaterialLayers, layerIndex);
result = true;
}
if (((LayerUVBaseMapping)layerUVBase[layerIndex].floatValue == LayerUVBaseMapping.Planar) ||
((LayerUVBaseMapping)layerUVBase[layerIndex].floatValue == LayerUVBaseMapping.Triplanar))
{

}
else
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(layerTiling[layerIndex], styles.layerTilingText);
EditorGUI.indentLevel--;
EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(layerUVDetail[layerIndex], styles.UVDetailText);
if (EditorGUI.EndChangeCheck())

if(layerIndex > 0)
{
if (!useHeightBasedBlend.hasMixedValue && useHeightBasedBlend.floatValue != 0.0f)
bool heightBasedBlendEnable = useHeightBasedBlend.floatValue != 0.0f;
bool heightBasedBlendV2Enable = useHeightBasedBlendV2.floatValue != 0.0f;
int paramIndex = layerIndex - 1;
EditorGUILayout.LabelField(styles.DensityOpacityInfluenceText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(opacityAsDensity[paramIndex], styles.opacityAsDensityText);
m_MaterialEditor.ShaderProperty(minimumOpacity[paramIndex], styles.minimumOpacityText);
EditorGUI.indentLevel--;
if (baseLayerModeEnable)
int heightParamIndex = layerIndex - 1;
EditorGUILayout.LabelField(styles.MainLayerInfluenceText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(heightOffset[heightParamIndex], styles.heightOffsetText);
m_MaterialEditor.ShaderProperty(heightFactor[heightParamIndex], styles.heightFactorText);
m_MaterialEditor.ShaderProperty(blendSize[heightParamIndex], styles.blendSizeText);
m_MaterialEditor.ShaderProperty(inheritBaseColor[paramIndex], styles.inheritBaseColorText);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(inheritBaseColorThreshold[paramIndex], styles.inheritBaseColorThresholdText);
EditorGUI.indentLevel--;
m_MaterialEditor.ShaderProperty(inheritBaseNormal[paramIndex], styles.inheritBaseNormalText);
// Main height influence is only available if the shader use the heightmap for displacement (per vertex or per level)
// We always display it as it can be tricky to know when per pixel displacement is enabled or not
m_MaterialEditor.ShaderProperty(inheritBaseHeight[paramIndex], styles.inheritBaseHeightText);
EditorGUI.indentLevel--;
}
if (!useHeightBasedBlend.hasMixedValue && heightBasedBlendEnable)
{
EditorGUILayout.LabelField(styles.heightControlText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(heightFactor[paramIndex], styles.heightFactorText);
if (!heightBasedBlendV2Enable)
{
m_MaterialEditor.ShaderProperty(heightOffset[paramIndex], styles.heightOffsetText);
m_MaterialEditor.ShaderProperty(blendSize[paramIndex], styles.blendSizeText);
}
else
{
m_MaterialEditor.ShaderProperty(heightCenterOffset[paramIndex], styles.heightCenterOffsetText);
m_MaterialEditor.ShaderProperty(blendUsingHeight[paramIndex], styles.blendUsingHeight);
}
EditorGUI.indentLevel--;
if(layerIndex == 0)
EditorGUILayout.Space();
return result;
}

m_MaterialEditor.TexturePropertySingleLine(styles.layerMapMaskText, layerMaskMap);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = useMainLayerInfluence.hasMixedValue;
bool mainLayerModeInfluenceEnable = EditorGUILayout.Toggle(styles.useMainLayerInfluenceModeText, useMainLayerInfluence.floatValue > 0.0f);
if (EditorGUI.EndChangeCheck())
{
useMainLayerInfluence.floatValue = mainLayerModeInfluenceEnable ? 1.0f : 0.0f;
}
m_MaterialEditor.ShaderProperty(vertexColorMode, styles.vertexColorModeText);
EditorGUI.BeginChangeCheck();
EditorGUI.showMixedValue = useHeightBasedBlend.hasMixedValue;
bool enabled = EditorGUILayout.Toggle(styles.useHeightBasedBlendText, useHeightBasedBlend.floatValue > 0.0f);
if (EditorGUI.EndChangeCheck())

if (enabled)
{
m_MaterialEditor.ShaderProperty(vertexColorHeightFactor, styles.vertexColorHeightMultiplierText);
}
else
{
m_MaterialEditor.ShaderProperty(layerMaskVertexColor, styles.layerMapVertexColorText);
EditorGUI.BeginChangeCheck();
EditorGUI.indentLevel++;
bool enabledV2 = EditorGUILayout.Toggle(styles.useHeightBasedBlendV2Text, useHeightBasedBlendV2.floatValue > 0.0f);
if (EditorGUI.EndChangeCheck())
{
useHeightBasedBlendV2.floatValue = enabledV2 ? 1.0f : 0.0f;
}
if(!enabledV2)
m_MaterialEditor.ShaderProperty(vertexColorHeightFactor, styles.vertexColorHeightMultiplierText);
EditorGUI.indentLevel--;
EditorGUILayout.Space();

SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap + i));
SetKeyword(material, "_DETAIL_MAP_WITH_NORMAL", ((DetailMapMode)material.GetFloat(kDetailMapMode)) == DetailMapMode.DetailWithNormal);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", ((HeightmapMode)material.GetFloat(kHeightMapMode)) == HeightmapMode.Displacement);
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
bool useHeightBasedBlend = material.GetFloat(kUseHeightBasedBlend) != 0.0f;
if(useHeightBasedBlend)
SetKeyword(material, "_MAIN_LAYER_INFLUENCE_MODE", material.GetFloat(kkUseMainLayerInfluence) != 0.0f);
VertexColorMode VCMode = (VertexColorMode)vertexColorMode.floatValue;
if (VCMode == VertexColorMode.Multiply)
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR", false);
SetKeyword(material, "_HEIGHT_BASED_BLEND", true);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", true);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
}
else if (VCMode == VertexColorMode.Add)
{
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", true);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR", material.GetFloat(kLayerMaskVertexColor) != 0.0f);
SetKeyword(material, "_HEIGHT_BASED_BLEND", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_MUL", false);
SetKeyword(material, "_LAYER_MASK_VERTEX_COLOR_ADD", false);
bool useHeightBasedBlend = material.GetFloat(kUseHeightBasedBlend) != 0.0f;
bool useHeightBasedBlendV2 = material.GetFloat(kUseHeightBasedBlendV2) != 0.0f;
SetKeyword(material, "_HEIGHT_BASED_BLEND", useHeightBasedBlend);
SetKeyword(material, "_HEIGHT_BASED_BLEND_V2", useHeightBasedBlend && useHeightBasedBlendV2);
bool UV2orUV3needed = false;
bool needUV3 = false;
bool needUV2 = false;
if (
((UVDetailMapping)material.GetFloat(uvDetail) == UVDetailMapping.UV2) ||
((LayerUVBaseMapping)material.GetFloat(uvBase) == LayerUVBaseMapping.UV2) ||
((UVDetailMapping)material.GetFloat(uvDetail) == UVDetailMapping.UV3) ||
((LayerUVBaseMapping)material.GetFloat(uvBase) == LayerUVBaseMapping.UV3)
)
if ( ((UVDetailMapping)material.GetFloat(uvDetail) == UVDetailMapping.UV2) ||
((LayerUVBaseMapping)material.GetFloat(uvBase) == LayerUVBaseMapping.UV2) )
UV2orUV3needed = true;
break;
needUV2 = true;
}
if ( ((UVDetailMapping)material.GetFloat(uvDetail) == UVDetailMapping.UV3) ||
((LayerUVBaseMapping)material.GetFloat(uvBase) == LayerUVBaseMapping.UV3) )
{
needUV3 = true;
break; // If we find it UV3 let's early out
SetKeyword(material, "_REQUIRE_UV2_OR_UV3", UV2orUV3needed);
if (needUV3)
{
material.DisableKeyword("_REQUIRE_UV2");
material.EnableKeyword("_REQUIRE_UV3");
}
else if (needUV2)
{
material.EnableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
else
{
material.DisableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
}
void SetupLayersKeywords(Material material)

180
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/LayeredLit/LayeredLit.shader


_HeightMap2("HeightMap2", 2D) = "black" {}
_HeightMap3("HeightMap3", 2D) = "black" {}
_HeightScale0("Height Scale0", Float) = 1
_HeightScale1("Height Scale1", Float) = 1
_HeightScale2("Height Scale2", Float) = 1
_HeightScale3("Height Scale3", Float) = 1
_HeightAmplitude0("Height Scale0", Float) = 1
_HeightAmplitude1("Height Scale1", Float) = 1
_HeightAmplitude2("Height Scale2", Float) = 1
_HeightAmplitude3("Height Scale3", Float) = 1
_HeightBias0("Height Bias0", Float) = 0
_HeightBias1("Height Bias1", Float) = 0
_HeightBias2("Height Bias2", Float) = 0
_HeightBias3("Height Bias3", Float) = 0
_HeightCenter0("Height Bias0", Float) = 0
_HeightCenter1("Height Bias1", Float) = 0
_HeightCenter2("Height Bias2", Float) = 0
_HeightCenter3("Height Bias3", Float) = 0
_DetailMap0("DetailMap0", 2D) = "black" {}
_DetailMap1("DetailMap1", 2D) = "black" {}

_DetailAOScale2("_DetailAOScale2", Range(-2.0, 2.0)) = 1
_DetailAOScale3("_DetailAOScale3", Range(-2.0, 2.0)) = 1
// Specific to planar mapping
_TexWorldScale0("TexWorldScale0", Float) = 1.0
_TexWorldScale1("TexWorldScale1", Float) = 1.0
_TexWorldScale2("TexWorldScale2", Float) = 1.0
_TexWorldScale3("TexWorldScale3", Float) = 1.0
[ToggleOff] _LayerMaskVertexColor("Use Vertex Color Mask", Float) = 0.0
// Layer blending options V2
[ToggleOff] _UseHeightBasedBlendV2("Use Height Blend V2", Float) = 0.0
[ToggleOff] _UseMainLayerInfluence("UseMainLayerInfluence", Float) = 0.0
_HeightFactor1("_HeightFactor1", Range(0, 5)) = 1
_HeightFactor2("_HeightFactor2", Range(0, 5)) = 1
_HeightFactor3("_HeightFactor3", Range(0, 5)) = 1
_HeightFactor1("_HeightFactor1", Float) = 1
_HeightFactor2("_HeightFactor2", Float) = 1
_HeightFactor3("_HeightFactor3", Float) = 1
_BlendSize1("_BlendSize1", Range(0, 0.30)) = 0.0
_BlendSize2("_BlendSize2", Range(0, 0.30)) = 0.0
_BlendSize3("_BlendSize3", Range(0, 0.30)) = 0.0
_BlendSize1("_BlendSize1", Range(0, 0.05)) = 0.0
_BlendSize2("_BlendSize2", Range(0, 0.05)) = 0.0
_BlendSize3("_BlendSize3", Range(0, 0.05)) = 0.0
_VertexColorHeightFactor("_VertexColorHeightFactor", Float) = 0.3
_VertexColorHeightFactor("_VertexColorHeightFactor", Float) = 1.0
_HeightCenterOffset1("_HeightCenterOffset1", Float) = 0.0
_HeightCenterOffset2("_HeightCenterOffset2", Float) = 0.0
_HeightCenterOffset3("_HeightCenterOffset3", Float) = 0.0
_BlendUsingHeight1("_BlendUsingHeight1", Float) = 0.0
_BlendUsingHeight2("_BlendUsingHeight2", Float) = 0.0
_BlendUsingHeight3("_BlendUsingHeight3", Float) = 0.0
_InheritBaseNormal1("_InheritBaseNormal1", Range(0, 1.0)) = 0.0
_InheritBaseNormal2("_InheritBaseNormal2", Range(0, 1.0)) = 0.0
_InheritBaseNormal3("_InheritBaseNormal3", Range(0, 1.0)) = 0.0
_InheritBaseHeight1("_InheritBaseHeight1", Range(0, 1.0)) = 0.0
_InheritBaseHeight2("_InheritBaseHeight2", Range(0, 1.0)) = 0.0
_InheritBaseHeight3("_InheritBaseHeight3", Range(0, 1.0)) = 0.0
_InheritBaseColor1("_InheritBaseColor1", Range(0, 1.0)) = 0.0
_InheritBaseColor2("_InheritBaseColor2", Range(0, 1.0)) = 0.0
_InheritBaseColor3("_InheritBaseColor3", Range(0, 1.0)) = 0.0
_InheritBaseColorThreshold1("_InheritBaseColorThreshold1", Range(0, 1.0)) = 1.0
_InheritBaseColorThreshold2("_InheritBaseColorThreshold2", Range(0, 1.0)) = 1.0
_InheritBaseColorThreshold3("_InheritBaseColorThreshold3", Range(0, 1.0)) = 1.0
_MinimumOpacity1("_MinimumOpacity1", Range(0, 1.0)) = 1.0
_MinimumOpacity2("_MinimumOpacity2", Range(0, 1.0)) = 1.0
_MinimumOpacity3("_MinimumOpacity3", Range(0, 1.0)) = 1.0
_OpacityAsDensity1("_OpacityAsDensity1", Range(0, 1.0)) = 0.0
_OpacityAsDensity2("_OpacityAsDensity2", Range(0, 1.0)) = 0.0
_OpacityAsDensity3("_OpacityAsDensity3", Range(0, 1.0)) = 0.0
_LayerTiling0("LayerTiling0", Float) = 1
_LayerTiling1("LayerTiling1", Float) = 1
_LayerTiling2("LayerTiling2", Float) = 1
_LayerTiling3("LayerTiling3", Float) = 1
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}

[Enum(Mask Alpha, 0, BaseColor Alpha, 1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 1
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
// WARNING
// All the following properties that concern the UV mapping are the same as in the Lit shader.
// This means that they will get overridden when synchronizing the various layers.
// To avoid this, make sure that all properties here are in the exclusion list in LayeredLitUI.SynchronizeLayerProperties
[Enum(None, 0, Multiply, 1, Add, 2)] _VertexColorMode("Vertex color mode", Float) = 0
// WARNING
// All the following properties that concern the UV mapping are the same as in the Lit shader.
// This means that they will get overridden when synchronizing the various layers.
// To avoid this, make sure that all properties here are in the exclusion list in LayeredLitUI.SynchronizeLayerProperties
_TexWorldScale0("Tiling", Float) = 1.0
_TexWorldScale1("Tiling", Float) = 1.0
_TexWorldScale2("Tiling", Float) = 1.0

HLSLINCLUDE
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma shader_feature _ _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _ _DOUBLESIDED _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_0

#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _REQUIRE_UV2_OR_UV3
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR
#pragma shader_feature _NORMALMAP

#pragma shader_feature _HEIGHTMAP
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _LAYER_MASK_VERTEX_COLOR
#pragma shader_feature _ _LAYER_MASK_VERTEX_COLOR_MUL _LAYER_MASK_VERTEX_COLOR_ADD
#pragma shader_feature _MAIN_LAYER_INFLUENCE_MODE
#pragma shader_feature _HEIGHT_BASED_BLEND_V2
#pragma shader_feature _ _LAYEREDLIT_3_LAYERS _LAYEREDLIT_4_LAYERS
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON

#include "common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Attributes.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
//-------------------------------------------------------------------------------------

#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassGBuffer.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassDebugViewMaterial.hlsl"
ENDHLSL

// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitMetaPass.hlsl"
#include "../Lit/LitMetaPass.hlsl"
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitVelocityPass.hlsl"
#include "../Lit/LitVelocityPass.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "../Lit/LitDepthPass.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDepthPass.hlsl"
#include "../Lit/LitDepthPass.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "../Lit/ShaderPass/LitDistortionPass.hlsl"
#include "../Lit/LitDistortionPass.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "../../Lighting/Forward.hlsl"
// #include "../../Lighting/Forward.hlsl"
//#pragma multi_compile SHADOWFILTERING_FIXED_SIZE_PCF
#include "../../Lighting/Lighting.hlsl"
#include "../../Lighting/Lighting.hlsl"
#include "../Lit/ShaderPass/LitSharePass.hlsl"
#include "../Lit/LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassForward.hlsl"
ENDHLSL

CustomEditor "Experimental.ScriptableRenderLoop.LayeredLitGUI"
CustomEditor "Experimental.Rendering.HDPipeline.LayeredLitGUI"
}

169
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/BaseLitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
public static string OptionText = "Options";
public static string SurfaceTypeText = "Surface Type";
public static string BlendModeText = "Blend Mode";
public static string optionText = "Options";
public static string surfaceTypeText = "Surface Type";
public static string blendModeText = "Blend Mode";
public static string textureControlText = "Input textures control";
public static string lightingText = "Inputs Lighting";
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");

public static GUIContent texWorldScaleText = new GUIContent("Tiling", "Tiling factor applied to Planar/Trilinear mapping");
public static GUIContent UVBaseDetailMappingText = new GUIContent("UV set for Base and Detail", "");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
public static GUIContent heightMapModeText = new GUIContent("Height Map Mode", "");
public static GUIContent enablePerPixelDisplacementText = new GUIContent("Enable Per Pixel Displacement", "");
public static GUIContent ppdMinSamplesText = new GUIContent("Minimum samples", "Minimun samples to use with per pixel displacement mapping");
public static GUIContent ppdMaxSamplesText = new GUIContent("Maximum samples", "Maximum samples to use with per pxiel displacement mapping");
public static GUIContent detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static GUIContent UVDetailMappingText = new GUIContent("UV set for Detail", "");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");

public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (DXT5) - Need to implement BC5");
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 static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map (G)", "Anisotropy");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map (B)", "Anisotropy");
public static GUIContent detailMaskText = new GUIContent("Detail Mask (B)", "Mask for detailMap");
public static GUIContent detailMaskText = new GUIContent("Detail Mask (G)", "Mask for detailMap");
public static GUIContent detailAlbedoScaleText = new GUIContent("Detail AlbedoScale", "Detail Albedo Scale factor");
public static GUIContent detailNormalScaleText = new GUIContent("Detail NormalScale", "Normal Scale factor");
public static GUIContent detailSmoothnessScaleText = new GUIContent("Detail SmoothnessScale", "Smoothness Scale factor");

public static GUIContent emissiveWarning = new GUIContent("Emissive value is animated but the material has not been configured to support emissive. Please make sure the material itself has some amount of emissive.");
public static GUIContent emissiveColorWarning = new GUIContent("Ensure emissive color is non-black for emission to have effect.");
public static string tessellationModeText = "Tessellation Mode";
public static readonly string[] tessellationModeNames = Enum.GetNames(typeof(TessellationMode));
public static GUIContent tessellationText = new GUIContent("Tessellation options", "Tessellation options");
public static GUIContent tessellationFactorText = new GUIContent("Tessellation factor", "This value is the tessellation factor use for tessellation, higher mean more tessellated");
public static GUIContent tessellationFactorMinDistanceText = new GUIContent("Start fade distance", "Distance (in unity unit) at which the tessellation start to fade out. Must be inferior at Max distance");
public static GUIContent tessellationFactorMaxDistanceText = new GUIContent("End fade distance", "Maximum distance (in unity unit) to the camera where triangle are tessellated");
public static GUIContent tessellationFactorTriangleSizeText = new GUIContent("Triangle size", "Desired screen space sized of triangle (in pixel). Smaller value mean smaller triangle.");
public static GUIContent tessellationShapeFactorText = new GUIContent("Shape factor", "Strength of Phong tessellation shape (lerp factor)");
public static GUIContent tessellationBackFaceCullEpsilonText = new GUIContent("Triangle culling Epsilon", "If -1.0 back face culling is enabled for tessellation, higher number mean more aggressive culling and better performance");
public static GUIContent tessellationObjectScaleText = new GUIContent("Enable object scale", "Tesselation displacement will take into account the object scale - Only work with uniform positive scale");
}
public enum SurfaceType

}
public enum BlendMode
{
Lerp,

Premultiply
}
public enum DoubleSidedMode
{
None,

}
public enum TessellationMode
{
Phong,
Displacement,
DisplacementPhong,
}
void SurfaceTypePopup()
{
EditorGUI.showMixedValue = surfaceType.hasMixedValue;

mode = (SurfaceType)EditorGUILayout.Popup(Styles.SurfaceTypeText, (int)mode, Styles.surfaceTypeNames);
mode = (SurfaceType)EditorGUILayout.Popup(Styles.surfaceTypeText, (int)mode, Styles.surfaceTypeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Surface Type");

EditorGUI.showMixedValue = false;
}
void TessellationModePopup()
{
EditorGUI.showMixedValue = tessellationMode.hasMixedValue;
var mode = (TessellationMode)tessellationMode.floatValue;
EditorGUI.BeginChangeCheck();
mode = (TessellationMode)EditorGUILayout.Popup(Styles.tessellationModeText, (int)mode, Styles.tessellationModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Tessellation Mode");
tessellationMode.floatValue = (float)mode;
}
EditorGUI.showMixedValue = false;
}
GUILayout.Label(Styles.OptionText, EditorStyles.boldLabel);
GUILayout.Label(Styles.optionText, EditorStyles.boldLabel);
SurfaceTypePopup();
if ((SurfaceType)surfaceType.floatValue == SurfaceType.Transparent)
{

m_MaterialEditor.ShaderProperty(depthOffsetEnable, Styles.depthOffsetEnableText.text);
EditorGUI.indentLevel--;
if (tessellationMode != null)
{
GUILayout.Label(Styles.tessellationText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
TessellationModePopup();
m_MaterialEditor.ShaderProperty(tessellationFactor, Styles.tessellationFactorText);
m_MaterialEditor.ShaderProperty(tessellationFactorMinDistance, Styles.tessellationFactorMinDistanceText);
m_MaterialEditor.ShaderProperty(tessellationFactorMaxDistance, Styles.tessellationFactorMaxDistanceText);
// clamp min distance to be below max distance
tessellationFactorMinDistance.floatValue = Math.Min(tessellationFactorMaxDistance.floatValue, tessellationFactorMinDistance.floatValue);
m_MaterialEditor.ShaderProperty(tessellationFactorTriangleSize, Styles.tessellationFactorTriangleSizeText);
if ((TessellationMode)tessellationMode.floatValue == TessellationMode.Phong ||
(TessellationMode)tessellationMode.floatValue == TessellationMode.DisplacementPhong)
{
m_MaterialEditor.ShaderProperty(tessellationShapeFactor, Styles.tessellationShapeFactorText);
}
if ((DoubleSidedMode)doubleSidedMode.floatValue == DoubleSidedMode.None)
{
m_MaterialEditor.ShaderProperty(tessellationBackFaceCullEpsilon, Styles.tessellationBackFaceCullEpsilonText);
}
m_MaterialEditor.ShaderProperty(tessellationObjectScale, Styles.tessellationObjectScaleText);
EditorGUI.indentLevel--;
}
}
private void BlendModePopup()

EditorGUI.BeginChangeCheck();
mode = (BlendMode)EditorGUILayout.Popup(Styles.BlendModeText, (int)mode, Styles.blendModeNames);
mode = (BlendMode)EditorGUILayout.Popup(Styles.blendModeText, (int)mode, Styles.blendModeNames);
if (EditorGUI.EndChangeCheck())
{
m_MaterialEditor.RegisterPropertyChangeUndo("Blend Mode");

distortionOnly = FindProperty(kDistortionOnly, props);
distortionDepthTest = FindProperty(kDistortionDepthTest, props);
depthOffsetEnable = FindProperty(kDepthOffsetEnable, props);
// tessellation specific, silent if not found
tessellationMode = FindProperty(kTessellationMode, props, false);
tessellationFactor = FindProperty(kTessellationFactor, props, false);
tessellationFactorMinDistance = FindProperty(kTessellationFactorMinDistance, props, false);
tessellationFactorMaxDistance = FindProperty(kTessellationFactorMaxDistance, props, false);
tessellationFactorTriangleSize = FindProperty(kTessellationFactorTriangleSize, props, false);
tessellationShapeFactor = FindProperty(kTessellationShapeFactor, props, false);
tessellationBackFaceCullEpsilon = FindProperty(kTessellationBackFaceCullEpsilon, props, false);
tessellationObjectScale = FindProperty(kTessellationObjectScale, props, false);
}
protected void SetupCommonOptionsKeywords(Material material)

BlendMode blendMode = (BlendMode)material.GetFloat(kBlendMode);
DoubleSidedMode doubleSidedMode = (DoubleSidedMode)material.GetFloat(kDoubleSidedMode);
if (surfaceType == SurfaceType.Opaque)
{
material.SetOverrideTag("RenderType", alphaTestEnable ? "TransparentCutout" : "");

if (doubleSidedMode == DoubleSidedMode.DoubleSidedLightingFlip)
{
material.DisableKeyword("_DOUBLESIDED");
material.DisableKeyword("_DOUBLESIDED");
else if (doubleSidedMode == DoubleSidedMode.DoubleSided)
{
material.EnableKeyword("_DOUBLESIDED");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}
material.DisableKeyword("_DOUBLESIDED");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_FLIP");
material.DisableKeyword("_DOUBLESIDED_LIGHTING_MIRROR");
}

SetKeyword(material, "_DEPTHOFFSET_ON", depthOffsetEnable);
SetupEmissionGIFlags(material);
if (tessellationMode != null)
{
TessellationMode tessMode = (TessellationMode)material.GetFloat(kTessellationMode);
if (tessMode == TessellationMode.Phong)
{
material.DisableKeyword("_TESSELLATION_DISPLACEMENT");
material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG");
}
else if (tessMode == TessellationMode.Displacement)
{
material.EnableKeyword("_TESSELLATION_DISPLACEMENT");
material.DisableKeyword("_TESSELLATION_DISPLACEMENT_PHONG");
}
else
{
material.DisableKeyword("_TESSELLATION_DISPLACEMENT");
material.EnableKeyword("_TESSELLATION_DISPLACEMENT_PHONG");
}
bool tessellationObjectScaleEnable = material.GetFloat(kTessellationObjectScale) == 1.0;
SetKeyword(material, "_TESSELLATION_OBJECT_SCALE", tessellationObjectScaleEnable);
}
}
protected void SetKeyword(Material m, string keyword, bool state)

protected MaterialEditor m_MaterialEditor;
MaterialProperty surfaceType = null;
const string kSurfaceType = "_SurfaceType";
const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
MaterialProperty alphaCutoff = null;
MaterialProperty doubleSidedMode = null;
MaterialProperty distortionEnable = null;
MaterialProperty distortionOnly = null;
MaterialProperty distortionDepthTest = null;
MaterialProperty depthOffsetEnable = null;
const string kSurfaceType = "_SurfaceType";
MaterialProperty alphaCutoff = null;
const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
MaterialProperty doubleSidedMode = null;
MaterialProperty distortionEnable = null;
MaterialProperty distortionOnly = null;
MaterialProperty distortionDepthTest = null;
MaterialProperty depthOffsetEnable = null;
// tessellation params
protected MaterialProperty tessellationMode = null;
const string kTessellationMode = "_TessellationMode";
MaterialProperty tessellationFactor = null;
const string kTessellationFactor = "_TessellationFactor";
MaterialProperty tessellationFactorMinDistance = null;
const string kTessellationFactorMinDistance = "_TessellationFactorMinDistance";
MaterialProperty tessellationFactorMaxDistance = null;
const string kTessellationFactorMaxDistance = "_TessellationFactorMaxDistance";
MaterialProperty tessellationFactorTriangleSize = null;
const string kTessellationFactorTriangleSize = "_TessellationFactorTriangleSize";
MaterialProperty tessellationShapeFactor = null;
const string kTessellationShapeFactor = "_TessellationShapeFactor";
MaterialProperty tessellationBackFaceCullEpsilon = null;
const string kTessellationBackFaceCullEpsilon = "_TessellationBackFaceCullEpsilon";
MaterialProperty tessellationObjectScale = null;
const string kTessellationObjectScale = "_TessellationObjectScale";
protected static string[] reservedProperties = new string[] { kSurfaceType, kBlendMode, kAlphaCutoff, kAlphaCutoffEnabled, kDoubleSidedMode };
protected abstract void FindMaterialProperties(MaterialProperty[] props);

76
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/LitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
class LitGUI : BaseLitGUI
{

protected const string kUVMappingPlanar = "_UVMappingPlanar";
protected MaterialProperty normalMapSpace = null;
protected const string kNormalMapSpace = "_NormalMapSpace";
protected MaterialProperty heightMapMode = null;
protected const string kHeightMapMode = "_HeightMapMode";
protected MaterialProperty enablePerPixelDisplacement = null;
protected const string kEnablePerPixelDisplacement = "_EnablePerPixelDisplacement";
protected MaterialProperty ppdMinSamples = null;
protected const string kPpdMinSamples = "_PPDMinSamples";
protected MaterialProperty ppdMaxSamples = null;
protected const string kPpdMaxSamples = "_PPDMaxSamples";
protected MaterialProperty detailMapMode = null;
protected const string kDetailMapMode = "_DetailMapMode";
protected MaterialProperty UVDetail = null;

protected const string kNormalScale = "_NormalScale";
protected MaterialProperty heightMap = null;
protected const string kHeightMap = "_HeightMap";
protected MaterialProperty heightScale = null;
protected const string kHeightScale = "_HeightScale";
protected MaterialProperty heightBias = null;
protected const string kHeightBias= "_HeightBias";
protected MaterialProperty heightAmplitude = null;
protected const string kHeightAmplitude = "_HeightAmplitude";
protected MaterialProperty heightCenter = null;
protected const string kHeightCenter = "_HeightCenter";
protected MaterialProperty tangentMap = null;
protected const string kTangentMap = "_TangentMap";
protected MaterialProperty anisotropy = null;

protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected MaterialProperty emissiveIntensity = null;
protected const string kEmissiveIntensity = "_EmissiveIntensity";
// These are options that are shared with the LayeredLit shader. Don't put anything that can't be shared here:
// For instance, properties like BaseColor and such don't exist in the LayeredLit so don't put them here.

normalMapSpace = FindProperty(kNormalMapSpace, props);
heightMapMode = FindProperty(kHeightMapMode, props);
enablePerPixelDisplacement = FindProperty(kEnablePerPixelDisplacement, props);
ppdMinSamples = FindProperty(kPpdMinSamples, props);
ppdMaxSamples = FindProperty(kPpdMaxSamples, props);
detailMapMode = FindProperty(kDetailMapMode, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
}

normalMap = FindProperty(kNormalMap, props);
normalScale = FindProperty(kNormalScale, props);
heightMap = FindProperty(kHeightMap, props);
heightScale = FindProperty(kHeightScale, props);
heightBias = FindProperty(kHeightBias, props);
heightAmplitude = FindProperty(kHeightAmplitude, props);
heightCenter = FindProperty(kHeightCenter, props);
tangentMap = FindProperty(kTangentMap, props);
anisotropy = FindProperty(kAnisotropy, props);
anisotropyMap = FindProperty(kAnisotropyMap, props);

UVDetailsMappingMask.colorValue = new Color(X, Y, Z, W);
//m_MaterialEditor.ShaderProperty(detailMapMode, Styles.detailMapModeText.text);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText.text);
m_MaterialEditor.ShaderProperty(heightMapMode, Styles.heightMapModeText.text);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText.text);
m_MaterialEditor.ShaderProperty(enablePerPixelDisplacement, Styles.enablePerPixelDisplacementText.text);
m_MaterialEditor.ShaderProperty(ppdMinSamples, Styles.ppdMinSamplesText.text);
m_MaterialEditor.ShaderProperty(ppdMaxSamples, Styles.ppdMaxSamplesText.text);
ppdMinSamples.floatValue = Mathf.Min(ppdMinSamples.floatValue, ppdMaxSamples.floatValue);
EditorGUI.indentLevel--;
}

m_MaterialEditor.TexturePropertySingleLine(Styles.normalMapText, normalMap, normalScale);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap, heightScale, heightBias);
m_MaterialEditor.TexturePropertySingleLine(Styles.heightMapText, heightMap);
if(!heightMap.hasMixedValue && heightMap.textureValue != null)
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(heightAmplitude, Styles.heightMapAmplitudeText);
heightAmplitude.floatValue = Math.Max(0.0f, heightAmplitude.floatValue); // Must be positive
m_MaterialEditor.ShaderProperty(heightCenter, Styles.heightMapCenterText);
EditorGUI.showMixedValue = false;
EditorGUI.indentLevel--;
}
m_MaterialEditor.TexturePropertySingleLine(Styles.tangentMapText, tangentMap);

EditorGUILayout.Space();
GUILayout.Label(Styles.textureControlText, EditorStyles.label);
m_MaterialEditor.TextureScaleOffsetProperty(baseColorMap);
EditorGUILayout.Space();

m_MaterialEditor.LightmapEmissionProperty(MaterialEditor.kMiniTextureFieldLabelIndentLevel + 1);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)

SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", ((SmoothnessMapChannel)material.GetFloat(kSmoothnessTextureChannel)) == SmoothnessMapChannel.AlbedoAlpha);
SetKeyword(material, "_MAPPING_TRIPLANAR", ((UVBaseMapping)material.GetFloat(kUVBase)) == UVBaseMapping.Triplanar);
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE", ((NormalMapSpace)material.GetFloat(kNormalMapSpace)) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", ((HeightmapMode)material.GetFloat(kHeightMapMode)) == HeightmapMode.Displacement);
bool perPixelDisplacement = material.GetFloat(kEnablePerPixelDisplacement) == 1.0;
SetKeyword(material, "_PER_PIXEL_DISPLACEMENT", perPixelDisplacement);
SetKeyword(material, "_DETAIL_MAP_WITH_NORMAL", ((DetailMapMode)material.GetFloat(kDetailMapMode)) == DetailMapMode.DetailWithNormal);
SetKeyword(material, "_EMISSIVE_COLOR", ((EmissiveColorMode)material.GetFloat(kEmissiveColorMode)) == EmissiveColorMode.UseEmissiveColor);

SetKeyword(material, "_ANISOTROPYMAP", material.GetTexture(kAnisotropyMap));
SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap));
SetKeyword(material, "_REQUIRE_UV2_OR_UV3", (
((UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV2 || (UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV3)
&& (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0)
);
}
bool needUV2 = (UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV2 && (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0;
bool needUV3 = (UVDetailMapping)material.GetFloat(kUVDetail) == UVDetailMapping.UV3 && (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0;
if (needUV3)
{
material.DisableKeyword("_REQUIRE_UV2");
material.EnableKeyword("_REQUIRE_UV3");
}
else if (needUV2)
{
material.EnableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
else
{
material.DisableKeyword("_REQUIRE_UV2");
material.DisableKeyword("_REQUIRE_UV3");
}
}
}
} // namespace UnityEditor

3
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/StandardSpecularToHDLitMaterialUpgrader.cs


using System;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
class StandardSpecularToHDLitMaterialUpgrader : MaterialUpgrader
{

6
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Editor/StandardToHDLitMaterialUpgrader.cs


using System;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
class StandardToHDLitMaterialUpgrader : MaterialUpgrader
class StandardToHDLitMaterialUpgrader : MaterialUpgrader
{
public StandardToHDLitMaterialUpgrader()
{

82
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.cs


using UnityEngine;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Lit
{

// Init precomputed texture
//-----------------------------------------------------------------------------
public bool isInit;
public bool isInit;
private Material m_InitPreFGD;
private Material m_InitPreFGD;
// For area lighting
private Texture2D m_LtcGGXMatrix; // RGBA
private Texture2D m_LtcDisneyDiffuseMatrix; // RGBA
private Texture2D m_LtcMultiGGXFresnelDisneyDiffuse; // RGB, A unused
// For area lighting - We pack all texture inside a texture array to reduce the number of resource required
private Texture2DArray m_LtcData; // 0: m_LtcGGXMatrix - RGBA, 2: m_LtcDisneyDiffuseMatrix - RGBA, 3: m_LtcMultiGGXFresnelDisneyDiffuse - RGB, A unused
Material CreateEngineMaterial(string shaderPath)
{
Material mat = new Material(Shader.Find(shaderPath) as Shader);
mat.hideFlags = HideFlags.HideAndDontSave;
return mat;
}
Texture2D CreateLUT(int width, int height, TextureFormat format, Color[] pixels)
{
Texture2D tex = new Texture2D(width, height, format, false /*mipmap*/, true /*linear*/);
tex.hideFlags = HideFlags.HideAndDontSave;
tex.wrapMode = TextureWrapMode.Clamp;
tex.SetPixels(pixels);
tex.Apply();
return tex;
}
Texture2D LoadLUT(TextureFormat format, float[] LUTScalar)
void LoadLUT(Texture2DArray tex, int arrayElement, TextureFormat format, float[] LUTScalar)
// amplitude
return CreateLUT(k_LtcLUTResolution, k_LtcLUTResolution, format, pixels);
tex.SetPixels(pixels, arrayElement);
Texture2D LoadLUT(TextureFormat format, double[,] LUTTransformInv)
void LoadLUT(Texture2DArray tex, int arrayElement, TextureFormat format, double[,] LUTTransformInv)
// transformInv
for (int i = 0; i < count; i++)
{
// Both GGX and Disney Diffuse BRDFs have zero values in columns 1, 3, 5, 7.

(float)LUTTransformInv[i, 6]);
}
return CreateLUT(k_LtcLUTResolution, k_LtcLUTResolution, format, pixels);
tex.SetPixels(pixels, arrayElement);
Texture2D LoadLUT(TextureFormat format, float[] LtcGGXMagnitudeData,
float[] LtcGGXFresnelData,
float[] LtcDisneyDiffuseMagnitudeData)
void LoadLUT(Texture2DArray tex, int arrayElement, TextureFormat format, float[] LtcGGXMagnitudeData,
float[] LtcGGXFresnelData,
float[] LtcDisneyDiffuseMagnitudeData)
{
const int count = k_LtcLUTResolution * k_LtcLUTResolution;
Color[] pixels = new Color[count];

LtcGGXFresnelData[i], LtcDisneyDiffuseMagnitudeData[i], 1);
}
return CreateLUT(k_LtcLUTResolution, k_LtcLUTResolution, format, pixels);
}
tex.SetPixels(pixels, arrayElement);
}
m_InitPreFGD = CreateEngineMaterial("Hidden/HDRenderPipeline/PreIntegratedFGD");
m_PreIntegratedFGD = new RenderTexture(128, 128, 0, RenderTextureFormat.ARGBHalf);
m_InitPreFGD = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/PreIntegratedFGD");
// TODO: switch to RGBA64 when it becomes available.
m_PreIntegratedFGD = new RenderTexture(128, 128, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_PreIntegratedFGD.filterMode = FilterMode.Bilinear;
m_PreIntegratedFGD.wrapMode = TextureWrapMode.Clamp;
m_PreIntegratedFGD.Create();
m_LtcData = new Texture2DArray(k_LtcLUTResolution, k_LtcLUTResolution, 3, TextureFormat.RGBAHalf, false /*mipmap*/, true /* linear */)
{
hideFlags = HideFlags.HideAndDontSave,
wrapMode = TextureWrapMode.Clamp,
filterMode = FilterMode.Bilinear
};
m_LtcGGXMatrix = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMatrixData);
m_LtcDisneyDiffuseMatrix = LoadLUT(TextureFormat.RGBAHalf, s_LtcDisneyDiffuseMatrixData);
LoadLUT(m_LtcData, 0, TextureFormat.RGBAHalf, s_LtcGGXMatrixData);
LoadLUT(m_LtcData, 1, TextureFormat.RGBAHalf, s_LtcDisneyDiffuseMatrixData);
m_LtcMultiGGXFresnelDisneyDiffuse = LoadLUT(TextureFormat.RGBAHalf, s_LtcGGXMagnitudeData,
s_LtcGGXFresnelData,
s_LtcDisneyDiffuseMagnitudeData);
LoadLUT(m_LtcData, 2, TextureFormat.RGBAHalf, s_LtcGGXMagnitudeData, s_LtcGGXFresnelData, s_LtcDisneyDiffuseMagnitudeData);
m_LtcData.Apply();
isInit = false;
}

public void Bind()
{
Shader.SetGlobalTexture("_PreIntegratedFGD", m_PreIntegratedFGD);
Shader.SetGlobalTexture("_LtcGGXMatrix", m_LtcGGXMatrix);
Shader.SetGlobalTexture("_LtcDisneyDiffuseMatrix", m_LtcDisneyDiffuseMatrix);
Shader.SetGlobalTexture("_LtcMultiGGXFresnelDisneyDiffuse", m_LtcMultiGGXFresnelDisneyDiffuse);
Shader.SetGlobalTexture("_PreIntegratedFGD", m_PreIntegratedFGD);
Shader.SetGlobalTexture("_LtcData", m_LtcData);
}
}
}

12
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


#ifndef LIT_CS_HLSL
#define LIT_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.Lit.MaterialId: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.MaterialId: static fields
//
#define MATERIALID_LIT_STANDARD (0)
#define MATERIALID_LIT_SSS (1)

//
// UnityEngine.Experimental.ScriptableRenderLoop.Lit.SurfaceData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.SurfaceData: static fields
//
#define DEBUGVIEW_LIT_SURFACEDATA_BASE_COLOR (1000)
#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_OCCLUSION (1001)

#define DEBUGVIEW_LIT_SURFACEDATA_SPECULAR_COLOR (1015)
//
// UnityEngine.Experimental.ScriptableRenderLoop.Lit.BSDFData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.BSDFData: static fields
//
#define DEBUGVIEW_LIT_BSDFDATA_DIFFUSE_COLOR (1030)
#define DEBUGVIEW_LIT_BSDFDATA_FRESNEL0 (1031)

#define DEBUGVIEW_LIT_BSDFDATA_COAT_ROUGHNESS (1046)
//
// UnityEngine.Experimental.ScriptableRenderLoop.Lit.GBufferMaterial: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Lit.GBufferMaterial: static fields
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Lit.SurfaceData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Lit.SurfaceData
// PackingRules = Exact
struct SurfaceData
{

float3 specularColor;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Lit.BSDFData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Lit.BSDFData
// PackingRules = Exact
struct BSDFData
{

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


//-----------------------------------------------------------------------------
// SurfaceData is define in Lit.cs which generate Lit.cs.hlsl
#include "Lit.cs.hlsl"
//TODO: return this original relative path include after fixing a bug in Unity side
//#include "Lit.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.cs.hlsl"
// In case we pack data uint16 buffer we need to change the output render target format to uint16
// TODO: Is there a way to automate these output type based on the format declare in lit.cs ?

// TODO: Check if anisotropy with a dynamic if on anisotropy > 0 is performant. Because it may mean we always calculate both isotropy and anisotropy case.
// Maybe we should always calculate anisotropy in case of standard ? Don't think the compile can optimize correctly.
// TODO: I haven't configure this sampler in the code, we should be able to do it (but Unity don't allow it for now...)
// By default Unity provide MIG_MAG_LINEAR_POINT sampler, so it fit with our need.
// TODO: to avoid the message Fragment program 'Frag' : sampler 'sampler_PreIntegratedFGD' has no matching texture and will be undefined.
// We need to test this define LIGHTLOOP_TILE_DIRECT, this is a bad workaround but no alternative until we can setup sampler correctly...
#if defined(LIT_DISPLAY_REFERENCE_IBL) || defined(LIGHTLOOP_TILE_DIRECT)
// When reference mode is enabled, then we need to chose another sampler not related to cubemap code...
SAMPLER2D(sampler_LtcGGXMatrix);
#define SRL_BilinearSampler sampler_LtcGGXMatrix // Used for all textures
#else
SAMPLER2D(sampler_PreIntegratedFGD);
#define SRL_BilinearSampler sampler_PreIntegratedFGD // Used for all textures
#endif
// TODO: we can share the sampler here and name it SRL_BilinearSampler. However Unity currently doesn't support to set sampler in C#
// + to avoid the message Fragment program 'Frag' : sampler 'sampler_PreIntegratedFGD' has no matching texture and will be undefined.
TEXTURE2D(_LtcGGXMatrix); // RGBA
TEXTURE2D(_LtcDisneyDiffuseMatrix); // RGBA
TEXTURE2D(_LtcMultiGGXFresnelDisneyDiffuse); // RGB, A unused
SAMPLER2D(sampler_PreIntegratedFGD);
TEXTURE2D_ARRAY(_LtcData); // We pack the 3 Ltc data inside a texture array
SAMPLER2D(sampler_LtcData);
#define LTC_GGX_MATRIX_INDEX 0 // RGBA
#define LTC_DISNEY_DIFFUSE_MATRIX_INDEX 1 // RGBA
#define LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX 2 // RGB, A unused
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material

// _PreIntegratedFGD.y = Gv * Fc
// Pre integrate DisneyDiffuse FGD:
// _PreIntegratedFGD.z = DisneyDiffuse
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, SRL_BilinearSampler, float2(NdotV, perceptualRoughness), 0).xyz;
float3 preFGD = SAMPLE_TEXTURE2D_LOD(_PreIntegratedFGD, sampler_PreIntegratedFGD, float2(NdotV, perceptualRoughness), 0).xyz;
// f0 * Gv * (1 - Fc) + Gv * Fc
specularFGD = fresnel0 * preFGD.x + preFGD.y;

bsdfData.diffuseColor = surfaceData.baseColor * (1.0 - surfaceData.metallic);
bsdfData.fresnel0 = lerp(float3(surfaceData.specular, surfaceData.specular, surfaceData.specular), surfaceData.baseColor, surfaceData.metallic);
bsdfData.tangentWS = surfaceData.tangentWS;
bsdfData.bitangentWS = cross(surfaceData.normalWS, surfaceData.tangentWS);
bsdfData.tangentWS = surfaceData.tangentWS;
bsdfData.bitangentWS = cross(surfaceData.normalWS, surfaceData.tangentWS);
ConvertAnisotropyToRoughness(bsdfData.roughness, surfaceData.anisotropy, bsdfData.roughnessT, bsdfData.roughnessB);
bsdfData.anisotropy = surfaceData.anisotropy;

}
else if (surfaceData.materialId == MATERIALID_LIT_SSS)
{
outGBuffer2 = float4(surfaceData.subSurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subSurfaceProfile / 8.0f); // Number of profile not define yet
outGBuffer2 = float4(surfaceData.subSurfaceRadius, surfaceData.thickness, 0.0, surfaceData.subSurfaceProfile / 8.0); // Number of profile not define yet
}
else if (surfaceData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

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;

bsdfData.fresnel0 = 0.028; // TODO take from subSurfaceProfile
bsdfData.subSurfaceRadius = inGBuffer2.r;
bsdfData.thickness = inGBuffer2.g;
bsdfData.subSurfaceProfile = inGBuffer2.a * 8.0f;
bsdfData.subSurfaceProfile = inGBuffer2.a * 8.0;
}
else if (bsdfData.materialId == MATERIALID_LIT_CLEAR_COAT)
{

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

{
PreLightData preLightData;
// TODO: check Eric idea about doing that when writting into the GBuffer (with our forward decal)
preLightData.NdotV = GetShiftedNdotV(bsdfData.normalWS, V, false);
// We have handle the case of NdotV being negative in GetData() function with GetShiftedNdotV.
// So we don't need to saturate or take the abs here.
// In case a material use negative normal for double sided lighting like speedtree this will be handle in the GetData() code too.
preLightData.NdotV = dot(bsdfData.normalWS, V);
preLightData.ggxLambdaV = GetSmithJointGGXLambdaV(preLightData.NdotV, bsdfData.roughness);

// NOTE: If we follow the theory we should use the modified normal for the different calculation implying a normal (like NDotV) and use iblNormalWS
// into function like GetSpecularDominantDir(). However modified normal is just a hack. The goal is just to stretch a cubemap, no accuracy here.
// With this in mind and for performance reasons we chose to only use modified normal to calculate R.
// iblNdotV = GetShiftedNdotV(iblNormalWS, V), false);
}
GetPreIntegratedFGD(iblNdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD);

preLightData.iblDirWS = GetSpecularDominantDir(bsdfData.normalWS, iblR, bsdfData.roughness);
preLightData.iblDirWS = GetSpecularDominantDir(bsdfData.normalWS, iblR, bsdfData.roughness, preLightData.NdotV);
preLightData.iblMipLevel = PerceptualRoughnessToMipmapLevel(bsdfData.perceptualRoughness);
float theta = FastACos(dot(bsdfData.normalWS, V));
float theta = FastACos(preLightData.NdotV);
// Scale and bias for the current precomputed table - the constant use here are the one that have been use when the table in LtcData.DisneyDiffuse.cs and LtcData.GGX.cs was use
float2 uv = 0.0078125 + 0.984375 * float2(bsdfData.perceptualRoughness, theta * INV_HALF_PI);

preLightData.ltcXformGGX._m22 = 1.0;
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_LOD(_LtcGGXMatrix, SRL_BilinearSampler, uv, 0);
preLightData.ltcXformGGX._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_GGX_MATRIX_INDEX, 0);
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_LOD(_LtcDisneyDiffuseMatrix, SRL_BilinearSampler, uv, 0);
preLightData.ltcXformDisneyDiffuse._m00_m02_m11_m20 = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_DISNEY_DIFFUSE_MATRIX_INDEX, 0);
float3 ltcMagnitude = SAMPLE_TEXTURE2D_LOD(_LtcMultiGGXFresnelDisneyDiffuse, SRL_BilinearSampler, uv, 0).r;
float3 ltcMagnitude = SAMPLE_TEXTURE2D_ARRAY_LOD(_LtcData, sampler_LtcData, uv, LTC_MULTI_GGX_FRESNEL_DISNEY_DIFFUSE_INDEX, 0).rgb;
preLightData.ltcGGXFresnelMagnitudeDiff = ltcMagnitude.r;
preLightData.ltcGGXFresnelMagnitude = ltcMagnitude.g;
preLightData.ltcDisneyDiffuseMagnitude = ltcMagnitude.b;

// Maybe always using aniso maybe a win ?
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
float TdotL = saturate(dot(bsdfData.tangentWS, L));
float BdotL = saturate(dot(bsdfData.bitangentWS, L));
// 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, preLightData.NdotV, TdotL, BdotL, NdotL,

bsdfData.roughnessT, bsdfData.roughnessB);
#endif
// For anisotropy we must not saturate these values
float TdotH = dot(bsdfData.tangentWS, H);
float BdotH = dot(bsdfData.bitangentWS, H);
bsdfData.roughness = ClampRoughnessForAnalyticalLights(bsdfData.roughness);
#ifdef LIT_USE_BSDF_PRE_LAMBDAV
Vis = V_SmithJointGGX(NdotL, preLightData.NdotV, bsdfData.roughness, preLightData.ggxLambdaV);
#else

specularLighting = float3(0.0, 0.0, 0.0);
float3 cookieColor = float3(1.0, 1.0, 1.0);
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0f)
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0)
{
float shadowAttenuation = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, lightData.shadowIndex, L, posInput.unPositionSS);

illuminance *= cookie.a;
}
[branch] if (illuminance > 0.0f)
[branch] if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, diffuseLighting, specularLighting);
diffuseLighting *= (cookieColor * lightData.color) * (illuminance * lightData.diffuseScale);

// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0
[branch] if (lightData.IESIndex >= 0 && illuminance > 0.0)
{
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
float2 sphericalCoord = GetIESTextureCoordinate(lightToWorld, L);
illuminance *= SampleIES(lightLoopContext, lightData.IESIndex, sphericalCoord, 0).r;
}
//[branch] if (lightData.IESIndex >= 0 && illuminance > 0.0)
//{
// float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
// float2 sphericalCoord = GetIESTextureCoordinate(lightToWorld, L);
// illuminance *= SampleIES(lightLoopContext, lightData.IESIndex, sphericalCoord, 0).r;
//}
[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0)
{

P1 -= positionWS;
P2 -= positionWS;
// Construct an orthonormal basis (local coordinate system) around N.
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
// Also consider using 'bsdfData.tangentWS', 'bsdfData.bitangentWS', 'bsdfData.normalWS'.
// Construct a view-dependent orthonormal basis around N.
// TODO: it could be stored in PreLightData, since all LTC lights compute it more than once.
float3x3 basis;
basis[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);
basis[1] = normalize(cross(bsdfData.normalWS, basis[0]));

float lightPdf = 0.0; // Pdf of the light sample
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
u = frac(u + randNum);
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(lightData.positionWS, 1.0));

// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateLambertIBLRef( LightLoopContext lightLoopContext,
EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
float3 IntegrateLambertIBLRef(LightLoopContext lightLoopContext,
float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
u = frac(u + randNum + 0.5);
u = frac(u + randNum);
float3 L;
float NdotL;

}
float3 IntegrateDisneyDiffuseIBLRef(LightLoopContext lightLoopContext,
float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float NdotV = GetShiftedNdotV(N, V, false);
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float2 randNum = InitRandom(N.xy * 0.5 + 0.5);
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
u = frac(u + randNum + 0.5);
u = frac(u + randNum);
float3 L;
float NdotL;

float LdotH = dot(L, H);
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
float disneyDiffuse = DisneyDiffuse(preLightData.NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);

}
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateSpecularGGXIBLRef( LightLoopContext lightLoopContext,
float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 2048)
float3 IntegrateSpecularGGXIBLRef(LightLoopContext lightLoopContext,
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
float3 N = bsdfData.normalWS;
float3 tangentX = bsdfData.tangentWS;
float3 tangentY = bsdfData.bitangentWS;
float3x3 localToWorld = GetLocalFrame(N, tangentX);
float NdotV = GetShiftedNdotV(N, V, false);
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d

{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum + 0.5);
u = frac(u + randNum);
float VdotH;
float NdotL;

// GGX BRDF
if (bsdfData.materialId = MATERIALID_LIT_ANISO)
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
ImportanceSampleAnisoGGX(u, V, N, tangentX, tangentY, bsdfData.roughnessT, bsdfData.roughnessB, NdotV, L, VdotH, NdotL, weightOverPdf);
ImportanceSampleAnisoGGX(u, V, localToWorld, bsdfData.roughnessT, bsdfData.roughnessB, preLightData.NdotV, L, VdotH, NdotL, weightOverPdf);
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, preLightData.NdotV, L, VdotH, NdotL, weightOverPdf);
}

#ifdef LIT_DISPLAY_REFERENCE_IBL
specularLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, lightData, bsdfData);
specularLighting = IntegrateSpecularGGXIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
diffuseLighting = IntegrateLambertIBLRef(lightData, bsdfData);
diffuseLighting = IntegrateLambertIBLRef(lightData, V, bsdfData);
diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, lightData, bsdfData);
diffuseLighting = IntegrateDisneyDiffuseIBLRef(lightLoopContext, V, preLightData, lightData, bsdfData);
#endif
*/
diffuseLighting = float3(0.0, 0.0, 0.0);

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

#endif
#endif

97
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Lit.shader


_NormalScale("_NormalScale", Range(0.0, 2.0)) = 1
_HeightMap("HeightMap", 2D) = "black" {}
_HeightScale("Height Scale", Float) = 0.01
_HeightBias("Height Bias", Float) = 0
_HeightAmplitude("Height Amplitude", Float) = 0.01 // In world units
_HeightCenter("Height Center", Float) = 0.5 // In texture space
_TangentMap("TangentMap", 2D) = "bump" {}
_Anisotropy("Anisotropy", Range(0.0, 1.0)) = 0

// Blending state
[HideInInspector] _SurfaceType("__surfacetype", Float) = 0.0
[HideInInspector] _BlendMode ("__blendmode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[HideInInspector] _BlendMode("__blendmode", Float) = 0.0
[HideInInspector] _SrcBlend("__src", Float) = 1.0
[HideInInspector] _DstBlend("__dst", Float) = 0.0
[HideInInspector] _ZWrite("__zw", Float) = 1.0
// Material Id
[HideInInspector] _MaterialId("_MaterialId", FLoat) = 0

[Enum(UV0, 0, Planar, 1, TriPlanar, 2)] _UVBase("UV Set for base", Float) = 0
_TexWorldScale("Scale to apply on world coordinate", Float) = 1.0
[HideInInspector] _UVMappingMask("_UVMappingMask", Color) = (1,0,0,0)
[HideInInspector] _UVMappingMask("_UVMappingMask", Color) = (1, 0, 0, 0)
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[ToggleOff] _EnablePerPixelDisplacement("Enable per pixel displacement", Float) = 0.0
_PPDMinSamples("Min sample for POM", Range(1.0, 64.0)) = 5
_PPDMaxSamples("Max sample for POM", Range(1.0, 64.0)) = 15
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1,0,0,0)
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1, 0, 0, 0)
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go futher in dev
//-------------------------------------------------------------------------------------
// Variant

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _DEPTHOFFSET_ON
#pragma shader_feature _ _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _ _DOUBLESIDED _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _REQUIRE_UV2_OR_UV3
#pragma shader_feature _PER_PIXEL_DISPLACEMENT
#pragma shader_feature _ _REQUIRE_UV2 _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR
#pragma shader_feature _NORMALMAP

#include "common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Attributes.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
//-------------------------------------------------------------------------------------

#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl"
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

Cull [_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "ShaderPass/LitSharePass.hlsl"
#include "LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassGBuffer.hlsl"
ENDHLSL

Cull[_CullMode]
HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "ShaderPass/LitSharePass.hlsl"
#include "LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassDebugViewMaterial.hlsl"
ENDHLSL

// Lightmap memo
// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitMetaPass.hlsl"
#include "LitMetaPass.hlsl"
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "ShaderPass/LitDepthPass.hlsl"
#include "LitDepthPass.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "ShaderPass/LitDepthPass.hlsl"
#include "LitDepthPass.hlsl"
#include "../../ShaderPass/ShaderPassDepthOnly.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "ShaderPass/LitVelocityPass.hlsl"
#include "LitVelocityPass.hlsl"
#include "../../ShaderPass/ShaderPassVelocity.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "../../Material/Material.hlsl"
#include "ShaderPass/LitDistortionPass.hlsl"
#include "LitDistortionPass.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"
ENDHLSL

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "../../Lighting/Forward.hlsl"
// #include "../../Lighting/Forward.hlsl"
//#pragma multi_compile SHADOWFILTERING_FIXED_SIZE_PCF
#include "ShaderPass/LitSharePass.hlsl"
#include "LitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassForward.hlsl"
ENDHLSL

CustomEditor "Experimental.ScriptableRenderLoop.LitGUI"
CustomEditor "Experimental.Rendering.HDPipeline.LitGUI"
}

447
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitData.hlsl


// Fill SurfaceData/Builtin data function
//-------------------------------------------------------------------------------------
#include "../MaterialUtilities.hlsl"
#include "../SampleLayer.hlsl"
void GetBuiltinData(FragInputs input, SurfaceData surfaceData, float alpha, float depthOffset, out BuiltinData builtinData)
{

builtinData.emissiveColor = float3(0.0, 0.0, 0.0);
#endif
builtinData.velocity = CalculateVelocity(input.positionCS, input.previousPositionCS);
builtinData.velocity = float2(0.0, 0.0);
#ifdef _DISTORTION_ON
float3 distortion = SAMPLE_TEXTURE2D(_DistortionVectorMap, sampler_DistortionVectorMap, input.texCoord0).rgb;

builtinData.depthOffset = depthOffset;
}
// Gather all kind of mapping in one struct, allow to improve code readability
struct LayerUV
{
float2 uv;
// triplanar
bool isTriplanar;
float2 uvYZ;
float2 uvZX;
float2 uvXY;
};
struct LayerTexCoord
{

// triplanar weight
float3 weights;
};
float4 SampleLayer(TEXTURE2D_ARGS(layerTex, layerSampler), LayerUV layerUV, float3 weights)
{
if (layerUV.isTriplanar)
{
float4 val = float4(0.0, 0.0, 0.0, 0.0);
if (weights.x > 0.0)
val += weights.x * SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ);
if (weights.y > 0.0)
val += weights.y * SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX);
if (weights.z > 0.0)
val += weights.z * SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY);
return val;
}
else
{
return SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv);
}
}
// TODO: Handle BC5 format, currently this code is for DXT5nm
// THis function below must call UnpackNormalmapRGorAG
float3 SampleNormalLayer(TEXTURE2D_ARGS(layerTex, layerSampler), LayerUV layerUV, float3 weights, float scale)
{
if (layerUV.isTriplanar)
{
float3 val = float3(0.0, 0.0, 0.0);
if (weights.x > 0.0)
val += weights.x * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ), scale);
if (weights.y > 0.0)
val += weights.y * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX), scale);
if (weights.z > 0.0)
val += weights.z * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY), scale);
return normalize(val);
}
else
{
return UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv), scale);
}
}
// This version is for normalmap with AG encoding only (use with details map)
float3 SampleNormalLayerAG(TEXTURE2D_ARGS(layerTex, layerSampler), LayerUV layerUV, float3 weights, float scale)
{
if (layerUV.isTriplanar)
{
float3 val = float3(0.0, 0.0, 0.0);
if (weights.x > 0.0)
val += weights.x * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ), scale);
if (weights.y > 0.0)
val += weights.y * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX), scale);
if (weights.z > 0.0)
val += weights.z * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY), scale);
return normalize(val);
}
else
{
return UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv), scale);
}
}
// This version is for normalmap with RGB encoding only, i.e non encoding. It is necessary to use this abstraction to handle correctly triplanar
// plus consistent with the normal scale parameter
float3 SampleNormalLayerRGB(TEXTURE2D_ARGS(layerTex, layerSampler), LayerUV layerUV, float3 weights, float scale)
{
if (layerUV.isTriplanar)
{
float3 val = float3(0.0, 0.0, 0.0);
if (weights.x > 0.0)
val += weights.x * UnpackNormalRGB(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ), scale);
if (weights.y > 0.0)
val += weights.y * UnpackNormalRGB(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX), scale);
if (weights.z > 0.0)
val += weights.z * UnpackNormalRGB(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY), scale);
return normalize(val);
}
else
{
return UnpackNormalRGB(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv), scale);
}
}
// Macro to improve readibility of surface data
#define SAMPLE_LAYER_TEXTURE2D(textureName, samplerName, coord) SampleLayer(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights)
#define SAMPLE_LAYER_NORMALMAP(textureName, samplerName, coord, scale) SampleNormalLayer(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale)
#define SAMPLE_LAYER_NORMALMAP_AG(textureName, samplerName, coord, scale) SampleNormalLayerAG(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale)
#define SAMPLE_LAYER_NORMALMAP_RGB(textureName, samplerName, coord, scale) SampleNormalLayerRGB(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights, scale)
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
// include LitDataInternal to define GetSurfaceData
#include "LitSurfaceData.hlsl"
#include "LitDataInternal.hlsl"
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
LayerTexCoord layerTexCoord;
layerTexCoord.weights = ComputeTriplanarWeights(input.tangentToWorld[2].xyz);
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
#endif
// Be sure that the compiler is aware that we don't touch UV1 to UV3 for base layer in case of non layer shader

#ifdef _MAPPING_TRIPLANAR
isTriplanar = true;
#endif
ComputeLayerTexCoord(input, isTriplanar, layerTexCoord);
// Transform view vector in tangent space
ComputeLayerTexCoord( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord);
}
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
// ref: https://www.gamedev.net/resources/_/technical/graphics-programming-and-theory/a-closer-look-at-parallax-occlusion-mapping-r3262
ApplyDisplacement(input, viewDirTS, layerTexCoord);
// Change the number of samples per ray depending on the viewing angle for the surface.
// Oblique angles require smaller step sizes to achieve more accurate precision for computing displacement.
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
ParallaxOcclusionMappingLayer(layerTexCoord, numSteps, viewDirTS);
// TODO: We are supposed to modify lightmaps coordinate (fetch in GetBuiltin), but this isn't the same uv mapping, so can't apply the offset here...
// Let's assume it will be "fine" as indirect diffuse is often low frequency
#endif
}
// Calculate displacement for per vertex displacement mapping
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
{
return SampleHeightmapLod(layerTexCoord, lod);
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerTexCoord layerTexCoord;
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
ApplyPerPixelDisplacement(input, V, layerTexCoord);
ApplyDepthOffsetPositionInput(V, builtinData.depthOffset, posInput);
ApplyDepthOffsetAttribute(depthOffset, input);
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData);
// We perform the conversion to world of the normalTS outside of the GetSurfaceData
// so it allow us to correctly deal with detail normal map and optimize the code for the layered shaders
float3 normalTS;
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData, normalTS);
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
// Caution: surfaceData must be fully initialize before calling GetBuiltinData
GetBuiltinData(input, surfaceData, alpha, depthOffset, builtinData);
}

// Generate function for all layer
// include LitDataInternal multiple time to define the variation of GetSurfaceData for each layer
#include "LitSurfaceData.hlsl"
#include "LitDataInternal.hlsl"
#include "LitSurfaceData.hlsl"
#include "LitDataInternal.hlsl"
#include "LitSurfaceData.hlsl"
#include "LitDataInternal.hlsl"
#include "LitSurfaceData.hlsl"
#include "LitDataInternal.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX

masks[0] = 1.0f; // Layer 0 is always full
masks[0] = 1.0; // Layer 0 is always full
float left = 1.0f;
// Algorithm is like this:
// Top layer have priority on others layers
// If a top layer doesn't use the full weight, the remaining can be use by the following layer.
float weightsSum = 0.0;
for (int i = _LAYER_COUNT - 1; i > 0; --i)
for (int i = _LAYER_COUNT - 1; i >= 0; --i)
outWeights[i] = masks[i] * left;
left -= outWeights[i];
outWeights[i] = min(masks[i], (1.0 - weightsSum));
weightsSum = saturate(weightsSum + masks[i]);
outWeights[0] = left;
float3 BlendLayeredColor(float3 rgb0, float3 rgb1, float3 rgb2, float3 rgb3, float weight[4])
float3 BlendLayeredVector3(float3 x0, float3 x1, float3 x2, float3 x3, float weight[4])
result = rgb0 * weight[0] + rgb1 * weight[1];
result = x0 * weight[0] + x1 * weight[1];
result += (rgb2 * weight[2]);
result += (x2 * weight[2]);
result += rgb3 * weight[3];
result += x3 * weight[3];
float3 BlendLayeredNormal(float3 normal0, float3 normal1, float3 normal2, float3 normal3, float weight[4])
{
float3 result = float3(0.0, 0.0, 0.0);
result = normal0 * weight[0] + normal1 * weight[1];
#if _LAYER_COUNT >= 3
result += normal2 * weight[2];
#endif
#if _LAYER_COUNT >= 4
result += normal3 * weight[3];
#endif
return normalize(result);
}
float BlendLayeredScalar(float x0, float x1, float x2, float x3, float weight[4])
{
float result = 0.0;

return result;
}
#define SURFACEDATA_BLEND_VECTOR3(surfaceData, name, mask) BlendLayeredVector3(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);
edgeBlendStrength = max(0.001, edgeBlendStrength);
float heightThreshold = previousLayerHeight + edgeBlendStrength;
edgeBlendStrength = max(0.00001, edgeBlendStrength);
if (previousLayerHeight >= finalLayerHeight)
{

return max(finalLayerHeight, previousLayerHeight);
}
#define SURFACEDATA_BLEND_COLOR(surfaceData, name, mask) BlendLayeredColor(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_NORMAL(surfaceData, name, mask) BlendLayeredNormal(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define SURFACEDATA_BLEND_SCALAR(surfaceData, name, mask) BlendLayeredScalar(surfaceData##0.##name, surfaceData##1.##name, surfaceData##2.##name, surfaceData##3.##name, mask);
#define PROP_BLEND_SCALAR(name, mask) BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);
float3 ApplyHeightBasedBlendV2(float3 inputMask, float3 inputHeight, float3 blendUsingHeight)
{
return saturate(lerp(inputMask * inputHeight * blendUsingHeight * 100, 1, inputMask * inputMask)); // 100 arbitrary scale to limit blendUsingHeight values.
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
void GetLayerTexCoord(float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
float3 positionWS, float3 normalWS, out LayerTexCoord layerTexCoord)
LayerTexCoord layerTexCoord;
layerTexCoord.weights = ComputeTriplanarWeights(input.tangentToWorld[2].xyz);
layerTexCoord.weights = ComputeTriplanarWeights(normalWS);
#endif
bool isTriplanar = false;

ComputeLayerTexCoord0(input, isTriplanar, layerTexCoord);
ComputeLayerTexCoord0( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling0);
ComputeLayerTexCoord1(input, isTriplanar, layerTexCoord);
ComputeLayerTexCoord1( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling1);
ComputeLayerTexCoord2(input, isTriplanar, layerTexCoord);
ComputeLayerTexCoord2( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling2);
ComputeLayerTexCoord3(input, isTriplanar, layerTexCoord);
ComputeLayerTexCoord3( texCoord0, texCoord1, texCoord2, texCoord3,
positionWS, normalWS, isTriplanar, layerTexCoord, _LayerTiling3);
}
// Transform view vector in tangent space
void ApplyPerPixelDisplacement(FragInputs input, float3 V, inout LayerTexCoord layerTexCoord)
{
#if defined(_HEIGHTMAP) && defined(_PER_PIXEL_DISPLACEMENT)
float height0 = ApplyDisplacement0(input, viewDirTS, layerTexCoord);
float height1 = ApplyDisplacement1(input, viewDirTS, layerTexCoord);
float height2 = ApplyDisplacement2(input, viewDirTS, layerTexCoord);
float height3 = ApplyDisplacement3(input, viewDirTS, layerTexCoord);
float depthOffset = 0.0;
int numSteps = (int)lerp(_PPDMaxSamples, _PPDMinSamples, viewDirTS.z);
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, builtinData.depthOffset, posInput);
ApplyDepthOffsetAttribute(depthOffset, input);
ParallaxOcclusionMappingLayer0(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer1(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer2(layerTexCoord, numSteps, viewDirTS);
ParallaxOcclusionMappingLayer3(layerTexCoord, numSteps, viewDirTS);
#endif
}
float3 ComputeInheritedNormalTS(FragInputs input, float3 normalTS0, float3 normalTS1, float3 normalTS2, float3 normalTS3, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
{
float3 normalTS;
// Compute how much we want to inherit from base layer normal base on the mask. Base layer always fully inherit from "itself" if it's the visible layer.
float inheritBaseNormal = BlendLayeredScalar(1.0, _InheritBaseNormal1, _InheritBaseNormal2, _InheritBaseNormal3, weights);
// Based on this inheritance parameters, fetch a lower level of the base layer normal map so that the less we inherit the more this tends to be "vertex normal"
float maxMipBias = log2(max(_NormalMap0_TexelSize.x, _NormalMap0_TexelSize.y)) + 1.0; // TODO: Use hardware instruction here (GetDimensions) that can retunr mipmaps num ? will this be faster
float3 inheritedBaseNormalTS = GetNormalTS0(input, layerTexCoord, float3(0.0, 0.0, 0.0), 0.0, true, maxMipBias * (1.0 - inheritBaseNormal));
// Blend all layers but the base one. This will then be added to the "inherited" normal of base layer (that's why base layer here is tangent space vertex normal so that if it's the visible layer we add nothing in term of normal map).
float3 layersNormalTS = BlendLayeredVector3(float3(0.0, 0.0, 1.0), normalTS1, normalTS2, normalTS3, weights);
// Add the inherited normal to the blended top layers.
normalTS = BlendNormalRNM(inheritedBaseNormalTS, layersNormalTS);
return normalTS;
}
float3 ComputeInheritedColor(float3 baseColor0, float3 baseColor1, float3 baseColor2, float3 baseColor3, float compoMask, LayerTexCoord layerTexCoord, float weights[_MAX_LAYER])
{
float inheritBaseColor = BlendLayeredScalar(1.0, _InheritBaseColor1, _InheritBaseColor2, _InheritBaseColor3, weights);
float inheritBaseColorThreshold = BlendLayeredScalar(1.0, _InheritBaseColorThreshold1, _InheritBaseColorThreshold2, _InheritBaseColorThreshold3, weights);
inheritBaseColor = inheritBaseColor * (1.0 - saturate(compoMask / inheritBaseColorThreshold));
// We want to calculate the mean color of the texture. For this we will sample a low mipmap
float textureBias = 15.0; // Force a high number to be sure we get the lowest mip
float3 baseMeanColor0 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap0, sampler_BaseColorMap0, layerTexCoord.base0, textureBias).rgb * _BaseColor0.rgb;
float3 baseMeanColor1 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap1, sampler_BaseColorMap0, layerTexCoord.base1, textureBias).rgb * _BaseColor1.rgb;
float3 baseMeanColor2 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap2, sampler_BaseColorMap0, layerTexCoord.base2, textureBias).rgb * _BaseColor2.rgb;
float3 baseMeanColor3 = SAMPLE_LAYER_TEXTURE2D_BIAS(_BaseColorMap3, sampler_BaseColorMap0, layerTexCoord.base3, textureBias).rgb * _BaseColor3.rgb;
float3 meanColor = BlendLayeredVector3(baseMeanColor0, baseMeanColor1, baseMeanColor2, baseMeanColor3, weights);
float3 baseColor = BlendLayeredVector3(baseColor0, baseColor1, baseColor2, baseColor3, weights);
// If we inherit from base layer, we will add a bit of it
return inheritBaseColor * (baseColor0 - meanColor) + baseColor;
}
// Calculate displacement for per vertex displacement mapping
float ComputePerVertexDisplacement(LayerTexCoord layerTexCoord, float4 vertexColor, float lod)
{
// Mask Values : Layer 1, 2, 3 are r, g, b. Always use layer0 parametrization for the mask
float3 inputMaskValues = SAMPLE_LAYER_TEXTURE2D_LOD(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0, lod).rgb;
#if defined(_LAYER_MASK_VERTEX_COLOR_MUL)
inputMaskValues *= vertexColor.rgb;
#elif defined(_LAYER_MASK_VERTEX_COLOR_ADD)
inputMaskValues = saturate(inputMaskValues + vertexColor.rgb * 2.0 - 1.0);
#endif
float weights[_MAX_LAYER];
ComputeMaskWeights(inputMaskValues, weights);
float height0 = SampleHeightmapLod0(layerTexCoord, lod);
float height1 = SampleHeightmapLod1(layerTexCoord, lod, _HeightCenterOffset1, _HeightFactor1);
float height2 = SampleHeightmapLod2(layerTexCoord, lod, _HeightCenterOffset2, _HeightFactor2);
float height3 = SampleHeightmapLod3(layerTexCoord, lod, _HeightCenterOffset3, _HeightFactor3);
float heightResult = BlendLayeredScalar(height0, height1, height2, height3, weights);
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
// Think that inheritbasedheight will be 0 if height0 is fully visible in weights. So there is no double contribution of height0
float inheritBaseHeight = BlendLayeredScalar(0.0, _InheritBaseHeight1, _InheritBaseHeight2, _InheritBaseHeight3, weights);
return heightResult + height0 * inheritBaseHeight;
SurfaceData surfaceData0;
SurfaceData surfaceData1;
SurfaceData surfaceData2;
SurfaceData surfaceData3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3);
return heightResult;
}
// Mask Values : Layer 1, 2, 3 are r, g, b
float3 maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
// Calculate weights to apply to each layer
// Caution: This function must not be use for per vertex of per pixel displacement, there is a dedicated function for them.
// this function handle triplanar
void ComputeLayerWeights(FragInputs input, LayerTexCoord layerTexCoord, float4 inputAlphaMask, out float outWeights[_MAX_LAYER])
{
// Mask Values : Layer 1, 2, 3 are r, g, b. Always use layer0 parametrization for the mask
float3 inputMaskValues = SAMPLE_LAYER_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, layerTexCoord.base0).rgb;
#if defined(_LAYER_MASK_VERTEX_COLOR)
maskValues *= input.vertexColor.rgb;
#if defined(_LAYER_MASK_VERTEX_COLOR_MUL)
inputMaskValues *= input.color.rgb;
#elif defined(_LAYER_MASK_VERTEX_COLOR_ADD)
inputMaskValues = saturate(inputMaskValues + input.color.rgb * 2.0 - 1.0);
float3 minOpaParam = float3(_MinimumOpacity1, _MinimumOpacity2, _MinimumOpacity3);
float3 remapedOpacity = lerp(minOpaParam, float3(1.0, 1.0, 1.0), inputAlphaMask.yzw); // Remap opacity mask from [0..1] to [minOpa..1]
float3 opacityAsDensity = saturate((inputAlphaMask.yzw - (float3(1.0, 1.0, 1.0) - inputMaskValues)) * 20.0);
float3 useOpacityAsDensityParam = float3(_OpacityAsDensity1, _OpacityAsDensity2, _OpacityAsDensity3);
inputMaskValues = lerp(inputMaskValues * remapedOpacity, opacityAsDensity, useOpacityAsDensityParam);
float baseLayerHeight = height0;
baseLayerHeight = ApplyHeightBasedBlend(maskValues.r, baseLayerHeight, height1, _HeightOffset1, _HeightFactor1, _BlendSize1, input.vertexColor.r);
baseLayerHeight = ApplyHeightBasedBlend(maskValues.g, baseLayerHeight, height2, _HeightOffset2 + _HeightOffset1, _HeightFactor2, _BlendSize2, input.vertexColor.g);
ApplyHeightBasedBlend(maskValues.b, baseLayerHeight, height3, _HeightOffset3 + _HeightOffset2 + _HeightOffset1, _HeightFactor3, _BlendSize3, input.vertexColor.b);
float height0 = SampleHeightmap0(layerTexCoord);
float height1 = SampleHeightmap1(layerTexCoord, _HeightCenterOffset1, _HeightFactor1);
float height2 = SampleHeightmap2(layerTexCoord, _HeightCenterOffset2, _HeightFactor2);
float height3 = SampleHeightmap3(layerTexCoord, _HeightCenterOffset3, _HeightFactor3);
float4 heights = float4(height0, height1, height2, height3);
#if !defined(_HEIGHT_BASED_BLEND_V2)
float baseLayerHeight = heights.x;
baseLayerHeight = ApplyHeightBasedBlend(inputMaskValues.r, baseLayerHeight, heights.y, _HeightOffset1, _HeightFactor1, _BlendSize1, input.color.r);
baseLayerHeight = ApplyHeightBasedBlend(inputMaskValues.g, baseLayerHeight, heights.z, _HeightOffset2 + _HeightOffset1, _HeightFactor2, _BlendSize2, input.color.g);
ApplyHeightBasedBlend(inputMaskValues.b, baseLayerHeight, heights.w, _HeightOffset3 + _HeightOffset2 + _HeightOffset1, _HeightFactor3, _BlendSize3, input.color.b);
#else
// HACK, use height0 to avoid compiler error for unused sampler
// To remove once we have POM
heights.y += (heights.x * 0.0001);
inputMaskValues = ApplyHeightBasedBlendV2(inputMaskValues, heights.yzw, float3(_BlendUsingHeight1, _BlendUsingHeight2, _BlendUsingHeight3));
#endif
#endif
ComputeMaskWeights(inputMaskValues, outWeights);
}
void GetSurfaceAndBuiltinData(FragInputs input, float3 V, inout PositionInputs posInput, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerTexCoord layerTexCoord;
GetLayerTexCoord(input.texCoord0, input.texCoord1, input.texCoord2, input.texCoord3,
input.positionWS, input.tangentToWorld[2].xyz, layerTexCoord);
ApplyPerPixelDisplacement(input, V, layerTexCoord);
float depthOffset = 0.0;
#ifdef _DEPTHOFFSET_ON
ApplyDepthOffsetPositionInput(V, depthOffset, posInput);
SurfaceData surfaceData0, surfaceData1, surfaceData2, surfaceData3;
float3 normalTS0, normalTS1, normalTS2, normalTS3;
float alpha0 = GetSurfaceData0(input, layerTexCoord, surfaceData0, normalTS0);
float alpha1 = GetSurfaceData1(input, layerTexCoord, surfaceData1, normalTS1);
float alpha2 = GetSurfaceData2(input, layerTexCoord, surfaceData2, normalTS2);
float alpha3 = GetSurfaceData3(input, layerTexCoord, surfaceData3, normalTS3);
ComputeMaskWeights(maskValues, weights);
ComputeLayerWeights(input, layerTexCoord, float4(alpha0, alpha1, alpha2, alpha3), weights);
// For layered shader, alpha of base color is used as either an opacity mask, a composition mask for inheritance parameters or a density mask.
float alpha = PROP_BLEND_SCALAR(alpha, weights);
surfaceData.baseColor = SURFACEDATA_BLEND_COLOR(surfaceData, baseColor, weights);
#if defined(_MAIN_LAYER_INFLUENCE_MODE)
surfaceData.baseColor = ComputeInheritedColor(surfaceData0.baseColor, surfaceData1.baseColor, surfaceData2.baseColor, surfaceData3.baseColor, alpha, layerTexCoord, weights);
float3 normalTS = ComputeInheritedNormalTS(input, normalTS0, normalTS1, normalTS2, normalTS3, layerTexCoord, weights);
#else
surfaceData.baseColor = SURFACEDATA_BLEND_VECTOR3(surfaceData, baseColor, weights);
float3 normalTS = BlendLayeredVector3(normalTS0, normalTS1, normalTS2, normalTS3, weights);
#endif
// Note: for normal map (in tangent space) it is possible to have better performance
// by blending in tangent space then transform to world and apply flip.
// Sadly this require a specific path (without taking into account that there is detail normal map)
// mean it add an extra cost of maintenance. We chose to not do this optimization in favor
// of simpler code and in the future will rely on shader graph to create optimize code.
surfaceData.normalWS = SURFACEDATA_BLEND_NORMAL(surfaceData, normalWS, weights);
surfaceData.tangentWS = normalize(input.tangentToWorld[0].xyz);
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
surfaceData.anisotropy = 0;
surfaceData.specular = 0.04;
surfaceData.subSurfaceRadius = 1.0;

surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
float alpha = PROP_BLEND_SCALAR(alpha, weights);
GetNormalAndTangentWS(input, V, normalTS, surfaceData.normalWS, surfaceData.tangentWS);
#ifdef TESSELLATION_ON
#include "LitTessellation.hlsl" // Must be after GetLayerTexCoord() declaration
#endif

61
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LitProperties.hlsl


TEXTURE2D(_HeightMap);
SAMPLER2D(sampler_HeightMap);
float4 _HeightMap_TexelSize; // Unity facility. This will provide the size of the heightmap to the shader
float _HeightScale;
float _HeightBias;
float _HeightAmplitude;
float _HeightCenter;
TEXTURE2D(_TangentMap);
SAMPLER2D(sampler_TangentMap);

float _UVMappingPlanar;
float4 _UVMappingMask;
float4 _UVDetailsMappingMask;
float _PPDMaxSamples;
float _PPDMinSamples;
#else // LAYERED_LIT_SHADER

PROP_DECL_TEX2D(_NormalMap);
PROP_DECL(float, _NormalScale);
float4 _NormalMap0_TexelSize; // Unity facility. This will provide the size of the base normal to the shader
float4 _HeightMap0_TexelSize;
float4 _HeightMap1_TexelSize;
float4 _HeightMap2_TexelSize;
float4 _HeightMap3_TexelSize;
PROP_DECL_TEX2D(_DetailMask);
PROP_DECL_TEX2D(_DetailMap);

PROP_DECL(float, _DetailHeightScale);
PROP_DECL(float, _DetailAOScale);
PROP_DECL(float, _HeightScale);
PROP_DECL(float, _HeightBias);
PROP_DECL(float, _HeightAmplitude);
PROP_DECL(float, _HeightCenter);
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);

float _BlendSize3;
float _VertexColorHeightFactor;
// Blend Properties V2
float _UseHeightBasedBlendV2;
float _HeightCenterOffset1;
float _HeightCenterOffset2;
float _HeightCenterOffset3;
float _BlendUsingHeight1;
float _BlendUsingHeight2;
float _BlendUsingHeight3;
float _InheritBaseNormal1;
float _InheritBaseNormal2;
float _InheritBaseNormal3;
float _InheritBaseHeight1;
float _InheritBaseHeight2;
float _InheritBaseHeight3;
float _InheritBaseColor1;
float _InheritBaseColor2;
float _InheritBaseColor3;
float _InheritBaseColorThreshold1;
float _InheritBaseColorThreshold2;
float _InheritBaseColorThreshold3;
float _MinimumOpacity1;
float _MinimumOpacity2;
float _MinimumOpacity3;
float _OpacityAsDensity1;
float _OpacityAsDensity2;
float _OpacityAsDensity3;
PROP_DECL(float, _LayerTiling);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);

float _AlphaCutoff;
float _PPDMaxSamples;
float _PPDMinSamples;
// Tessellation specific
#ifdef TESSELLATION_ON
float _TessellationFactor;
float _TessellationFactorMinDistance;
float _TessellationFactorMaxDistance;
float _TessellationFactorTriangleSize;
float _TessellationShapeFactor;
float _TessellationBackFaceCullEpsilon;
float _TessellationObjectScale;
#endif

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LtcData.DisneyDiffuse.cs


using UnityEngine.Rendering;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Lit
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/LtcData.GGX.cs


using UnityEngine.Rendering;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Lit
{

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Lit/Resources/PreIntegratedFGD.shader


HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#include "Common.hlsl"
#include "ImageBasedLighting.hlsl"

float3 V = float3(sqrt(1 - NdotV * NdotV), 0, NdotV);
float3 N = float3(0.0, 0.0, 1.0);
const int numSamples = 2048;
float4 preFGD = IntegrateGGXAndDisneyFGD(V, N, PerceptualRoughnessToRoughness(perceptualRoughness), numSamples);
float4 preFGD = IntegrateGGXAndDisneyFGD(V, N, PerceptualRoughnessToRoughness(perceptualRoughness));
return float4(preFGD.xyz, 1.0);
}

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


void ADD_IDX(ComputeLayerTexCoord)(FragInputs input, bool isTriplanar, inout LayerTexCoord layerTexCoord)
void ADD_IDX(ComputeLayerTexCoord)( float2 texCoord0, float2 texCoord1, float2 texCoord2, float2 texCoord3,
float3 positionWS, float3 normalWS, bool isTriplanar, inout LayerTexCoord layerTexCoord, float additionalTiling = 1.0)
float2 uvBase = ADD_IDX(_UVMappingMask).x * input.texCoord0 +
ADD_IDX(_UVMappingMask).y * input.texCoord1 +
ADD_IDX(_UVMappingMask).z * input.texCoord2 +
ADD_IDX(_UVMappingMask).w * input.texCoord3;
float2 uvBase = ADD_IDX(_UVMappingMask).x * texCoord0 +
ADD_IDX(_UVMappingMask).y * texCoord1 +
ADD_IDX(_UVMappingMask).z * texCoord2 +
ADD_IDX(_UVMappingMask).w * texCoord3;
uvBase *= additionalTiling.xx;
float2 uvDetails = ADD_IDX(_UVDetailsMappingMask).x * input.texCoord0 +
ADD_IDX(_UVDetailsMappingMask).y * input.texCoord1 +
ADD_IDX(_UVDetailsMappingMask).z * input.texCoord2 +
ADD_IDX(_UVDetailsMappingMask).w * input.texCoord3;
float2 uvDetails = ADD_IDX(_UVDetailsMappingMask).x * texCoord0 +
ADD_IDX(_UVDetailsMappingMask).y * texCoord1 +
ADD_IDX(_UVDetailsMappingMask).z * texCoord2 +
ADD_IDX(_UVDetailsMappingMask).w * texCoord3;
//float3 position = localTriplanar ? TransformWorldToObject(input.positionWS) : input.positionWS;
float3 position = input.positionWS;
//float3 position = localTriplanar ? TransformWorldToObject(positionWS) : positionWS;
float3 position = positionWS;
position *= ADD_IDX(_TexWorldScale);
if (ADD_IDX(_UVMappingPlanar) > 0.0)

// triplanar
ADD_IDX(layerTexCoord.base).isTriplanar = isTriplanar;
float3 direction = sign(input.tangentToWorld[2].xyz);
float3 direction = sign(normalWS);
// In triplanar, if we are facing away from the world axis, a different axis will be flipped for each direction.
// This is particularly problematic for tangent space normal maps which need to be in the right direction.

ADD_IDX(layerTexCoord.details).uvXY = TRANSFORM_TEX(uvXY, ADD_IDX(_DetailMap));
}
float ADD_IDX(ApplyDisplacement)(inout FragInputs input, float3 viewDirTS, inout LayerTexCoord layerTexCoord)
float ADD_IDX(SampleHeightmap)(LayerTexCoord layerTexCoord, float centerOffset = 0.0, float multiplier = 1.0)
float height = 0.0f;
#ifdef _HEIGHTMAP
return (SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base)).r - ADD_IDX(_HeightCenter) - centerOffset) * ADD_IDX(_HeightAmplitude) * multiplier;
#else
return 0.0;
#endif
}
float ADD_IDX(SampleHeightmapLod)(LayerTexCoord layerTexCoord, float lod, float centerOffset = 0.0, float multiplier = 1.0)
{
height = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base)).r * ADD_IDX(_HeightScale) + ADD_IDX(_HeightBias);
return (SAMPLE_LAYER_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base), lod).r - ADD_IDX(_HeightCenter) - centerOffset) * ADD_IDX(_HeightAmplitude) * multiplier;
#else
return 0.0;
#endif
}
//#ifndef _HEIGHTMAP_AS_DISPLACEMENT
// //height = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base)).r * ADD_IDX(_HeightScale) + ADD_IDX(_HeightBias);
// float2 offset = ParallaxOffset(viewDirTS, height);
// Note: The sampling of heightmap inside POM don't use sampling abstraction (with triplanar) as
// POM must be apply separately for each uv set (so 3 time for triplanar)
void ADD_IDX(ParallaxOcclusionMappingLayer)(inout LayerTexCoord layerTexCoord, int numSteps, float3 viewDirTS)
{
// Convention: 1.0 is top, 0.0 is bottom - POM is always inward, no extrusion
float stepSize = 1.0 / (float)numSteps;
// ADD_IDX(layerTexCoord.base).uv += offset;
// ADD_IDX(layerTexCoord.base).uvYZ += offset;
// ADD_IDX(layerTexCoord.base).uvZX += offset;
// ADD_IDX(layerTexCoord.base).uvXY += offset;
// View vector is from the point to the camera, but we want to raymarch from camera to point, so reverse the sign
// The length of viewDirTS vector determines the furthest amount of displacement:
// float parallaxLimit = -length(viewDirTS.xy) / viewDirTS.z;
// float2 parallaxDir = normalize(Out.viewDirTS.xy);
// float2 parallaxMaxOffsetTS = parallaxDir * parallaxLimit;
// Above code simplify to
float2 parallaxMaxOffsetTS = (viewDirTS.xy / -viewDirTS.z) * ADD_IDX(_HeightAmplitude);
float2 texOffsetPerStep = stepSize * parallaxMaxOffsetTS;
// ADD_IDX(layerTexCoord.details).uv += offset;
// ADD_IDX(layerTexCoord.details).uvYZ += offset;
// ADD_IDX(layerTexCoord.details).uvZX += offset;
// ADD_IDX(layerTexCoord.details).uvXY += offset;
float2 uv = ADD_IDX(layerTexCoord.base).uv;
// Compute lod as we will sample inside a loop (so can't use regular sampling)
// It appear that CALCULATE_TEXTURE2D_LOD only return interger lod. We want to use float lod to have smoother transition and fading
// float lod = CALCULATE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv);
float lod = ComputeTextureLOD(uv, GET_TEXELSIZE_NAME(ADD_IDX(_HeightMap)));
// Do a first step before the loop to init all value correctly
float2 texOffsetCurrent = 0;
float prevHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
texOffsetCurrent += texOffsetPerStep;
float currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
float rayHeight = 1.0 - stepSize; // Start at top less one sample
// Linear search
for (int stepIndex = 0; stepIndex < numSteps; ++stepIndex)
{
// Have we found a height below our ray height ? then we have an intersection
if (currHeight > rayHeight)
break; // end the loop
prevHeight = currHeight;
rayHeight -= stepSize;
texOffsetCurrent += texOffsetPerStep;
// Sample height map which in this case is stored in the alpha channel of the normal map:
currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + texOffsetCurrent, lod).r;
}
// Found below and above points, now perform line interesection (ray) with piecewise linear heightfield approximation
// Refine the search by adding few extra intersection
#define POM_REFINE 1
#if POM_REFINE
float pt0 = rayHeight + stepSize;
float pt1 = rayHeight;
float delta0 = pt0 - prevHeight;
float delta1 = pt1 - currHeight;
float2 offset = float2(0.0, 0.0);
float threshold = 1.0;
for (int i = 0; i < 5; ++i)
{
float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
offset = (1 - t) * texOffsetPerStep * numSteps;
currHeight = SAMPLE_TEXTURE2D_LOD(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), uv + offset, lod).r;
// // Only modify texcoord for first layer, this will be use by for builtin data (like lightmap)
// if (LAYER_INDEX == 0)
// {
// input.texCoord0 += offset;
// input.texCoord1 += offset;
// input.texCoord2 += offset;
// input.texCoord3 += offset;
// }
threshold = t - currHeight;
// // Need to refetch for the right parallaxed height for layer blending to behave correctly...
// height = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_HeightMap), ADD_ZERO_IDX(sampler_HeightMap), ADD_IDX(layerTexCoord.base)).r * ADD_IDX(_HeightScale) + ADD_IDX(_HeightBias);
if (abs(threshold) <= 0.01)
break;
// #endif
if (threshold < 0.0)
{
delta1 = threshold;
pt1 = t;
}
else
{
delta0 = threshold;
pt0 = t;
}
}
#else
//float pt0 = rayHeight + stepSize;
//float pt1 = rayHeight;
//float delta0 = pt0 - prevHeight;
//float delta1 = pt1 - currHeight;
//float t = (pt0 * delta1 - pt1 * delta0) / (delta1 - delta0);
//float2 offset = (1 - t) * texOffsetPerStep * numSteps;
// A bit more optimize
float delta0 = currHeight - rayHeight;
float delta1 = (rayHeight + stepSize) - prevHeight;
float ratio = delta0 / (delta0 + delta1);
float2 offset = texOffsetCurrent - ratio * texOffsetPerStep;
return height;
// TODO: expose LOD fading
//float lodThreshold = 0.0;
//offset *= (1.0 - saturate(lod - lodThreshold));
// Apply offset only on base. Details could use another mapping and will not be consistant...
// Don't know if this will still ok.
// TODO: check with artists
ADD_IDX(layerTexCoord.base).uv += offset;
}
float3 ADD_IDX(GetNormalTS)(FragInputs input, LayerTexCoord layerTexCoord, float3 detailNormalTS, float detailMask, bool useBias, float bias)
{
float3 normalTS;
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
if (useBias)
{
normalTS = SAMPLE_LAYER_NORMALMAP_BIAS(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale), bias);
}
else
{
normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
}
#else // Object space
// to be able to combine object space normal with detail map we transform it to tangent space (object space normal composition is not simple).
// then later we will re-transform it to world space.
if (useBias)
{
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB_BIAS(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale), bias).rgb;
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
}
else
{
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale)).rgb;
normalTS = TransformObjectToTangent(normalOS, input.tangentToWorld);
}
#endif
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif
#else
normalTS = float3(0.0, 0.0, 1.0);
#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalTS = -normalTS;
#else
// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalTS = reflect(normalTS, float3(0.0, 0.0, 1.0)); // Reflect around vertex normal (in tangent space this is z)
#endif
// TODO : Test if GetOddNegativeScale() is necessary here in case of normal map, as GetOddNegativeScale is take into account in CreateTangentToWorld();
normalTS = input.isFrontFace ?
(GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS) :
(-GetOddNegativeScale() >= 0.0 ? normalTS : oppositeNormalTS);
#endif
return normalTS;
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData)
float ADD_IDX(GetSurfaceData)(FragInputs input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData, out float3 normalTS)
{
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = ADD_IDX(_BaseColor).a;

clip(alpha - _AlphaCutoff);
#endif
float3 detailNormalTS = float3(0.0, 0.0, 0.0);
float detailMask = 0.0;
float detailMask = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMask), ADD_ZERO_IDX(sampler_DetailMask), ADD_IDX(layerTexCoord.base)).b;
detailMask = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMask), ADD_ZERO_IDX(sampler_DetailMask), ADD_IDX(layerTexCoord.base)).g;
float2 detailAlbedoAndSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMap), ADD_ZERO_IDX(sampler_DetailMap), ADD_IDX(layerTexCoord.details)).rb;
float detailAlbedo = detailAlbedoAndSmoothness.r;
float detailSmoothness = detailAlbedoAndSmoothness.g;

float3 detailNormalTS = SAMPLE_LAYER_NORMALMAP_AG(ADD_IDX(_DetailMap), ADD_ZERO_IDX(sampler_DetailMap), ADD_IDX(layerTexCoord.details), ADD_ZERO_IDX(_DetailNormalScale));
detailNormalTS = SAMPLE_LAYER_NORMALMAP_AG(ADD_IDX(_DetailMap), ADD_ZERO_IDX(sampler_DetailMap), ADD_IDX(layerTexCoord.details), ADD_ZERO_IDX(_DetailNormalScale));
float3 detailNormalTS = float3(0.0, 0.0, 1.0);
detailNormalTS = float3(0.0, 0.0, 1.0);
//float detailAO = detail.b;
#endif
#endif

//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
#endif
surfaceData.normalWS = float3(0.0, 0.0, 0.0); // Need to init this so that the compiler leaves us alone.
float3 vertexNormalWS = normalize(input.tangentToWorld[2].xyz);
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, BlendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space
float3 normalOS = SAMPLE_LAYER_NORMALMAP_RGB(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base), ADD_ZERO_IDX(_NormalScale)).rgb;
surfaceData.normalWS = TransformObjectToWorldDir(normalOS);
#ifdef _DETAIL_MAP
float3 detailNormalWS = TransformTangentToWorld(detailNormalTS, input.tangentToWorld);
surfaceData.normalWS = lerp(surfaceData.normalWS, BlendNormal(surfaceData.normalWS, detailNormalWS), detailMask);
#endif
#endif
#else
surfaceData.normalWS = vertexNormalWS;
#endif
#if defined(_DOUBLESIDED_LIGHTING_FLIP) || defined(_DOUBLESIDED_LIGHTING_MIRROR)
#ifdef _DOUBLESIDED_LIGHTING_FLIP
float3 oppositeNormalWS = -surfaceData.normalWS;
#else
// Mirror the normal with the plane define by vertex normal
float3 oppositeNormalWS = reflect(surfaceData.normalWS, vertexNormalWS);
#endif
// TODO : Test if GetOdddNegativeScale() is necessary here in case of normal map, as GetOdddNegativeScale is take into account in CreateTangentToWorld();
surfaceData.normalWS = input.isFrontFace ?
(GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS) :
(-GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
#endif
normalTS = ADD_IDX(GetNormalTS)(input, layerTexCoord, detailNormalTS, detailMask, false, 0.0);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
surfaceData.perceptualSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).a;

// TODO: Is there anything todo regarding flip normal but for the tangent ?
#ifdef _ANISOTROPYMAP
surfaceData.anisotropy = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_AnisotropyMap), ADD_ZERO_IDX(sampler_AnisotropyMap), ADD_IDX(layerTexCoord.base)).g;
surfaceData.anisotropy = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_AnisotropyMap), ADD_ZERO_IDX(sampler_AnisotropyMap), ADD_IDX(layerTexCoord.base)).b;
#else
surfaceData.anisotropy = 1.0;
#endif

29
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/MaterialUtilities.hlsl


// TODO: Move all this to C++!
float4x4 identity = 0;
identity._m00_m11_m22_m33 = 1.0;
float4x4 WorldToTexture = (unity_ProbeVolumeParams.y == 1.0f) ? unity_ProbeVolumeWorldToObject : identity;
float4x4 WorldToTexture = (unity_ProbeVolumeParams.y == 1.0) ? unity_ProbeVolumeWorldToObject : identity;
float4x4 translation = identity;
translation._m30_m31_m32 = -unity_ProbeVolumeMin.xyz;

#ifdef DIRLIGHTMAP_COMBINED
bakeDiffuseLighting += SampleDirectionalLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap),
TEXTURE2D_PARAM(unity_LightmapInd, samplerunity_Lightmap),
uvStaticLightmap, unity_LightmapST, normalWS);
uvStaticLightmap, unity_LightmapST, normalWS, true);
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap), uvStaticLightmap, unity_LightmapST);
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_Lightmap, samplerunity_Lightmap), uvStaticLightmap, unity_LightmapST, true);
#endif
#endif

TEXTURE2D_PARAM(unity_DynamicDirectionality, samplerunity_DynamicLightmap),
uvDynamicLightmap, unity_DynamicLightmapST, normalWS);
uvDynamicLightmap, unity_DynamicLightmapST, normalWS, false);
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_DynamicLightmap, samplerunity_DynamicLightmap), uvDynamicLightmap, unity_DynamicLightmapST);
bakeDiffuseLighting += SampleSingleLightmap(TEXTURE2D_PARAM(unity_DynamicLightmap, samplerunity_DynamicLightmap), uvDynamicLightmap, unity_DynamicLightmapST, false);
#endif
#endif

#else
return float2(0.0, 0.0);
#endif
}
}
// This function convert the tangent space normal/tangent to world space and orthonormalize it + apply a correction of the normal if it is not pointing towards the near plane
void GetNormalAndTangentWS(FragInputs input, float3 V, float3 normalTS, inout float3 normalWS, inout float3 tangentWS, bool twoSided = false)
{
normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal
// should be modified to become valid (i.e facing the camera) to avoid weird artifacts.
// Note: certain applications (e.g. SpeedTree) require to still have negative normal to perform their own two sided lighting
// This will potentially reduce the length of the normal at edges of geometry.
GetShiftedNdotV(normalWS, V, twoSided);
// Orthonormalize the basis vectors using the Gram-Schmidt process.
// We assume that the length of the surface normal is sufficiently close to 1.
tangentWS = normalize(tangentWS - dot(tangentWS, normalWS));
}

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/BaseUnlitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
public abstract class BaseUnlitGUI : ShaderGUI
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Editor/UnlitUI.cs


using UnityEngine;
using UnityEngine.Rendering;
namespace UnityEditor.Experimental.ScriptableRenderLoop
namespace UnityEditor.Experimental.Rendering.HDPipeline
{
class UnlitGUI : BaseUnlitGUI
{

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
namespace Unlit
{

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.cs.hlsl


#ifndef UNLIT_CS_HLSL
#define UNLIT_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.Unlit.SurfaceData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Unlit.SurfaceData: static fields
// UnityEngine.Experimental.ScriptableRenderLoop.Unlit.BSDFData: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.Unlit.BSDFData: static fields
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Unlit.SurfaceData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Unlit.SurfaceData
// PackingRules = Exact
struct SurfaceData
{

// Generated from UnityEngine.Experimental.ScriptableRenderLoop.Unlit.BSDFData
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.Unlit.BSDFData
// PackingRules = Exact
struct BSDFData
{

156
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/Unlit.shader


_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}
_EmissiveIntensity("EmissiveIntensity", Float) = 0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0
_DistortionVectorMap("DistortionVectorMap", 2D) = "black" {}
[ToggleOff] _DistortionEnable("Enable Distortion", Float) = 0.0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Depth Test Enable", Float) = 0.0
[ToggleOff] _AlphaCutoffEnable("Alpha Cutoff Enable", Float) = 0.0
_AlphaCutoff("Alpha Cutoff", Range(0.0, 1.0)) = 0.5

[HideInInspector] _BlendMode ("__blendmode", Float) = 0.0
[HideInInspector] _SrcBlend ("__src", Float) = 1.0
[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[HideInInspector] _BlendMode("__blendmode", Float) = 0.0
[HideInInspector] _SrcBlend("__src", Float) = 1.0
[HideInInspector] _DstBlend("__dst", Float) = 0.0
[HideInInspector] _ZWrite("__zw", Float) = 1.0
[HideInInspector] _ZTestMode("_ZTestMode", Int) = 8
[Enum(None, 0, DoubleSided, 1)] _DoubleSidedMode("Double sided mode", Float) = 0
}

#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
//-------------------------------------------------------------------------------------
// Variant

#pragma shader_feature _DISTORTION_ON
#pragma shader_feature _ _DOUBLESIDED
#pragma shader_feature _EMISSIVE_COLOR_MAP
//-------------------------------------------------------------------------------------

#include "common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Attributes.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/FragInputs.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl"
//-------------------------------------------------------------------------------------

float _AlphaCutoff;
// All our shaders use same name for entry point
#pragma vertex Vert
#pragma fragment Frag
ENDHLSL
SubShader

HLSLPROGRAM
#pragma vertex VertDefault
#pragma fragment Frag
#include "ShaderPass/UnlitSharePass.hlsl"
#include "UnlitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassDebugViewMaterial.hlsl"
ENDHLSL

Pass
{
Name "ForwardUnlit"
Tags { "LightMode" = "ForwardUnlit" }
Tags { "LightMode" = "Forward" }
Blend [_SrcBlend] [_DstBlend]
ZWrite [_ZWrite]

#pragma vertex VertDefault
#pragma fragment Frag
#include "ShaderPass/UnlitSharePass.hlsl"
#include "UnlitSharePass.hlsl"
#include "../../ShaderPass/ShaderPassForwardUnlit.hlsl"
ENDHLSL

// DYNAMICLIGHTMAP_ON is used when we have an "enlighten lightmap" ie a lightmap updated at runtime by enlighten.This lightmap contain indirect lighting from realtime lights and realtime emissive material.Offline baked lighting(from baked material / light,
// both direct and indirect lighting) will hand up in the "regular" lightmap->LIGHTMAP_ON.
#pragma vertex Vert
#pragma fragment Frag
#include "../../Material/Material.hlsl"
#include "UnlitData.hlsl"
CBUFFER_START(UnityMetaPass)
// x = use uv1 as raster position
// y = use uv2 as raster position
bool4 unity_MetaVertexControl;
// x = return albedo
// y = return normal
bool4 unity_MetaFragmentControl;
CBUFFER_END
// This was not in constant buffer in original unity, so keep outiside. But should be in as ShaderRenderPass frequency
float unity_OneOverOutputBoost;
float unity_MaxOutputValue;
struct Attributes
{
float3 positionOS : POSITION;
float3 normalOS : NORMAL;
float2 uv0 : TEXCOORD0;
float2 uv1 : TEXCOORD1;
float2 uv2 : TEXCOORD2;
};
struct Varyings
{
float4 positionCS;
float2 texCoord0;
float2 texCoord1;
};
struct PackedVaryings
{
float4 positionCS : SV_Position;
float4 interpolators[1] : TEXCOORD0;
};
// Function to pack data to use as few interpolator as possible, the ShaderGraph should generate these functions
PackedVaryings PackVaryings(Varyings input)
{
PackedVaryings output;
output.positionCS = input.positionCS;
output.interpolators[0].xy = input.texCoord0;
output.interpolators[0].zw = input.texCoord1;
#include "../../Material/Material.hlsl"
#include "ShaderPass/UnlitMetaPass.hlsl"
#include "UnlitData.hlsl"
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"
return output;
}
FragInputs UnpackVaryings(PackedVaryings input)
{
FragInputs output;
ZERO_INITIALIZE(FragInputs, output);
output.unPositionSS = input.positionCS;
output.texCoord0 = input.interpolators[0].xy;
output.texCoord1 = input.interpolators[0].zw;
return output;
}
PackedVaryings Vert(Attributes input)
{
Varyings output;
// Output UV coordinate in vertex shader
if (unity_MetaVertexControl.x)
{
input.positionOS.xy = input.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
//v.positionOS.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
if (unity_MetaVertexControl.y)
{
input.positionOS.xy = input.uv2 * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
//v.positionOS.z = vertex.z > 0 ? 1.0e-4f : 0.0f;
}
ENDHLSL
}
float3 positionWS = TransformObjectToWorld(input.positionOS);
output.positionCS = TransformWorldToHClip(positionWS);
output.texCoord0 = input.uv0;
output.texCoord1 = input.uv1;
Pass
{
Name "Distortion" // Name is not used
Tags { "LightMode" = "DistortionVectors" } // This will be only for transparent object based on the RenderQueue index
return PackVaryings(output);
}
Blend One One
ZTest [_ZTestMode]
ZWrite off
Cull [_CullMode]
HLSLPROGRAM
#include "../../ShaderPass/ShaderPassLightTransport.hlsl"
#define SHADERPASS SHADERPASS_DISTORTION
#include "../../Material/Material.hlsl"
#include "ShaderPass/UnlitSharePass.hlsl"
#include "UnlitData.hlsl"
#include "../../ShaderPass/ShaderPassDistortion.hlsl"
CustomEditor "Experimental.ScriptableRenderLoop.UnlitGUI"
CustomEditor "Experimental.Rendering.HDPipeline.UnlitGUI"
}

7
Assets/ScriptableRenderLoop/HDRenderPipeline/Material/Unlit/UnlitData.hlsl


builtinData.velocity = float2(0.0, 0.0);
#ifdef _DISTORTION_ON
float3 distortion = SAMPLE_TEXTURE2D(_DistortionVectorMap, sampler_DistortionVectorMap, input.texCoord0).rgb;
builtinData.distortion = distortion.rg;
builtinData.distortionBlur = distortion.b;
#else
#endif

207
Assets/ScriptableRenderLoop/HDRenderPipeline/PostProcess/Resources/FinalPass.shader


// Final compositing pass, just does gamma correction for now.
_ToneMapCoeffs1("Parameters for neutral tonemap", Vector) = (0.0, 0.0, 0.0, 0.0)
_ToneMapCoeffs2("Parameters for neutral tonemap", Vector) = (0.0, 0.0, 0.0, 0.0)
_Exposure("Exposure", Range(-32.0, 32.0)) = 0
[ToggleOff] _EnableToneMap("Enable Tone Map", Float) = 0
SubShader {
Pass {
ZTest Always Cull Off ZWrite Off
HLSLINCLUDE
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma target 5.0
#pragma target 4.5
#include "Common.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
#include "ColorGrading.hlsl"
#include "Common.hlsl"
#include "Color.hlsl"
#include "Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl"
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
TEXTURE2D(_MainTex);
SAMPLER2D(sampler_MainTex);
TEXTURE2D(_AutoExposure);
SAMPLER2D(sampler_AutoExposure);
float4 _ToneMapCoeffs1;
float4 _ToneMapCoeffs2;
TEXTURE2D(_LogLut);
SAMPLER2D(sampler_LogLut);
#define InBlack _ToneMapCoeffs1.x
#define OutBlack _ToneMapCoeffs1.y
#define InWhite _ToneMapCoeffs1.z
#define OutWhite _ToneMapCoeffs1.w
#define WhiteLevel _ToneMapCoeffs2.z
#define WhiteClip _ToneMapCoeffs2.w
float4 _LogLut_Params;
float _Exposure;
float _EnableToneMap;
float _Exposure;
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
float4 _NeutralTonemapperParams1;
float4 _NeutralTonemapperParams2;
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
struct Attributes
{
float3 vertex : POSITION;
float2 texcoord : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
struct Varyings
{
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
float3 evalCurve(float3 x, float A, float B, float C, float D, float E, float F)
{
return ((x*(A*x + C*B) + D*E) / (x*(A*x + B) + D*F)) - E / F;
}
Varyings Vert(Attributes input)
{
Varyings output;
output.vertex = TransformWorldToHClip(input.vertex);
output.texcoord = input.texcoord.xy;
return output;
}
float3 applyTonemapFilmicAD(float3 linearColor)
{
float blackRatio = InBlack / OutBlack;
float whiteRatio = InWhite / OutWhite;
// Neutral tonemapping (Hable/Hejl/Frostbite)
// Input is linear RGB
float3 NeutralCurve(float3 x, float a, float b, float c, float d, float e, float f)
{
return ((x * (a * x + c * b) + d * e) / (x * (a * x + b) + d * f)) - e / f;
}
float3 NeutralTonemap(float3 x, float4 params1, float4 params2)
{
// ACES supports negative color values and WILL output negative values when coming from ACES or ACEScg
// Make sure negative channels are clamped to 0.0 as this neutral tonemapper can't deal with them properly
x = max((0.0).xxx, x);
// Tonemap
float a = params1.x;
float b = params1.y;
float c = params1.z;
float d = params1.w;
float e = params2.x;
float f = params2.y;
float whiteLevel = params2.z;
float whiteClip = params2.w;
// blend tunable coefficients
float B = lerp(0.57, 0.37, blackRatio);
float C = lerp(0.01, 0.24, whiteRatio);
float D = lerp(0.02, 0.20, blackRatio);
float3 whiteScale = (1.0).xxx / NeutralCurve(whiteLevel, a, b, c, d, e, f);
x = NeutralCurve(x * whiteScale, a, b, c, d, e, f);
x *= whiteScale;
// constants
float A = 0.2;
float E = 0.02;
float F = 0.30;
// Post-curve white point adjustment
x /= whiteClip.xxx;
// eval and correct for white point
float3 whiteScale = 1.0f / evalCurve(WhiteLevel, A, B, C, D, E, F);
float3 curr = evalCurve(linearColor * whiteScale, A, B, C, D, E, F);
return x;
}
return curr * whiteScale;
}
float4 Frag(Varyings input) : SV_Target
{
float4 color = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.texcoord);
float3 remapWhite(float3 inPixel, float whitePt)
#if EYE_ADAPTATION
// var breakout for readability
const float inBlack = 0;
const float outBlack = 0;
float inWhite = whitePt;
const float outWhite = 1;
// remap input range to output range
float3 outPixel = ((inPixel.rgb) - inBlack.xxx) / (inWhite.xxx - inBlack.xxx) * (outWhite.xxx - outBlack.xxx) + outBlack.xxx;
return (outPixel.rgb);
float autoExposure = SAMPLE_TEXTURE2D(_AutoExposure, sampler_AutoExposure, input.texcoord).r;
color *= autoExposure;
#endif
float3 NeutralTonemap(float3 x)
color.rgb *= _Exposure; // Exposure is in ev units (or 'stops'), precomputed CPU-side
#if NEUTRAL_GRADING
float3 finalColor = applyTonemapFilmicAD(x); // curve (dynamic coeffs differ per level)
finalColor = remapWhite(finalColor, WhiteClip); // post-curve white point adjustment
finalColor = saturate(finalColor);
return finalColor;
color.rgb = NeutralTonemap(color.rgb, _NeutralTonemapperParams1, _NeutralTonemapperParams2);
#elif CUSTOM_GRADING
{
float3 uvw = saturate(LinearToLogC(color));
float3 ApplyToneMap(float3 color)
// Strip lut format where `height = sqrt(width)`
uvw.z *= _LogLut_Params.z;
half shift = floor(uvw.z);
uvw.xy = uvw.xy * _LogLut_Params.z * _LogLut_Params.xy + _LogLut_Params.xy * 0.5;
uvw.x += shift * _LogLut_Params.y;
uvw.xyz = lerp(
SAMPLE_TEXTURE2D(_LogLut, sampler_LogLut, uvw.xy).rgb,
SAMPLE_TEXTURE2D(_LogLut, sampler_LogLut, uvw.xy + half2(_LogLut_Params.y, 0)).rgb,
uvw.z - shift
);
color.rgb = uvw;
}
#else
if (_EnableToneMap > 0.0)
{
return NeutralTonemap(color);
}
else
{
return saturate(color);
}
color = saturate(color);
#endif
float4 Frag(Varyings input) : SV_Target
{
float4 c = SAMPLE_TEXTURE2D(_MainTex, sampler_MainTex, input.texcoord);
// Gamma correction
return color;
}
// TODO: Currenlt in the editor there a an additional pass were the result is copyed in a render target RGBA8_sRGB.
// So we must not correct the sRGB here else it will be done two time.
// To fix!
ENDHLSL
c.rgb = ApplyToneMap(c.rgb * exp2(_Exposure));
SubShader
{
Cull Off ZWrite Off ZTest Always
// return LinearToSRGB(c);
return c;
Pass
{
HLSLPROGRAM
#pragma vertex Vert
#pragma fragment Frag
#pragma multi_compile __ NEUTRAL_GRADING CUSTOM_GRADING
#pragma multi_compile __ EYE_ADAPTATION
}
Fallback Off
}

2
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/CommonSettings.cs


using System.Linq;
using System.Reflection;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[ExecuteInEditMode]
[DisallowMultipleComponent]

2
Assets/ScriptableRenderLoop/HDRenderPipeline/SceneSettings/Editor/CommonSettingsEditor.cs


using System.Linq;
using System.Reflection;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[CustomEditor(typeof(CommonSettings))]
[CanEditMultipleObjects]

2
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs


// Configuration
//-----------------------------------------------------------------------------
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL(PackingRules.Exact)]
public enum ShaderOptions

2
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderConfig.cs.hlsl


#ifndef SHADERCONFIG_CS_HLSL
#define SHADERCONFIG_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.ShaderOptions: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.ShaderOptions: static fields
//
#define SHADEROPTIONS_VELOCITY_IN_GBUFFER (0)
#define SHADEROPTIONS_PACK_GBUFFER_IN_U16 (0)

4
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[GenerateHLSL(PackingRules.Exact)]
public enum ShaderPass

2
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPass.cs.hlsl


#ifndef SHADERPASS_CS_HLSL
#define SHADERPASS_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.ShaderPass: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.ShaderPass: static fields
//
#define SHADERPASS_GBUFFER (0)
#define SHADERPASS_FORWARD (1)

26
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDebugViewMaterial.hlsl


#include "Color.hlsl"
int _DebugViewMaterial;
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
float4 Frag(PackedVaryings packedInput) : SV_Target
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
FragInputs input = UnpackVaryings(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

28
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDepthOnly.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
void Frag( PackedVaryings packedInput,
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
void Frag( PackedVaryingsToPS packedInput,
out float4 outColor : SV_Target
#ifdef _DEPTHOFFSET_ON
, out float outputDepth : SV_Depth

FragInputs input = UnpackVaryings(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

outColor = float4(0.0, 0.0, 0.0, 0.0);
#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.rawDepth;
outputDepth = posInput.depthRaw;
#endif
}

26
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassDistortion.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
float4 Frag(PackedVaryings packedInput) : SV_Target
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
FragInputs input = UnpackVaryings(packedInput);
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
{
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

37
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
void Frag( PackedVaryings packedInput,
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
void Frag( PackedVaryingsToPS packedInput,
out float4 outColor : SV_Target
#ifdef _DEPTHOFFSET_ON
, out float outputDepth : SV_Depth

FragInputs input = UnpackVaryings(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

SurfaceData surfaceData;
BuiltinData builtinData;
GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData);
SurfaceData surfaceData;
BuiltinData builtinData;
GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData);
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
PreLightData preLightData = GetPreLightData(V, posInput, bsdfData);
float3 diffuseLighting;

outColor = float4(diffuseLighting + specularLighting, builtinData.opacity);
#ifdef _DEPTHOFFSET_ON
outputDepth = posInput.rawDepth;
outputDepth = posInput.depthRaw;
#endif
}

26
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassForwardUnlit.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
float4 Frag(PackedVaryings packedInput) : SV_Target
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
FragInputs input = UnpackVaryings(packedInput);
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
{
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

34
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassGBuffer.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
void Frag( PackedVaryings packedInput,
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
void Frag( PackedVaryingsToPS packedInput,
, float outputDepth : SV_Depth
, out float outputDepth : SV_Depth
FragInputs input = UnpackVaryings(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

BuiltinData builtinData;
GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData);
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
float3 bakeDiffuseLighting = GetBakedDiffuseLigthing(surfaceData, builtinData, bsdfData, preLightData);
ENCODE_INTO_GBUFFER(surfaceData, bakeDiffuseLighting, outGBuffer);

outputDepth = posInput.rawDepth;
outputDepth = posInput.depthRaw;
#endif
}

53
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassLightTransport.hlsl


#include "Color.hlsl"
// TODO: This is the max value allowed for emissive (bad name - but keep for now to retrieve it) (It is 8^2.2 (gamma) and 8 is the limit of punctual light slider...), comme from UnityCg.cginc. Fix it!
// Ask Jesper if this can be change for HDRenderPipeline
#define EMISSIVE_RGBM_SCALE 97.0
CBUFFER_START(UnityMetaPass)
// x = use uv1 as raster position
// y = use uv2 as raster position
bool4 unity_MetaVertexControl;
// x = return albedo
// y = return normal
bool4 unity_MetaFragmentControl;
CBUFFER_END
// This was not in constant buffer in original unity, so keep outiside. But should be in as ShaderRenderPass frequency
float unity_OneOverOutputBoost;
float unity_MaxOutputValue;
#include "VertMesh.hlsl"
PackedVaryingsToPS Vert(AttributesMesh inputMesh)
{
VaryingsToPS output;
// Output UV coordinate in vertex shader
if (unity_MetaVertexControl.x)
{
inputMesh.positionOS.xy = inputMesh.uv1 * unity_LightmapST.xy + unity_LightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
//v.positionOS.z = vertex.z > 0 ? 1.0e-4 : 0.0;
}
if (unity_MetaVertexControl.y)
{
inputMesh.positionOS.xy = inputMesh.uv2 * unity_DynamicLightmapST.xy + unity_DynamicLightmapST.zw;
// OpenGL right now needs to actually use incoming vertex position,
// so use it in a very dummy way
//v.positionOS.z = vertex.z > 0 ? 1.0e-4 : 0.0;
}
float4 Frag(PackedVaryings packedInput) : SV_Target
float3 positionWS = TransformObjectToWorld(inputMesh.positionOS);
output.vmesh.positionCS = TransformWorldToHClip(positionWS);
output.vmesh.texCoord0 = inputMesh.uv0;
output.vmesh.texCoord1 = inputMesh.uv1;
return PackVaryingsToPS(output);
}
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
FragInputs input = UnpackVaryings(packedInput);
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

{
// TODO: THIS LIMIT MUST BE REMOVE, IT IS NOT HDR, change when RGB9e5 is here.
// Do we assume here that emission is [0..1] ?
res = PackRGBM(lightTransportData.emissiveColor, EMISSIVE_RGBM_SCALE);
res = PackEmissiveRGBM(lightTransportData.emissiveColor);
}
return res;

126
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl


#error SHADERPASS_is_not_correctly_define
#endif
float4 Frag(PackedVaryings packedInput) : SV_Target
// Available semantic start from TEXCOORD4
struct AttributesPass
{
float3 previousPositionOS : NORMAL; // Contain previous transform position (in case of skinning for example)
// TODO: Caution - For now the tesselation doesn't displace along the normal with Velocity shader as the previous previous position
// conflict with the normal in the semantic. This need to be fix!
};
struct VaryingsPassToPS
{
// Note: Z component is not use currently
// This is the clip space position. Warning, do not confuse with the value of positionCS in PackedVarying which is SV_POSITION and store in unPositionSS
float4 positionCS;
float4 previousPositionCS;
};
// Available interpolator start from TEXCOORD8
struct PackedVaryingsPassToPS
{
// Note: Z component is not use
float3 interpolators0 : TEXCOORD8;
float3 interpolators1 : TEXCOORD9;
};
PackedVaryingsPassToPS PackVaryingsPassToPS(VaryingsPassToPS input)
{
PackedVaryingsPassToPS output;
output.interpolators0 = float3(input.positionCS.xyw);
output.interpolators1 = float3(input.previousPositionCS.xyw);
return output;
}
VaryingsPassToPS UnpackVaryingsPassToPS(PackedVaryingsPassToPS input)
{
VaryingsPassToPS output;
output.positionCS = float4(input.interpolators0.xy, 0.0, input.interpolators0.z);
output.previousPositionCS = float4(input.interpolators1.xy, 0.0, input.interpolators1.z);
return output;
}
#ifdef TESSELLATION_ON
// Available interpolator start from TEXCOORD4
// Same as ToPS here
#define VaryingsPassToDS VaryingsPassToPS
#define PackedVaryingsPassToDS PackedVaryingsPassToPS
#define PackVaryingsPassToDS PackVaryingsPassToPS
#define UnpackVaryingsPassToDS UnpackVaryingsPassToPS
VaryingsPassToDS InterpolateWithBaryCoordsPassToDS(VaryingsPassToDS input0, VaryingsPassToDS input1, VaryingsPassToDS input2, float3 baryCoords)
FragInputs input = UnpackVaryings(packedInput);
VaryingsPassToDS ouput;
TESSELLATION_INTERPOLATE_BARY(positionCS, baryCoords);
TESSELLATION_INTERPOLATE_BARY(previousPositionCS, baryCoords);
return ouput;
}
#endif // TESSELLATION_ON
#ifdef TESSELLATION_ON
#define VaryingsPassType VaryingsPassToDS
#else
#define VaryingsPassType VaryingsPassToPS
#endif
// We will use custom attributes for this pass
#define VARYINGS_NEED_PASS
#include "VertMesh.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh,
AttributesPass inputPass)
{
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
// It is not possible to correctly generate the motion vector for tesselated geometry as tessellation parameters can change
// from one frame to another (adaptative, lod) + in Unity we only receive information for one non tesselated vertex.
// So motion vetor will be based on interpolate previous position at vertex level instead.
varyingsType.vpass.positionCS = mul(_NonJitteredVP, mul(unity_ObjectToWorld, float4(inputMesh.positionOS, 1.0)));
varyingsType.vpass.previousPositionCS = mul(_PreviousVP, mul(_PreviousM, _HasLastPositionData ? float4(inputPass.previousPositionOS, 1.0) : float4(inputMesh.positionOS, 1.0)));
return PackVaryingsType(varyingsType);
}
#ifdef TESSELLATION_ON
PackedVaryingsToPS VertTesselation(VaryingsToDS input)
{
VaryingsToPS output;
output.vmesh = VertMeshTesselation(input.vmesh);
output.vpass.positionCS = input.vpass.positionCS;
output.vpass.previousPositionCS = input.vpass.previousPositionCS;
return PackVaryingsToPS(output);
}
#include "TessellationShare.hlsl"
#endif // TESSELLATION_ON
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
{
FragInputs input = UnpackVaryingsMeshToFragInputs(packedInput.vmesh);
// input.unPositionSS is SV_Position
PositionInputs posInput = GetPositionInput(input.unPositionSS.xy, _ScreenSize.zw);

BuiltinData builtinData;
GetSurfaceAndBuiltinData(input, V, posInput, surfaceData, builtinData);
VaryingsPassToPS inputPass = UnpackVaryingsPassToPS(packedInput.vpass);
#ifdef _DEPTHOFFSET_ON
inputPass.positionCS.w += builtinData.depthOffset;
inputPass.previousPositionCS.w += builtinData.depthOffset;
#endif
// TODO: How to allow overriden velocity vector from GetSurfaceAndBuiltinData ?
float2 velocity = CalculateVelocity(inputPass.positionCS, inputPass.previousPositionCS);
EncodeVelocity(builtinData.velocity, outBuffer);
EncodeVelocity(velocity, outBuffer);

32
Assets/ScriptableRenderLoop/HDRenderPipeline/ShaderVariables.hlsl


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

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

{
return normalize(_WorldSpaceCameraPos.xyz - positionWS);
float3 V = _WorldSpaceCameraPos.xyz - positionWS;
// Uncomment this once the compiler bug is fixed.
// if (unity_OrthoParams.w == 1.0)
// {
// float4x4 M = GetWorldToViewMatrix();
// V = M[1].xyz;
// }
return normalize(V);
}
float3 TransformTangentToWorld(float3 dirTS, float3 tangentToWorld[3])

return normalize(mul(float3x3(tangentToWorld[0].xyz, tangentToWorld[1].xyz, tangentToWorld[2].xyz), dirWS));
}
float3 TransformTangentToObject(float3 dirTS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
// worldToTangent is orthonormal so inverse <==> transpose
float3x3 mWorldToTangent = float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz);
float3 normalWS = mul(dirTS, mWorldToTangent);
return normalize(mul((float3x3)unity_WorldToObject, normalWS));
}
// Assume TBN is orthonormal.
float3 TransformObjectToTangent(float3 dirOS, float3 worldToTangent[3])
{
// TODO check: do we need to normalize ?
return normalize(mul(float3x3(worldToTangent[0].xyz, worldToTangent[1].xyz, worldToTangent[2].xyz), mul((float3x3)unity_ObjectToWorld, dirOS)));
}
#endif // UNITY_SHADER_VARIABLES_INCLUDED

4
Assets/ScriptableRenderLoop/HDRenderPipeline/Shadow/FixedSizePCF/FixedSizePCF.cs


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class ShadowFilteringFixedSizePCF
{

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Shadow/Shadow.hlsl


// - Could be return by GetShadowTextureCoordinate() and pass to GetPunctualShadowAttenuation(). But in this case, who control the atlas application ?
// TODO:
// Caution: formula doesn't work as we are texture atlas...
// if (max3(abs(NDC.x), abs(NDC.y), 1.0f - texCoordXYZ.z) <= 1.0f) return 1.0;
// if (max3(abs(NDC.x), abs(NDC.y), 1.0 - texCoordXYZ.z) <= 1.0) return 1.0;

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/Editor/HDRISkyEditor.cs


using UnityEngine;
using UnityEditor;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[CanEditMultipleObjects]
[CustomEditor(typeof(HDRISkyParameters))]

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/HDRISkyParameters.cs


using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[DisallowMultipleComponent]
public class HDRISkyParameters

20
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/HDRISkyRenderer.cs


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class HDRISkyRenderer
: SkyRenderer<HDRISkyParameters>

return GetParameters(skyParameters).skyHDRI != null;
}
override public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters)
public override void SetRenderTargets(BuiltinSkyParameters builtinParams)
{
if (builtinParams.depthBuffer == BuiltinSkyParameters.nullRT)
{
Utilities.SetRenderTarget(builtinParams.renderContext, builtinParams.colorBuffer);
}
else
{
Utilities.SetRenderTarget(builtinParams.renderContext, builtinParams.colorBuffer, builtinParams.depthBuffer);
}
}
override public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters, bool renderForCubemap)
{
HDRISkyParameters hdriSkyParams = GetParameters(skyParameters);

var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(builtinParams.skyMesh, Matrix4x4.identity, m_SkyHDRIMaterial);
cmd.DrawMesh(builtinParams.skyMesh, Matrix4x4.identity, m_SkyHDRIMaterial, 0, renderForCubemap ? 0 : 1);
builtinParams.renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}

113
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/HDRISky/Resources/SkyHDRI.shader


Shader "Hidden/HDRenderPipeline/Sky/SkyHDRI"
{
SubShader
HLSLINCLUDE
#pragma vertex Vert
#pragma fragment Frag
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#include "Color.hlsl"
#include "Common.hlsl"
#include "CommonLighting.hlsl"
TEXTURECUBE(_Cubemap);
SAMPLERCUBE(sampler_Cubemap);
float4 _SkyParam; // x exposure, y multiplier, z rotation
struct Attributes
Pass
{
ZWrite Off
ZTest LEqual
Blend One Zero
float3 positionCS : POSITION;
float3 eyeVector : NORMAL;
};
HLSLPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 eyeVector : TEXCOORD0;
};
#pragma vertex Vert
#pragma fragment Frag
Varyings Vert(Attributes input)
{
// TODO: implement SV_vertexID full screen quad
Varyings output;
output.positionCS = float4(input.positionCS.xy, UNITY_RAW_FAR_CLIP_VALUE, 1.0);
output.eyeVector = input.eyeVector;
#include "Color.hlsl"
#include "Common.hlsl"
#include "CommonLighting.hlsl"
return output;
}
TEXTURECUBE(_Cubemap);
SAMPLERCUBE(sampler_Cubemap);
float4 Frag(Varyings input) : SV_Target
{
float3 dir = normalize(input.eyeVector);
float4 _SkyParam; // x exposure, y multiplier, z rotation
struct Attributes
{
float3 positionCS : POSITION;
float3 eyeVector : NORMAL;
};
// Rotate direction
float phi = DegToRad(_SkyParam.z);
float cosPhi, sinPhi;
sincos(phi, sinPhi, cosPhi);
float3 rotDirX = float3(cosPhi, 0, -sinPhi);
float3 rotDirY = float3(sinPhi, 0, cosPhi);
dir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 eyeVector : TEXCOORD0;
};
float3 skyColor = ClampToFloat16Max(SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, dir, 0).rgb * exp2(_SkyParam.x) * _SkyParam.y);
return float4(skyColor, 1.0);
}
Varyings Vert(Attributes input)
{
// TODO: implement SV_vertexID full screen quad
Varyings output;
output.positionCS = float4(input.positionCS.xy, UNITY_RAW_FAR_CLIP_VALUE, 1.0);
output.eyeVector = input.eyeVector;
ENDHLSL
return output;
}
SubShader
{
Pass
{
ZWrite Off
ZTest Always
Blend One Zero
float4 Frag(Varyings input) : SV_Target
{
float3 dir = normalize(input.eyeVector);
HLSLPROGRAM
ENDHLSL
// Rotate direction
float phi = DegToRad(_SkyParam.z);
float cosPhi, sinPhi;
sincos(phi, sinPhi, cosPhi);
float3 rotDirX = float3(cosPhi, 0, -sinPhi);
float3 rotDirY = float3(sinPhi, 0, cosPhi);
dir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
}
float3 skyColor = ClampToFloat16Max(SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, dir, 0).rgb * exp2(_SkyParam.x) * _SkyParam.y);
return float4(skyColor, 1.0);
}
Pass
{
ZWrite Off
ZTest LEqual
Blend One Zero
HLSLPROGRAM
ENDHLSL
}

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Editor/ProceduralSkyEditor.cs


using UnityEngine;
using UnityEditor;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
//[CanEditMultipleObjects]
//[CustomEditor(typeof(ProceduralSkyParameters))]

32
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyParameters.cs


using System.Collections.Generic;
using UnityEngine;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[ExecuteInEditMode]
[DisallowMultipleComponent]

public Gradient worldMieColorRamp = null;
public float worldMieDensity = 15f;
public float worldMieExtinctionFactor = 0f;
public float worldMieNearScatterPush = 0f;
public float worldNearScatterPush = 0f;
public float worldNormalDistance = 1000f;
public float worldRayleighColorIntensity = 1f;
public Gradient worldRayleighColorRamp = null;

public float worldRayleighNearScatterPush = 0f;
public float heightNearScatterPush = 0f;
public float heightMieNearScatterPush = 0f;
public float heightRayleighNearScatterPush = 0f;
public float heightSeaLevel = 0f;
/*

public void OnValidate()
{
worldMieDensity = Mathf.Clamp(worldMieDensity, 0f, 1000f);
worldMiePhaseAnisotropy = Mathf.Clamp01(worldMiePhaseAnisotropy);
worldNearScatterPush = Mathf.Clamp(worldNearScatterPush, -200f, 300f);
worldNormalDistance = Mathf.Clamp(worldNormalDistance, 1f, 10000f);
worldRayleighDensity = Mathf.Clamp(worldRayleighDensity, 0, 1000f);
worldRayleighIndirectScatter = Mathf.Clamp(worldRayleighIndirectScatter, 0f, 1f);
worldMieDensity = Mathf.Clamp(worldMieDensity, 0f, 1000f);
worldMiePhaseAnisotropy = Mathf.Clamp01(worldMiePhaseAnisotropy);
worldMieNearScatterPush = Mathf.Clamp(worldMieNearScatterPush, -200f, 300f);
worldNormalDistance = Mathf.Clamp(worldNormalDistance, 1f, 10000f);
worldRayleighDensity = Mathf.Clamp(worldRayleighDensity, 0, 1000f);
worldRayleighIndirectScatter = Mathf.Clamp(worldRayleighIndirectScatter, 0f, 1f);
worldRayleighNearScatterPush = Mathf.Clamp(worldRayleighNearScatterPush, -200f, 300f);
heightMieDensity = Mathf.Clamp(heightMieDensity, 0, 1000f);
heightNearScatterPush = Mathf.Clamp(heightNearScatterPush, -200f, 300f);
heightNormalDistance = Mathf.Clamp(heightNormalDistance, 1f, 10000f);
heightRayleighDensity = Mathf.Clamp(heightRayleighDensity, 0, 1000f);
heightMieDensity = Mathf.Clamp(heightMieDensity, 0, 1000f);
heightMieNearScatterPush = Mathf.Clamp(heightMieNearScatterPush, -200f, 300f);
heightNormalDistance = Mathf.Clamp(heightNormalDistance, 1f, 10000f);
heightRayleighDensity = Mathf.Clamp(heightRayleighDensity, 0, 1000f);
heightRayleighNearScatterPush = Mathf.Clamp(heightRayleighNearScatterPush, -200f, 300f);
worldScaleExponent = Mathf.Clamp(worldScaleExponent, 1f, 2f);
worldScaleExponent = Mathf.Clamp(worldScaleExponent, 1f, 2f);
/*
occlusionBias = Mathf.Clamp01(occlusionBias);

77
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/ProceduralSkyRenderer.cs


using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
public class ProceduralSkyRenderer
: SkyRenderer<ProceduralSkyParameters>

allParams.worldRayleighColorRamp != null;
}
void SetKeywords(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param)
public override void SetRenderTargets(BuiltinSkyParameters builtinParams)
{
// We do not bind the depth buffer as a depth-stencil target since it is
// bound as a color texture which is then sampled from within the shader.
Utilities.SetRenderTarget(builtinParams.renderContext, builtinParams.colorBuffer);
}
void SetKeywords(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param, bool renderForCubemap)
{
// Ensure that all preprocessor symbols are initially undefined.
m_ProceduralSkyMaterial.DisableKeyword("ATMOSPHERICS");

*/
// Expected to be valid for the sky pass, and invalid for the cube map generation pass.
if (builtinParams.depthBuffer != BuiltinSkyParameters.invalidRTI)
if (!renderForCubemap)
{
m_ProceduralSkyMaterial.EnableKeyword("PERFORM_SKY_OCCLUSION_TEST");
}

}
}
void SetUniforms(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param)
void SetUniforms(BuiltinSkyParameters builtinParams, ProceduralSkyParameters param, bool renderForCubemap, ref MaterialPropertyBlock properties)
m_ProceduralSkyMaterial.SetTexture("_Cubemap", param.skyHDRI);
m_ProceduralSkyMaterial.SetVector("_SkyParam", new Vector4(param.exposure, param.multiplier, param.rotation, 0.0f));
m_ProceduralSkyMaterial.SetMatrix("_ViewProjMatrix", builtinParams.viewProjMatrix);
m_ProceduralSkyMaterial.SetMatrix("_InvViewProjMatrix", builtinParams.invViewProjMatrix);
m_ProceduralSkyMaterial.SetVector("_CameraPosWS", builtinParams.cameraPosWS);
m_ProceduralSkyMaterial.SetVector("_ScreenSize", builtinParams.screenSize);
properties.SetTexture("_Cubemap", param.skyHDRI);
properties.SetVector("_SkyParam", new Vector4(param.exposure, param.multiplier, param.rotation, 0.0f));
properties.SetMatrix("_InvViewProjMatrix", builtinParams.invViewProjMatrix);
properties.SetVector("_CameraPosWS", builtinParams.cameraPosWS);
properties.SetVector("_ScreenSize", builtinParams.screenSize);
m_ProceduralSkyMaterial.SetInt("_AtmosphericsDebugMode", (int)param.debugMode);

var pixelRect = new Rect(0f, 0f, builtinParams.screenSize.x, builtinParams.screenSize.y);
var scale = 1.0f; //(float)(int)occlusionDownscale;
var depthTextureScaledTexelSize = new Vector4(scale / pixelRect.width,
scale / pixelRect.height,
-scale / pixelRect.width,
-scale / pixelRect.height);
properties.SetVector("_DepthTextureScaledTexelSize", depthTextureScaledTexelSize);
/*
m_ProceduralSkyMaterial.SetFloat("_ShadowBias", useOcclusion ? occlusionBias : 1f);
m_ProceduralSkyMaterial.SetFloat("_ShadowBiasIndirect", useOcclusion ? occlusionBiasIndirect : 1f);

m_ProceduralSkyMaterial.SetVector("_OcclusionTexture_TexelSize", ???);
*/
var pixelRect = new Rect(0f, 0f, builtinParams.screenSize.x, builtinParams.screenSize.y);
var scale = 1.0f; //(float)(int)occlusionDownscale;
var depthTextureScaledTexelSize = new Vector4(scale / pixelRect.width,
scale / pixelRect.height,
-scale / pixelRect.width,
-scale / pixelRect.height);
m_ProceduralSkyMaterial.SetVector("_DepthTextureScaledTexelSize", depthTextureScaledTexelSize);
m_ProceduralSkyMaterial.SetFloat("_WorldNearScatterPush", -Mathf.Pow(Mathf.Abs(param.worldNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.worldNearScatterPush));
m_ProceduralSkyMaterial.SetFloat("_WorldMieNearScatterPush", -Mathf.Pow(Mathf.Abs(param.worldMieNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.worldMieNearScatterPush));
m_ProceduralSkyMaterial.SetFloat("_WorldRayleighNearScatterPush", -Mathf.Pow(Mathf.Abs(param.worldRayleighNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.worldRayleighNearScatterPush));
m_ProceduralSkyMaterial.SetFloat("_WorldRayleighDensity", -param.worldRayleighDensity / 100000f);
m_ProceduralSkyMaterial.SetFloat("_WorldMieDensity", -param.worldMieDensity / 100000f);

m_ProceduralSkyMaterial.SetVector("_MieColorP20", (Vector4)mieColorP20 * param.worldMieColorIntensity);
m_ProceduralSkyMaterial.SetFloat("_HeightNormalDistanceRcp", 1f / param.heightNormalDistance);
m_ProceduralSkyMaterial.SetFloat("_HeightNearScatterPush", -Mathf.Pow(Mathf.Abs(param.heightNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.heightNearScatterPush));
m_ProceduralSkyMaterial.SetFloat("_HeightRayleighDensity", -param.heightRayleighDensity / 100000f);
m_ProceduralSkyMaterial.SetFloat("_HeightMieDensity", -param.heightMieDensity / 100000f);
m_ProceduralSkyMaterial.SetFloat("_HeightMieNearScatterPush", -Mathf.Pow(Mathf.Abs(param.heightMieNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.heightMieNearScatterPush));
m_ProceduralSkyMaterial.SetFloat("_HeightRayleighNearScatterPush", -Mathf.Pow(Mathf.Abs(param.heightRayleighNearScatterPush), param.worldScaleExponent) * Mathf.Sign(param.heightRayleighNearScatterPush));
// m_ProceduralSkyMaterial.SetFloat("_HeightRayleighDensity", -param.heightRayleighDensity / 100000f);
// m_ProceduralSkyMaterial.SetFloat("_HeightMieDensity", -param.heightMieDensity / 100000f);
m_ProceduralSkyMaterial.SetFloat("_HeightSeaLevel", param.heightSeaLevel);
m_ProceduralSkyMaterial.SetVector("_HeightPlaneShift", param.heightPlaneShift);
m_ProceduralSkyMaterial.SetFloat("_HeightDistanceRcp", 1f / param.heightDistance);

m_ProceduralSkyMaterial.SetFloat("_MiePhaseAnisotropy", param.worldMiePhaseAnisotropy);
m_ProceduralSkyMaterial.SetFloat("_MieExtinctionFactor", param.worldMieExtinctionFactor);
// Since we use the material for rendering the sky both into the cubemap, and
// during the fullscreen pass, setting the 'PERFORM_SKY_OCCLUSION_TEST' keyword has no effect.
properties.SetFloat("_DisableSkyOcclusionTest", renderForCubemap ? 1.0f : 0.0f);
// We flip the screens-space Y axis in case we follow the D3D convention.
properties.SetFloat("_FlipY", renderForCubemap ? 1.0f : 0.0f);
// We do not render the height fog into the sky IBL cubemap.
properties.SetFloat("_HeightRayleighDensity", renderForCubemap ? -0.0f : -param.heightRayleighDensity / 100000f);
properties.SetFloat("_HeightMieDensity", renderForCubemap ? -0.0f : -param.heightMieDensity / 100000f);
override public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters)
override public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters, bool renderForCubemap)
MaterialPropertyBlock properties = new MaterialPropertyBlock();
SetKeywords(builtinParams, proceduralSkyParams);
SetKeywords(builtinParams, proceduralSkyParams, renderForCubemap);
SetUniforms(builtinParams, proceduralSkyParams);
SetUniforms(builtinParams, proceduralSkyParams, renderForCubemap, ref properties);
if (builtinParams.depthBuffer != BuiltinSkyParameters.invalidRTI)
if (!renderForCubemap)
cmd.DrawMesh(builtinParams.skyMesh, Matrix4x4.identity, m_ProceduralSkyMaterial);
cmd.DrawMesh(builtinParams.skyMesh, Matrix4x4.identity, m_ProceduralSkyMaterial, 0, 0, properties);
builtinParams.renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}

35
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Resources/AtmosphericScattering.hlsl


uniform float _WorldScaleExponent;
uniform float _WorldNormalDistanceRcp;
uniform float _WorldNearScatterPush;
uniform float _WorldRayleighNearScatterPush;
uniform float _WorldMieNearScatterPush;
uniform float _WorldRayleighDensity;
uniform float _WorldMieDensity;

uniform float3 _MieColorP45;
uniform float _HeightNormalDistanceRcp;
uniform float _HeightNearScatterPush;
uniform float _HeightMieNearScatterPush;
uniform float _HeightRayleighNearScatterPush;
uniform float _HeightRayleighDensity;
uniform float _HeightMieDensity;
uniform float _HeightSeaLevel;

if(angleY >= 0.f) mieColor = lerp(_MieColorO00, _MieColorP20, saturate(angleY / angle20));
else mieColor = lerp(_MieColorM20, _MieColorO00, saturate((angleY + angle20) / angle20));
const float pushedDistance = max(0.f, worldVecLen + _WorldNearScatterPush);
const float pushedDensity = /*HeightDensity **/ pushedDistance /** exp(-scaledWorldPos.y / 8000.f)*/;
const float rayleighScatter = (1.f - exp(_WorldRayleighDensity * pushedDensity)) * rayleighPh;
const float pushedMieDistance = max(0.f, worldVecLen + _WorldMieNearScatterPush);
const float pushedRayleighDistance = max(0.f, worldVecLen + _WorldRayleighNearScatterPush);
const float pushedMieDensity = /*HeightDensity **/ pushedMieDistance /** exp(-scaledWorldPos.y / 8000.f)*/;
const float pushedRayleighDensity = /*HeightDensity **/ pushedRayleighDistance /** exp(-scaledWorldPos.y / 8000.f)*/;
const float rayleighScatter = (1.f - exp(_WorldRayleighDensity * pushedRayleighDensity)) * rayleighPh;
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedDensity));
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedMieDensity));
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedDensity)) * miePh;
const float mieScatter = (1.f - exp(_WorldMieDensity * pushedMieDensity)) * miePh;
const float pushedHeightDistance = max(0.f, worldVecLen + _HeightNearScatterPush);
const float heightScatter = (1.f - exp(_HeightRayleighDensity * pushedHeightDistance)) * HeightDensity;
const float pushedRayleighHeightDistance = max(0.f, worldVecLen + _HeightRayleighNearScatterPush);
const float pushedMieHeightDistance = max(0.f, worldVecLen + _HeightMieNearScatterPush);
const float heightRayleighScatter = (1.f - exp(_HeightRayleighDensity * pushedRayleighHeightDistance)) * HeightDensity;
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedHeightDistance)) * HeightDensity;
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedMieHeightDistance)) * HeightDensity;
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedHeightDistance)) * HeightDensity * miePh;
const float heightMieScatter = (1.f - exp(_HeightMieDensity * pushedMieHeightDistance)) * HeightDensity * miePh;
rayleighColor = lerp(Luminance(rayleighColor).rrr, rayleighColor, saturate(pushedDistance * _WorldNormalDistanceRcp));
float3 heightRayleighColor = lerp(Luminance(_HeightRayleighColor.xyz).rrr, _HeightRayleighColor.xyz, saturate(pushedHeightDistance * _HeightNormalDistanceRcp));
rayleighColor = lerp(Luminance(rayleighColor).rrr, rayleighColor, saturate(pushedRayleighDistance * _WorldNormalDistanceRcp));
float3 heightRayleighColor = lerp(Luminance(_HeightRayleighColor.xyz).rrr, _HeightRayleighColor.xyz, saturate(pushedRayleighHeightDistance * _HeightNormalDistanceRcp));
coords3.rgb = saturate(heightScatter) * heightRayleighColor;
coords3.a = heightScatter;
coords3.rgb = saturate(heightRayleighScatter) * heightRayleighColor;
coords3.a = heightRayleighScatter;
coords2.rgb = mieScatter * mieColor + saturate(heightMieScatter) * mieColor;
coords2.a = mieScatter;

40
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/ProceduralSky/Resources/SkyProcedural.shader


Pass
{
ZWrite Off
ZTest LEqual
ZTest Always
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma vertex Vert
#pragma fragment Frag

float4 _CameraPosWS;
float4x4 _InvViewProjMatrix;
float4x4 _ViewProjMatrix;
float _DisableSkyOcclusionTest;
float _FlipY;
#define IS_RENDERING_SKY
#include "AtmosphericScattering.hlsl"

sincos(phi, sinPhi, cosPhi);
float3 rotDirX = float3(cosPhi, 0, -sinPhi);
float3 rotDirY = float3(sinPhi, 0, cosPhi);
dir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
float3 rotatedDir = float3(dot(rotDirX, dir), dir.y, dot(rotDirY, dir));
// input.positionCS is SV_Position
// input.positionCS is SV_Position
// If the sky box is too far away (depth set to 0), the resulting look is too foggy.
const float skyDepth = 0.002;
// An arbitrary value attempting to match the size of the sky mesh from the Blacksmith demo.
const float skyDepth = 0.00025;
float rawDepth = max(skyDepth, LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r);
float skyTexWeight = (rawDepth > skyDepth) ? 0.0 : 1.0;
float depthRaw = max(skyDepth, LOAD_TEXTURE2D(_CameraDepthTexture, posInput.unPositionSS).r);
float skyTexWeight = (depthRaw > skyDepth) ? 0.0 : 1.0;
float rawDepth = skyDepth;
float depthRaw = skyDepth;
UpdatePositionInput(rawDepth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
if (_DisableSkyOcclusionTest != 0.0)
{
depthRaw = skyDepth;
skyTexWeight = 1.0;
}
// Since we only need the world space position, so we don't pass the view-projection matrix.
UpdatePositionInput(depthRaw, _InvViewProjMatrix, k_identity4x4, posInput, _FlipY != 0);
float4 c1, c2, c3;
VolundTransferScatter(posInput.positionWS, c1, c2, c3);

#endif
float3 skyColor = float3(0.0, 0.0, 0.0);
float opacity = extinction;
// Opacity should be proportional to extinction, but this produces wrong results.
// It appears what the algorithm computes is not actually extinction.
float opacity = (1.0 - extinction);
skyColor = SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, dir, 0).rgb;
skyColor = SAMPLE_TEXTURECUBE_LOD(_Cubemap, sampler_Cubemap, rotatedDir, 0).rgb;
skyColor *= exp2(_SkyParam.x) * _SkyParam.y;
opacity = 1.0; // Fully overwrite unoccluded scene regions.
}

30
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/Resources/GGXConvolve.shader


Pass
{
ZWrite Off
ZTest LEqual
ZTest Always
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: unitl we go futher in dev
#pragma multi_compile _ USE_MIS

TEXTURECUBE(_MainTex);
SAMPLERCUBE(sampler_MainTex);
TEXTURE2D(_GgxIblSamples);
#ifdef USE_MIS
TEXTURE2D(_MarginalRowDensities);

float _Level;
float _MaxLevel;
float _LastLevel;
float _InvOmegaP;
half4 Frag(Varyings input) : SV_Target

// Remove view-dependency from GGX, effectively making the BSDF isotropic.
float3 V = N;
float perceptualRoughness = mipmapLevelToPerceptualRoughness(_Level);
float perceptualRoughness = MipmapLevelToPerceptualRoughness(_Level);
uint sampleCount = GetIBLRuntimeFilterSampleCount(_Level);
#ifdef USE_MIS
float4 val = IntegrateLD_MIS(TEXTURECUBE_PARAM(_MainTex, sampler_MainTex),

1024,
false);
#else
uint sampleCount = 0;
switch (_Level)
{
case 1: sampleCount = 21; break;
case 2: sampleCount = 34; break;
case 3: sampleCount = 55; break;
case 4: sampleCount = 89; break;
case 5: sampleCount = 89; break;
case 6: sampleCount = 89; break; // UNITY_SPECCUBE_LOD_STEPS
}
_GgxIblSamples,
_MaxLevel,
_Level - 1,
_LastLevel,
true,
true);
#endif

134
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[Serializable]
public enum SkyResolution

public class BuiltinSkyParameters
{
public Matrix4x4 viewProjMatrix;
public Matrix4x4 invViewProjMatrix;
public Vector3 cameraPosWS;
public Vector4 screenSize;

public RenderTargetIdentifier colorBuffer;
public RenderTargetIdentifier depthBuffer;
public static RenderTargetIdentifier invalidRTI = -1;
public static RenderTargetIdentifier nullRT = -1;
}
public class SkyManager

RenderTexture m_SkyboxConditionalCdfRT = null;
Material m_StandardSkyboxMaterial = null; // This is the Unity standard skybox material. Used to pass the correct cubemap to Enlighten.
Material m_GGXConvolveMaterial = null; // Apply GGX convolution to cubemap
ComputeShader m_BuildProbabilityTablesCS = null;
int m_ConditionalDensitiesKernel = -1;
int m_MarginalRowDensitiesKernel = -1;
IBLFilterGGX m_iblFilterGgx = null;
Vector4 m_CubemapScreenSize;
Matrix4x4[] m_faceCameraViewProjectionMatrix = new Matrix4x4[6];

if (m_SkyboxCubemapRT == null)
{
m_SkyboxCubemapRT = new RenderTexture(resolution, resolution, 1, RenderTextureFormat.ARGBHalf);
m_SkyboxCubemapRT = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_SkyboxCubemapRT.dimension = TextureDimension.Cube;
m_SkyboxCubemapRT.useMipMap = true;
m_SkyboxCubemapRT.autoGenerateMips = true; // Generate regular mipmap for filtered importance sampling

m_SkyboxGGXCubemapRT = new RenderTexture(resolution, resolution, 1, RenderTextureFormat.ARGBHalf);
m_SkyboxGGXCubemapRT = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
m_SkyboxGGXCubemapRT.dimension = TextureDimension.Cube;
m_SkyboxGGXCubemapRT.useMipMap = true;
m_SkyboxGGXCubemapRT.autoGenerateMips = false;

int height = (int)LightSamplingParameters.TextureHeight;
// + 1 because we store the value of the integral of the cubemap at the end of the texture.
m_SkyboxMarginalRowCdfRT = new RenderTexture(height + 1, 1, 1, RenderTextureFormat.RFloat);
m_SkyboxMarginalRowCdfRT.dimension = TextureDimension.Tex2D;
m_SkyboxMarginalRowCdfRT = new RenderTexture(height + 1, 1, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
m_SkyboxMarginalRowCdfRT.useMipMap = false;
m_SkyboxMarginalRowCdfRT.autoGenerateMips = false;
m_SkyboxMarginalRowCdfRT.enableRandomWrite = true;

// TODO: switch the format to R16 (once it's available) to save some bandwidth.
m_SkyboxConditionalCdfRT = new RenderTexture(width, height, 1, RenderTextureFormat.RFloat);
m_SkyboxConditionalCdfRT.dimension = TextureDimension.Tex2D;
m_SkyboxConditionalCdfRT = new RenderTexture(width, height, 0, RenderTextureFormat.RFloat, RenderTextureReadWrite.Linear);
m_SkyboxConditionalCdfRT.useMipMap = false;
m_SkyboxConditionalCdfRT.autoGenerateMips = false;
m_SkyboxConditionalCdfRT.enableRandomWrite = true;

m_CubemapScreenSize = new Vector4((float)resolution, (float)resolution, 1.0f / (float)resolution, 1.0f / (float)resolution);
}
void RebuildSkyMeshes()
void RebuildSkyMeshes(float nearPlane, float farPlane)
Matrix4x4 cubeProj = Matrix4x4.Perspective(90.0f, 1.0f, 0.1f, 1.0f);
Matrix4x4 cubeProj = Matrix4x4.Perspective(90.0f, 1.0f, nearPlane, farPlane);
Vector3[] lookAtList = {
new Vector3(1.0f, 0.0f, 0.0f),

m_faceCameraViewProjectionMatrix[i] = Utilities.GetViewProjectionMatrix(lookAt, cubeProj);
m_faceCameraInvViewProjectionMatrix[i] = m_faceCameraViewProjectionMatrix[i].inverse;
// When rendering into a texture the render will be flip (due to legacy unity openGL behavior), so we need to flip UV here...
m_CubemapFaceMesh[i] = BuildSkyMesh(Vector3.zero, m_faceCameraInvViewProjectionMatrix[i], true);
}
}

Shader.SetGlobalTexture("_SkyTexture", m_SkyboxGGXCubemapRT);
}
public void Resize()
public void Resize(float nearPlane, float farPlane)
RebuildSkyMeshes();
RebuildSkyMeshes(nearPlane, farPlane);
}
public void Build()

// Create unititialized. Lazy initialization is performed later.
m_iblFilterGgx = new IBLFilterGGX();
m_GGXConvolveMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/GGXConvolve");
m_BuildProbabilityTablesCS = Resources.Load<ComputeShader>("BuildProbabilityTables");
m_ConditionalDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeConditionalDensities");
m_MarginalRowDensitiesKernel = m_BuildProbabilityTablesCS.FindKernel("ComputeMarginalRowDensities");
m_CurrentUpdateTime = 0.0f;
}

Utilities.Destroy(m_StandardSkyboxMaterial);
Utilities.Destroy(m_GGXConvolveMaterial);
Utilities.Destroy(m_SkyboxCubemapRT);
Utilities.Destroy(m_SkyboxGGXCubemapRT);
Utilities.Destroy(m_SkyboxMarginalRowCdfRT);

{
for (int i = 0; i < 6; ++i)
{
Utilities.SetRenderTarget(builtinParams.renderContext, target, ClearFlag.ClearNone, 0, (CubemapFace)i);
builtinParams.viewProjMatrix = m_faceCameraViewProjectionMatrix[i];
builtinParams.depthBuffer = BuiltinSkyParameters.invalidRTI;
m_Renderer.RenderSky(builtinParams, skyParameters);
builtinParams.depthBuffer = BuiltinSkyParameters.nullRT;
Utilities.SetRenderTarget(builtinParams.renderContext, target, ClearFlag.ClearNone, 0, (CubemapFace)i);
m_Renderer.RenderSky(builtinParams, skyParameters, true);
private void BuildProbabilityTables(ScriptableRenderContext renderContext)
{
// Bind the input cubemap.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "envMap", m_SkyboxCubemapRT);
// Bind the outputs.
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "marginalRowDensities", m_SkyboxMarginalRowCdfRT);
m_BuildProbabilityTablesCS.SetTexture(m_ConditionalDensitiesKernel, "conditionalDensities", m_SkyboxConditionalCdfRT);
m_BuildProbabilityTablesCS.SetTexture(m_MarginalRowDensitiesKernel, "marginalRowDensities", m_SkyboxMarginalRowCdfRT);
var cmd = new CommandBuffer() { name = "" };
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_ConditionalDensitiesKernel, (int)LightSamplingParameters.TextureHeight, 1, 1);
cmd.DispatchCompute(m_BuildProbabilityTablesCS, m_MarginalRowDensitiesKernel, 1, 1, 1);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
private void RenderCubemapGGXConvolution(ScriptableRenderContext renderContext, BuiltinSkyParameters builtinParams, SkyParameters skyParams, Texture input, RenderTexture target)
{
using (new Utilities.ProfilingSample("Sky Pass: GGX Convolution", renderContext))

return;
}
if (m_useMIS)
if (!m_iblFilterGgx.IsInitialized())
BuildProbabilityTables(renderContext);
m_iblFilterGgx.Initialize(renderContext);
// Copy the first mip.
// WARNING:
// Since we can't instanciate the parameters anymore (we don't know the final type here)
// we can't make sure that exposure/multiplier etc are at neutral values
// This will be solved with proper CopyTexture
// TEMP code until CopyTexture is implemented for command buffer
// All parameters are neutral because exposure/multiplier have already been applied in the first copy.
//SkyParameters skyParams = new SkyParameters();
//skyParams.exposure = 0.0f;
//skyParams.multiplier = 1.0f;
//skyParams.rotation = 0.0f;
//skyParams.skyHDRI = input;
RenderSkyToCubemap(builtinParams, skyParams, target);
// End temp
//for (int f = 0; f < 6; f++)
// Graphics.CopyTexture(input, f, 0, target, f, 0);
// Copy the first mip
var cmd = new CommandBuffer { name = "" };
for (int f = 0; f < 6; f++)
{
cmd.CopyTexture(input, f, 0, target, f, 0);
}
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
m_GGXConvolveMaterial.EnableKeyword("USE_MIS");
m_GGXConvolveMaterial.SetTexture("_MarginalRowDensities", m_SkyboxMarginalRowCdfRT);
m_GGXConvolveMaterial.SetTexture("_ConditionalDensities", m_SkyboxConditionalCdfRT);
m_iblFilterGgx.FilterCubemapMIS(renderContext, input, target, mipCount, m_SkyboxConditionalCdfRT, m_SkyboxMarginalRowCdfRT, m_CubemapFaceMesh);
m_GGXConvolveMaterial.DisableKeyword("USE_MIS");
m_iblFilterGgx.FilterCubemap(renderContext, input, target, mipCount, m_CubemapFaceMesh);
// Do the convolution on remaining mipmaps
float invOmegaP = (6.0f * input.width * input.width) / (4.0f * Mathf.PI); // Solid angle associated to a pixel of the cubemap;
m_GGXConvolveMaterial.SetTexture("_MainTex", input);
m_GGXConvolveMaterial.SetFloat("_MaxLevel", mipCount - 1);
m_GGXConvolveMaterial.SetFloat("_InvOmegaP", invOmegaP);
for (int mip = 1; mip < ((int)EnvConstants.SpecCubeLodStep + 1); ++mip)
{
MaterialPropertyBlock propertyBlock = new MaterialPropertyBlock();
propertyBlock.SetFloat("_Level", mip);
for (int face = 0; face < 6; ++face)
{
Utilities.SetRenderTarget(renderContext, target, ClearFlag.ClearNone, mip, (CubemapFace)face);
var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(m_CubemapFaceMesh[face], Matrix4x4.identity, m_GGXConvolveMaterial, 0, 0, propertyBlock);
renderContext.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
}
}

{
// Render sky into a cubemap - doesn't happen every frame, can be controlled
RenderSkyToCubemap(m_BuiltinParameters, skyParameters, m_SkyboxCubemapRT);
// Note that m_SkyboxCubemapRT is created with auto-generate mipmap, it mean that here we have also our mipmap correctly box filtered for importance sampling.
// Convolve downsampled cubemap
RenderCubemapGGXConvolution(renderContext, m_BuiltinParameters, skyParameters, m_SkyboxCubemapRT, m_SkyboxGGXCubemapRT);

m_BuiltinParameters.renderContext = renderContext;
m_BuiltinParameters.sunLight = sunLight;
m_BuiltinParameters.invViewProjMatrix = camera.invViewProjectionMatrix;
m_BuiltinParameters.viewProjMatrix = camera.viewProjectionMatrix;
m_BuiltinParameters.cameraPosWS = camera.camera.transform.position;
m_BuiltinParameters.screenSize = camera.screenSize;
m_BuiltinParameters.skyMesh = BuildSkyMesh(camera.camera.GetComponent<Transform>().position, m_BuiltinParameters.invViewProjMatrix, false);

Utilities.SetRenderTarget(renderContext, colorBuffer, depthBuffer);
m_Renderer.RenderSky(m_BuiltinParameters, skyParameters);
m_Renderer.SetRenderTargets(m_BuiltinParameters);
m_Renderer.RenderSky(m_BuiltinParameters, skyParameters, false);
}
}
}

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyManager.cs.hlsl


#ifndef SKYMANAGER_CS_HLSL
#define SKYMANAGER_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.LightSamplingParameters: static fields
// UnityEngine.Experimental.Rendering.HDPipeline.LightSamplingParameters: static fields
//
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_HEIGHT (256)
#define LIGHTSAMPLINGPARAMETERS_TEXTURE_WIDTH (512)

2
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyParameters.cs


using System.Reflection;
using System.Linq;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[ExecuteInEditMode]
public class SkyParameters : MonoBehaviour

8
Assets/ScriptableRenderLoop/HDRenderPipeline/Sky/SkyRenderer.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
abstract public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters);
abstract public void SetRenderTargets(BuiltinSkyParameters builtinParams);
// renderForCubemap: When rendering into a cube map, no depth buffer is available so user has to make sure not to use depth testing or the depth texture.
abstract public void RenderSky(BuiltinSkyParameters builtinParams, SkyParameters skyParameters, bool renderForCubemap);
abstract public bool IsSkyValid(SkyParameters skyParameters);
virtual public bool IsParameterValid(SkyParameters skyParameters) { return false; }

21
Assets/ScriptableRenderLoop/HDRenderPipeline/Utilities.cs


using System;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Experimental.Rendering.HDPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.HDPipeline
{
[Flags]
public enum ClearFlag

public class Utilities
{
public const RendererConfiguration kRendererConfigurationBakedLighting = RendererConfiguration.PerObjectLightProbe | RendererConfiguration.PerObjectReflectionProbes | RendererConfiguration.PerObjectLightmaps | RendererConfiguration.PerObjectLightProbeProxyVolume;
public const RendererConfiguration kRendererConfigurationBakedLighting = RendererConfiguration.PerObjectLightProbe | RendererConfiguration.PerObjectLightmaps | RendererConfiguration.PerObjectLightProbeProxyVolume;
public static void SetRenderTarget(ScriptableRenderContext renderContext, RenderTargetIdentifier buffer, ClearFlag clearFlag = ClearFlag.ClearNone, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
public static void SetRenderTarget(ScriptableRenderContext renderContext, RenderTargetIdentifier buffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
if (clearFlag != ClearFlag.ClearNone)
cmd.ClearRenderTarget((clearFlag & ClearFlag.ClearDepth) != 0, (clearFlag & ClearFlag.ClearColor) != 0, clearColor);
public static void SetRenderTarget(ScriptableRenderContext renderContext, RenderTargetIdentifier buffer, ClearFlag clearFlag = ClearFlag.ClearNone, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
{
SetRenderTarget(renderContext, buffer, clearFlag, Color.black, miplevel, cubemapFace);
}
SetRenderTarget(renderContext, colorBuffer, depthBuffer, ClearFlag.ClearNone, new Color(0.0f, 0.0f, 0.0f, 0.0f), miplevel, cubemapFace);
SetRenderTarget(renderContext, colorBuffer, depthBuffer, ClearFlag.ClearNone, Color.black, miplevel, cubemapFace);
SetRenderTarget(renderContext, colorBuffer, depthBuffer, clearFlag, new Color(0.0f, 0.0f, 0.0f, 0.0f), miplevel, cubemapFace);
SetRenderTarget(renderContext, colorBuffer, depthBuffer, clearFlag, Color.black, miplevel, cubemapFace);
}
public static void SetRenderTarget(ScriptableRenderContext renderContext, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)

public static HDRenderPipeline GetHDRenderPipeline()
{
HDRenderPipeline renderContext = UnityEngine.Rendering.GraphicsSettings.renderPipeline as HDRenderPipeline;
HDRenderPipeline renderContext = GraphicsSettings.renderPipelineAsset as HDRenderPipeline;
if (renderContext == null)
{
Debug.LogWarning("SkyParameters component can only be used with HDRenderPipeline custom RenderPipeline.");

4
Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs


using System.Collections.Generic;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering
{
[System.Serializable]
public class ShadowSettings

commandBuffer.Dispose();
// Render
loop.DrawShadows(ref settings);
loop.DrawShadows(settings);
}
}
}

9
Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl


// Do not exist on some platform, in this case we need to have a standard name that call a function that will initialize all parameters to 0
#define ZERO_INITIALIZE(type, name) name = (type)0;
// Texture util abstraction
#define CALCULATE_TEXTURE2D_LOD(textureName, samplerName, coord2) textureName.CalculateLevelOfDetail(samplerName, coord2)
// Texture abstraction
#define TEXTURE2D(textureName) Texture2D textureName

#define SAMPLE_TEXTURE2D(textureName, samplerName, coord2) textureName.Sample(samplerName, coord2)
#define SAMPLE_TEXTURE2D_LOD(textureName, samplerName, coord2, lod) textureName.SampleLevel(samplerName, coord2, lod)
#define SAMPLE_TEXTURE2D_BIAS(textureName, samplerName, coord2, bias) textureName.SampleBias(samplerName, coord2, bias)
#define SAMPLE_TEXTURE2D_GRAD(textureName, samplerName, coord2, ddx, ddy) textureName.SampleGrad(samplerName, coord2, ddx, ddy)
#define SAMPLE_TEXTURE2D_ARRAY_BIAS(textureName, samplerName, coord2, index, bias) textureName.SampleBias(samplerName, float3(coord2, index), bias)
#define SAMPLE_TEXTURECUBE_BIAS(textureName, samplerName, coord3, bias) textureName.SampleBias(samplerName, coord3, bias)
#define SAMPLE_TEXTURECUBE_ARRAY_BIAS(textureName, samplerName, coord3, index, bias) textureName.SampleBias(samplerName, float4(coord3, index), bias)
#define SAMPLE_TEXTURE3D(textureName, samplerName, coord3) textureName.Sample(samplerName, coord3)
#define SAMPLE_TEXTURE2D_SHADOW(textureName, samplerName, coord3) textureName.SampleCmpLevelZero(samplerName, (coord3).xy, (coord3).z)
#define SAMPLE_TEXTURE2D_ARRAY_SHADOW(textureName, samplerName, coord3, index) textureName.SampleCmpLevelZero(samplerName, float3((coord3).xy, index), (coord3).z)

11
Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl


// Clamp to avoid artifacts. This particular constant gives the best results.
cosTheta = Clamp(cosTheta, -0.9999, 0.9999);
float theta = FastACos(cosTheta);
float res = cross(v1, v2).z * theta * rsqrt(1.0f - cosTheta * cosTheta); // optimization from * 1 / sin(theta)
float res = cross(v1, v2).z * theta * rsqrt(1.0 - cosTheta * cosTheta); // optimization from * 1 / sin(theta)
return res;
}

{
// 1. ClipQuadToHorizon
// detect clipping config
// detect clipping config
uint config = 0;
if (L[0].z > 0) config += 1;
if (L[1].z > 0) config += 2;

// For polygonal lights.
float LTCEvaluate(float4x3 L, float3 V, float3 N, float NdotV, bool twoSided, float3x3 invM)
{
// Construct local orthonormal basis around N, aligned with N
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
// Also consider using 'bsdfData.tangentWS', 'bsdfData.bitangentWS', 'bsdfData.normalWS'.
// Construct a view-dependent orthonormal basis around N.
// TODO: it could be stored in PreLightData, since all LTC lights compute it more than once.
float3x3 basis;
basis[0] = normalize(V - N * NdotV);
basis[1] = normalize(cross(N, basis[0]));

// 'normal' is the direction orthogonal to the tangent. It is the shortest vector between
// the shaded point and the line, pointing away from the shaded point.
float LineIrradiance(float l1, float l2, float3 normal, float3 tangent)
{
{
float d = length(normal);
float l1rcpD = l1 * rcp(d);
float l2rcpD = l2 * rcp(d);

38
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 ClampRoughnessForAnalyticalLights(float roughness)
{
return max(roughness, UNITY_MIN_ROUGHNESS);
}
roughness = max(roughness, UNITY_MIN_ROUGHNESS);
float a2 = roughness * roughness;
float f = (NdotH * a2 - NdotH) * NdotH + 1.0;
return a2 / (f * f);

return INV_PI * D_GGXNoPI(NdotH, roughness);
}
float D_GGX_Inverse(float NdotH, float roughness)
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 19, 29.
float G_MaskingSmithGGX(float NdotV, float VdotH, float roughness)
roughness = max(roughness, UNITY_MIN_ROUGHNESS);
// G1(V, H) = HeavisideStep(VdotH) / (1 + Λ(V)).
// Λ(V) = -0.5 + 0.5 * sqrt(1 + 1 / a²).
// a = 1 / (roughness * tan(theta)).
// 1 + Λ(V) = 0.5 + 0.5 * sqrt(1 + roughness² * tan²(theta)).
// tan²(theta) = (1 - cos²(theta)) / cos²(theta) = 1 / cos²(theta) - 1.
float hs = VdotH > 0.0 ? 1.0 : 0.0;
float f = (NdotH * a2 - NdotH) * NdotH + 1.0;
float g = (f * f) / a2;
float z2 = NdotV * NdotV;
return PI * g;
return hs / (0.5 + 0.5 * sqrt(1.0 + a2 * (1.0 / z2 - 1.0)));
}
// Ref: Understanding the Masking-Shadowing Function in Microfacet-Based BRDFs, p. 12.
float D_GGX_Visible(float NdotH, float NdotV, float VdotH, float roughness)
{
// Note that we pass 1.0 instead of 'VdotH' since the multiplication will already clamp.
return D_GGX(NdotH, roughness) * G_MaskingSmithGGX(NdotV, 1.0, roughness) * VdotH / NdotV;
}
// Ref: http://jcgt.org/published/0003/02/03/paper.pdf

// lambda_l = (-1 + sqrt(a2 * (1 - NdotV2) / NdotV2 + 1)) * 0.5f;
// G = 1 / (1 + lambda_v + lambda_l);
float a = roughness;
float a = roughness;
// Simplify visibility term: (2.0f * NdotL * NdotV) / ((4.0f * NdotL * NdotV) * (lambda_v + lambda_l));
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l));
return 0.5 / (lambdaV + lambdaL);
}

lambdaV *= NdotL;
float lambdaL = NdotV * sqrt((-NdotL * a2 + NdotL) * NdotL + a2);
// Simplify visibility term: (2.0f * NdotL * NdotV) / ((4.0f * NdotL * NdotV) * (lambda_v + lambda_l));
// Simplify visibility term: (2.0 * NdotL * NdotV) / ((4.0 * NdotL * NdotV) * (lambda_v + lambda_l));
return 0.5 / (lambdaV + lambdaL);
}

// roughnessB -> roughness in bitangent direction
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 f = TdotH * TdotH / (roughnessT * roughnessT) + BdotH * BdotH / (roughnessB * roughnessB) + NdotH * NdotH;
return 1.0 / (roughnessT * roughnessB * f * f);
}

88
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


// Include language header
#if defined(SHADER_API_D3D11)
#include "API/D3D11.hlsl"
#elif defined(SHADER_API_PSSL)
#include "API/PSSL.hlsl"
#elif defined(SHADER_API_METAL)
#include "API/Metal.hlsl"
#else
#error unsupported shader api
#endif

float3 adir = abs(dir);
// +Z -Z
faceIndex = dir.z > 0.0f ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
faceIndex = dir.z > 0.0 ? CUBEMAPFACE_NEGATIVE_Z : CUBEMAPFACE_POSITIVE_Z;
// +X -X
if (adir.x > adir.y && adir.x > adir.z)

{
float x = abs(inX);
float res = (0.0468878 * x + -0.203471) * x + 1.570796; // p(x)
res *= sqrt(1.0f - x);
res *= sqrt(1.0 - x);
return (inX >= 0) ? res : PI - res; // Undo range reduction
}

return x * x * (3.0 - (2.0 * x));
}
const float3x3 k_identity3x3 = {1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
static const float3x3 k_identity3x3 = {1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
const float4x4 k_identity4x4 = {1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0 };
static const float4x4 k_identity4x4 = {1.0, 0.0, 0.0, 0.0,
0.0, 1.0, 0.0, 0.0,
0.0, 0.0, 1.0, 0.0,
0.0, 0.0, 0.0, 1.0};
// Using pow often result to a warning like this
// "pow(f, e) will not work for negative f, use abs(f) or conditionally handle negative values if you expect them"

}
// ----------------------------------------------------------------------------
// Texture utilities
// ----------------------------------------------------------------------------
// texelSize is Unity XXX_TexelSize feature parameters
// x contains 1.0/width, y contains 1.0 / height, z contains width, w contains height
float ComputeTextureLOD(float2 uv, float4 texelSize)
{
uv *= texelSize.zw;
float2 ddx_ = ddx(uv);
float2 ddy_ = ddy(uv);
float d = max(dot(ddx_, ddx_), dot(ddy_, ddy_));
return max(0.5 * log2(d), 0.0);
}
// ----------------------------------------------------------------------------
// Texture format sampling
// ----------------------------------------------------------------------------
float2 DirectionToLatLongCoordinate(float3 dir)
{
// coordinate frame is (-Z, X) meaning negative Z is primary axis and X is secondary axis.
return float2(1.0 - 0.5 * INV_PI * atan2(dir.x, -dir.z), asin(dir.y) * INV_PI + 0.5);
}
// ----------------------------------------------------------------------------
// World position reconstruction / transformation
// ----------------------------------------------------------------------------

// From deferred or compute shader
// depth must be the depth from the raw depth buffer. This allow to handle all kind of depth automatically with the inverse view projection matrix.
// For information. In Unity Depth is always in range 0..1 (even on OpenGL) but can be reversed.
void UpdatePositionInput(float depth, float4x4 invViewProjectionMatrix, float4x4 ViewProjectionMatrix, inout PositionInputs posInput)
// It may be necessary to flip the Y axis as the origin of the screen-space coordinate system
// of Direct3D is at the top left corner of the screen, with the Y axis pointing downwards.
void UpdatePositionInput(float depth, float4x4 invViewProjectionMatrix, float4x4 ViewProjectionMatrix,
inout PositionInputs posInput, bool flipY = false)
// TODO: Do we need to flip Y axis here on OGL ?
posInput.positionCS = float4(posInput.positionSS.xy * 2.0 - 1.0, depth, 1.0);
float4 hpositionWS = mul(invViewProjectionMatrix, posInput.positionCS);
float2 screenSpacePos;
screenSpacePos.x = posInput.positionSS.x;
screenSpacePos.y = flipY ? 1.0 - posInput.positionSS.y : posInput.positionSS.y;
posInput.positionCS = float4(screenSpacePos * 2.0 - 1.0, depth, 1.0);
float4 hpositionWS = mul(invViewProjectionMatrix, posInput.positionCS);
posInput.positionWS = hpositionWS.xyz / hpositionWS.w;
// The compiler should optimize this (less expensive than reconstruct depth VS from depth buffer)

}
// depthOffsetVS is always in the direction of the view vector (V)
void ApplyDepthOffsetPositionInput(float V, float depthOffsetVS, inout PositionInputs posInput)
void ApplyDepthOffsetPositionInput(float3 V, float depthOffsetVS, inout PositionInputs posInput)
{
posInput.depthVS += depthOffsetVS;
// TODO: it is an approx, need a correct value where we use projection matrix to reproject the depth from VS

posInput.positionCS = float4(posInput.positionSS.xy * 2.0 - 1.0, posInput.depthRaw, 1.0) * posInput.depthVS;
// Just add the offset along the view vector is sufficiant for world position
posInput.positionWS += V * depthOffsetVS;
}
//-----------------------------------------------------------------------------
// various helper
//-----------------------------------------------------------------------------
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal
// should be modified to become valid (i.e facing the camera) to avoid weird artifacts.
// Note: certain applications (e.g. SpeedTree) make use of two-sided lighting.
float GetShiftedNdotV(inout float3 N, float3 V, bool twoSided)
{
float NdotV = dot(N, V);
float limit = 1e-4;
if (!twoSided && NdotV < limit)
{
// We do not renormalize the normal because { abs(length(N) - 1.0) < limit }.
N += (-NdotV + limit) * V;
NdotV = limit;
}
return NdotV;
}
#endif // UNITY_COMMON_INCLUDED

33
Assets/ScriptableRenderLoop/ShaderLibrary/CommonLighting.hlsl


float SmoothDistanceAttenuation(float squaredDistance, float invSqrAttenuationRadius)
{
float factor = squaredDistance * invSqrAttenuationRadius;
float smoothFactor = saturate(1.0f - factor * factor);
float smoothFactor = saturate(1.0 - factor * factor);
return smoothFactor * smoothFactor;
}

{
float sqrDist = dot(unL, unL);
float attenuation = 1.0f / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist));
float attenuation = 1.0 / (max(PUNCTUAL_LIGHT_THRESHOLD * PUNCTUAL_LIGHT_THRESHOLD, sqrDist));
// Non physically based hack to limit light influence to attenuationRadius.
attenuation *= SmoothDistanceAttenuation(sqrDist, invSqrAttenuationRadius);

}
//-----------------------------------------------------------------------------
// Get local frame
// Helper functions
// Generates an orthonormal basis from two orthogonal unit vectors.
float3x3 GetLocalFrame(float3 localZ, float3 localX)
// NdotV should not be negative for visible pixels, but it can happen due to the
// perspective projection and the normal mapping + decals. In that case, the normal
// should be modified to become valid (i.e facing the camera) to avoid weird artifacts.
// Note: certain applications (e.g. SpeedTree) require to still have negative normal to perform their own two sided lighting
// This will potentially reduce the length of the normal at edges of geometry.
float GetShiftedNdotV(inout float3 N, float3 V, bool twoSided)
float3 localY = cross(localZ, localX);
float NdotV = dot(N, V);
float limit = rcp(256.0); // Determined mostly by the quality of the G-buffer normal encoding
if (!twoSided && NdotV < limit)
{
// We do not renormalize the normal because { abs(length(N) - 1.0) < limit }.
N += (-NdotV + limit) * V;
NdotV = limit;
}
return float3x3(localX, localY, localZ);
return NdotV;
}
// Generates an orthonormal basis from a unit vector.

float3 localX = normalize(cross(upVector, localZ));
float3 localY = cross(localZ, localX);
return GetLocalFrame(localZ, localX);
return float3x3(localX, localY, localZ);
}
// TODO: test

float a = 1.0 / (1.0 + N.z);
float b = -N.x * N.y * a;
tangentX = float3(1.0f - N.x * N.x * a , b, -N.x);
tangentY = float3(b, 1.0f - N.y * N.y * a, -N.y);
tangentX = float3(1.0 - N.x * N.x * a , b, -N.x);
tangentY = float3(b, 1.0 - N.y * N.y * a, -N.y);
}
*/

22
Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl


return viewDirTS.xy * height;
}
// ref https://www.gamedev.net/topic/678043-how-to-blend-world-space-normals/#entry5287707
// assume compositing in world space
// Note: Using vtxNormal = float3(0, 0, 1) give the BlendNormalRNM formulation.
// TODO: Untested
float3 BlendNormalWorldspaceRNM(float3 n1, float3 n2, float3 vtxNormal)
{
// Build the shortest-arc quaternion
float4 q = float4(cross(vtxNormal, n2), dot(vtxNormal, n2) + 1.0) / sqrt(2.0 * (dot(vtxNormal, n2) + 1));
// Rotate the normal
return n1 * (q.w * q.w - dot(q.xyz, q.xyz)) + 2 * q.xyz * dot(q.xyz, n1) + 2 * q.w * cross(q.xyz, n1);
}
// assume compositing in tangent space
float3 BlendNormalRNM(float3 n1, float3 n2)
{
float3 t = n1.xyz + float3(0.0, 0.0, 1.0);

}
// assume compositing in tangent space
float3 BlendNormal(float3 n1, float3 n2)
{
return normalize(float3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z));

float3 ComputeTriplanarWeights(float3 normal)
{
// Determine the blend weights for the 3 planar projections.
// N_orig is the vertex-interpolated normal vector.
float3 blendWeights = abs(normal);
// Tighten up the blending zone
blendWeights = (blendWeights - 0.2) * 7.0;

float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}
// MACRO from Legacy Untiy
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex, name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
#define GET_TEXELSIZE_NAME(name) (name##_TexelSize)
#endif // UNITY_COMMON_MATERIAL_INCLUDED

62
Assets/ScriptableRenderLoop/ShaderLibrary/EntityLighting.hlsl


}
// Following functions are to sample enlighten lightmaps (or lightmaps encoded the same way as our
// enlighten implementation). They assume use of RGB9E5 for illuminance map.
// enlighten implementation). They assume use of RGB9E5 for dynamic illuminance map and RGBM for baked ones.
float3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform)
#define LIGHTMAP_RGBM_RANGE 5.0
// TODO: This is the max value allowed for emissive (bad name - but keep for now to retrieve it) (It is 8^2.2 (gamma) and 8 is the limit of punctual light slider...), comme from UnityCg.cginc. Fix it!
// Ask Jesper if this can be change for HDRenderPipeline
#define EMISSIVE_RGBM_SCALE 97.0
// RGBM stuff is temporary. For now baked lightmap are in RGBM and the RGBM range for lightmaps is specific so we can't use the generic method.
// In the end baked lightmaps are going to be BC6H so the code will be the same as dynamic lightmaps.
// Same goes for emissive packed as an input for Enlighten with another hard coded multiplier.
// TODO: This function is used with the LightTransport pass to encode lightmap or emissive
float4 PackEmissiveRGBM(float3 rgb)
{
float kOneOverRGBMMaxRange = 1.0 / EMISSIVE_RGBM_SCALE;
const float kMinMultiplier = 2.0 * 1e-2;
float4 rgbm = float4(rgb * kOneOverRGBMMaxRange, 1.0);
rgbm.a = max(max(rgbm.r, rgbm.g), max(rgbm.b, kMinMultiplier));
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
// Division-by-zero warning from d3d9, so make compiler happy.
rgbm.a = max(rgbm.a, kMinMultiplier);
rgbm.rgb /= rgbm.a;
return rgbm;
}
float3 UnpackLightmapRGBM(float4 rgbmInput)
{
return rgbmInput.rgb * rgbmInput.a * LIGHTMAP_RGBM_RANGE;
}
float3 SampleSingleLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), float2 uv, float4 transform, bool lightmapRGBM)
// Remark: Lightmap is RGB9E5
float3 illuminance = float3(0.0, 0.0, 0.0);
// Remark: baked lightmap is RGBM for now, dynamic lightmap is RGB9E5
if (lightmapRGBM)
{
illuminance = UnpackLightmapRGBM(SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba);
}
else
{
illuminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgb;
}
float3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS)
float3 SampleDirectionalLightmap(TEXTURE2D_ARGS(lightmapTex, lightmapSampler), TEXTURE2D_ARGS(lightmapDirTex, lightmapDirSampler), float2 uv, float4 transform, float3 normalWS, bool lightmapRGBM)
{
// In directional mode Enlighten bakes dominant light direction
// in a way, that using it for half Lambert and then dividing by a "rebalancing coefficient"

uv = uv * transform.xy + transform.zw;
float4 direction = SAMPLE_TEXTURE2D(lightmapDirTex, lightmapDirSampler, uv);
// Remark: Lightmap is RGB9E5
float3 illuminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgb;
// Remark: baked lightmap is RGBM for now, dynamic lightmap is RGB9E5
float3 illuminance = float3(0.0, 0.0, 0.0);
if (lightmapRGBM)
{
illuminance = UnpackLightmapRGBM(SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgba);
}
else
{
illuminance = SAMPLE_TEXTURE2D(lightmapTex, lightmapSampler, uv).rgb;
}
#endif // UNITY_ENTITY_LIGHTING_INCLUDED
#endif // UNITY_ENTITY_LIGHTING_INCLUDED

4
Assets/ScriptableRenderLoop/ShaderLibrary/Fibonacci.hlsl


}
static const int k_FibonacciSeq[] = {
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610
0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597, 2584, 4181
};
static const float2 k_Fibonacci2dSeq21[] = {

int fibN2 = sampleCount;
// These are all constants, so this loop will be optimized away.
for (int j = 1; j < 16; j++)
for (int j = 1; j < 20; j++)
{
if (k_FibonacciSeq[j] == fibN1)
{

343
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// Util image based lighting
//-----------------------------------------------------------------------------
float perceptualRoughnessToMipmapLevel(float perceptualRoughness)
// The *approximated* version of the non-linear remapping. It works by
// approximating the cone of the specular lobe, and then computing the MIP map level
// which (approximately) covers the footprint of the lobe with a single texel.
// Improves the perceptual roughness distribution.
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness)
// TODO: Clean a bit this code
// CAUTION: remap from Morten may work only with offline convolution, see impact with runtime convolution!
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
}
// The *accurate* version of the non-linear remapping. It works by
// approximating the cone of the specular lobe, and then computing the MIP map level
// which (approximately) covers the footprint of the lobe with a single texel.
// Improves the perceptual roughness distribution and adds reflection (contact) hardening.
// TODO: optimize!
float PerceptualRoughnessToMipmapLevel(float perceptualRoughness, float NdotR)
{
float m = PerceptualRoughnessToRoughness(perceptualRoughness);
// Remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
float n = (2.0 / max(FLT_EPSILON, m * m)) - 2.0;
// Remap from n_dot_h formulation to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
n /= (4.0 * max(NdotR, FLT_EPSILON));
// remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
perceptualRoughness = pow(2.0 / (n + 2.0), 0.25);
// For now disabled
#if 0
float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
float n = (2.0 / max(FLT_EPSILON, m*m)) - 2.0; // remap to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
}
n /= 4.0; // remap from n_dot_h formulatino to n_dot_r. See section "Pre-convolved Cube Maps vs Path Tracers" --> https://s3.amazonaws.com/docs.knaldtech.com/knald/1.0.0/lys_power_drops.html
// The inverse of the *approximated* version of perceptualRoughnessToMipmapLevel().
float MipmapLevelToPerceptualRoughness(float mipmapLevel)
{
float perceptualRoughness = saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
perceptualRoughness = pow(2.0 / (n + 2.0), 0.25); // remap back to square root of real roughness (0.25 include both the sqrt root of the conversion and sqrt for going from roughness to perceptualRoughness)
return saturate(1.7 / 1.4 - sqrt(2.89 - 2.8 * perceptualRoughness) / 1.4);
}
// Ref: "Moving Frostbite to PBR", p. 69.
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness, float NdotV)
{
float a = 1.0 - roughness;
float s = sqrt(a);
#ifdef USE_FB_DSD
// This is the original formulation.
float lerpFactor = (s + roughness) * a;
// MM: came up with a surprisingly close approximation to what the #if 0'ed out code above does.
perceptualRoughness = perceptualRoughness * (1.7 - 0.7 * perceptualRoughness);
// TODO: tweak this further to achieve a closer match to the reference.
float lerpFactor = (s + roughness) * saturate(a * a + lerp(0.0, a, NdotV * NdotV));
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
// The result is not normalized as we fetch in a cubemap
return lerp(N, R, lerpFactor);
float mipmapLevelToPerceptualRoughness(float mipmapLevel)
//-----------------------------------------------------------------------------
// Anisotropic image based lighting
//-----------------------------------------------------------------------------
// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84
float AnisotropicStrechAtGrazingAngle(float roughness, float perceptualRoughness, float NdotV)
return saturate(mipmapLevel / UNITY_SPECCUBE_LOD_STEPS);
return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
}
//-----------------------------------------------------------------------------

// Transforms the unit vector from the spherical to the Cartesian (right-handed, Z up) coordinate.
float3 SphericalToCartesian(float phi, float sinTheta, float cosTheta)
float3 SphericalToCartesian(float phi, float cosTheta)
float sinTheta = sqrt(saturate(1.0 - cosTheta * cosTheta));
return float3(sinTheta * cosPhi, sinTheta * sinPhi, cosTheta);
}

// coordinate system with Y pointing up and Z facing forward (DirectX style).
float3 TransformGLtoDX(float x, float y, float z)
{
return float3(x, z, y);
}
float3 TransformGLtoDX(float3 v)
{
return v.xzy;

float3 ConvertEquiarealToCubemap(float u, float v)
{
// The equiareal mapping is defined as follows:
// phi = TWO_PI * (1.0 - u)
// cos(theta) = 1.0 - 2.0 * v
// sin(theta) = sqrt(1.0 - cos^2(theta)) = 2.0 * sqrt(v - v * v)
float sinTheta = 2.0 * sqrt(v - v * v);
return TransformGLtoDX(SphericalToCartesian(phi, sinTheta, cosTheta));
}
// Ref: See "Moving Frostbite to PBR" Listing 22
// This formulation is for GGX only (with smith joint visibility or regular)
float3 GetSpecularDominantDir(float3 N, float3 R, float roughness)
{
float a = 1.0 - roughness;
float lerpFactor = a * (sqrt(a) + roughness);
// The result is not normalized as we fetch in a cubemap
return lerp(N, R, lerpFactor);
}
//-----------------------------------------------------------------------------
// Anisotropic image based lighting
//-----------------------------------------------------------------------------
// To simulate the streching of highlight at grazing angle for IBL we shrink the roughness
// which allow to fake an anisotropic specular lobe.
// Ref: http://www.frostbite.com/2015/08/stochastic-screen-space-reflections/ - slide 84
float AnisotropicStrechAtGrazingAngle(float roughness, float perceptualRoughness, float NdotV)
{
return roughness * lerp(saturate(NdotV * 2.0), 1.0, perceptualRoughness);
return TransformGLtoDX(SphericalToCartesian(phi, cosTheta));
}
// ----------------------------------------------------------------------------

void ImportanceSampleCosDir(float2 u,
float3x3 localToWorld,
out float3 L)
// Performs uniform sampling of the unit disk.
// Ref: PBRT v3, p. 777.
float2 SampleDiskUniform(float2 u)
// Cosine sampling - ref: http://www.rorydriscoll.com/2009/01/07/better-sampling/
float cosTheta = sqrt(saturate(1.0 - u.x));
float sinTheta = sqrt(u.x);
float phi = TWO_PI * u.y;
float r = sqrt(u.x);
float phi = TWO_PI * u.y;
float sinPhi, cosPhi;
sincos(phi, sinPhi, cosPhi);
L = SphericalToCartesian(phi, sinTheta, cosTheta);
L = mul(L, localToWorld);
return r * float2(cosPhi, sinPhi);
void ImportanceSampleGGXDir(float2 u,
float3 V,
// Performs cosine-weighted sampling of the hemisphere.
// Ref: PBRT v3, p. 780.
void SampleHemisphereCosine(float2 u,
float roughness,
out float NdotH,
out float VdotH,
bool VeqN = false)
out float NdotL)
{
float3 localL;
// Since we don't really care about the area distortion,
// we substitute uniform disk sampling for the concentric one.
localL.xy = SampleDiskUniform(u);
// Project the point from the disk onto the hemisphere.
localL.z = sqrt(1.0 - u.x);
NdotL = localL.z;
L = mul(localL, localToWorld);
}
void SampleGGXDir(float2 u,
float3 V,
float3x3 localToWorld,
float roughness,
out float3 L,
out float NdotL,
out float NdotH,
out float VdotH,
bool VeqN = false)
float sinTheta = sqrt(1.0 - cosTheta * cosTheta);
float3 localH = SphericalToCartesian(phi, sinTheta, cosTheta);
float3 localH = SphericalToCartesian(phi, cosTheta);
NdotH = cosTheta;

VdotH = saturate(dot(localV, localH));
}
// Compute { L = reflect(-localV, localH) }
L = -localV + 2.0 * VdotH * localH;
// Compute { localL = reflect(-localV, localH) }
float3 localL = -localV + 2.0 * VdotH * localH;
NdotL = localL.z;
L = mul(L, localToWorld);
L = mul(localL, localToWorld);
void ImportanceSampleAnisoGGXDir( float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughnessT,
float roughnessB,
out float3 H,
out float3 L)
void SampleAnisoGGXDir(float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughnessT,
float roughnessB,
out float3 H,
out float3 L)
// Local to world
// H = tangentX * H.x + tangentY * H.y + N * H.z;
// Convert sample from half angle to incident angle
L = 2.0 * saturate(dot(V, H)) * H - V;

out float NdotL,
out float weightOverPdf)
{
ImportanceSampleCosDir(u, localToWorld, L);
NdotL = saturate(dot(localToWorld[2], L));
SampleHemisphereCosine(u, localToWorld, L, NdotL);
// Importance sampling weight for each sample
// pdf = N.L / PI

out float NdotL,
out float weightOverPdf)
{
float3 H;
float NdotH;
ImportanceSampleGGXDir(u, V, localToWorld, roughness, L, NdotH, VdotH);
NdotL = saturate(dot(localToWorld[2], L));
float NdotH;
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, VdotH);
// Importance sampling weight for each sample
// pdf = D(H) * (N.H) / (4 * (L.H))

}
// weightOverPdf return the weight (without the Fresnel term) over pdf. Fresnel term must be apply by the caller.
void ImportanceSampleAnisoGGX(
float2 u,
float3 V,
float3 N,
float3 tangentX,
float3 tangentY,
float roughnessT,
float roughnessB,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
void ImportanceSampleAnisoGGX(float2 u,
float3 V,
float3x3 localToWorld,
float roughnessT,
float roughnessB,
float NdotV,
out float3 L,
out float VdotH,
out float NdotL,
out float weightOverPdf)
float3 tangentX = localToWorld[0];
float3 tangentY = localToWorld[1];
float3 N = localToWorld[2];
ImportanceSampleAnisoGGXDir(u, V, N, tangentX, tangentY, roughnessT, roughnessB, H, L);
SampleAnisoGGXDir(u, V, N, tangentX, tangentY, roughnessT, roughnessB, H, L);
float NdotH = saturate(dot(N, H));
// Note: since L and V are symmetric around H, LdotH == VdotH

// weightOverPdf = F(H) * 4 * (N.L) * V(V, L) * (L.H) / (N.H) with V(V, L) = G(V, L) / (4 * (N.L) * (N.V))
// Remind (L.H) == (V.H)
// F is apply outside the function
// For anisotropy we must not saturate these values
float TdotL = saturate(dot(tangentX, L));
float BdotL = saturate(dot(tangentY, L));
float TdotL = dot(tangentX, L);
float BdotL = dot(tangentY, L);
float Vis = V_SmithJointGGXAniso(TdotV, BdotV, NdotV, TdotL, BdotL, NdotL, roughnessT, roughnessB);
weightOverPdf = 4.0 * Vis * NdotL * VdotH / NdotH;

// ----------------------------------------------------------------------------
// Ref: Listing 18 in "Moving Frostbite to PBR" + https://knarkowicz.wordpress.com/2014/12/27/analytical-dfg-term-for-ibl/
float4 IntegrateGGXAndDisneyFGD(float3 V, float3 N, float roughness, uint sampleCount)
float4 IntegrateGGXAndDisneyFGD(float3 V, float3 N, float roughness, uint sampleCount = 4096)
float NdotV = GetShiftedNdotV(N, V, false); // This fix some rare artifact at edge.
float NdotV = saturate(dot(N, V));
float4 acc = float4(0.0, 0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);

return acc / sampleCount;
}
uint GetIBLRuntimeFilterSampleCount(uint mipLevel)
{
uint sampleCount = 0;
switch (mipLevel)
{
case 1: sampleCount = 21; break;
case 2: sampleCount = 34; break;
case 3: sampleCount = 55; break;
case 4: sampleCount = 89; break;
case 5: sampleCount = 89; break;
case 6: sampleCount = 89; break; // UNITY_SPECCUBE_LOD_STEPS
}
return sampleCount;
}
float3 V,
float3 N,
float roughness,
float maxMipLevel,
float invOmegaP,
uint sampleCount, // Must be a Fibonacci number
bool prefilter)
TEXTURE2D(ggxIblSamples),
float3 V,
float3 N,
float roughness,
float index, // Current MIP level minus one
float lastMipLevel,
float invOmegaP,
uint sampleCount, // Must be a Fibonacci number
bool prefilter,
bool usePrecomputedSamples)
// Bias samples towards the mirror direction to reduce variance.
// This will have a side effect of making the reflection sharper.
// Ref: Stochastic Screen-Space Reflections, p. 67.
const float bias = 0.5 * roughness;
float2 u = Fibonacci2d(i, sampleCount);
float3 L;
float NdotL, NdotH, VdotH;
bool isValid;
if (usePrecomputedSamples)
{
float3 localL = LOAD_TEXTURE2D(ggxIblSamples, uint2(i, index)).xyz;
// Bias samples towards the mirror direction to reduce variance.
// This will have a side effect of making the reflection sharper.
// Ref: Stochastic Screen-Space Reflections, p. 67.
const float bias = 0.2;
u.x = lerp(u.x, 0.0, bias);
L = mul(localL, localToWorld);
NdotL = localL.z;
isValid = true;
}
else
{
float2 u = Fibonacci2d(i, sampleCount);
u.x = lerp(u.x, 0.0, bias);
float3 L;
float NdotH, VdotH;
ImportanceSampleGGXDir(u, V, localToWorld, roughness, L, NdotH, VdotH, true);
SampleGGXDir(u, V, localToWorld, roughness, L, NdotL, NdotH, VdotH, true);
float NdotL = saturate(dot(N, L));
isValid = NdotL > 0.0;
}
float mipLevel;

// can be simplified:
// pdf = D * NdotH / (4 * LdotH) = D * 0.25;
//
// - OmegaS : Solid angle associated to a sample
// - OmegaP : Solid angle associated to a pixel of the cubemap
// - OmegaS : Solid angle associated with the sample
// - OmegaP : Solid angle associated with the texel of the cubemap
float omegaS;
float invPdf = D_GGX_Inverse(NdotH, roughness) * 4.0;
// TODO: check the accuracy of the sample's solid angle fit for GGX.
float omegaS = rcp(sampleCount) * invPdf;
if (usePrecomputedSamples)
{
omegaS = LOAD_TEXTURE2D(ggxIblSamples, uint2(i, index)).w;
}
else
{
float pdf = D_GGX(NdotH, roughness) * 0.25;
// TODO: check the accuracy of the sample's solid angle fit for GGX.
omegaS = rcp(sampleCount) / pdf;
}
// float omegaP = FOUR_PI / (6.0f * cubemapWidth * cubemapWidth);
// float omegaP = FOUR_PI / (6.0 * cubemapWidth * cubemapWidth);
}
if (isValid)
{
mipLevel = lerp(mipLevel, maxMipLevel, bias);
}
mipLevel = lerp(mipLevel, lastMipLevel, bias);
if (NdotL > 0.0)
{
// *********************************************************************************
// Our goal is to use Monte-Carlo integration with importance sampling to evaluate
// X(V) = Integral{Radiance(L) * CBSDF(L, N, V) dL} / Integral{CBSDF(L, N, V) dL}.
// CBSDF = F * D * G * NdotL / (4 * NdotL * NdotV) = F * D * G / (4 * NdotV).

// (LdotH == NdotH) && (NdotV == 1) && (Weight == F * G).
// We use the approximation of Brian Karis from "Real Shading in Unreal Engine 4":
// Weight ≈ NdotL, which produces nearly identical results in practice.
// *********************************************************************************
lightInt += NdotL * val;
cbsdfInt += NdotL;

42
Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl


vResult.xy = Xp_Y_XYZp.xy / Xp_Y_XYZp.z;
float Le = 2.0 * log2(Xp_Y_XYZp.y) + 127.0;
vResult.w = frac(Le);
vResult.z = (Le - (floor(vResult.w*255.0f)) / 255.0f) / 255.0f;
vResult.z = (Le - (floor(vResult.w * 255.0)) / 255.0) / 255.0;
return vResult;
}

Xp_Y_XYZp.x = vLogLuv.x * Xp_Y_XYZp.z;
float3 vRGB = mul(Xp_Y_XYZp, InverseM);
return max(vRGB, float3(0.0, 0.0, 0.0));
}
// TODO: This function is used with the LightTransport pass to encode lightmap or emissive
float4 PackRGBM(float3 rgb, float maxRGBM)
{
float kOneOverRGBMMaxRange = 1.0 / maxRGBM;
const float kMinMultiplier = 2.0 * 1e-2;
float4 rgbm = float4(rgb * kOneOverRGBMMaxRange, 1.0);
rgbm.a = max(max(rgbm.r, rgbm.g), max(rgbm.b, kMinMultiplier));
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
// Division-by-zero warning from d3d9, so make compiler happy.
rgbm.a = max(rgbm.a, kMinMultiplier);
rgbm.rgb /= rgbm.a;
return rgbm;
}
// Alternative...
#define RGBMRANGE (8.0)
float4 PackRGBM(float3 color)
{
float4 rgbm;
color *= (1.0 / RGBMRANGE);
rgbm.a = saturate(max(max(color.r, color.g), max(color.b, 1e-6)));
rgbm.a = ceil(rgbm.a * 255.0) / 255.0;
rgbm.rgb = color / rgbm.a;
return rgbm;
}
float3 UnpackRGBM(float4 rgbm)
{
return RGBMRANGE * rgbm.rgb * rgbm.a;
}
// The standard 32-bit HDR color format

return PackFloatInt(f, i, maxi, 255.0);
}
float UnpackFloatInt8bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt8bit(float val, float maxi, out float f, out int i)
{
UnpackFloatInt(val, maxi, 255.0, f, i);
}

return PackFloatInt(f, i, maxi, 1024.0);
}
float UnpackFloatInt10bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt10bit(float val, float maxi, out float f, out int i)
{
UnpackFloatInt(val, maxi, 1024.0, f, i);
}

return PackFloatInt(f, i, maxi, 65536.0);
}
float UnpackFloatInt16bit(float val, float maxi, out float f, out int i)
void UnpackFloatInt16bit(float val, float maxi, out float f, out int i)
{
UnpackFloatInt(val, maxi, 65536.0, f, i);
}

2
Assets/ScriptableRenderLoop/common/TextureCache.cs


}
public abstract class TextureCache : Object
public abstract class TextureCache
{
protected int m_NumMipLevels;

2
Assets/ScriptableRenderLoop/common/TextureSettings.cs


namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering
{
[System.Serializable]
public struct TextureSettings

4
Assets/ScriptableRenderLoop/core/RenderPipeline.cs


using System;
using System.Collections.Generic;
using UnityEngine.Experimental.Rendering;
namespace UnityEngine.ScriptableRenderPipeline
namespace UnityEngine.Experimental.Rendering
{
public abstract class RenderPipeline : IRenderPipeline
{

10
Assets/ScriptableRenderLoop/fptl/FptlLighting.cs


using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using UnityEngine.ScriptableRenderPipeline;
namespace UnityEngine.Experimental.ScriptableRenderLoop
namespace UnityEngine.Experimental.Rendering.Fptl
{
public class FptlLightingInstance : RenderPipeline
{

//@TODO: need to get light probes + LPPV too?
settings.inputFilter.SetQueuesOpaque();
settings.rendererConfiguration = RendererConfiguration.PerObjectLightmaps | RendererConfiguration.PerObjectLightProbe;
loop.DrawRenderers(ref settings);
loop.DrawRenderers(settings);
}
void RenderForward(CullResults cull, Camera camera, ScriptableRenderContext loop, bool opaquesOnly)

if (opaquesOnly) settings.inputFilter.SetQueuesOpaque();
else settings.inputFilter.SetQueuesTransparent();
loop.DrawRenderers(ref settings);
loop.DrawRenderers(settings);
}
static void DepthOnlyForForwardOpaques(CullResults cull, Camera camera, ScriptableRenderContext loop)

sorting = { flags = SortFlags.CommonOpaque }
};
settings.inputFilter.SetQueuesOpaque();
loop.DrawRenderers(ref settings);
loop.DrawRenderers(settings);
}
bool usingFptl

292
Assets/ScriptableRenderLoop/fptl/Internal-DeferredComputeShading.compute


#pragma kernel ShadeDeferred_Fptl SHADE_DEFERRED_ENTRY=ShadeDeferred_Fptl USE_FPTL_LIGHTLIST=1 ENABLE_DEBUG=0
#pragma kernel ShadeDeferred_Clustered SHADE_DEFERRED_ENTRY=ShadeDeferred_Clustered USE_CLUSTERED_LIGHTLIST=1 ENABLE_DEBUG=0 //TODO: disabled clustered permutations so far as it leads to the error "All kernels must use same constant buffer layouts"
#pragma kernel ShadeDeferred_Fptl_Debug SHADE_DEFERRED_ENTRY=ShadeDeferred_Fptl_Debug USE_FPTL_LIGHTLIST=1 ENABLE_DEBUG=1
#pragma kernel ShadeDeferred_Clustered_Debug SHADE_DEFERRED_ENTRY=ShadeDeferred_Clustered_Debug USE_CLUSTERED_LIGHTLIST=1 ENABLE_DEBUG=1
#define TILE_SIZE 8
// Hacks to get the header to compile in compute
#define SHADER_TARGET 50
#define UNITY_PBS_USE_BRDF1
#define fixed4 float4
#include "UnityLightingCommon.cginc"
#undef fixed4
float3 EvalMaterial(UnityLight light, UnityIndirect ind);
float3 EvalIndirectSpecular(UnityLight light, UnityIndirect ind);
// uses the optimized single layered light list for opaques only
#ifdef USE_FPTL_LIGHTLIST
#define OPAQUES_ONLY
#endif
#include "TiledLightingTemplate.hlsl"
#include "TiledReflectionTemplate.hlsl"
Texture2D _CameraDepthTexture;
Texture2D _CameraGBufferTexture0;
Texture2D _CameraGBufferTexture1;
Texture2D _CameraGBufferTexture2;
Texture2D _CameraGBufferTexture3;
RWTexture2D<float4> uavOutput : register(u0);
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(float4 vertex : POSITION, float2 texcoord : TEXCOORD0)
{
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
}
struct StandardData
{
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
float occlusion;
float3 emission;
};
struct LocalDataBRDF
{
StandardData gbuf;
// extras
float oneMinusReflectivity;
float3 Vworld;
};
static LocalDataBRDF g_localParams;
StandardData UnityStandardDataFromGbufferAux(float4 gbuffer0, float4 gbuffer1, float4 gbuffer2, float4 gbuffer3)
{
StandardData data;
data.normalWorld = normalize(2 * gbuffer2.xyz - 1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
data.occlusion = gbuffer0.a;
data.emission = gbuffer3.xyz;
return data;
}
half3 BRDF3_Direct2(half3 diffColor, half3 specColor, half rlPow4, half smoothness)
{
half LUT_RANGE = 16.0; // must match range in NHxRoughness() function in GeneratedTextures.cpp
// Lookup texture to save instructions
half specular = tex2Dlod(unity_NHxRoughness, half4(rlPow4, SmoothnessToPerceptualRoughness(smoothness), 0, 0)).UNITY_ATTEN_CHANNEL * LUT_RANGE;
#if defined(_SPECULARHIGHLIGHTS_OFF)
specular = 0.0;
#endif
return diffColor + specular * specColor;
}
float3 EvalMaterial(UnityLight light, UnityIndirect ind)
{
StandardData data = g_localParams.gbuf;
return UNITY_BRDF_PBS(data.diffuseColor, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind);
}
float3 EvalIndirectSpecular(UnityLight light, UnityIndirect ind)
{
StandardData data = g_localParams.gbuf;
return data.occlusion * UNITY_BRDF_PBS(0, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind).rgb;
}
[numthreads(TILE_SIZE, TILE_SIZE, 1)]
void SHADE_DEFERRED_ENTRY(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupId : SV_GroupID)
{
uint2 pixCoord = dispatchThreadId;
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float3 vP = GetViewPosFromLinDepth(pixCoord, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float4 gbuffer0 = _CameraGBufferTexture0.Load(uint3(pixCoord.xy, 0));
float4 gbuffer1 = _CameraGBufferTexture1.Load(uint3(pixCoord.xy, 0));
float4 gbuffer2 = _CameraGBufferTexture2.Load(uint3(pixCoord.xy, 0));
float4 gbuffer3 = _CameraGBufferTexture3.Load(uint3(pixCoord.xy, 0));
StandardData data = UnityStandardDataFromGbufferAux(gbuffer0, gbuffer1, gbuffer2, gbuffer3);
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
uint2 tileCoord = groupId >> 1;
uint numLightsProcessed = 0;
float3 c = data.emission + ExecuteLightList(numLightsProcessed, tileCoord, vP, vPw, Vworld);
uint numReflectionsProcessed = 0;
c += ExecuteReflectionList(numReflectionsProcessed, tileCoord, vP, data.normalWorld, Vworld, data.smoothness);
#if ENABLE_DEBUG
c = OverlayHeatMap(pixCoord & 15, numLightsProcessed, c);
#endif
uavOutput[pixCoord] = float4(c, 1.0);
}
#pragma kernel ShadeDeferred_Fptl SHADE_DEFERRED_ENTRY=ShadeDeferred_Fptl USE_FPTL_LIGHTLIST=1 ENABLE_DEBUG=0
#pragma kernel ShadeDeferred_Clustered SHADE_DEFERRED_ENTRY=ShadeDeferred_Clustered USE_CLUSTERED_LIGHTLIST=1 ENABLE_DEBUG=0 //TODO: disabled clustered permutations so far as it leads to the error "All kernels must use same constant buffer layouts"
#pragma kernel ShadeDeferred_Fptl_Debug SHADE_DEFERRED_ENTRY=ShadeDeferred_Fptl_Debug USE_FPTL_LIGHTLIST=1 ENABLE_DEBUG=1
#pragma kernel ShadeDeferred_Clustered_Debug SHADE_DEFERRED_ENTRY=ShadeDeferred_Clustered_Debug USE_CLUSTERED_LIGHTLIST=1 ENABLE_DEBUG=1
#define TILE_SIZE 8
// Hacks to get the header to compile in compute
#define SHADER_TARGET 50
#define UNITY_PBS_USE_BRDF1
#define fixed4 float4
#include "UnityLightingCommon.cginc"
#undef fixed4
float3 EvalMaterial(UnityLight light, UnityIndirect ind);
float3 EvalIndirectSpecular(UnityLight light, UnityIndirect ind);
// uses the optimized single layered light list for opaques only
#ifdef USE_FPTL_LIGHTLIST
#define OPAQUES_ONLY
#endif
#include "TiledLightingTemplate.hlsl"
#include "TiledReflectionTemplate.hlsl"
UNITY_DECLARE_TEX2D_FLOAT(_CameraDepthTexture);
Texture2D _CameraGBufferTexture0;
Texture2D _CameraGBufferTexture1;
Texture2D _CameraGBufferTexture2;
Texture2D _CameraGBufferTexture3;
RWTexture2D<float4> uavOutput : register(u0);
struct v2f {
float4 vertex : SV_POSITION;
float2 texcoord : TEXCOORD0;
};
v2f vert(float4 vertex : POSITION, float2 texcoord : TEXCOORD0)
{
v2f o;
o.vertex = UnityObjectToClipPos(vertex);
o.texcoord = texcoord.xy;
return o;
}
struct StandardData
{
float3 specularColor;
float3 diffuseColor;
float3 normalWorld;
float smoothness;
float occlusion;
float3 emission;
};
struct LocalDataBRDF
{
StandardData gbuf;
// extras
float oneMinusReflectivity;
float3 Vworld;
};
static LocalDataBRDF g_localParams;
StandardData UnityStandardDataFromGbufferAux(float4 gbuffer0, float4 gbuffer1, float4 gbuffer2, float4 gbuffer3)
{
StandardData data;
data.normalWorld = normalize(2 * gbuffer2.xyz - 1);
data.smoothness = gbuffer1.a;
data.diffuseColor = gbuffer0.xyz; data.specularColor = gbuffer1.xyz;
data.occlusion = gbuffer0.a;
data.emission = gbuffer3.xyz;
return data;
}
half3 BRDF3_Direct2(half3 diffColor, half3 specColor, half rlPow4, half smoothness)
{
half LUT_RANGE = 16.0; // must match range in NHxRoughness() function in GeneratedTextures.cpp
// Lookup texture to save instructions
half specular = tex2Dlod(unity_NHxRoughness, half4(rlPow4, SmoothnessToPerceptualRoughness(smoothness), 0, 0)).UNITY_ATTEN_CHANNEL * LUT_RANGE;
#if defined(_SPECULARHIGHLIGHTS_OFF)
specular = 0.0;
#endif
return diffColor + specular * specColor;
}
float3 EvalMaterial(UnityLight light, UnityIndirect ind)
{
StandardData data = g_localParams.gbuf;
return UNITY_BRDF_PBS(data.diffuseColor, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind);
}
float3 EvalIndirectSpecular(UnityLight light, UnityIndirect ind)
{
StandardData data = g_localParams.gbuf;
return data.occlusion * UNITY_BRDF_PBS(0, data.specularColor, g_localParams.oneMinusReflectivity, data.smoothness, data.normalWorld, g_localParams.Vworld, light, ind).rgb;
}
[numthreads(TILE_SIZE, TILE_SIZE, 1)]
void SHADE_DEFERRED_ENTRY(uint2 dispatchThreadId : SV_DispatchThreadID, uint2 groupId : SV_GroupID)
{
uint2 pixCoord = dispatchThreadId;
float zbufDpth = FetchDepth(_CameraDepthTexture, pixCoord.xy).x;
float linDepth = GetLinearDepth(zbufDpth);
float3 vP = GetViewPosFromLinDepth(pixCoord, linDepth);
float3 vPw = mul(g_mViewToWorld, float4(vP, 1)).xyz;
float3 Vworld = normalize(mul((float3x3) g_mViewToWorld, -vP).xyz); //unity_CameraToWorld
float4 gbuffer0 = _CameraGBufferTexture0.Load(uint3(pixCoord.xy, 0));
float4 gbuffer1 = _CameraGBufferTexture1.Load(uint3(pixCoord.xy, 0));
float4 gbuffer2 = _CameraGBufferTexture2.Load(uint3(pixCoord.xy, 0));
float4 gbuffer3 = _CameraGBufferTexture3.Load(uint3(pixCoord.xy, 0));
StandardData data = UnityStandardDataFromGbufferAux(gbuffer0, gbuffer1, gbuffer2, gbuffer3);
g_localParams.gbuf = data;
g_localParams.oneMinusReflectivity = 1.0 - SpecularStrength(data.specularColor.rgb);
g_localParams.Vworld = Vworld;
uint2 tileCoord = groupId >> 1;
uint numLightsProcessed = 0;
float3 c = data.emission + ExecuteLightList(numLightsProcessed, tileCoord, vP, vPw, Vworld);
uint numReflectionsProcessed = 0;
c += ExecuteReflectionList(numReflectionsProcessed, tileCoord, vP, data.normalWorld, Vworld, data.smoothness);
#if ENABLE_DEBUG
c = OverlayHeatMap(pixCoord & 15, numLightsProcessed, c);
#endif
uavOutput[pixCoord] = float4(c, 1.0);
}

部分文件因为文件数量过多而无法显示

正在加载...
取消
保存