浏览代码

Merge remote-tracking branch 'origin/master' into scriptablerenderloop-materialgraph

/scriptablerenderloop-materialgraph
Paul Demeulenaere 8 年前
当前提交
16333450
共有 44 个文件被更改,包括 2056 次插入1067 次删除
  1. 6
      Assets/BasicRenderLoopTutorial/BasicRenderLoop.cs
  2. 40
      Assets/ScriptableRenderLoop/HDRenderLoop/Editor/HDRenderLoopInspector.cs
  3. 274
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  4. 7
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs
  5. 6
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Lighting.hlsl
  6. 13
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Resources/Deferred.shader
  7. 3
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.cs
  8. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePassLoop.hlsl
  9. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ClusteredUtils.hlsl
  10. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/scrbound.compute
  11. 4
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ShaderBase.hlsl
  12. 116
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs
  13. 38
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.hlsl
  14. 157
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePassLoop.hlsl
  15. 3
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Builtin/BuiltinData.hlsl
  16. 287
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/LayeredLit/Editor/LayeredLitUI.cs
  17. 215
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/LayeredLit/LayeredLit.shader
  18. 272
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Editor/LitUI.cs
  19. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  20. 66
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.shader
  21. 638
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitData.hlsl
  22. 24
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSharePass.hlsl
  23. 36
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Material.hlsl
  24. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Unlit/Unlit.hlsl
  25. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Unlit/UnlitData.hlsl
  26. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/ShaderPass/ShaderPassForward.hlsl
  27. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/ShaderPass/ShaderPassForwardUnlit.hlsl
  28. 5
      Assets/ScriptableRenderLoop/HDRenderLoop/ShaderVariables.hlsl
  29. 151
      Assets/ScriptableRenderLoop/HDRenderLoop/Sky/SkyRenderer.cs
  30. 116
      Assets/ScriptableRenderLoop/HDRenderLoop/Utilities.cs
  31. 4
      Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs
  32. 4
      Assets/ScriptableRenderLoop/ShaderLibrary/API/D3D11.hlsl
  33. 38
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  34. 26
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  35. 23
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl
  36. 8
      Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl
  37. 2
      ProjectSettings/ProjectVersion.txt
  38. 35
      .collabignore
  39. 232
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSurfaceData.hlsl
  40. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSurfaceData.hlsl.meta
  41. 68
      Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/GGXConvolve.shader
  42. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/GGXConvolve.shader.meta
  43. 141
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/Chrome.mat
  44. 8
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/Chrome.mat.meta

6
Assets/BasicRenderLoopTutorial/BasicRenderLoop.cs


// per-camera built-in shader variables).
loop.SetupCameraProperties (camera);
// clear depth buffer
var cmd = new CommandBuffer();
cmd.ClearRenderTarget(true, false, Color.black);
loop.ExecuteCommandBuffer(cmd);
cmd.Release();
// Setup global lighting shader variables
SetupLightShaderVariables (cull.visibleLights, loop);

40
Assets/ScriptableRenderLoop/HDRenderLoop/Editor/HDRenderLoopInspector.cs


public readonly GUIContent skyExposure = new GUIContent("Sky Exposure");
public readonly GUIContent skyRotation = new GUIContent("Sky Rotation");
public readonly GUIContent skyMultiplier = new GUIContent("Sky Multiplier");
public readonly GUIContent shadowSettings = new GUIContent("Shadow Settings");
public readonly GUIContent shadowsEnabled = new GUIContent("Enabled");
public readonly GUIContent shadowsAtlasWidth = new GUIContent("Atlas width");
public readonly GUIContent shadowsAtlasHeight = new GUIContent("Atlas height");
public readonly GUIContent shadowsMaxShadowDistance = new GUIContent("Maximum shadow distance");
public readonly GUIContent shadowsDirectionalLightCascadeCount = new GUIContent("Directional cascade count");
public readonly GUIContent[] shadowsCascadeCounts = new GUIContent[] { new GUIContent("1"), new GUIContent("2"), new GUIContent("3"), new GUIContent("4") };
public readonly int[] shadowsCascadeCountValues = new int[] { 1, 2, 3, 4 };
public readonly GUIContent shadowsCascades = new GUIContent("Cascade values");
}
private static Styles s_Styles = null;

}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
var skyParameters = renderLoop.skyParameters;
EditorGUILayout.LabelField(styles.skyParameters);

skyParameters.multiplier = Mathf.Max(EditorGUILayout.FloatField(styles.skyMultiplier, skyParameters.multiplier), 0);
skyParameters.rotation = Mathf.Max(Mathf.Min(EditorGUILayout.FloatField(styles.skyRotation, skyParameters.rotation), 360), -360);
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(renderLoop); // Repaint
}
EditorGUI.indentLevel--;
EditorGUILayout.Space();
var shadowParameters = renderLoop.shadowSettings;
EditorGUILayout.LabelField(styles.shadowSettings);
EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
shadowParameters.enabled = EditorGUILayout.Toggle(styles.shadowsEnabled, shadowParameters.enabled);
shadowParameters.shadowAtlasWidth = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasWidth, shadowParameters.shadowAtlasWidth));
shadowParameters.shadowAtlasHeight = Mathf.Max(0, EditorGUILayout.IntField(styles.shadowsAtlasHeight, shadowParameters.shadowAtlasHeight));
shadowParameters.maxShadowDistance = Mathf.Max(0, EditorGUILayout.FloatField(styles.shadowsMaxShadowDistance, shadowParameters.maxShadowDistance));
shadowParameters.directionalLightCascadeCount = EditorGUILayout.IntPopup(styles.shadowsDirectionalLightCascadeCount, shadowParameters.directionalLightCascadeCount, styles.shadowsCascadeCounts, styles.shadowsCascadeCountValues);
EditorGUI.indentLevel++;
for (int i = 0; i < shadowParameters.directionalLightCascadeCount-1; i++)
{
shadowParameters.directionalLightCascades[i] = Mathf.Max(0, EditorGUILayout.FloatField(shadowParameters.directionalLightCascades[i]));
}
EditorGUI.indentLevel--;
if (EditorGUI.EndChangeCheck())
{
EditorUtility.SetDirty(renderLoop); // Repaint

274
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


[SerializeField]
ShadowSettings m_ShadowSettings = ShadowSettings.Default;
public ShadowSettings shadowSettings
{
get { return m_ShadowSettings; }
}
ShadowRenderPass m_ShadowPass;

int m_CameraDepthBuffer;
int m_VelocityBuffer;
int m_DistortionBuffer;
bool m_Dirty = false;
RenderTargetIdentifier m_CameraColorBufferRT;
RenderTargetIdentifier m_CameraDepthBufferRT;

void OnValidate()
{
Rebuild();
m_Dirty = true;
}
public override void Rebuild()

m_lightList = new LightList();
m_lightList.Allocate();
m_Dirty = false;
}
void OnDisable()

void InitAndClearBuffer(Camera camera, RenderLoop renderLoop)
{
using (new Utilities.ProfilingSample("InitAndClearBuffer", renderLoop))
{
{
var cmd = new CommandBuffer();
cmd.name = "InitGBuffers and clear Depth/Stencil";
using (new Utilities.ProfilingSample("InitGBuffers and clear Depth/Stencil", renderLoop))
{
var cmd = new CommandBuffer();
cmd.name = "";
// Init buffer
// With scriptable render loop we must allocate ourself depth and color buffer (We must be independent of backbuffer for now, hope to fix that later).
// Also we manage ourself the HDR format, here allocating fp16 directly.
// With scriptable render loop we can allocate temporary RT in a command buffer, they will not be release with ExecuteCommandBuffer
// These temporary surface are release automatically at the end of the scriptable renderloop if not release explicitly
int w = camera.pixelWidth;
int h = camera.pixelHeight;
// Init buffer
// With scriptable render loop we must allocate ourself depth and color buffer (We must be independent of backbuffer for now, hope to fix that later).
// Also we manage ourself the HDR format, here allocating fp16 directly.
// With scriptable render loop we can allocate temporary RT in a command buffer, they will not be release with ExecuteCommandBuffer
// These temporary surface are release automatically at the end of the scriptable renderloop if not release explicitly
int w = camera.pixelWidth;
int h = camera.pixelHeight;
cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
cmd.GetTemporaryRT(m_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
if (!debugParameters.useForwardRenderingOnly)
{
m_gbufferManager.InitGBuffers(w, h, cmd);
}
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
cmd.GetTemporaryRT(m_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
if (!debugParameters.useForwardRenderingOnly)
{
m_gbufferManager.InitGBuffers(w, h, cmd);
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearDepth);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearDepth);
}
// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// Clear HDR target
using (new Utilities.ProfilingSample("Clear HDR target", renderLoop))
{
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
}
// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// Clear HDR target
{
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black, "Clear HDR target");
}
// Clear GBuffers
using (new Utilities.ProfilingSample("Clear GBuffer", renderLoop))
{
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
}
// Clear GBuffers
{
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black, "Clear GBuffer");
// END TEMP
// END TEMP
}
void RenderOpaqueRenderList(CullResults cull, Camera camera, RenderLoop renderLoop, string passName, RendererConfiguration rendererConfiguration = 0)

if (!debugParameters.useDepthPrepass)
return;
// TODO: Must do opaque then alpha masked for performance!
// TODO: front to back for opaque and by materal for opaque tested when we split in two
Utilities.SetRenderTarget(renderLoop, m_CameraDepthBufferRT, "Depth Prepass");
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");
using (new Utilities.ProfilingSample("Depth Prepass", renderLoop))
{
// TODO: Must do opaque then alpha masked for performance!
// TODO: front to back for opaque and by materal for opaque tested when we split in two
Utilities.SetRenderTarget(renderLoop, m_CameraDepthBufferRT);
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");
}
}
void RenderGBuffer(CullResults cull, Camera camera, RenderLoop renderLoop)

return ;
}
// setup GBuffer for rendering
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, "GBuffer Pass");
// render opaque objects into GBuffer
RenderOpaqueRenderList(cull, camera, renderLoop, "GBuffer", Utilities.kRendererConfigurationBakedLighting);
using (new Utilities.ProfilingSample("GBuffer Pass", renderLoop))
{
// setup GBuffer for rendering
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT);
// render opaque objects into GBuffer
RenderOpaqueRenderList(cull, camera, renderLoop, "GBuffer", Utilities.kRendererConfigurationBakedLighting);
}
}
// This pass is use in case of forward opaque and deferred rendering. We need to render forward objects before tile lighting pass

if (debugParameters.useDepthPrepass)
return;
// TODO: Use the render queue index to only send the forward opaque!
Utilities.SetRenderTarget(renderLoop, m_CameraDepthBufferRT, "Clear HDR target");
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");
using (new Utilities.ProfilingSample("Depth Prepass", renderLoop))
{
// TODO: Use the render queue index to only send the forward opaque!
Utilities.SetRenderTarget(renderLoop, m_CameraDepthBufferRT);
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");
}
using (new Utilities.ProfilingSample("DebugView Material Mode Pass", renderLoop))
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, Utilities.kClearAll, Color.black, "DebugView Material Mode Pass");
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, Utilities.kClearAll, Color.black);
Shader.SetGlobalInt("_DebugViewMaterial", (int)debugParameters.debugViewMaterial);

return ;
}
// Bind material data
m_LitRenderLoop.Bind();
m_SinglePassLightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBuffer);
// m_TilePassLightLoop.RenderDeferredLighting(camera, renderLoop, );
using (new Utilities.ProfilingSample("Single Pass - Deferred Lighting Pass", renderLoop))
{
// Bind material data
m_LitRenderLoop.Bind();
m_SinglePassLightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBuffer);
// m_TilePassLightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBuffer);
}
}
void RenderSky(Camera camera, RenderLoop renderLoop)

void RenderForward(CullResults cullResults, Camera camera, RenderLoop renderLoop)
{
// Bind material data
m_LitRenderLoop.Bind();
using (new Utilities.ProfilingSample("Forward Pass", renderLoop))
{
// Bind material data
m_LitRenderLoop.Bind();
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, "Forward Pass");
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT);
if (debugParameters.useForwardRenderingOnly)
{
RenderOpaqueRenderList(cullResults, camera, renderLoop, "Forward");
}
if (debugParameters.useForwardRenderingOnly)
{
RenderOpaqueRenderList(cullResults, camera, renderLoop, "Forward");
}
RenderTransparentRenderList(cullResults, camera, renderLoop, "Forward", Utilities.kRendererConfigurationBakedLighting);
RenderTransparentRenderList(cullResults, camera, renderLoop, "Forward", Utilities.kRendererConfigurationBakedLighting);
}
// Bind material data
m_LitRenderLoop.Bind();
using (new Utilities.ProfilingSample("Forward Unlit Pass", renderLoop))
{
// Bind material data
m_LitRenderLoop.Bind();
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, "Forward Unlit Pass");
RenderOpaqueRenderList(cullResults, camera, renderLoop, "ForwardUnlit");
RenderTransparentRenderList(cullResults, camera, renderLoop, "ForwardUnlit");
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT);
RenderOpaqueRenderList(cullResults, camera, renderLoop, "ForwardUnlit");
RenderTransparentRenderList(cullResults, camera, renderLoop, "ForwardUnlit");
}
// warning CS0162: Unreachable code detected // warning CS0429: Unreachable expression code detected
#pragma warning disable 162, 429
// If opaque velocity have been render during GBuffer no need to render it here
if ((ShaderConfig.VelocityInGbuffer == 0) || debugParameters.useForwardRenderingOnly)
return ;
using (new Utilities.ProfilingSample("Velocity Pass", renderLoop))
{
// warning CS0162: Unreachable code detected // warning CS0429: Unreachable expression code detected
#pragma warning disable 162, 429
// If opaque velocity have been render during GBuffer no need to render it here
if ((ShaderConfig.VelocityInGbuffer == 0) || debugParameters.useForwardRenderingOnly)
return ;
int w = camera.pixelWidth;
int h = camera.pixelHeight;
int w = camera.pixelWidth;
int h = camera.pixelHeight;
var cmd = new CommandBuffer { name = "Velocity Pass" };
cmd.GetTemporaryRT(m_VelocityBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetVelocityBufferFormat(), Builtin.RenderLoop.GetVelocityBufferReadWrite());
cmd.SetRenderTarget(m_VelocityBufferRT, m_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
var cmd = new CommandBuffer { name = "" };
cmd.GetTemporaryRT(m_VelocityBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetVelocityBufferFormat(), Builtin.RenderLoop.GetVelocityBufferReadWrite());
cmd.SetRenderTarget(m_VelocityBufferRT, m_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
RenderOpaqueRenderList(cullResults, camera, renderLoop, "MotionVectors");
#pragma warning restore 162, 429
RenderOpaqueRenderList(cullResults, camera, renderLoop, "MotionVectors");
#pragma warning restore 162, 429
}
int w = camera.pixelWidth;
int h = camera.pixelHeight;
using (new Utilities.ProfilingSample("Distortion Pass", renderLoop))
{
int w = camera.pixelWidth;
int h = camera.pixelHeight;
var cmd = new CommandBuffer { name = "Distortion Pass" };
cmd.GetTemporaryRT(m_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetDistortionBufferFormat(), Builtin.RenderLoop.GetDistortionBufferReadWrite());
cmd.SetRenderTarget(m_DistortionBufferRT, m_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
var cmd = new CommandBuffer { name = "" };
cmd.GetTemporaryRT(m_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetDistortionBufferFormat(), Builtin.RenderLoop.GetDistortionBufferReadWrite());
cmd.SetRenderTarget(m_DistortionBufferRT, m_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
// Only transparent object can render distortion vectors
RenderTransparentRenderList(cullResults, camera, renderLoop, "DistortionVectors");
// Only transparent object can render distortion vectors
RenderTransparentRenderList(cullResults, camera, renderLoop, "DistortionVectors");
}
// 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;
using (new Utilities.ProfilingSample("Final Pass", renderLoop))
{
// 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;
// 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);
// 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);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs1", tonemapCoeff1);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs2", tonemapCoeff2);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs1", tonemapCoeff1);
m_FinalPassMaterial.SetVector("_ToneMapCoeffs2", tonemapCoeff2);
m_FinalPassMaterial.SetFloat("_EnableToneMap", debugParameters.enableTonemap ? 1.0f : 0.0f);
m_FinalPassMaterial.SetFloat("_Exposure", debugParameters.exposure);
m_FinalPassMaterial.SetFloat("_EnableToneMap", debugParameters.enableTonemap ? 1.0f : 0.0f);
m_FinalPassMaterial.SetFloat("_Exposure", debugParameters.exposure);
var cmd = new CommandBuffer { name = "FinalPass" };
var cmd = new CommandBuffer { name = "" };
// Resolve our HDR texture to CameraTarget.
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget, m_FinalPassMaterial, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
// Resolve our HDR texture to CameraTarget.
cmd.Blit(m_CameraColorBufferRT, BuiltinRenderTextureType.CameraTarget, m_FinalPassMaterial, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
// Function to prepare light structure for GPU lighting

// build per tile light lists
m_SinglePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
m_TilePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
//m_TilePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
}
void Resize(Camera camera)

public override void Render(Camera[] cameras, RenderLoop renderLoop)
{
if (m_Dirty)
{
Rebuild();
}
if (!m_LitRenderLoop.isInit)
{
m_LitRenderLoop.RenderInit(renderLoop);

else
{
ShadowOutput shadows;
m_ShadowPass.Render(renderLoop, cullResults, out shadows);
using (new Utilities.ProfilingSample("Shadow Pass", renderLoop))
{
m_ShadowPass.Render(renderLoop, cullResults, out shadows);
}
PrepareLightsForGPU(cullResults, camera, ref shadows, ref m_lightList);
m_TilePassLightLoop.BuildGPULightLists(camera, renderLoop, m_lightList, m_CameraDepthBuffer);
using (new Utilities.ProfilingSample("Build Light list", renderLoop))
{
PrepareLightsForGPU(cullResults, camera, ref shadows, ref m_lightList);
//m_TilePassLightLoop.BuildGPULightLists(camera, renderLoop, m_lightList, m_CameraDepthBuffer);
PushGlobalParams(camera, renderLoop, m_lightList);
PushGlobalParams(camera, renderLoop, m_lightList);
}
RenderDeferredLighting(camera, renderLoop);
RenderSky(camera, renderLoop);

7
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs


};
[GenerateHLSL]
public enum EnvConstants
{
SpecCubeLodStep = 6
}
[GenerateHLSL]
public struct EnvLightData
{
public Vector3 positionWS;

6
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Lighting.hlsl


#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl"
#ifdef LIGHTLOOP_SINGLE_PASS
#ifdef LIGHTLOOP_SINGLE_PASS
#elif LIGHTLOOP_TILED_PASS
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.hlsl"
#endif
// Shadow use samling function define in header above and must be include before Material.hlsl

// LightLoop use evaluation BSDF function for light type define in Material.hlsl
#ifdef LIGHTLOOP_SINGLE_PASS
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePassLoop.hlsl"
#elif LIGHTLOOP_TILED_PASS
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePassLoop.hlsl"
#endif

13
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Resources/Deferred.shader


#pragma fragment FragDeferred
// Chose supported lighting architecture in case of deferred rendering
#pragma multi_compile LIGHTLOOP_SINGLE_PASS
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS
// TODO: This must be on lightloop side and include here....
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#pragma multi_compile __ ENABLE_DEBUG
// 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
#pragma multi_compile USE_FPTL_LIGHTLIST USE_CLUSTERED_LIGHTLIST
#pragma multi_compile _ ENABLE_DEBUG
//-------------------------------------------------------------------------------------
// Include

Coordinate coord = GetCoordinate(unPositionSS.xy, _ScreenSize.zw);
// No need to manage inverse depth, this is handled by the projection matrix
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, uint3(coord.unPositionSS, 0)).x;
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, coord.unPositionSS).x;
float3 positionWS = UnprojectToWorld(depth, coord.positionSS, _InvViewProjMatrix);
float3 V = GetWorldSpaceNormalizeViewDir(positionWS);

float3 diffuseLighting;
float3 specularLighting;
LightLoop(V, positionWS, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
LightLoop(V, positionWS, coord, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
return float4(diffuseLighting + specularLighting, 1.0);
}

3
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.cs


s_PunctualShadowList = new ComputeBuffer(HDRenderLoop.k_MaxShadowOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(PunctualShadowData)));
m_DeferredMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/Deferred");
m_DeferredMaterial.EnableKeyword("LIGHTLOOP_SINGLE_PASS");
}
public void OnDisable()

// m_gbufferManager.BindBuffers(m_DeferredMaterial);
// TODO: Bind depth textures
var cmd = new CommandBuffer { name = "Single Pass - Deferred Ligthing Pass" };
var cmd = new CommandBuffer { name = "" };
cmd.Blit(null, colorBuffer, m_DeferredMaterial, 0);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();

2
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePassLoop.hlsl


// ----------------------------------------------------------------------------
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, float3 positionWS, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
void LightLoop( float3 V, float3 positionWS, Coordinate coord, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
{

4
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ClusteredUtils.hlsl


#ifndef __CLUSTEREDUTILS_H__
#define __CLUSTEREDUTILS_H__
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.192092896e-07f
#endif
float GetScaleFromBase(float base)
{
const float C = (float)(1 << g_iLog2NumClusters);

2
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/scrbound.compute


StructuredBuffer<SFiniteLightBound> g_data : register( t0 );
#define FLT_EPSILON 1.192092896e-07F // smallest such that 1.0+FLT_EPSILON != 1.0
#define NR_THREADS 64
// output buffer

4
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ShaderBase.hlsl


float FetchDepth(Texture2D depthTexture, uint2 pixCoord)
{
return 1 - LOAD_TEXTURE2D(depthTexture, uint3(pixCoord.xy, 0)).x;
return 1.0 - LOAD_TEXTURE2D(depthTexture, pixCoord.xy).x;
return 1 - LOAD_TEXTURE2D_MSAA(depthTexture, uint3(pixCoord.xy, 0), sampleIdx).x;
return 1.0 - LOAD_TEXTURE2D_MSAA(depthTexture, pixCoord.xy, sampleIdx).x;
}
#endif

116
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs


{
string GetKeyword()
{
return "LIGHTLOOP_SINGLE_PASS";
return "LIGHTLOOP_TILE_PASS";
}
public const int MaxNumLights = 1024;

private static ComputeBuffer s_GlobalLightListAtomic;
// clustered light list specific buffers and data end
const int k_TileSize = 16;
SFiniteLightBound[] m_boundData;
SFiniteLightData[] m_lightData;
int m_lightCount;

Material m_DeferredMaterial;
Material m_DeferredReflectionMaterial;
const int k_TileSize = 16;
int GetNumTileX(Camera camera)
{
return (camera.pixelWidth + (k_TileSize - 1)) / k_TileSize;
}
int GetNumTileY(Camera camera)
{
return (camera.pixelWidth + (k_TileSize - 1)) / k_TileSize;
}
// Local function
void ClearComputeBuffers()
{

s_EnvLightList = new ComputeBuffer(HDRenderLoop.k_MaxEnvLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));
s_PunctualShadowList = new ComputeBuffer(HDRenderLoop.k_MaxShadowOnScreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(PunctualShadowData)));
// m_DeferredMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/TileDeferred");
// m_DeferredReflectionMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/TileDeferredReflection");
m_DeferredMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/Deferred");
m_DeferredMaterial.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredMaterial.EnableKeyword("LIGHTLOOP_TILE_DIRECT");
m_DeferredReflectionMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/Deferred");
m_DeferredReflectionMaterial.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredReflectionMaterial.EnableKeyword("LIGHTLOOP_TILE_INDIRECT");
}
public void OnDisable()

s_EnvLightList = null;
s_PunctualShadowList.Release();
s_PunctualShadowList = null;
/*
*/
}
public bool NeedResize()

}
}
// TEMP: These functions should be implemented C++ side, for now do it in C#
private static void SetMatrixCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4 mat)
{
var data = new float[16];
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[4 * c + r] = mat[r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
private static void SetMatrixArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4[] matArray)
{
int numMatrices = matArray.Length;
var data = new float[numMatrices * 16];
for (int n = 0; n < numMatrices; n++)
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[16 * n + 4 * c + r] = matArray[n][r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
private static void SetVectorArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Vector4[] vecArray)
{
int numVectors = vecArray.Length;
var data = new float[numVectors * 4];
for (int n = 0; n < numVectors; n++)
for (int i = 0; i < 4; i++)
data[4 * n + i] = vecArray[n][i];
cmd.SetComputeFloatParams(shadercs, name, data);
}
static Matrix4x4 GetFlipMatrix()
{
Matrix4x4 flip = Matrix4x4.identity;

cmd.DispatchCompute(buildPerVoxelLightListShader, s_ClearVoxelAtomicKernel, 1, 1, 1);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_iNrVisibLights", m_lightCount);
SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mScrProjection", projscr);
SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mInvScrProjection", invProjscr);
Utilities.SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mScrProjection", projscr);
Utilities.SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mInvScrProjection", invProjscr);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_iLog2NumClusters", k_Log2NumClusters);

cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_logBaseBuffer", s_PerTileLogBaseTweak);
}
var numTilesX = (camera.pixelWidth + 15) / 16;
var numTilesY = (camera.pixelHeight + 15) / 16;
var numTilesX = GetNumTileX(camera);
var numTilesY = GetNumTileY(camera);
cmd.DispatchCompute(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, numTilesX, numTilesY, 1);
}

var h = camera.pixelHeight;
var numTilesX = (w + 15) / 16;
var numTilesY = (h + 15) / 16;
var numTilesX = GetNumTileX(camera);
var numTilesY = GetNumTileY(camera);
var numBigTilesX = (w + 63) / 64;
var numBigTilesY = (h + 63) / 64;

var projscr = temp * proj;
var invProjscr = projscr.inverse;
var cmd = new CommandBuffer() { name = "Build light list" };
var cmd = new CommandBuffer() { name = "" };
// generate screen-space AABBs (used for both fptl and clustered).
{

var invProjh = projh.inverse;
cmd.SetComputeIntParam(buildScreenAABBShader, "g_iNrVisibLights", m_lightCount);
SetMatrixCS(cmd, buildScreenAABBShader, "g_mProjection", projh);
SetMatrixCS(cmd, buildScreenAABBShader, "g_mInvProjection", invProjh);
Utilities.SetMatrixCS(cmd, buildScreenAABBShader, "g_mProjection", projh);
Utilities.SetMatrixCS(cmd, buildScreenAABBShader, "g_mInvProjection", invProjh);
cmd.SetComputeBufferParam(buildScreenAABBShader, s_GenAABBKernel, "g_vBoundsBuffer", s_AABBBoundsBuffer);
cmd.DispatchCompute(buildScreenAABBShader, s_GenAABBKernel, (m_lightCount + 7) / 8, 1, 1);
}

{
cmd.SetComputeIntParams(buildPerBigTileLightListShader, "g_viDimensions", new int[2] { w, h });
cmd.SetComputeIntParam(buildPerBigTileLightListShader, "g_iNrVisibLights", m_lightCount);
SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mScrProjection", projscr);
SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mInvScrProjection", invProjscr);
Utilities.SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mScrProjection", projscr);
Utilities.SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mInvScrProjection", invProjscr);
/*
SetMatrixCS(cmd, buildPerTileLightListShader, "g_mScrProjection", projscr);
SetMatrixCS(cmd, buildPerTileLightListShader, "g_mInvScrProjection", invProjscr);
Utilities.SetMatrixCS(cmd, buildPerTileLightListShader, "g_mScrProjection", projscr);
Utilities.SetMatrixCS(cmd, buildPerTileLightListShader, "g_mInvScrProjection", invProjscr);
cmd.SetComputeTextureParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_depth_tex", new RenderTargetIdentifier(cameraDepthBuffer));
cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_vLightList", s_LightList);
if (enableBigTilePrepass) cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_vBigTileLightList", s_BigTileLightList);

{
VoxelLightListGeneration(cmd, camera, projscr, invProjscr, cameraDepthBuffer);
}
*/
loop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}

Shader.SetGlobalBuffer("_AreaLightList", s_AreaLightList);
Shader.SetGlobalBuffer("_PunctualShadowList", s_PunctualShadowList);
Shader.SetGlobalBuffer("_EnvLightList", s_EnvLightList);
/*
var cmd = new CommandBuffer { name = "Push Global Parameters" };
cmd.SetGlobalFloat("_NumTileX", (float)GetNumTileX(camera));
cmd.SetGlobalFloat("_NumTileY", (float)GetNumTileY(camera));
if (enableBigTilePrepass)
cmd.SetGlobalBuffer("g_vBigTileLightList", s_BigTileLightList);

}
}
cmd.SetGlobalFloat("g_nNumDirLights", numDirLights);
cmd.SetGlobalBuffer("g_dirLightData", s_DirLightList);
*/
/*
var bUseClusteredForDeferred = !usingFptl; // doesn't work on reflections yet but will soon
var cmd = new CommandBuffer();

}
else
{*/
// cmd.Blit(0, colorBuffer, m_DeferredMaterial, 0);
// cmd.Blit(0, colorBuffer, m_DeferredReflectionMaterial, 0);
cmd.Blit(0, colorBuffer, m_DeferredMaterial, 0);
cmd.Blit(0, colorBuffer, m_DeferredReflectionMaterial, 0);
// renderLoop.ExecuteCommandBuffer(cmd);
// cmd.Dispose();
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
}

38
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.hlsl


// uses the optimized single layered light list for opaques only
#if defined (LIGHTLOOP_TILE_DIRECT) || defined(LIGHTLOOP_TILE_ALL)
#define PROCESS_DIRECTIONAL_LIGHT
#define PROCESS_PUNCTUAL_LIGHT
#define PROCESS_AREA_LIGHT
#endif
#ifdef USE_FPTL_LIGHTLIST
#define OPAQUES_ONLY
#if defined (LIGHTLOOP_TILE_INDIRECT) || defined(LIGHTLOOP_TILE_ALL)
#define PROCESS_ENV_LIGHT
uint _NumTileX;
uint _NumTileY;
#define TILE_SIZE 16 // This is fixed
#define DWORD_PER_TILE 16 // See dwordsPerTile in TilePass.cs, we have roomm for 31 lights and a number of light value all store on 16 bit (ushort)
// these uniforms are only needed for when OPAQUES_ONLY is NOT defined
// but there's a problem with our front-end compilation of compute shaders with multiple kernels causing it to error
//#ifdef USE_CLUSTERED_LIGHTLIST
float g_fClustScale;
float g_fClustBase;
float g_fNearPlane;
float g_fFarPlane;
int g_iLog2NumClusters; // We need to always define these to keep constant buffer layouts compatible
uint g_isLogBaseBufferEnabled;
uint g_isOpaquesOnlyEnabled;
//#endif
#ifdef USE_CLUSTERED_LIGHTLIST
Buffer<uint> g_vLayeredOffsetsBuffer;
Buffer<float> g_logBaseBuffer;
#endif
// TODO: Need to correctly define the shadow framework, WIP
#include "../SinglePass/SinglePass.hlsl"

157
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePassLoop.hlsl


// LightLoop
// ----------------------------------------------------------------------------
// Calculate the offset in global light index light for current light category
int GetTileOffset(Coordinate coord, uint lightCategory)
{
uint2 tileIndex = coord.unPositionSS / TILE_SIZE;
return (tileIndex.y + lightCategory * _NumTileY) * _NumTileX + tileIndex.x;
}
void GetCountAndStartOpaque(Coordinate coord, uint lightCategory, float linearDepth, out uint start, out uint lightCount)
{
const int tileOffset = GetTileOffset(coord, lightCategory);
// The first entry inside a tile is the number of light for lightCategory (thus the +0)
lightCount = g_vLightListGlobal[DWORD_PER_TILE * tileOffs + 0] & 0xffff;
start = tileOffset;
}
uint FetchIndexOpaque(uint tileOffset, uint lightIndex)
{
const uint lightIndexPlusOne = lightIndex + 1; // Add +1 as first slot is reserved to store number of light
// Light index are store on 16bit
return (g_vLightListGlobal[DWORD_PER_TILE * tileOffset + (lightIndexPlusOne >> 1)] >> ((lightIndexPlusOne & 1) * DWORD_PER_TILE)) & 0xffff;
}
#ifdef USE_FPTL_LIGHTLIST
void GetCountAndStart(Coordinate coord, uint lightCategory, float linearDepth, out uint start, out uint lightCount)
{
GetCountAndStartOpaque(coord, lightCategory, linearDepth, start, lightCount);
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
return FetchIndexOpaque(tileOffs, lightIndex);
}
#else
#include "ClusteredUtils.hlsl"
void GetCountAndStart(Coordinate coord, uint lightCategory, float linearDepth, out uint start, out uint lightCount)
{
if(g_isOpaquesOnlyEnabled)
{
GetCountAndStartOpaque(coord, lightCategory, linearDepth, start, lightCount);
}
else
{
uint2 tileIndex = coord.unPositionSS / TILE_SIZE;
float logBase = g_fClustBase;
if (g_isLogBaseBufferEnabled)
{
logBase = g_logBaseBuffer[tileIndex.y * _NumTileX + tileIndex.x];
}
int clustIdx = SnapToClusterIdxFlex(linearDepth, logBase, g_isLogBaseBufferEnabled != 0);
int nrClusters = (1 << g_iLog2NumClusters);
const int idx = ((model * nrClusters + clustIdx) * _NumTileY + tileIndex.y) * _NumTileX + tileIndex.x;
uint dataPair = g_vLayeredOffsetsBuffer[idx];
start = dataPair & 0x7ffffff;
lightCount = (dataPair >> 27) & 31;
}
}
uint FetchIndex(uint tileOffset, uint lightIndex)
{
if(g_isOpaquesOnlyEnabled)
return FetchIndexOpaque(tileOffset, lightIndex);
else
return g_vLightListGlobal[tileOffset + lightIndex];
}
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
// todo (simplify): m22 is zero and m23 is +1/-1 (depends on left/right hand proj)
float m22 = g_mInvScrProjection[2].z, m23 = g_mInvScrProjection[2].w;
float m32 = g_mInvScrProjection[3].z, m33 = g_mInvScrProjection[3].w;
return (m22 * zDptBufSpace + m23) / (m32 * zDptBufSpace + m33);
//float3 vP = float3(0.0f,0.0f,zDptBufSpace);
//float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
//return v4Pres.z / v4Pres.w;
}
#endif
void LightLoop(float3 V, float3 positionWS, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
void LightLoop( float3 V, float3 positionWS, Coordinate coord, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
#if USE_CLUSTERED_LIGHTLIST
// TODO: Think more about the design, it is ok to do that ? hope the compiler could optimize it out as we do it before LightLoop call, else need to pass it as argument...
float depth = LOAD_TEXTURE2D(_CameraDepthTexture, coord.unPositionSS).x;
float linearDepth = GetLinearDepth(depth); // View space linear depth
#else
float linearDepth = 0.0; // unsued
#endif
LightLoopContext context;
ZERO_INITIALIZE(LightLoopContext, context);

int i = 0; // Declare once to avoid the D3D11 compiler warning.
#ifdef PROCESS_DIRECTIONAL_LIGHT
EvaluateBSDF_Directional(context, V, positionWS, prelightData, _DirectionalLightList[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Directional( context, V, positionWS, prelightData, _DirectionalLightList[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
#endif
for (i = 0; i < _PunctualLightCount; ++i)
#ifdef PROCESS_PUNCTUAL_LIGHT
uint punctualLightStart;
uint punctualLightCount;
GetCountAndStart(coord, DIRECT_LIGHT, linearDepth, punctualLightStart, punctualLightCount);
for (i = 0; i < punctualLightCount; ++i)
EvaluateBSDF_Punctual(context, V, positionWS, prelightData, _PunctualLightList[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Punctual( context, V, positionWS, prelightData, _PunctualLightList[FetchIndex(punctualLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
#endif
for (i = 0; i < _AreaLightCount; ++i)
#ifdef PROCESS_AREA_LIGHT
/*
// TODO: Area lights are where the sorting is important (Morten approach with while loop)
uint areaLightStart;
uint areaLightCount;
GetCountAndStart(coord, LightCatergory.AreaLight, linearDepth, areaLightStart, areaLightCount);
for (i = 0; i < areaLightCount; ++i)
EvaluateBSDF_Area(context, V, positionWS, prelightData, _AreaLightList[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Area( context, V, positionWS, prelightData, _AreaLightList[FetchIndex(areaLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
*/
#endif
#ifdef PROCESS_ENV_LIGHT
uint envLightStart;
uint envLightCount;
GetCountAndStart(coord, REFLECTION_LIGHT, linearDepth, envLightStart, envLightCount);
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
for (i = 0; i < envLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, positionWS, prelightData, _EnvLightList[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
#endif
// TODO
#if ENABLE_DEBUG
// c = OverlayHeatMap(pixCoord & 15, numLightsProcessed, c);
#endif
}

3
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Builtin/BuiltinData.hlsl


result = builtinData.bakeDiffuseLighting;
break;
case DEBUGVIEW_BUILTIN_BUILTINDATA_EMISSIVE_COLOR:
result = builtinData.emissiveColor; needLinearToSRGB = true;
// emissiveColor is premultiply by emissive intensity
result = (builtinData.emissiveColor / builtinData.emissiveIntensity); needLinearToSRGB = true;
break;
case DEBUGVIEW_BUILTIN_BUILTINDATA_EMISSIVE_INTENSITY:
result = builtinData.emissiveIntensity.xxx;

287
Assets/ScriptableRenderLoop/HDRenderLoop/Material/LayeredLit/Editor/LayeredLitUI.cs


{
internal class LayeredLitGUI : LitGUI
{
public enum LayerMapping
public enum LayerUVBaseMapping
UV3,
//Triplanar,
Triplanar,
private class Styles
public enum LayerUVDetailMapping
{
UV0,
UV1,
UV3
}
private class StylesLayer
{
public readonly GUIContent[] layerLabels =
{

new GUIContent("Layer 3"),
};
public readonly GUIContent materialLayer = new GUIContent("Material");
public readonly GUIContent syncButton = new GUIContent("Re-Synchronize Layers", "Re-synchronize all layers's properties with the referenced Material");
public readonly GUIContent layers = new GUIContent("Layers");
public readonly GUIContent emission = new GUIContent("Emissive");
public readonly GUIContent layerMapMask = new GUIContent("Layer Mask", "Layer mask (multiplied by vertex color if enabled)");
public readonly GUIContent layerMapVertexColor = new GUIContent("Use Vertex Color", "Layer mask (multiplied by layer mask if enabled)");
public readonly GUIContent layerCount = new GUIContent("Layer Count", "Number of layers.");
public readonly GUIContent layerSize = new GUIContent("Size", "Size of the layer mapping in world units.");
public readonly GUIContent layerMapping = new GUIContent("Mapping", "Mapping mode of the layer.");
public readonly GUIContent materialLayerText = new GUIContent("Material");
public readonly GUIContent syncButtonText = new GUIContent("Re-Synchronize Layers", "Re-synchronize all layers's properties with the referenced Material");
public readonly GUIContent layersText = new GUIContent("Layers");
public readonly GUIContent emissiveText = new GUIContent("Emissive");
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 layerCountText = new GUIContent("Layer Count", "Number of layers.");
public readonly GUIContent layerTexWorldScaleText = new GUIContent("Tex world scale", "Scale to apply to world position for Planar/Trilinear");
public readonly GUIContent UVBaseText = new GUIContent("Base UV Mapping", "Base UV Mapping mode of the layer.");
public readonly GUIContent UVDetailText = new GUIContent("Detail UV Mapping", "Detail UV Mapping mode of the layer.");
static Styles s_Styles = null;
private static Styles styles { get { if (s_Styles == null) s_Styles = new Styles(); return s_Styles; } }
static StylesLayer s_Styles = null;
private static StylesLayer styles { get { if (s_Styles == null) s_Styles = new StylesLayer(); return s_Styles; } }
// Needed for json serialization to work
[Serializable]

}
private const int kMaxLayerCount = 4;
private const int kSyncButtonWidth = 58;
private const string kLayerMaskMap = "_LayerMaskMap";
private const string kLayerMaskVertexColor = "_LayerMaskVertexColor";
private const string kLayerCount = "_LayerCount";
private const string kLayerMapping = "_LayerMapping";
private const string kLayerSize = "_LayerSize";
const int kMaxLayerCount = 4;
const int kSyncButtonWidth = 58;
private Material[] m_MaterialLayers = new Material[kMaxLayerCount];
Material[] m_MaterialLayers = new Material[kMaxLayerCount];
MaterialProperty layerCountProperty = null;
MaterialProperty layerMaskMapProperty = null;
MaterialProperty layerMaskVertexColorProperty = null;
MaterialProperty[] layerMappingProperty = new MaterialProperty[kMaxLayerCount];
MaterialProperty[] layerSizeProperty = new MaterialProperty[kMaxLayerCount];
MaterialProperty layerMaskMap = null;
const string kLayerMaskMap = "_LayerMaskMap";
MaterialProperty layerMaskVertexColor = null;
const string kLayerMaskVertexColor = "_LayerMaskVertexColor";
MaterialProperty layerCount = null;
const string kLayerCount = "_LayerCount";
MaterialProperty[] layerTexWorldScale = new MaterialProperty[kMaxLayerCount];
const string kLayerTexWorldScale = "_TexWorldScale";
MaterialProperty[] layerUVBase = new MaterialProperty[kMaxLayerCount];
const string kLayerUVBase = "_UVBase";
MaterialProperty[] layerUVMappingMask = new MaterialProperty[kMaxLayerCount];
const string kLayerUVMappingMask = "_UVMappingMask";
MaterialProperty[] layerUVDetail = new MaterialProperty[kMaxLayerCount];
const string kLayerUVDetail = "_UVDetail";
MaterialProperty[] layerUVDetailsMappingMask = new MaterialProperty[kMaxLayerCount];
const string kLayerUVDetailsMappingMask = "_UVDetailsMappingMask";
int layerCount
MaterialProperty layerEmissiveColor = null;
const string kLayerEmissiveColor = "_EmissiveColor";
MaterialProperty layerEmissiveColorMap = null;
const string kLayerEmissiveColorMap = "_EmissiveColorMap";
MaterialProperty layerEmissiveIntensity = null;
const string kLayerEmissiveIntensity = "_EmissiveIntensity";
private void FindLayerProperties(MaterialProperty[] props)
set { layerCountProperty.floatValue = (float)value; }
get { return (int)layerCountProperty.floatValue; }
layerMaskMap = FindProperty(kLayerMaskMap, props);
layerMaskVertexColor = FindProperty(kLayerMaskVertexColor, props);
layerCount = FindProperty(kLayerCount, props);
for (int i = 0; i < numLayer; ++i)
{
layerTexWorldScale[i] = FindProperty(string.Format("{0}{1}", kLayerTexWorldScale, i), props);
layerUVBase[i] = FindProperty(string.Format("{0}{1}", kLayerUVBase, i), props);
layerUVMappingMask[i] = FindProperty(string.Format("{0}{1}", kLayerUVMappingMask, i), props);
layerUVDetail[i] = FindProperty(string.Format("{0}{1}", kLayerUVDetail, i), props);
layerUVDetailsMappingMask[i] = FindProperty(string.Format("{0}{1}", kLayerUVDetailsMappingMask, i), props);
}
layerEmissiveColor = FindProperty(kLayerEmissiveColor, props);
layerEmissiveColorMap = FindProperty(kLayerEmissiveColorMap, props);
layerEmissiveIntensity = FindProperty(kLayerEmissiveIntensity, props);
}
int numLayer
{
set { layerCount.floatValue = (float)value; }
get { return (int)layerCount.floatValue; }
for (int i = 0; i < layerCount; ++i)
for (int i = 0; i < numLayer; ++i)
{
SynchronizeLayerProperties(i);
}

{
bool result = true;
outValueNames = "";
for (int i = 0; i < layerCount; ++i)
for (int i = 0; i < numLayer; ++i)
{
Material layer = m_MaterialLayers[i];
if (layer != null)

outValueNames += shortNames[currentValue] + " ";
for (int j = i + 1; j < layerCount; ++j)
for (int j = i + 1; j < numLayer; ++j)
{
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)

{
bool result = true;
outValueNames = "";
for (int i = 0; i < layerCount; ++i)
for (int i = 0; i < numLayer; ++i)
{
Material layer = m_MaterialLayers[i];
if (layer != null)

for (int j = i + 1; j < layerCount; ++j)
for (int j = i + 1; j < numLayer; ++j)
{
Material otherLayer = m_MaterialLayers[j];
if (otherLayer != null)

{
string optionValueNames = "";
// We need to check consistency between all layers.
// Each input options and each input maps might can result in different #defines in the shader so all of them need to be consistent
// Each input options and each input maps can result in different #defines in the shader so all of them need to be consistent
string[] emissiveModeShortNames = { "Color", "Mask" };
string[] detailModeShortNames = { "DNormal", "DAOHeight" };
if (!CheckInputOptionConsistency(kSmoothnessTextureChannelProp, smoothnessSourceShortNames, ref optionValueNames))
if (!CheckInputOptionConsistency(kSmoothnessTextureChannel, smoothnessSourceShortNames, ref optionValueNames))
if (!CheckInputOptionConsistency(kEmissiveColorMode, emissiveModeShortNames, ref optionValueNames))
{
warningInputOptions += "Emissive Mode: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kNormalMapSpace, normalMapShortNames, ref optionValueNames))
{
warningInputOptions += "Normal Map Space: " + optionValueNames + "\n";

warningInputOptions += "Height Map Mode: " + optionValueNames + "\n";
}
if (!CheckInputOptionConsistency(kDetailMapMode, detailModeShortNames, ref optionValueNames))
{
warningInputOptions += "Detail Map Mode: " + optionValueNames + "\n";
}
if (warningInputOptions != string.Empty)

{
warningInputMaps += "Normal Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kDetailMap, ref optionValueNames))
{
warningInputMaps += "Detail Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kspecularOcclusionMap, ref optionValueNames))
if (!CheckInputMapConsistency(kSpecularOcclusionMap, ref optionValueNames))
}
if (!CheckInputMapConsistency(kEmissiveColorMap, ref optionValueNames))
{
warningInputMaps += "Emissive Color Map: " + optionValueNames + "\n";
}
if (!CheckInputMapConsistency(kHeightMap, ref optionValueNames))
{

// We synchronize input options with the firsts non null Layer (all layers should have consistent options)
Material firstLayer = null;
int i = 0;
while (i < layerCount && !(firstLayer = m_MaterialLayers[i])) ++i;
while (i < numLayer && !(firstLayer = m_MaterialLayers[i])) ++i;
material.SetFloat(kSmoothnessTextureChannelProp, firstLayer.GetFloat(kSmoothnessTextureChannelProp));
material.SetFloat(kEmissiveColorMode, firstLayer.GetFloat(kEmissiveColorMode));
material.SetFloat(kSmoothnessTextureChannel, firstLayer.GetFloat(kSmoothnessTextureChannel));
// Force emissive to be emissive color
material.SetFloat(kEmissiveColorMode, (float)EmissiveColorMode.UseEmissiveColor);
}
}

EditorGUI.indentLevel++;
EditorGUI.BeginChangeCheck();
m_MaterialLayers[layerIndex] = EditorGUILayout.ObjectField(styles.materialLayer, m_MaterialLayers[layerIndex], typeof(Material), true) as Material;
m_MaterialLayers[layerIndex] = EditorGUILayout.ObjectField(styles.materialLayerText, m_MaterialLayers[layerIndex], typeof(Material), true) as Material;
if (EditorGUI.EndChangeCheck())
{
Undo.RecordObject(materialImporter, "Change layer material");

EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(layerMappingProperty[layerIndex], styles.layerMapping);
m_MaterialEditor.ShaderProperty(layerUVBase[layerIndex], styles.UVBaseText);
if ((LayerMapping)layerMappingProperty[layerIndex].floatValue == LayerMapping.Planar)
if (((LayerUVBaseMapping)layerUVBase[layerIndex].floatValue == LayerUVBaseMapping.Planar) ||
((LayerUVBaseMapping)layerUVBase[layerIndex].floatValue == LayerUVBaseMapping.Triplanar))
m_MaterialEditor.ShaderProperty(layerSizeProperty[layerIndex], styles.layerSize);
m_MaterialEditor.ShaderProperty(layerTexWorldScale[layerIndex], styles.layerTexWorldScaleText);
else
{
EditorGUI.BeginChangeCheck();
m_MaterialEditor.ShaderProperty(layerUVDetail[layerIndex], styles.UVDetailText);
if (EditorGUI.EndChangeCheck())
{
result = true;
}
}
EditorGUI.indentLevel--;

GUI.changed = false;
EditorGUI.indentLevel++;
GUILayout.Label(styles.layers, EditorStyles.boldLabel);
GUILayout.Label(styles.layersText, EditorStyles.boldLabel);
int newLayerCount = EditorGUILayout.IntSlider(styles.layerCount, (int)layerCountProperty.floatValue, 2, 4);
int newLayerCount = EditorGUILayout.IntSlider(styles.layerCountText, (int)layerCount.floatValue, 2, 4);
layerCountProperty.floatValue = (float)newLayerCount;
layerCount.floatValue = (float)newLayerCount;
m_MaterialEditor.ShaderProperty(layerMaskVertexColorProperty, styles.layerMapVertexColor);
m_MaterialEditor.TexturePropertySingleLine(styles.layerMapMask, layerMaskMapProperty);
m_MaterialEditor.ShaderProperty(layerMaskVertexColor, styles.layerMapVertexColorText);
m_MaterialEditor.TexturePropertySingleLine(styles.layerMapMaskText, layerMaskMap);
for (int i = 0; i < layerCount; i++)
for (int i = 0; i < numLayer; i++)
{
layerChanged |= DoLayerGUI(materialImporter, i);
}

{
GUILayout.FlexibleSpace();
if (GUILayout.Button(styles.syncButton))
if (GUILayout.Button(styles.syncButtonText))
{
SynchronizeAllLayersProperties();
layerChanged = true;

{
// Find first non null layer
int i = 0;
while (i < layerCount && (m_MaterialLayers[i] == null)) ++i;
while (i < numLayer && (m_MaterialLayers[i] == null)) ++i;
if (i < layerCount)
if (i < numLayer)
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap + i));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kSpecularOcclusionMap + i));
SetKeyword(material, "_LAYER_MASK_MAP", material.GetTexture(kLayerMaskMap));
protected override void SetupEmissionGIFlags(Material material)
{
// Setup lightmap emissive flags
bool nonNullEmissive = false;
for(int i = 0 ; i < layerCount ; ++i)
{
string paramName = string.Format("_EmissiveIntensity{0}", i);
if (material.GetFloat(paramName) > 0.0f)
{
nonNullEmissive = true;
break;
}
}
var realtimeEmission = (material.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
bool shouldEmissionBeEnabled = nonNullEmissive || realtimeEmission;
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{
if (shouldEmissionBeEnabled)
flags &= ~MaterialGlobalIlluminationFlags.EmissiveIsBlack;
else
flags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
material.globalIlluminationFlags = flags;
}
}
if (layerCount == 4)
if (numLayer == 4)
else if (layerCount == 3)
else if (numLayer == 3)
{
SetKeyword(material, "_LAYEREDLIT_4_LAYERS", false);
SetKeyword(material, "_LAYEREDLIT_3_LAYERS", true);

SetKeyword(material, "_LAYEREDLIT_3_LAYERS", false);
}
const string kLayerMappingUV1 = "_LAYER_MAPPING_UV1_";
const string kLayerMappingPlanar = "_LAYER_MAPPING_PLANAR_";
for (int i = 0 ; i <layerCount ; ++i)
for (int i = 0 ; i < numLayer; ++i)
string layerMappingParam = string.Format("{0}{1}", kLayerMapping, i);
LayerMapping layerMapping = (LayerMapping)material.GetFloat(layerMappingParam);
string currentLayerMappingUV1 = string.Format("{0}{1}", kLayerMappingUV1, i);
string currentLayerMappingPlanar = string.Format("{0}{1}", kLayerMappingPlanar, i);
// We setup the masking map based on the enum for each layer.
// using mapping mask allow to reduce the number of generated combination for a very small increase in ALU
string layerUVBaseParam = string.Format("{0}{1}", kLayerUVBase, i);
LayerUVBaseMapping layerUVBaseMapping = (LayerUVBaseMapping)material.GetFloat(layerUVBaseParam);
string layerUVDetailParam = string.Format("{0}{1}", kLayerUVDetail, i);
LayerUVDetailMapping layerUVDetailMapping = (LayerUVDetailMapping)material.GetFloat(layerUVDetailParam);
if(layerMapping == LayerMapping.UV1)
float X, Y, Z, W;
X = (layerUVBaseMapping == LayerUVBaseMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVBaseMapping == LayerUVBaseMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVBaseMapping == LayerUVBaseMapping.UV3) ? 1.0f : 0.0f;
W = (layerUVBaseMapping == LayerUVBaseMapping.Planar) ? 1.0f : 0.0f;
layerUVMappingMask[i].colorValue = new Color(X, Y, Z, W);
if (layerUVBaseMapping == LayerUVBaseMapping.Triplanar)
SetKeyword(material, currentLayerMappingUV1, true);
SetKeyword(material, currentLayerMappingPlanar, false);
SetKeyword(material, currentLayerMappingTriplanar, false);
SetKeyword(material, currentLayerMappingTriplanar, true);
else if(layerMapping == LayerMapping.Planar)
// If base is planar mode, detail is planar too
if (W > 0.0f)
SetKeyword(material, currentLayerMappingUV1, false);
SetKeyword(material, currentLayerMappingPlanar, true);
SetKeyword(material, currentLayerMappingTriplanar, false);
X = Y = Z = 0.0f;
}
else
{
X = (layerUVDetailMapping == LayerUVDetailMapping.UV0) ? 1.0f : 0.0f;
Y = (layerUVDetailMapping == LayerUVDetailMapping.UV1) ? 1.0f : 0.0f;
Z = (layerUVDetailMapping == LayerUVDetailMapping.UV3) ? 1.0f : 0.0f;
//else if(layerMapping == LayerMapping.Triplanar)
//{
// SetKeyword(material, currentLayerMappingUV1, false);
// SetKeyword(material, currentLayerMappingPlanar, false);
// SetKeyword(material, currentLayerMappingTriplanar, true);
//}
}
}
private void FindLayerProperties(MaterialProperty[] props)
{
layerMaskMapProperty = FindProperty(kLayerMaskMap, props);
layerMaskVertexColorProperty = FindProperty(kLayerMaskVertexColor, props);
layerCountProperty = FindProperty(kLayerCount, props);
for (int i = 0; i < layerCount; ++i)
{
layerMappingProperty[i] = FindProperty(string.Format("{0}{1}", kLayerMapping, i), props);
layerSizeProperty[i] = FindProperty(string.Format("{0}{1}", kLayerSize, i), props);
layerUVDetailsMappingMask[i].colorValue = new Color(X, Y, Z, 0.0f); // W Reuse planar mode from base
}
}

EditorGUI.BeginChangeCheck();
{
ShaderOptionsGUI();
EditorGUI.indentLevel++;
EditorGUILayout.LabelField(styles.emission);
m_MaterialEditor.LightmapEmissionProperty(1);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
}
if (EditorGUI.EndChangeCheck())

bool layerChanged = DoLayersGUI(materialImporter);
EditorGUILayout.Space();
GUILayout.Label(Styles.emissiveText, EditorStyles.boldLabel);
EditorGUI.indentLevel++;
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, layerEmissiveColorMap, layerEmissiveColor);
m_MaterialEditor.ShaderProperty(layerEmissiveIntensity, Styles.emissiveIntensityText);
m_MaterialEditor.LightmapEmissionProperty(1);
EditorGUI.indentLevel--;
CheckLayerConsistency();

215
Assets/ScriptableRenderLoop/HDRenderLoop/Material/LayeredLit/LayeredLit.shader


// They are use to fill a SurfaceData. With a MaterialGraph this should not exist.
// Reminder. Color here are in linear but the UI (color picker) do the conversion sRGB to linear
_BaseColor0("BaseColor0", Color) = (1,1,1,1)
_BaseColor0("BaseColor0", Color) = (1, 1, 1, 1)
_BaseColor1("BaseColor1", Color) = (1, 1, 1, 1)
_BaseColor2("BaseColor2", Color) = (1, 1, 1, 1)
_BaseColor3("BaseColor3", Color) = (1, 1, 1, 1)

_NormalMap2("NormalMap2", 2D) = "bump" {}
_NormalMap3("NormalMap3", 2D) = "bump" {}
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
_HeightMap0("HeightMap0", 2D) = "black" {}
_HeightMap1("HeightMap1", 2D) = "black" {}
_HeightMap2("HeightMap2", 2D) = "black" {}

_HeightBias2("Height Bias2", Float) = 0
_HeightBias3("Height Bias3", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
_DetailMap0("DetailMap0", 2D) = "black" {}
_DetailMap1("DetailMap1", 2D) = "black" {}
_DetailMap2("DetailMap2", 2D) = "black" {}
_DetailMap3("DetailMap3", 2D) = "black" {}
_EmissiveColor0("EmissiveColor0", Color) = (0, 0, 0)
_EmissiveColor1("EmissiveColor1", Color) = (0, 0, 0)
_EmissiveColor2("EmissiveColor2", Color) = (0, 0, 0)
_EmissiveColor3("EmissiveColor3", Color) = (0, 0, 0)
_DetailMask0("DetailMask0", 2D) = "white" {}
_DetailMask1("DetailMask1", 2D) = "white" {}
_DetailMask2("DetailMask2", 2D) = "white" {}
_DetailMask3("DetailMask3", 2D) = "white" {}
_EmissiveColorMap0("EmissiveColorMap0", 2D) = "white" {}
_EmissiveColorMap1("EmissiveColorMap1", 2D) = "white" {}
_EmissiveColorMap2("EmissiveColorMap2", 2D) = "white" {}
_EmissiveColorMap3("EmissiveColorMap3", 2D) = "white" {}
_DetailAlbedoScale0("_DetailAlbedoScale0", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale1("_DetailAlbedoScale1", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale2("_DetailAlbedoScale2", Range(-2.0, 2.0)) = 1
_DetailAlbedoScale3("_DetailAlbedoScale3", Range(-2.0, 2.0)) = 1
_EmissiveIntensity0("EmissiveIntensity0", Float) = 0
_EmissiveIntensity1("EmissiveIntensity1", Float) = 0
_EmissiveIntensity2("EmissiveIntensity2", Float) = 0
_EmissiveIntensity3("EmissiveIntensity3", Float) = 0
_DetailNormalScale0("_DetailNormalScale0", Range(0.0, 2.0)) = 1
_DetailNormalScale1("_DetailNormalScale1", Range(0.0, 2.0)) = 1
_DetailNormalScale2("_DetailNormalScale2", Range(0.0, 2.0)) = 1
_DetailNormalScale3("_DetailNormalScale3", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale0("_DetailSmoothnessScale0", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale1("_DetailSmoothnessScale1", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale2("_DetailSmoothnessScale2", Range(-2.0, 2.0)) = 1
_DetailSmoothnessScale3("_DetailSmoothnessScale3", Range(-2.0, 2.0)) = 1
_DetailHeightScale0("_DetailHeightScale0", Range(-2.0, 2.0)) = 1
_DetailHeightScale1("_DetailHeightScale1", Range(-2.0, 2.0)) = 1
_DetailHeightScale2("_DetailHeightScale2", Range(-2.0, 2.0)) = 1
_DetailHeightScale3("_DetailHeightScale3", Range(-2.0, 2.0)) = 1
_LayerSize0("LayerSize0", Float) = 1.0
_LayerSize1("LayerSize1", Float) = 1.0
_LayerSize2("LayerSize2", Float) = 1.0
_LayerSize3("LayerSize3", Float) = 1.0
_DetailAOScale0("_DetailAOScale0", Range(-2.0, 2.0)) = 1
_DetailAOScale1("_DetailAOScale1", Range(-2.0, 2.0)) = 1
_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
// Blend mask between layer
_EmissiveColor("EmissiveColor", Color) = (0, 0, 0)
_EmissiveColorMap("EmissiveColorMap", 2D) = "white" {}
_EmissiveIntensity("EmissiveIntensity", Float) = 0
[ToggleOff] _DistortionOnly("Distortion Only", Float) = 0.0
[ToggleOff] _DistortionDepthTest("Distortion Only", Float) = 0.0

[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[HideInInspector] _CullMode("__cullmode", Float) = 2.0
// Material Id
[HideInInspector] _MaterialId("_MaterialId", FLoat) = 0
[HideInInspector] _LayerCount("__layerCount", Float) = 2.0
[Enum(None, 0, DoubleSided, 1, DoubleSidedLigthingFlip, 2, DoubleSidedLigthingMirror, 3)] _DoubleSidedMode("Double sided mode", Float) = 0
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(None, 0, DoubleSided, 1, DoubleSidedLigthingFlip, 2, DoubleSidedLigthingMirror, 3)] _DoubleSidedMode("Double sided mode", Float) = 0
//[Enum(UV0, 0, UV1, 1, Planar, 2, Triplanar, 3)] _LayerMapping0("Layer 0 Mapping", Float) = 0
//[Enum(UV0, 0, UV1, 1, Planar, 2, Triplanar, 3)] _LayerMapping1("Layer 1 Mapping", Float) = 0
//[Enum(UV0, 0, UV1, 1, Planar, 2, Triplanar, 3)] _LayerMapping2("Layer 2 Mapping", Float) = 0
//[Enum(UV0, 0, UV1, 1, Planar, 2, Triplanar, 3)] _LayerMapping3("Layer 3 Mapping", Float) = 0
[HideInInspector] _LayerCount("_LayerCount", Float) = 2.0
[Enum(UV0, 0, UV1, 1, Planar, 2)] _LayerMapping0("Layer 0 Mapping", Float) = 0
[Enum(UV0, 0, UV1, 1, Planar, 2)] _LayerMapping1("Layer 1 Mapping", Float) = 0
[Enum(UV0, 0, UV1, 1, Planar, 2)] _LayerMapping2("Layer 2 Mapping", Float) = 0
[Enum(UV0, 0, UV1, 1, Planar, 2)] _LayerMapping3("Layer 3 Mapping", Float) = 0
_TexWorldScale0("Scale to apply on world coordinate", Float) = 1.0
_TexWorldScale1("Scale to apply on world coordinate", Float) = 1.0
_TexWorldScale2("Scale to apply on world coordinate", Float) = 1.0
_TexWorldScale3("Scale to apply on world coordinate", Float) = 1.0
[Enum(UV0, 0, UV1, 1, UV3, 2, Planar, 3, Triplanar, 4)] _UVBase0("UV Set for base0", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2, Planar, 3, Triplanar, 4)] _UVBase1("UV Set for base1", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2, Planar, 3, Triplanar, 4)] _UVBase2("UV Set for base2", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2, Planar, 3, Triplanar, 4)] _UVBase3("UV Set for base3", Float) = 0
[HideInInspector] _UVMappingMask0("_UVMappingMask0", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask1("_UVMappingMask1", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask2("_UVMappingMask2", Color) = (1, 0, 0, 0)
[HideInInspector] _UVMappingMask3("_UVMappingMask3", Color) = (1, 0, 0, 0)
[Enum(UV0, 0, UV1, 1, UV3, 2)] _UVDetail0("UV Set for detail0", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2)] _UVDetail1("UV Set for detail1", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2)] _UVDetail2("UV Set for detail2", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2)] _UVDetail3("UV Set for detail3", Float) = 0
[HideInInspector] _UVDetailsMappingMask0("_UVDetailsMappingMask0", Float) = 0
[HideInInspector] _UVDetailsMappingMask1("_UVDetailsMappingMask1", Float) = 0
[HideInInspector] _UVDetailsMappingMask2("_UVDetailsMappingMask2", Float) = 0
[HideInInspector] _UVDetailsMappingMask3("_UVDetailsMappingMask3", Float) = 0
// Unused but to be able to share litUI.Sahder and layeredUI.Shader
[HideInInspector] _UVBase("UV Set for base", Float) = 0
[HideInInspector] _UVDetail("UV Set for base", Float) = 0
[HideInInspector] _TexWorldScale("Scale to apply on world coordinate", Float) = 1.0
[HideInInspector] _UVMappingMask("_UVMappingMask", Color) = (1, 0, 0, 0)
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1, 0, 0, 0)
}
HLSLINCLUDE

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _ _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_0
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_1
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_2
#pragma shader_feature _LAYER_MAPPING_TRIPLANAR_3
#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _REQUIRE_UV3
#pragma shader_feature _EMISSIVE_COLOR
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
#pragma shader_feature _EMISSIVE_COLOR
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _LAYER_MASK_MAP
#pragma shader_feature _LAYER_MASK_VERTEX_COLOR
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _LAYER_VERTEX_COLOR
#pragma shader_feature _ _LAYER_MAPPING_UV1_0 _LAYER_MAPPING_PLANAR_0 _LAYER_MAPPING_TRIPLANAR_0
#pragma shader_feature _ _LAYER_MAPPING_UV1_1 _LAYER_MAPPING_PLANAR_1 _LAYER_MAPPING_TRIPLANAR_1
#pragma shader_feature _ _LAYER_MAPPING_UV1_2 _LAYER_MAPPING_PLANAR_2 _LAYER_MAPPING_TRIPLANAR_2
#pragma shader_feature _ _LAYER_MAPPING_UV1_3 _LAYER_MAPPING_PLANAR_3 _LAYER_MAPPING_TRIPLANAR_3
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED
#pragma multi_compile DYNAMICLIGHTMAP_OFF DYNAMICLIGHTMAP_ON
// TODO: We should have this keyword only if VelocityInGBuffer is enable, how to do that ?
//#pragma multi_compile VELOCITYOUTPUT_OFF VELOCITYOUTPUT_ON
//-------------------------------------------------------------------------------------
// Define

# define _LAYER_COUNT 2
#endif
struct LayerCoordinates
{
float2 texcoord[_MAX_LAYER];
bool isTriplanar[_MAX_LAYER];
};
float4 SampleLayer(TEXTURE2D_ARGS(layerTex, layerSampler), LayerCoordinates layerCoord, int layerIndex)
{
if (layerCoord.isTriplanar[layerIndex])
{
// TODO
return SAMPLE_TEXTURE2D(layerTex, layerSampler, layerCoord.texcoord[layerIndex]);
}
else
{
return SAMPLE_TEXTURE2D(layerTex, layerSampler, layerCoord.texcoord[layerIndex]);
}
}
// Set of users variables
#define PROP_DECL(type, name) type name, name##0, name##1, name##2, name##3;
#define PROP_DECL_TEX2D(name)\

TEXTURE2D(name##2); \
TEXTURE2D(name##3);
#define PROP_SAMPLE(name, textureName, layerCoord, swizzle)\
name##0 = SampleLayer(TEXTURE2D_PARAM(textureName##0, sampler##textureName##0), layerCoord, 0).##swizzle; \
name##1 = SampleLayer(TEXTURE2D_PARAM(textureName##1, sampler##textureName##0), layerCoord, 1).##swizzle; \
name##2 = SampleLayer(TEXTURE2D_PARAM(textureName##2, sampler##textureName##0), layerCoord, 2).##swizzle; \
name##3 = SampleLayer(TEXTURE2D_PARAM(textureName##3, sampler##textureName##0), layerCoord, 3).##swizzle;
#define PROP_MUL(name, multiplier, swizzle)\
name##0 *= multiplier##0.##swizzle; \
name##1 *= multiplier##1.##swizzle; \
name##2 *= multiplier##2.##swizzle; \
name##3 *= multiplier##3.##swizzle;
#define PROP_ASSIGN(name, input, swizzle)\
name##0 = input##0.##swizzle; \
name##1 = input##1.##swizzle; \
name##2 = input##2.##swizzle; \
name##3 = input##3.##swizzle;
#define PROP_ASSIGN_VALUE(name, input)\
name##0 = input; \
name##1 = input; \
name##2 = input; \
name##3 = input;
#define PROP_BLEND_COLOR(name, mask) name = BlendLayeredColor(name##0, name##1, name##2, name##3, mask);
#define PROP_BLEND_SCALAR(name, mask) name = BlendLayeredScalar(name##0, name##1, name##2, name##3, mask);
//-------------------------------------------------------------------------------------
// variable declaration

PROP_DECL(float4, _BaseColor);
PROP_DECL_TEX2D(_BaseColorMap);
PROP_DECL_TEX2D(_DetailMask);
PROP_DECL_TEX2D(_DetailMap);
float4 _DetailMap0_ST;
float4 _DetailMap1_ST;
float4 _DetailMap2_ST;
float4 _DetailMap3_ST;
PROP_DECL(float, _UVDetail);
PROP_DECL(float, _DetailAlbedoScale);
PROP_DECL(float, _DetailNormalScale);
PROP_DECL(float, _DetailSmoothnessScale);
PROP_DECL(float, _DetailHeightScale);
PROP_DECL(float, _DetailAOScale);
PROP_DECL(float3, _EmissiveColor);
PROP_DECL(float, _EmissiveIntensity);
PROP_DECL(float, _LayerSize);
float _AlphaCutoff;
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
PROP_DECL(float, _TexWorldScale);
PROP_DECL(float4, _UVMappingMask);
PROP_DECL(float4, _UVDetailsMappingMask);
float _AlphaCutoff;
ENDHLSL

272
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Editor/LitUI.cs


{
protected static class Styles
{
public enum DetailMapMode
{
DetailWithNormal,
DetailWithAOHeight,
}
public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static string detailText = "Inputs Detail";
public static string lightingText = "Inputs Lighting";

public static string InputsOptionsText = "Inputs options";
public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent UVBaseMappingText = new GUIContent("UV set for Base", "");
public static GUIContent texWorldScaleText = new GUIContent("Scale to apply on world coordinate in case of Planar/Triplanar", "");
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 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 detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static string InputsText = "Inputs";

public static GUIContent specularOcclusionMapText = new GUIContent("Specular Occlusion Map (RGBA)", "Specular Occlusion Map");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC5) - DXT5 for test");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (DXT5) - Need to implement BC5");
public static GUIContent heightMapModeText = new GUIContent("Height Map Mode", "");
public static GUIContent tangentMapText = new GUIContent("Tangent Map", "Tangent Map (BC5) - DXT5 for test");
public static GUIContent anisotropyText = new GUIContent("Anisotropy", "Anisotropy scale factor");

public static GUIContent 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 enum SurfaceType

protected MaterialEditor m_MaterialEditor;
private MaterialProperty surfaceType = null;
private MaterialProperty alphaCutoffEnable = null;
private MaterialProperty blendMode = null;
private MaterialProperty alphaCutoff = null;
private MaterialProperty doubleSidedMode = null;
MaterialProperty surfaceType = null;
MaterialProperty alphaCutoffEnable = null;
MaterialProperty blendMode = null;
MaterialProperty alphaCutoff = null;
MaterialProperty doubleSidedMode = null;
private const string kSurfaceType = "_SurfaceType";
private const string kBlendMode = "_BlendMode";
private const string kAlphaCutoff = "_AlphaCutoff";
private const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
private const string kDoubleSidedMode = "_DoubleSidedMode";
const string kSurfaceType = "_SurfaceType";
const string kBlendMode = "_BlendMode";
const string kAlphaCutoff = "_AlphaCutoff";
const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
const string kDoubleSidedMode = "_DoubleSidedMode";
protected static string[] reservedProperties = new string[] { kSurfaceType, kBlendMode, kAlphaCutoff, kAlphaCutoffEnabled, kDoubleSidedMode };
protected abstract void FindInputProperties(MaterialProperty[] props);

MaskAlpha,
AlbedoAlpha,
}
public enum EmissiveColorMode
public enum UVBaseMapping
UseEmissiveColor,
UseEmissiveMask,
UV0,
Planar,
Triplanar
public enum NormalMapSpace
{
TangentSpace,

Parallax,
Displacement,
}
public enum DetailMapMode
{
DetailWithNormal,

MaterialProperty UVDetail = null;
MaterialProperty smoothnessMapChannel = null;
MaterialProperty emissiveColorMode = null;
MaterialProperty detailMapMode = null;
public enum UVDetailMapping
{
UV0,
UV1,
UV3
}
MaterialProperty baseColor = null;
MaterialProperty baseColorMap = null;
MaterialProperty metallic = null;
MaterialProperty smoothness = null;
MaterialProperty maskMap = null;
MaterialProperty specularOcclusionMap = null;
MaterialProperty normalMap = null;
MaterialProperty normalMapSpace = null;
MaterialProperty heightMap = null;
MaterialProperty heightScale = null;
MaterialProperty heightBias = null;
MaterialProperty tangentMap = null;
MaterialProperty anisotropy = null;
MaterialProperty anisotropyMap = null;
MaterialProperty heightMapMode = null;
MaterialProperty detailMap = null;
MaterialProperty detailMask = null;
MaterialProperty detailAlbedoScale = null;
MaterialProperty detailNormalScale = null;
MaterialProperty detailSmoothnessScale = null;
MaterialProperty detailHeightScale = null;
MaterialProperty detailAOScale = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;
// MaterialProperty subSurfaceRadius = null;
// MaterialProperty subSurfaceRadiusMap = null;
public enum EmissiveColorMode
{
UseEmissiveColor,
UseEmissiveMask,
}
protected const string kUVDetail = "_UVDetail";
protected const string kSmoothnessTextureChannelProp = "_SmoothnessTextureChannel";
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected MaterialProperty smoothnessMapChannel = null;
protected const string kSmoothnessTextureChannel = "_SmoothnessTextureChannel";
protected MaterialProperty UVBase = null;
protected const string kUVBase = "_UVBase";
protected MaterialProperty TexWorldScale = null;
protected const string kTexWorldScale = "_TexWorldScale";
protected MaterialProperty UVMappingMask = null;
protected const string kUVMappingMask = "_UVMappingMask";
protected MaterialProperty normalMapSpace = null;
protected MaterialProperty heightMapMode = null;
protected MaterialProperty detailMapMode = null;
protected MaterialProperty UVDetail = null;
protected const string kUVDetail = "_UVDetail";
protected MaterialProperty UVDetailsMappingMask = null;
protected const string kUVDetailsMappingMask = "_UVDetailsMappingMask";
protected MaterialProperty emissiveColorMode = null;
protected const string kEmissiveColorMode = "_EmissiveColorMode";
protected const string kNormalMap = "_NormalMap";
protected MaterialProperty baseColor = null;
protected const string kBaseColor = "_BaseColor";
protected MaterialProperty baseColorMap = null;
protected const string kBaseColorMap = "_BaseColorMap";
protected MaterialProperty metallic = null;
protected const string kMetallic = "_Metallic";
protected MaterialProperty smoothness = null;
protected const string kSmoothness = "_Smoothness";
protected MaterialProperty maskMap = null;
protected const string kspecularOcclusionMap = "_SpecularOcclusionMap";
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected MaterialProperty specularOcclusionMap = null;
protected const string kSpecularOcclusionMap = "_SpecularOcclusionMap";
protected MaterialProperty normalMap = null;
protected const string kNormalMap = "_NormalMap";
protected MaterialProperty heightMap = null;
protected MaterialProperty heightScale = null;
protected const string kHeightScale = "_HeightScale";
protected MaterialProperty heightBias = null;
protected const string kHeightBias= "_HeightBias";
protected MaterialProperty tangentMap = null;
protected MaterialProperty anisotropy = null;
protected const string kAnisotropy = "_Anisotropy";
protected MaterialProperty anisotropyMap = null;
protected MaterialProperty detailMap = null;
protected MaterialProperty detailMask = null;
protected MaterialProperty detailAlbedoScale = null;
protected MaterialProperty detailNormalScale = null;
protected MaterialProperty detailSmoothnessScale = null;
protected MaterialProperty detailHeightScale = null;
protected MaterialProperty detailAOScale = null;
// MaterialProperty subSurfaceRadius = null;
// MaterialProperty subSurfaceRadiusMap = null;
protected MaterialProperty emissiveColor = null;
protected const string kEmissiveColor = "_EmissiveColor";
protected MaterialProperty emissiveColorMap = null;
protected const string kEmissiveColorMap = "_EmissiveColorMap";
protected MaterialProperty emissiveIntensity = null;
protected const string kEmissiveIntensity = "_EmissiveIntensity";
{
UVDetail = FindProperty(kUVDetail, props);
smoothnessMapChannel = FindProperty(kSmoothnessTextureChannelProp, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
{
smoothnessMapChannel = FindProperty(kSmoothnessTextureChannel, props);
UVBase = FindProperty(kUVBase, props);
TexWorldScale = FindProperty(kTexWorldScale, props);
UVMappingMask = FindProperty(kUVMappingMask, props);
UVDetail = FindProperty(kUVDetail, props);
UVDetailsMappingMask = FindProperty(kUVDetailsMappingMask, props);
emissiveColorMode = FindProperty(kEmissiveColorMode, props);
baseColor = FindProperty("_BaseColor", props);
baseColorMap = FindProperty("_BaseColorMap", props);
metallic = FindProperty("_Metallic", props);
smoothness = FindProperty("_Smoothness", props);
baseColor = FindProperty(kBaseColor, props);
baseColorMap = FindProperty(kBaseColorMap, props);
metallic = FindProperty(kMetallic, props);
smoothness = FindProperty(kSmoothness, props);
specularOcclusionMap = FindProperty(kspecularOcclusionMap, props);
specularOcclusionMap = FindProperty(kSpecularOcclusionMap, props);
heightScale = FindProperty("_HeightScale", props);
heightBias = FindProperty("_HeightBias", props);
tangentMap = FindProperty("_TangentMap", props);
anisotropy = FindProperty("_Anisotropy", props);
anisotropyMap = FindProperty("_AnisotropyMap", props);
emissiveColor = FindProperty("_EmissiveColor", props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);
heightScale = FindProperty(kHeightScale, props);
heightBias = FindProperty(kHeightBias, props);
tangentMap = FindProperty(kTangentMap, props);
anisotropy = FindProperty(kAnisotropy, props);
anisotropyMap = FindProperty(kAnisotropyMap, props);
detailMap = FindProperty(kDetailMap, props);
detailMask = FindProperty(kDetailMask, props);
detailAlbedoScale = FindProperty(kDetailAlbedoScale, props);

detailAOScale = FindProperty(kDetailAOScale, props);
emissiveColor = FindProperty(kEmissiveColor, props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty(kEmissiveIntensity, props);
// When Planar or Triplanar is enable the UVDetail use the same mode, so we disable the choice on UVDetail
bool enableUVDetail = (UVBaseMapping)UVBase.floatValue == UVBaseMapping.UV0;
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText.text);
m_MaterialEditor.ShaderProperty(UVBase, enableUVDetail ? Styles.UVBaseDetailMappingText.text : Styles.UVBaseMappingText.text);
float X, Y, Z, W;
X = ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.UV0) ? 1.0f : 0.0f;
W = ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Planar) ? 1.0f : 0.0f;
UVMappingMask.colorValue = new Color(X, 0.0f, 0.0f, W);
if (((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Planar) || ((UVBaseMapping)UVBase.floatValue == UVBaseMapping.Triplanar))
{
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(TexWorldScale, Styles.texWorldScaleText.text);
EditorGUI.indentLevel--;
}
if (enableUVDetail)
{
m_MaterialEditor.ShaderProperty(UVDetail, Styles.UVDetailMappingText.text);
}
// If base is planar mode, detail is planar too
if (W > 0.0f)
{
X = Y = Z = 0.0f;
}
else
{
X = ((UVDetailMapping)UVDetail.floatValue == UVDetailMapping.UV0) ? 1.0f : 0.0f;
Y = ((UVDetailMapping)UVDetail.floatValue == UVDetailMapping.UV1) ? 1.0f : 0.0f;
Z = ((UVDetailMapping)UVDetail.floatValue == UVDetailMapping.UV3) ? 1.0f : 0.0f;
}
UVDetailsMappingMask.colorValue = new Color(X, Y, Z, 0.0f); // W Reuse planar mode from base
m_MaterialEditor.ShaderProperty(detailMapMode, Styles.detailMapModeText.text);
m_MaterialEditor.ShaderProperty(detailMapMode, Styles.detailMapModeText.text);
m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText.text);
EditorGUI.indentLevel--;
}

bool smoothnessInAlbedoAlpha = (SmoothnessMapChannel)smoothnessMapChannel.floatValue == SmoothnessMapChannel.AlbedoAlpha;
bool useEmissiveMask = (EmissiveColorMode)emissiveColorMode.floatValue == EmissiveColorMode.UseEmissiveMask;
bool smoothnessInAlbedoAlpha = (SmoothnessMapChannel)smoothnessMapChannel.floatValue == SmoothnessMapChannel.AlbedoAlpha;
bool useEmissiveMask = (EmissiveColorMode)emissiveColorMode.floatValue == EmissiveColorMode.UseEmissiveMask;
GUILayout.Label(Styles.InputsText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(smoothnessInAlbedoAlpha ? Styles.baseColorSmoothnessText : Styles.baseColorText, baseColorMap, baseColor);

EditorGUILayout.Space();
GUILayout.Label(Styles.detailText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
m_MaterialEditor.ShaderProperty(UVDetail, Styles.uvSetLabel.text);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
if (useDetailMapWithNormal)
{

EditorGUI.indentLevel--;
}
// TODO: try to setup minimun value to fall back to standard shaders and reverse
public override void AssignNewShaderToMaterial(Material material, Shader oldShader, Shader newShader)
{
base.AssignNewShaderToMaterial(material, oldShader, newShader);

{
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap) || material.GetTexture(kDetailMap)); // With details map, we always use a normal map and Unity provide a default (0, 0, 1) normal map for ir
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kSpecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));
SetKeyword(material, "_HEIGHTMAP", material.GetTexture(kHeightMap));
SetKeyword(material, "_TANGENTMAP", material.GetTexture(kTangentMap));

public static bool ShouldEmissionBeEnabled(Material mat)
{
float emissiveIntensity = mat.GetFloat(kEmissiveIntensity);
var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
return emissiveIntensity > 0.0f || realtimeEmission;
}
MaterialGlobalIlluminationFlags flags = material.globalIlluminationFlags;
if ((flags & (MaterialGlobalIlluminationFlags.BakedEmissive | MaterialGlobalIlluminationFlags.RealtimeEmissive)) != 0)
{

{
// Note: keywords must be based on Material value not on MaterialProperty due to multi-edit & material animation
// (MaterialProperty value might come from renderer material property block)
SetKeyword(material, "_NORMALMAP_TANGENT_SPACE", (NormalMapSpace)material.GetFloat(kNormalMapSpace) == NormalMapSpace.TangentSpace);
SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", ((SmoothnessMapChannel)material.GetFloat(kSmoothnessTextureChannelProp)) == SmoothnessMapChannel.AlbedoAlpha);
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);
SetKeyword(material, "_DETAIL_MAP_WITH_NORMAL", ((DetailMapMode)material.GetFloat(kDetailMapMode)) == DetailMapMode.DetailWithNormal);
SetKeyword(material, "_REQUIRE_UV3", ((UVDetailMapping)material.GetFloat(kUVDetail)) == UVDetailMapping.UV3 && (UVBaseMapping)material.GetFloat(kUVBase) == UVBaseMapping.UV0);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", (HeightmapMode)material.GetFloat(kHeightMapMode) == HeightmapMode.Displacement);
SetKeyword(material, "_DETAIL_MAP_WITH_NORMAL", (DetailMapMode)material.GetFloat(kDetailMapMode) == DetailMapMode.DetailWithNormal);
public static bool ShouldEmissionBeEnabled(Material mat)
{
float emissiveIntensity = mat.GetFloat("_EmissiveIntensity");
var realtimeEmission = (mat.globalIlluminationFlags & MaterialGlobalIlluminationFlags.RealtimeEmissive) > 0;
return emissiveIntensity > 0.0f || realtimeEmission;
}
// TODO: ? or remove
bool HasValidEmissiveKeyword(Material material)
{
/*

16
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl


TEXTURE2D(_LtcDisneyDiffuseMatrix); // RGBA
TEXTURE2D(_LtcMultiGGXFresnelDisneyDiffuse); // RGB, A unused
static const float3x3 _identity3x3 = {1.0, 0.0, 0.0,
0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material
//-----------------------------------------------------------------------------

GetPreIntegratedFGD(iblNdotV, bsdfData.perceptualRoughness, bsdfData.fresnel0, preLightData.specularFGD, preLightData.diffuseFGD);
// #if SHADERPASS == SHADERPASS_GBUFFER
// preLightData.ambientOcclusion = LOAD_TEXTURE2D(_AmbientOcclusion, uint3(coord.unPositionSS, 0)).x;
// preLightData.ambientOcclusion = LOAD_TEXTURE2D(_AmbientOcclusion, coord.unPositionSS).x;
// #endif
// Area light specific

float3 GetBakedDiffuseLigthing(SurfaceData surfaceData, BuiltinData builtinData, BSDFData bsdfData, PreLightData preLightData)
{
// Premultiply bake diffuse lighting information with DisneyDiffuse pre-integration
return builtinData.bakeDiffuseLighting * preLightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor * builtinData.emissiveIntensity;
return builtinData.bakeDiffuseLighting * preLightData.diffuseFGD * surfaceData.ambientOcclusion * bsdfData.diffuseColor + builtinData.emissiveColor;
}
//-----------------------------------------------------------------------------

// we want to take some of that into account too.
lightTransportData.diffuseColor = bsdfData.diffuseColor + bsdfData.fresnel0 * bsdfData.roughness * 0.5 * surfaceData.metallic;
lightTransportData.emissiveColor = builtinData.emissiveColor * builtinData.emissiveIntensity;
lightTransportData.emissiveColor = builtinData.emissiveColor;
return lightTransportData;
}

P2 = mul(P2, transpose(basis));
// Compute the binormal.
float3 B = normalize(cross(P2 - P1, P1));
float3 B = normalize(cross(P1, P2));
float ltcValue;

ltcValue = LTCEvaluate(P1, P2, B, _identity3x3);
ltcValue = LTCEvaluate(P1, P2, B, k_identity3x3);
#else
ltcValue = LTCEvaluate(P1, P2, B, preLightData.ltcXformDisneyDiffuse);
#endif

{
#ifdef LIT_DIFFUSE_LAMBERT_BRDF
ltcValue = LTCEvaluate(matL, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
_identity3x3);
k_identity3x3);
#else
ltcValue = LTCEvaluate(matL, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformDisneyDiffuse);

66
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.shader


_SpecularOcclusionMap("SpecularOcclusion", 2D) = "white" {}
_NormalMap("NormalMap", 2D) = "bump" {}
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
_TangentMap("TangentMap", 2D) = "bump" {}
_Anisotropy("Anisotropy", Range(0.0, 1.0)) = 0

_DetailNormalScale("_DetailNormalScale", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(-2.0, 2.0)) = 1
_DetailHeightScale("_DetailHeightScale", Range(-2.0, 2.0)) = 1
_DetailAOScale("_DetailAOScale", Range(-2.0, 2.0)) = 1
[Enum(UV0, 0, UV1, 1)] _UVDetail("UV Set for detailMap", Float) = 0
_DetailAOScale("_DetailAOScale", Range(-2.0, 2.0)) = 1
_SubSurfaceRadius("SubSurfaceRadius", Range(0.0, 1.0)) = 0
_SubSurfaceRadiusMap("SubSurfaceRadiusMap", 2D) = "white" {}

[HideInInspector] _DstBlend ("__dst", Float) = 0.0
[HideInInspector] _ZWrite ("__zw", Float) = 1.0
[HideInInspector] _CullMode("__cullmode", Float) = 2.0
[Enum(None, 0, DoubleSided, 1, DoubleSidedLigthingFlip, 2, DoubleSidedLigthingMirror, 3)] _DoubleSidedMode("Double sided mode", 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)
[Enum(TangentSpace, 0, ObjectSpace, 1)] _NormalMapSpace("NormalMap space", Float) = 0
[Enum(Parallax, 0, Displacement, 1)] _HeightMapMode("Heightmap usage", Float) = 0
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
[Enum(UV0, 0, UV1, 1, UV3, 2)] _UVDetail("UV Set for detail", Float) = 0
[HideInInspector] _UVDetailsMappingMask("_UVDetailsMappingMask", Color) = (1,0,0,0)
[Enum(None, 0, DoubleSided, 1, DoubleSidedLigthingFlip, 2, DoubleSidedLigthingMirror, 3)] _DoubleSidedMode("Double sided mode", Float) = 0
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
}
HLSLINCLUDE

#pragma shader_feature _ALPHATEST_ON
#pragma shader_feature _ _DOUBLESIDED_LIGHTING_FLIP _DOUBLESIDED_LIGHTING_MIRROR
#pragma shader_feature _NORMALMAP
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _MAPPING_TRIPLANAR
#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma shader_feature _NORMALMAP_TANGENT_SPACE
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _REQUIRE_UV3
#pragma shader_feature _NORMALMAP
#pragma shader_feature _MASKMAP
#pragma shader_feature _SPECULAROCCLUSIONMAP
#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma shader_feature _DETAIL_MAP
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED

SAMPLER2D(sampler_DetailMask);
TEXTURE2D(_DetailMap);
SAMPLER2D(sampler_DetailMap);
float4 _DetailMap_ST;
float _UVDetail;
float4 _DetailMap_ST;
float _DetailAlbedoScale;
float _DetailNormalScale;
float _DetailSmoothnessScale;

TEXTURE2D(_AnisotropyMap);
SAMPLER2D(sampler_AnisotropyMap);
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
float _SubSurfaceRadius;
TEXTURE2D(_SubSurfaceRadiusMap);
SAMPLER2D(sampler_SubSurfaceRadiusMap);
//float _SubSurfaceRadius;
//TEXTURE2D(_SubSurfaceRadiusMap);
//SAMPLER2D(sampler_SubSurfaceRadiusMap);
// float _Thickness;
//TEXTURE2D(_ThicknessMap);

// float _CoatRoughness;
//TEXTURE2D(_CoatRoughnessMap);
//SAMPLER2D(sampler_CoatRoughnessMap);
TEXTURE2D(_DiffuseLightingMap);
SAMPLER2D(sampler_DiffuseLightingMap);
float3 _EmissiveColor;
TEXTURE2D(_EmissiveColorMap);
SAMPLER2D(sampler_EmissiveColorMap);
float _EmissiveIntensity;
float _TexWorldScale;
float4 _UVMappingMask;
float4 _UVDetailsMappingMask;
ENDHLSL

638
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitData.hlsl


return float2(0.0, 0.0);
#endif
}
float3 LerpWhiteTo(float3 b, float t)
{
float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
void GetBuiltinData(FragInput input, SurfaceData surfaceData, float alpha, out BuiltinData builtinData)
{
// Builtin Data
builtinData.opacity = alpha;
// TODO: Sample lightmap/lightprobe/volume proxy
// This should also handle projective lightmap
// Note that data input above can be use to sample into lightmap (like normal)
builtinData.bakeDiffuseLighting = SampleBakedGI(input.positionWS, surfaceData.normalWS, input.texCoord1, input.texCoord2);
#if !defined(LAYERED_LIT_SHADER)
// Emissive Intensity is only use here, but is part of BuiltinData to enforce UI parameters as we want the users to fill one color and one intensity
builtinData.emissiveIntensity = _EmissiveIntensity; // We still store intensity here so we can reuse it with debug code
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
#ifdef _HEIGHTMAP
// TODO: in case of shader graph, a node like parallax must be nullify if use to generate code for Meta pass
#ifndef _HEIGHTMAP_AS_DISPLACEMENT
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS); // This should be remove by the compiler as we usually cal it before.
float height = SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, input.texCoord0).r * _HeightScale + _HeightBias;
// Transform view vector in tangent space
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
float2 offset = ParallaxOffset(viewDirTS, height);
input.texCoord0 += offset;
input.texCoord1 += offset;
#endif
// If we chose an emissive color, we have a dedicated texture for it and don't use MaskMap
#ifdef _EMISSIVE_COLOR
#ifdef _EMISSIVE_COLOR_MAP
builtinData.emissiveColor = SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor * builtinData.emissiveIntensity;
#else
builtinData.emissiveColor = _EmissiveColor * builtinData.emissiveIntensity;
#ifdef _DETAIL_MAP
float2 texCoordDetail = TRANSFORM_TEX(_UVDetail ? input.texCoord1 : input.texCoord0, _DetailMap);
float detailMask = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, input.texCoord0).b;
float4 detail = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail);
float detailAlbedo = detail.r;
float detailSmoothness = detail.b;
#ifdef _DETAIL_MAP_WITH_NORMAL
float3 detailNormalTS = UnpackNormalAG(detail, _DetailNormalScale);
//float detailAO = 0.0;
#else
// TODO: Use heightmap as a derivative with Morten Mikklesen approach
// Or reconstruct
float U = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0.005, 0)).a;
float V = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0, 0.005)).a;
float dHdU = U - detail.a; //create bump map U offset
float dHdV = V - detail.a; //create bump map V offset
//float3 detailNormal = 1 - float3(dHdU, dHdV, 0.05); //create the tangent space normal
float3 detailNormalTS = float3(0.0, 0.0, 1.0);
//float3 detailNormal = UnpackNormalAG(unifiedDetail.r).a;
//float detailAO = detail.b;
#endif
// If we have a MaskMap, use emissive slot as a mask on baseColor
#elif defined(_MASKMAP) && !defined(LAYERED_LIT_SHADER) // With layered lit we have no emissive mask option
builtinData.emissiveColor = surfaceData.baseColor * (SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).b * builtinData.emissiveIntensity).xxx;
#else
builtinData.emissiveColor = float3(0.0, 0.0, 0.0);
surfaceData.baseColor = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).rgb * _BaseColor.rgb;
#ifdef _DETAIL_MAP
surfaceData.baseColor *= LerpWhiteTo(2.0 * saturate(detailAlbedo * _DetailAlbedoScale), detailMask);
#endif
builtinData.velocity = CalculateVelocity(input.positionCS, input.previousPositionCS);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = _BaseColor.a;
#else
float alpha = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).a * _BaseColor.a;
#endif
builtinData.distortion = float2(0.0, 0.0);
builtinData.distortionBlur = 0.0;
}
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
// 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;
};
#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
surfaceData.specularOcclusion = SAMPLE_TEXTURE2D(_SpecularOcclusionMap, sampler_SpecularOcclusionMap, input.texCoord0).a;
struct LayerTexCoord
{
#ifndef LAYERED_LIT_SHADER
LayerUV base;
LayerUV details;
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);
// smooth it
//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
// Regular texcoord
LayerUV base0;
LayerUV base1;
LayerUV base2;
LayerUV base3;
LayerUV details0;
LayerUV details1;
LayerUV details2;
LayerUV details3;
// TODO: think about using BC5
float3 vertexNormalWS = input.tangentToWorld[2].xyz;
// triplanar weight
float3 weights;
};
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, blendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space
float3 normalOS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).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
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 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
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);
}
}
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
surfaceData.perceptualSmoothness = SAMPLE_TEXTURE2D(_BaseColorMap, sampler_BaseColorMap, input.texCoord0).a;
#elif defined(_MASKMAP)
surfaceData.perceptualSmoothness = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).a;
#else
surfaceData.perceptualSmoothness = 1.0;
#endif
surfaceData.perceptualSmoothness *= _Smoothness;
#ifdef _DETAIL_MAP
surfaceData.perceptualSmoothness *= LerpWhiteTo(2.0 * saturate(detailSmoothness * _DetailSmoothnessScale), detailMask);
#endif
// 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)
{
if (layerUV.isTriplanar)
{
float3 val = float3(0.0, 0.0, 0.0);
surfaceData.materialId = 0;
if (weights.x > 0.0)
val += weights.x * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ));
if (weights.y > 0.0)
val += weights.y * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX));
if (weights.z > 0.0)
val += weights.z * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY));
// MaskMap is Metallic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
#ifdef _MASKMAP
surfaceData.metallic = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).r;
surfaceData.ambientOcclusion = SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).g;
#else
surfaceData.metallic = 1.0;
surfaceData.ambientOcclusion = 1.0;
#endif
surfaceData.metallic *= _Metallic;
return normalize(val);
}
else
{
return UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv));
}
}
// TODO: think about using BC5
#ifdef _TANGENTMAP
#ifdef _NORMALMAP_TANGENT_SPACE // Normal and tangent use same space
float3 tangentTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_TangentMap, sampler_TangentMap, input.texCoord0));
surfaceData.tangentWS = TransformTangentToWorld(tangentTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here! - Require to pass world transform)
surfaceData.tangentWS = SAMPLE_TEXTURE2D(_TangentMap, sampler_TangentMap, input.texCoord0).rgb;
#endif
#else
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
#endif
// TODO: Is there anything todo regarding flip normal but for the tangent ?
// This version is for normalmap with AG encoding only (use with details map)
float3 SampleNormalLayerAG(TEXTURE2D_ARGS(layerTex, layerSampler), LayerUV layerUV, float3 weights)
{
if (layerUV.isTriplanar)
{
float3 val = float3(0.0, 0.0, 0.0);
#ifdef _ANISOTROPYMAP
surfaceData.anisotropy = SAMPLE_TEXTURE2D(_AnisotropyMap, sampler_AnisotropyMap, input.texCoord0).g;
#else
surfaceData.anisotropy = 1.0;
#endif
surfaceData.anisotropy *= _Anisotropy;
if (weights.x > 0.0)
val += weights.x * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvYZ));
if (weights.y > 0.0)
val += weights.y * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvZX));
if (weights.z > 0.0)
val += weights.z * UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uvXY));
surfaceData.specular = 0.04;
return normalize(val);
}
else
{
return UnpackNormalAG(SAMPLE_TEXTURE2D(layerTex, layerSampler, layerUV.uv));
}
}
surfaceData.subSurfaceRadius = 1.0;
surfaceData.thickness = 0.0;
surfaceData.subSurfaceProfile = 0;
// 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) SampleNormalLayer(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights)
#define SAMPLE_LAYER_NORMALMAP_AG(textureName, samplerName, coord) SampleNormalLayerAG(TEXTURE2D_PARAM(textureName, samplerName), coord, layerTexCoord.weights)
surfaceData.coatNormalWS = float3(1.0, 0.0, 0.0);
surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
#ifndef LAYERED_LIT_SHADER
// Builtin Data
builtinData.opacity = alpha;
#define LAYER_INDEX 0
#define ADD_IDX(Name) Name
#define ADD_ZERO_IDX(Name) Name
#include "LitSurfaceData.hlsl"
// TODO: Sample lightmap/lightprobe/volume proxy
// This should also handle projective lightmap
// Note that data input above can be use to sample into lightmap (like normal)
builtinData.bakeDiffuseLighting = SampleBakedGI(input.positionWS, surfaceData.normalWS, input.texCoord1, input.texCoord2);
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerTexCoord layerTexCoord;
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
// If we chose an emissive color, we have a dedicated texture for it and don't use MaskMap
#ifdef _EMISSIVE_COLOR
#ifdef _EMISSIVE_COLOR_MAP
builtinData.emissiveColor = SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
#else
builtinData.emissiveColor = _EmissiveColor;
#endif
#elif defined(_MASKMAP) // If we have a MaskMap, use emissive slot as a mask on baseColor
builtinData.emissiveColor = surfaceData.baseColor * SAMPLE_TEXTURE2D(_MaskMap, sampler_MaskMap, input.texCoord0).bbb;
#else
builtinData.emissiveColor = float3(0.0, 0.0, 0.0);
#ifdef _MAPPING_TRIPLANAR
// one weight for each direction XYZ - Use vertex normal for triplanar
layerTexCoord.weights = ComputeTriplanarWeights(input.tangentToWorld[2].xyz);
builtinData.emissiveIntensity = _EmissiveIntensity;
// Be sure that the compiler is aware that we don't touch UV1 and UV3 for base layer in case of non layer shader
// so it can remove code
_UVMappingMask.yz = float2(0.0, 0.0);
bool isTriplanar = false;
#ifdef _MAPPING_TRIPLANAR
isTriplanar = true;
#endif
ComputeLayerTexCoord(input, isTriplanar, layerTexCoord);
ApplyDisplacement(input, layerTexCoord);
builtinData.velocity = CalculateVelocity(input.positionCS, input.previousPositionCS);
builtinData.distortion = float2(0.0, 0.0);
builtinData.distortionBlur = 0.0;
float alpha = GetSurfaceData(input, layerTexCoord, surfaceData);
GetBuiltinData(input, surfaceData, alpha, builtinData);
#define ADD_ZERO_IDX(Name) Name##0
// Generate function for all layer
#define LAYER_INDEX 0
#define ADD_IDX(Name) Name##0
#include "LitSurfaceData.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX
#define LAYER_INDEX 1
#define ADD_IDX(Name) Name##1
#include "LitSurfaceData.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX
#define LAYER_INDEX 2
#define ADD_IDX(Name) Name##2
#include "LitSurfaceData.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX
#define LAYER_INDEX 3
#define ADD_IDX(Name) Name##3
#include "LitSurfaceData.hlsl"
#undef LAYER_INDEX
#undef ADD_IDX
void ComputeMaskWeights(float3 inputMasks, out float outWeights[_MAX_LAYER])
{
float masks[_MAX_LAYER];
masks[0] = 1.0f; // Layer 0 is always full
masks[1] = inputMasks.r;
masks[2] = inputMasks.g;
masks[3] = inputMasks.b;
// calculate weight of each layers
float left = 1.0f;
[unroll]
for (int i = _LAYER_COUNT - 1; i > 0; --i)
{
outWeights[i] = masks[i] * left;
left -= outWeights[i];
}
outWeights[0] = left;
}
float3 BlendLayeredColor(float3 rgb0, float3 rgb1, float3 rgb2, float3 rgb3, float weight[4])
{

{
float3 result = float3(0.0, 0.0, 0.0);
// TODO : real normal map blending function
result = normal0 * weight[0] + normal1 * weight[1];
result = normal0 * weight[0] + normal1 * weight[1];
#if _LAYER_COUNT >= 3
result += normal2 * weight[2];
#endif

return result;
return normalize(result);
}
float BlendLayeredScalar(float x0, float x1, float x2, float x3, float weight[4])

return result;
}
void ComputeMaskWeights(float3 inputMasks, out float outWeights[_MAX_LAYER])
{
float masks[_MAX_LAYER];
masks[0] = 1.0f; // Layer 0 is always full
masks[1] = inputMasks.r;
masks[2] = inputMasks.g;
masks[3] = inputMasks.b;
// calculate weight of each layers
float left = 1.0f;
[unroll]
for (int i = _LAYER_COUNT - 1; i > 0; --i)
{
outWeights[i] = masks[i] * left;
left -= outWeights[i];
}
outWeights[0] = left;
}
#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);
float2 ComputePlanarXZCoord(float3 worldPos, float layerSize)
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
return frac(worldPos.xz / layerSize);
}
LayerTexCoord layerTexCoord;
ZERO_INITIALIZE(LayerTexCoord, layerTexCoord);
void ComputeLayerCoordinates(out LayerCoordinates outCoord, FragInput input)
{
#if defined(_LAYER_MAPPING_UV1_0)
outCoord.texcoord[0] = input.texCoord1;
outCoord.isTriplanar[0] = false;
#elif defined(_LAYER_MAPPING_PLANAR_0)
outCoord.texcoord[0] = ComputePlanarXZCoord(input.positionWS, _LayerSize0);
outCoord.isTriplanar[0] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_0)
outCoord.texcoord[0] = input.texCoord0;
outCoord.isTriplanar[0] = true;
#else
outCoord.texcoord[0] = input.texCoord0;
outCoord.isTriplanar[0] = false;
#if defined(_LAYER_MAPPING_TRIPLANAR_0) || defined(_LAYER_MAPPING_TRIPLANAR_1) || defined(_LAYER_MAPPING_TRIPLANAR_2) || defined(_LAYER_MAPPING_TRIPLANAR_3)
// one weight for each direction XYZ - Use vertex normal for triplanar
layerTexCoord.weights = ComputeTriplanarWeights(input.tangentToWorld[2].xyz);
#if defined(_LAYER_MAPPING_UV1_1)
outCoord.texcoord[1] = input.texCoord1;
outCoord.isTriplanar[1] = false;
#elif defined(_LAYER_MAPPING_PLANAR_1)
outCoord.texcoord[1] = ComputePlanarXZCoord(input.positionWS, _LayerSize1);
outCoord.isTriplanar[1] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_1)
outCoord.texcoord[1] = input.texCoord0;
outCoord.isTriplanar[1] = true;
#else
outCoord.texcoord[1] = input.texCoord0;
outCoord.isTriplanar[1] = false;
bool isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR_0
isTriplanar = true;
#if defined(_LAYER_MAPPING_UV1_2)
outCoord.texcoord[2] = input.texCoord1;
outCoord.isTriplanar[2] = false;
#elif defined(_LAYER_MAPPING_PLANAR_2)
outCoord.texcoord[2] = ComputePlanarXZCoord(input.positionWS, _LayerSize2);
outCoord.isTriplanar[2] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_2)
outCoord.texcoord[2] = input.texCoord0;
outCoord.isTriplanar[2] = true;
#else
outCoord.texcoord[2] = input.texCoord0;
outCoord.isTriplanar[2] = false;
ComputeLayerTexCoord0(input, isTriplanar, layerTexCoord);
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR_1
isTriplanar = true;
#if defined(_LAYER_MAPPING_UV1_3)
outCoord.texcoord[3] = input.texCoord1;
outCoord.isTriplanar[3] = false;
#elif defined(_LAYER_MAPPING_PLANAR_3)
outCoord.texcoord[3] = ComputePlanarXZCoord(input.positionWS, _LayerSize3);
outCoord.isTriplanar[3] = false;
#elif defined(_LAYER_MAPPING_TRIPLANAR_3)
outCoord.texcoord[3] = input.texCoord0;
outCoord.isTriplanar[3] = true;
#else
outCoord.texcoord[3] = input.texCoord0;
outCoord.isTriplanar[3] = false;
ComputeLayerTexCoord1(input, isTriplanar, layerTexCoord);
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR_2
isTriplanar = true;
}
ComputeLayerTexCoord2(input, isTriplanar, layerTexCoord);
isTriplanar = false;
#ifdef _LAYER_MAPPING_TRIPLANAR_3
isTriplanar = true;
#endif
ComputeLayerTexCoord3(input, isTriplanar, layerTexCoord);
ApplyDisplacement0(input, layerTexCoord);
ApplyDisplacement1(input, layerTexCoord);
ApplyDisplacement2(input, layerTexCoord);
ApplyDisplacement3(input, layerTexCoord);
void GetSurfaceAndBuiltinData(FragInput input, out SurfaceData surfaceData, out BuiltinData builtinData)
{
LayerCoordinates layerCoord;
ComputeLayerCoordinates(layerCoord, input);
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);
float3 maskValues = float3(0.0, 0.0, 0.0);
#if defined(_LAYER_MASK_MAP)
maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
#endif
float3 maskValues = SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
maskValues = input.vertexColor.rgb;
#endif
#if defined(_LAYER_MASK_MAP) && defined(_LAYER_MASK_VERTEX_COLOR)
maskValues = input.vertexColor.rgb * SAMPLE_TEXTURE2D(_LayerMaskMap, sampler_LayerMaskMap, input.texCoord0).rgb;
maskValues *= input.vertexColor.rgb;
PROP_DECL(float3, baseColor);
PROP_SAMPLE(baseColor, _BaseColorMap, layerCoord, rgb);
PROP_MUL(baseColor, _BaseColor, rgb);
PROP_BLEND_COLOR(baseColor, weights);
surfaceData.baseColor = baseColor;
PROP_DECL(float, alpha);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
PROP_ASSIGN(alpha, _BaseColor, a);
#else
PROP_SAMPLE(alpha, _BaseColorMap, layerCoord, a);
PROP_MUL(alpha, _BaseColor, a);
#endif
PROP_BLEND_SCALAR(alpha, weights);
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
builtinData.opacity = alpha;
PROP_DECL(float, specularOcclusion);
#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
PROP_SAMPLE(specularOcclusion, _SpecularOcclusionMap, layerCoord, a);
#else
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);
// smooth it
//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
PROP_ASSIGN_VALUE(specularOcclusion, 1.0);
#endif
PROP_BLEND_SCALAR(specularOcclusion, weights);
surfaceData.specularOcclusion = specularOcclusion;
// TODO: think about using BC5
float3 vertexNormalWS = input.tangentToWorld[2].xyz;
#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS0 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap0, sampler_NormalMap0), layerCoord, 0));
float3 normalTS1 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap1, sampler_NormalMap0), layerCoord, 1));
float3 normalTS2 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap2, sampler_NormalMap0), layerCoord, 2));
float3 normalTS3 = UnpackNormalAG(SampleLayer(TEXTURE2D_PARAM(_NormalMap3, sampler_NormalMap0), layerCoord, 3));
float3 normalTS = BlendLayeredNormal(normalTS0, normalTS1, normalTS2, normalTS3, weights);
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here!)
surfaceData.normalWS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).rgb;
#endif
#else
surfaceData.normalWS = vertexNormalWS;
#endif
surfaceData.baseColor = SURFACEDATA_BLEND_COLOR(surfaceData, baseColor, weights);
surfaceData.specularOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, specularOcclusion, weights);
// 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.perceptualSmoothness = SURFACEDATA_BLEND_SCALAR(surfaceData, perceptualSmoothness, weights);
surfaceData.ambientOcclusion = SURFACEDATA_BLEND_SCALAR(surfaceData, ambientOcclusion, weights);
surfaceData.metallic = SURFACEDATA_BLEND_SCALAR(surfaceData, metallic, weights);
#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 = IS_FRONT_VFACE(input.cullFace, GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS, -GetOdddNegativeScale() >= 0.0 ? surfaceData.normalWS : oppositeNormalWS);
#endif
PROP_DECL(float, perceptualSmoothness);
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
PROP_SAMPLE(perceptualSmoothness, _BaseColorMap, layerCoord, a);
#elif defined(_MASKMAP)
PROP_SAMPLE(perceptualSmoothness, _MaskMap, layerCoord, a);
#else
PROP_ASSIGN_VALUE(perceptualSmoothness, 1.0);
#endif
PROP_MUL(perceptualSmoothness, _Smoothness, r);
PROP_BLEND_SCALAR(perceptualSmoothness, weights);
surfaceData.perceptualSmoothness = perceptualSmoothness;
// Init other unused parameter
// MaskMap is Metallic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
PROP_DECL(float, metallic);
PROP_DECL(float, ambientOcclusion);
#ifdef _MASKMAP
PROP_SAMPLE(metallic, _MaskMap, layerCoord, a);
PROP_SAMPLE(ambientOcclusion, _MaskMap, layerCoord, g);
#else
PROP_ASSIGN_VALUE(metallic, 1.0);
PROP_ASSIGN_VALUE(ambientOcclusion, 1.0);
#endif
PROP_MUL(metallic, _Metallic, r);
PROP_BLEND_SCALAR(metallic, weights);
PROP_BLEND_SCALAR(ambientOcclusion, weights);
surfaceData.metallic = metallic;
surfaceData.ambientOcclusion = ambientOcclusion;
surfaceData.tangentWS = float3(1.0, 0.0, 0.0);
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
// Builtin Data
// TODO: Sample lightmap/lightprobe/volume proxy
// This should also handle projective lightmap
// Note that data input above can be use to sample into lightmap (like normal)
builtinData.bakeDiffuseLighting = SampleBakedGI(input.positionWS, surfaceData.normalWS, input.texCoord1, input.texCoord2);
// If we chose an emissive color, we have a dedicated texture for it and don't use MaskMap
PROP_DECL(float3, emissiveColor);
#ifdef _EMISSIVE_COLOR
#ifdef _EMISSIVE_COLOR_MAP
PROP_SAMPLE(emissiveColor, _EmissiveColorMap, layerCoord, rgb);
#else
PROP_ASSIGN(emissiveColor, _EmissiveColor, rgb);
#endif
#elif defined(_MASKMAP) // If we have a MaskMap, use emissive slot as a mask on baseColor
PROP_SAMPLE(emissiveColor, _MaskMap, layerCoord, bbb);
PROP_MUL(emissiveColor, baseColor, rgb);
#else
PROP_ASSIGN_VALUE(emissiveColor, float3(0.0, 0.0, 0.0));
#endif
PROP_BLEND_COLOR(emissiveColor, weights);
builtinData.emissiveColor = emissiveColor;
PROP_DECL(float, emissiveIntensity);
PROP_ASSIGN(emissiveIntensity, _EmissiveIntensity, r);
PROP_BLEND_SCALAR(emissiveIntensity, weights);
builtinData.emissiveIntensity = emissiveIntensity;
builtinData.velocity = CalculateVelocity(input.positionCS, input.previousPositionCS);
builtinData.distortion = float2(0.0, 0.0);
builtinData.distortionBlur = 0.0;
float alpha = PROP_BLEND_SCALAR(alpha, weights);
GetBuiltinData(input, surfaceData, alpha, builtinData);
#endif
#endif // #ifndef LAYERED_LIT_SHADER

24
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSharePass.hlsl


float2 uv1 : TEXCOORD1;
#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL)
float2 uv2 : TEXCOORD2;
#endif
#endif
#ifdef _REQUIRE_UV3
float2 uv3 : TEXCOORD3;
#endif
float4 tangentOS : TANGENT; // Always present as we require it also in case of anisotropic lighting
float4 color : COLOR;

#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL)
float2 texCoord2;
#endif
#ifdef _REQUIRE_UV3
float2 texCoord3;
#endif
float3 tangentToWorld[3];
float4 color;
};

float4 positionCS : SV_Position;
#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL)
#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL) || defined(_REQUIRE_UV3)
float4 interpolators[6] : TEXCOORD0;
#else
float4 interpolators[5] : TEXCOORD0;

output.interpolators[4] = input.color;
#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL) || defined(_REQUIRE_UV3)
output.interpolators[5] = float4(0.0, 0.0, 0.0, 0.0);
output.interpolators[5] = float4(input.texCoord2.xy, 0.0, 0.0);
output.interpolators[5].xy = input.texCoord2.xy;
#endif
#ifdef _REQUIRE_UV3
output.interpolators[5].zw = input.texCoord3.xy;
#endif
#endif
return output;

#if (DYNAMICLIGHTMAP_ON) || (SHADERPASS == SHADERPASS_DEBUG_VIEW_MATERIAL)
output.texCoord2 = input.interpolators[5].xy;
#endif
#ifdef _REQUIRE_UV3
output.texCoord3 = input.interpolators[5].zw;
#endif
#if SHADER_STAGE_FRAGMENT

36
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Material.hlsl


TEXTURE2D(MERGE_NAME(NAME, 0)); \
TEXTURE2D(MERGE_NAME(NAME, 1));
#define FETCH_GBUFFER(NAME, TEX, UV) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), uint3(UV, 0)); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), uint3(UV, 0));
#define FETCH_GBUFFER(NAME, TEX, unCoord2) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), unCoord2); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), unCoord2);
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, NAME) EncodeIntoGBuffer(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1))
#define DECODE_FROM_GBUFFER(NAME, BSDF_DATA, BAKE_DIFFUSE_LIGHTING) DecodeFromGBuffer(MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), BSDF_DATA, BAKE_DIFFUSE_LIGHTING)

TEXTURE2D(MERGE_NAME(NAME, 1)); \
TEXTURE2D(MERGE_NAME(NAME, 2));
#define FETCH_GBUFFER(NAME, TEX, UV) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), uint3(UV, 0)); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), uint3(UV, 0)); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), uint3(UV, 0));
#define FETCH_GBUFFER(NAME, TEX, unCoord2) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), unCoord2); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), unCoord2); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), unCoord2);
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, NAME) EncodeIntoGBuffer(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2))
#define DECODE_FROM_GBUFFER(NAME, BSDF_DATA, BAKE_DIFFUSE_LIGHTING) DecodeFromGBuffer(MERGE_NAME(NAME,0), MERGE_NAME(NAME,1), MERGE_NAME(NAME,2), BSDF_DATA, BAKE_DIFFUSE_LIGHTING)

TEXTURE2D(MERGE_NAME(NAME, 2)); \
TEXTURE2D(MERGE_NAME(NAME, 3));
#define FETCH_GBUFFER(NAME, TEX, UV) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), uint3(UV, 0)); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), uint3(UV, 0)); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), uint3(UV, 0)); \
GBufferType3 MERGE_NAME(NAME, 3) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 3), uint3(UV, 0));
#define FETCH_GBUFFER(NAME, TEX, unCoord2) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), unCoord2); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), unCoord2); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), unCoord2); \
GBufferType3 MERGE_NAME(NAME, 3) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 3), unCoord2);
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, NAME) EncodeIntoGBuffer(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3))
#define DECODE_FROM_GBUFFER(NAME, BSDF_DATA, BAKE_DIFFUSE_LIGHTING) DecodeFromGBuffer(MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3), BSDF_DATA, BAKE_DIFFUSE_LIGHTING)

TEXTURE2D(MERGE_NAME(NAME, 3)); \
TEXTURE2D(MERGE_NAME(NAME, 4));
#define FETCH_GBUFFER(NAME, TEX, UV) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), uint3(UV, 0)); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), uint3(UV, 0)); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), uint3(UV, 0)); \
GBufferType3 MERGE_NAME(NAME, 3) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 3), uint3(UV, 0)); \
GBufferType4 MERGE_NAME(NAME, 4) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 4), uint3(UV, 0));
#define FETCH_GBUFFER(NAME, TEX, unCoord2) \
GBufferType0 MERGE_NAME(NAME, 0) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 0), unCoord2); \
GBufferType1 MERGE_NAME(NAME, 1) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 1), unCoord2); \
GBufferType2 MERGE_NAME(NAME, 2) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 2), unCoord2); \
GBufferType3 MERGE_NAME(NAME, 3) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 3), unCoord2); \
GBufferType4 MERGE_NAME(NAME, 4) = LOAD_TEXTURE2D(MERGE_NAME(TEX, 4), unCoord2);
#define ENCODE_INTO_GBUFFER(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, NAME) EncodeIntoGBuffer(SURFACE_DATA, BAKE_DIFFUSE_LIGHTING, MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3), MERGE_NAME(NAME, 4))
#define DECODE_FROM_GBUFFER(NAME, BSDF_DATA, BAKE_DIFFUSE_LIGHTING) DecodeFromGBuffer(MERGE_NAME(NAME, 0), MERGE_NAME(NAME, 1), MERGE_NAME(NAME, 2), MERGE_NAME(NAME, 3), MERGE_NAME(NAME, 4), BSDF_DATA, BAKE_DIFFUSE_LIGHTING)

2
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Unlit/Unlit.hlsl


LighTransportData lightTransportData;
lightTransportData.diffuseColor = float3(0.0, 0.0, 0.0);
lightTransportData.emissiveColor = builtinData.emissiveColor * builtinData.emissiveIntensity;
lightTransportData.emissiveColor = builtinData.emissiveColor;
return lightTransportData;
}

9
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Unlit/UnlitData.hlsl


builtinData.bakeDiffuseLighting = float3(0.0, 0.0, 0.0);
// Emissive Intensity is only use here, but is part of BuiltinData to enforce UI parameters as we want the users to fill one color and one intensity
builtinData.emissiveIntensity = _EmissiveIntensity;
builtinData.emissiveColor = SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor;
builtinData.emissiveColor = SAMPLE_TEXTURE2D(_EmissiveColorMap, sampler_EmissiveColorMap, input.texCoord0).rgb * _EmissiveColor * builtinData.emissiveIntensity;
builtinData.emissiveColor = _EmissiveColor;
builtinData.emissiveColor = _EmissiveColor * builtinData.emissiveIntensity;
builtinData.emissiveIntensity = _EmissiveIntensity;
builtinData.velocity = float2(0.0, 0.0);

2
Assets/ScriptableRenderLoop/HDRenderLoop/ShaderPass/ShaderPassForward.hlsl


float3 diffuseLighting;
float3 specularLighting;
float3 bakeDiffuseLighting = GetBakedDiffuseLigthing(surfaceData, builtinData, bsdfData, preLightData);
LightLoop(V, positionWS, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
LightLoop(V, positionWS, coord, preLightData, bsdfData, bakeDiffuseLighting, diffuseLighting, specularLighting);
return float4(diffuseLighting + specularLighting, builtinData.opacity);
}

2
Assets/ScriptableRenderLoop/HDRenderLoop/ShaderPass/ShaderPassForwardUnlit.hlsl


BSDFData bsdfData = ConvertSurfaceDataToBSDFData(surfaceData);
// TODO: we must not access bsdfData here, it break the genericity of the code!
return float4(bsdfData.color + builtinData.emissiveColor * builtinData.emissiveIntensity, builtinData.opacity);
return float4(bsdfData.color + builtinData.emissiveColor, builtinData.opacity);
}

5
Assets/ScriptableRenderLoop/HDRenderLoop/ShaderVariables.hlsl


return mul(GetObjectToWorldMatrix(), float4(positionOS, 1.0)).xyz;
}
float3 TransformWorldToObject(float3 positionWS)
{
return mul(GetWorldToObjectMatrix(), float4(positionWS, 1.0)).xyz;
}
float3 TransformObjectToView(float3 positionOS)
{
return mul(GetObjectToWorldViewMatrix(), float4(positionOS, 1.0)).xyz;

151
Assets/ScriptableRenderLoop/HDRenderLoop/Sky/SkyRenderer.cs


using System.Collections.Generic;
using System;
public Cubemap skyHDRI;
public Texture skyHDRI;
public float rotation = 0.0f;
public float exposure = 0.0f;
public float multiplier = 1.0f;

const int kSkyCubemapSize = 256;
RenderTexture m_SkyboxCubemapRT = null;
RenderTexture m_SkyboxGGXCubemapRT = null;
Material m_GGXConvolveMaterial = null; // Apply GGX convolution to cubemap
MaterialPropertyBlock m_RenderSkyPropertyBlock = null;
GameObject[] m_CubemapFaceCamera = new GameObject[6];

};
}
void RebuildTextures()
{
if(m_SkyboxCubemapRT == null)
{
m_SkyboxCubemapRT = new RenderTexture(kSkyCubemapSize, kSkyCubemapSize, 1, RenderTextureFormat.ARGBHalf);
m_SkyboxCubemapRT.dimension = TextureDimension.Cube;
m_SkyboxCubemapRT.useMipMap = true;
m_SkyboxCubemapRT.autoGenerateMips = true;
m_SkyboxCubemapRT.filterMode = FilterMode.Point;
m_SkyboxCubemapRT.Create();
}
if(m_SkyboxGGXCubemapRT == null)
{
m_SkyboxGGXCubemapRT = new RenderTexture(kSkyCubemapSize, kSkyCubemapSize, 1, RenderTextureFormat.ARGBHalf);
m_SkyboxGGXCubemapRT.dimension = TextureDimension.Cube;
m_SkyboxGGXCubemapRT.useMipMap = true;
m_SkyboxGGXCubemapRT.autoGenerateMips = false;
m_SkyboxGGXCubemapRT.filterMode = FilterMode.Trilinear;
m_SkyboxGGXCubemapRT.Create();
}
}
public void Rebuild()
{
// TODO: We need to have an API to send our sky information to Enlighten. For now use a workaround through skybox/cubemap material...

m_GGXConvolveMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderLoop/GGXConvolve");
m_SkyboxCubemapRT = new RenderTexture(kSkyCubemapSize, kSkyCubemapSize, 1, RenderTextureFormat.ARGBHalf);
m_SkyboxCubemapRT.dimension = TextureDimension.Cube;
m_SkyboxCubemapRT.useMipMap = true;
m_SkyboxCubemapRT.autoGenerateMips = true;
m_SkyboxCubemapRT.Create();
m_RenderSkyPropertyBlock = new MaterialPropertyBlock();
RebuildTextures();
Matrix4x4 cubeProj = Matrix4x4.Perspective(90.0f, 1.0f, 0.1f, 1.0f);

{
Utilities.Destroy(m_StandardSkyboxMaterial);
Utilities.Destroy(m_SkyHDRIMaterial);
Utilities.Destroy(m_GGXConvolveMaterial);
Utilities.Destroy(m_SkyboxGGXCubemapRT);
for(int i = 0 ; i < 6 ; ++i)
{

}
bool IsSkyValid(SkyParameters parameters)
{
// Later we will also test shader for procedural skies.
return parameters.skyHDRI != null;
}
m_SkyHDRIMaterial.SetTexture("_Cubemap", skyParameters.skyHDRI);
m_SkyHDRIMaterial.SetVector("_SkyParam", new Vector4(skyParameters.exposure, skyParameters.multiplier, skyParameters.rotation, 0.0f));
m_RenderSkyPropertyBlock.SetTexture("_Cubemap", skyParameters.skyHDRI);
m_RenderSkyPropertyBlock.SetVector("_SkyParam", new Vector4(skyParameters.exposure, skyParameters.multiplier, skyParameters.rotation, 0.0f));
var cmd = new CommandBuffer { name = "Skybox" };
cmd.DrawMesh(skyMesh, Matrix4x4.identity, m_SkyHDRIMaterial);
var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(skyMesh, Matrix4x4.identity, m_SkyHDRIMaterial, 0, 0, m_RenderSkyPropertyBlock);
public void RenderSky(Camera camera, SkyParameters skyParameters, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, RenderLoop renderLoop)
private void RenderSkyToCubemap(SkyParameters skyParameters, RenderTexture target, RenderLoop renderLoop)
// Render sky into a cubemap - doesn't happen every frame, can be control
Utilities.SetRenderTarget(renderLoop, m_SkyboxCubemapRT, "", 0, (CubemapFace)i);
Utilities.SetRenderTarget(renderLoop, target, 0, (CubemapFace)i);
}
m_StandardSkyboxMaterial.SetTexture("_Tex", m_SkyboxCubemapRT);
RenderSettings.skybox = m_StandardSkyboxMaterial; // Setup this material as the default to be use in RenderSettings
RenderSettings.ambientIntensity = 1.0f; // fix this to 1, this parameter should not exist!
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox; // Force skybox for our HDRI
RenderSettings.reflectionIntensity = 1.0f;
DynamicGI.UpdateEnvironment();
private void RenderCubemapGGXConvolution(Texture input, RenderTexture target, RenderLoop renderLoop)
{
using (new Utilities.ProfilingSample("Sky Pass: GGX Convolution", renderLoop))
{
int mipCount = 1 + (int)Mathf.Log(input.width, 2.0f);
if (mipCount < ((int)EnvConstants.SpecCubeLodStep + 1))
{
Debug.LogWarning("RenderCubemapGGXConvolution: Cubemap size is too small for GGX convolution, needs at least " + ((int)EnvConstants.SpecCubeLodStep + 1) + " mip levels");
return;
}
// Copy the first mip.
// 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(skyParams, target, renderLoop);
// 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("_MipMapCount", mipCount);
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(renderLoop, target, mip, (CubemapFace)face);
Camera faceCamera = m_CubemapFaceCamera[face].GetComponent<Camera>();
Mesh skyMesh = BuildSkyMesh(faceCamera, true);
var cmd = new CommandBuffer { name = "" };
cmd.DrawMesh(skyMesh, Matrix4x4.identity, m_GGXConvolveMaterial, 0, 0, propertyBlock);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
}
}
}
// TODO: do a render to texture here
public void RenderSky(Camera camera, SkyParameters skyParameters, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, RenderLoop renderLoop)
{
using (new Utilities.ProfilingSample("Sky Pass", renderLoop))
{
//using (new EditorGUI.DisabledScope(m_LookDevEnvLibrary.hdriList.Count <= 1))
if (IsSkyValid(skyParameters))
{
// When loading RenderDoc, RenderTextures will go null
RebuildTextures();
// Downsample the cubemap and provide it to Enlighten
using (new Utilities.ProfilingSample("Sky Pass: Render Cubemap", renderLoop))
{
// Render sky into a cubemap - doesn't happen every frame, can be controlled
RenderSkyToCubemap(skyParameters, m_SkyboxCubemapRT, renderLoop);
// Convolve downsampled cubemap
RenderCubemapGGXConvolution(m_SkyboxCubemapRT, m_SkyboxGGXCubemapRT, renderLoop);
// TODO: currently workaround is to set the cubemap in a Skybox/cubemap material
//m_SkyboxMaterial.SetTexture(cubemap);
// TODO: Properly send the cubemap to Enlighten. Currently workaround is to set the cubemap in a Skybox/cubemap material
m_StandardSkyboxMaterial.SetTexture("_Tex", m_SkyboxCubemapRT);
RenderSettings.skybox = m_StandardSkyboxMaterial; // Setup this material as the default to be use in RenderSettings
RenderSettings.ambientIntensity = 1.0f; // fix this to 1, this parameter should not exist!
RenderSettings.ambientMode = UnityEngine.Rendering.AmbientMode.Skybox; // Force skybox for our HDRI
RenderSettings.reflectionIntensity = 1.0f;
RenderSettings.customReflection = null;
//DynamicGI.UpdateEnvironment();
}
// Render the sky itself
Utilities.SetRenderTarget(renderLoop, colorBuffer, depthBuffer, "Sky Pass");
RenderSky(camera, skyParameters, false, renderLoop);
// Render the sky itself
Utilities.SetRenderTarget(renderLoop, colorBuffer, depthBuffer);
RenderSky(camera, skyParameters, false, renderLoop);
}
}
}
}
}

116
Assets/ScriptableRenderLoop/HDRenderLoop/Utilities.cs


// Render Target Management.
public const ClearFlag kClearAll = ClearFlag.ClearDepth | ClearFlag.ClearColor;
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier buffer, string name = "", int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier buffer, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
cmd.name = name;
cmd.name = "";
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, string name = "", int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
SetRenderTarget(renderLoop, colorBuffer, depthBuffer, ClearFlag.ClearNone, new Color(0.0f, 0.0f, 0.0f, 0.0f), name, miplevel, cubemapFace);
SetRenderTarget(renderLoop, colorBuffer, depthBuffer, ClearFlag.ClearNone, new Color(0.0f, 0.0f, 0.0f, 0.0f), miplevel, cubemapFace);
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, string name = "", int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
SetRenderTarget(renderLoop, colorBuffer, depthBuffer, clearFlag, new Color(0.0f, 0.0f, 0.0f, 0.0f), name, miplevel, cubemapFace);
SetRenderTarget(renderLoop, colorBuffer, depthBuffer, clearFlag, new Color(0.0f, 0.0f, 0.0f, 0.0f), miplevel, cubemapFace);
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, string name = "", int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier colorBuffer, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, int miplevel = 0, CubemapFace cubemapFace = CubemapFace.Unknown)
cmd.name = name;
cmd.name = "";
cmd.SetRenderTarget(colorBuffer, depthBuffer, miplevel, cubemapFace);
if (clearFlag != ClearFlag.ClearNone)
cmd.ClearRenderTarget((clearFlag & ClearFlag.ClearDepth) != 0, (clearFlag & ClearFlag.ClearColor) != 0, clearColor);

public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, string name = "")
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer)
SetRenderTarget(renderLoop, colorBuffers, depthBuffer, ClearFlag.ClearNone, Color.black, name);
SetRenderTarget(renderLoop, colorBuffers, depthBuffer, ClearFlag.ClearNone, Color.black);
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag = ClearFlag.ClearNone, string name = "")
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag = ClearFlag.ClearNone)
SetRenderTarget(renderLoop, colorBuffers, depthBuffer, clearFlag, Color.black, name);
SetRenderTarget(renderLoop, colorBuffers, depthBuffer, clearFlag, Color.black);
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor, string name = "")
public static void SetRenderTarget(RenderLoop renderLoop, RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthBuffer, ClearFlag clearFlag, Color clearColor)
cmd.name = name;
cmd.name = "";
cmd.SetRenderTarget(colorBuffers, depthBuffer);
if (clearFlag != ClearFlag.ClearNone)
cmd.ClearRenderTarget((clearFlag & ClearFlag.ClearDepth) != 0, (clearFlag & ClearFlag.ClearColor) != 0, clearColor);

#endif
}
}
public class ProfilingSample
: IDisposable
{
bool disposed = false;
RenderLoop renderLoop;
string name;
public ProfilingSample(string _name, RenderLoop _renderloop)
{
renderLoop = _renderloop;
name = _name;
CommandBuffer cmd = new CommandBuffer();
cmd.name = "";
cmd.BeginSample(name);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
~ProfilingSample()
{
Dispose(false);
}
public void Dispose()
{
Dispose(true);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
CommandBuffer cmd = new CommandBuffer();
cmd.name = "";
cmd.EndSample(name);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();
}
disposed = true;
}
}
public static Matrix4x4 GetViewProjectionMatrix(Camera camera)
{
// The actual projection matrix used in shaders is actually massaged a bit to work across all platforms

public static Vector4 ComputeScreenSize(Camera camera)
{
return new Vector4(camera.pixelWidth, camera.pixelHeight, 1.0f / camera.pixelWidth, 1.0f / camera.pixelHeight);
}
// TEMP: These functions should be implemented C++ side, for now do it in C#
public static void SetMatrixCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4 mat)
{
var data = new float[16];
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[4 * c + r] = mat[r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
public static void SetMatrixArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4[] matArray)
{
int numMatrices = matArray.Length;
var data = new float[numMatrices * 16];
for (int n = 0; n < numMatrices; n++)
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[16 * n + 4 * c + r] = matArray[n][r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
public static void SetVectorArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Vector4[] vecArray)
{
int numVectors = vecArray.Length;
var data = new float[numVectors * 4];
for (int n = 0; n < numVectors; n++)
for (int i = 0; i < 4; i++)
data[4 * n + i] = vecArray[n][i];
cmd.SetComputeFloatParams(shadercs, name, data);
}
}
}

4
Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs


namespace UnityEngine.Experimental.ScriptableRenderLoop
{
[System.Serializable]
public struct ShadowSettings
public class ShadowSettings
{
public bool enabled;
public int shadowAtlasWidth;

{
get
{
ShadowSettings settings;
ShadowSettings settings = new ShadowSettings();
settings.enabled = true;
settings.shadowAtlasHeight = settings.shadowAtlasWidth = 4096;
settings.directionalLightCascadeCount = 1;

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


#define SAMPLER2D_HALF SAMPLER2D
#define SAMPLER2D_FLOAT SAMPLER2D
#define LOAD_TEXTURE2D(textureName, unCoord3) textureName.Load(unCoord3)
#define LOAD_TEXTURE2D_MSAA(textureName, unCoord3, sampleIndex) textureName.Load(unCoord3, sampleIndex)
#define LOAD_TEXTURE2D(textureName, unCoord2) textureName.Load(int3(unCoord2, 0))
#define LOAD_TEXTURE2D_MSAA(textureName, unCoord2, sampleIndex) textureName.Load(unCoord2, sampleIndex)

38
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 / sin(theta);
float res = cross(v1, v2).z * theta * rsqrt(1.0f - cosTheta * cosTheta); // optimization from * 1 / sin(theta)
return res;
}

float LineFpo(float tLDDL, float lrcpD, float rcpD)
{
// Compute: ((l / d) / (d * d + l * l)) + (1.0 / (d * d)) * atan(l / d).
return tLDDL + sq(rcpD) * atan(lrcpD);
return tLDDL + (rcpD * rcpD) * FastATan(lrcpD);
}
float LineFwt(float tLDDL, float l)

float d = length(normal);
float l1rcpD = l1 * rcp(d);
float l2rcpD = l2 * rcp(d);
float tLDDL1 = l1rcpD * rcp(sq(d) + sq(l1));
float tLDDL2 = l2rcpD * rcp(sq(d) + sq(l2));
float tLDDL1 = l1rcpD / (d * d + l1 * l1);
float tLDDL2 = l2rcpD / (d * d + l2 * l2);
return intP0 * normal.z + intWt * tangent.z;
// Guard against numerical precision issues.
return max(intP0 * normal.z + intWt * tangent.z, 0.0);
}
// Computes 1.0 / length(mul(ortho, transpose(inverse(invM)))).
float ComputeLineWidthFactor(float3x3 invM, float3 ortho)
{
// transpose(inverse(M)) = (1.0 / determinant(M)) * cofactor(M).
// Take into account that m12 = m21 = m23 = m32 = 0 and m33 = 1.
float det = invM._11 * invM._22 - invM._22 * invM._31 * invM._13;
float3x3 cof = {invM._22, 0.0, -invM._22 * invM._31,
0.0, invM._11 - invM._13 * invM._31, 0.0,
-invM._13 * invM._22, 0.0, invM._11 * invM._22};
// 1.0 / length(mul(V, (1.0 / s * M))) = abs(s) / length(mul(V, M)).
return abs(det) / length(mul(ortho, cof));
// Inverse-transform the endpoints and the binormal.
// Inverse-transform the endpoints.
B = mul(B, invM);
float width = ComputeLineWidthFactor(invM, B);
swap(P1, P2);
Swap(P1, P2);
}
// Recompute the length and the tangent in the new coordinate system.

// Integrate the clamped cosine over the line segment.
float irradiance = LineIrradiance(l1, l2, P0, T);
// Compute the width factor. We take the absolute value because the points may be swapped.
float width = abs(dot(B, normalize(cross(T, P1))));
// Guard against numerical precision issues.
return max(INV_PI * width * irradiance, 0.0);
return INV_PI * width * irradiance;
}
#endif // UNITY_AREA_LIGHTING_INCLUDED

26
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


}
#endif // INTRINSIC_MINMAX3
float sq(float x)
{
return x * x;
}
void swap(inout float a, inout float b)
void Swap(inout float a, inout float b)
void swap(inout float2 a, inout float2 b)
void Swap(inout float2 a, inout float2 b)
void swap(inout float3 a, inout float3 b)
void Swap(inout float3 a, inout float3 b)
void swap(inout float4 a, inout float4 b)
void Swap(inout float4 a, inout float4 b)
{
float4 t = a; a = b; b = t;
}

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};
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 };
// ----------------------------------------------------------------------------
// World position reconstruction / transformation
// ----------------------------------------------------------------------------

// Normalize coordinates
float2 positionSS;
// Unormalize coordinates
int2 unPositionSS;
uint2 unPositionSS;
};
// This function is use to provide an easy way to sample into a screen texture, either from a pixel or a compute shaders.

#endif
coord.positionSS *= invScreenSize;
coord.unPositionSS = int2(unPositionSS);
coord.unPositionSS = uint2(unPositionSS);
return coord;
}

23
Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl


// ref https://gist.github.com/selfshadow/8048308
// Reoriented Normal Mapping
// Blending when n1 and n2 are already 'unpacked' and normalised
float3 blendNormalRNM(float3 n1, float3 n2)
float3 BlendNormalRNM(float3 n1, float3 n2)
{
float3 t = n1.xyz + float3(0.0, 0.0, 1.0);
float3 u = n2.xyz * float3(-1.0, -1.0, 1.0);

float3 blendNormal(float3 n1, float3 n2)
float3 BlendNormal(float3 n1, float3 n2)
// Ref: http://http.developer.nvidia.com/GPUGems3/gpugems3_ch01.html
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;
// Force weights to sum to 1.0 (very important!)
blendWeights = max(blendWeights, float3(0.0, 0.0, 0.0));
blendWeights /= dot(blendWeights, 1.0);
return blendWeights;
}
float3 LerpWhiteTo(float3 b, float t)
{
float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}
#endif // UNITY_COMMON_MATERIAL_INCLUDED

8
Assets/ScriptableRenderLoop/ShaderLibrary/ImageBasedLighting.hlsl


// For now disabled
#if 0
float m = PerceptualRoughnessToRoughness(perceptualRoughness); // m is the real roughness parameter
const float fEps = 1.192092896e-07F; // smallest such that 1.0+FLT_EPSILON != 1.0 (+1e-4h is NOT good here. is visibly very wrong)
float n = (2.0 / max(fEps, m*m)) - 2.0; // 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 to spec power. See eq. 21 in --> https://dl.dropboxusercontent.com/u/55891920/papers/mm_brdf.pdf
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

#endif
return perceptualRoughness * UNITY_SPECCUBE_LOD_STEPS;
}
float mipmapLevelToPerceptualRoughness(float mipmapLevel)
{
return mipmapLevel / UNITY_SPECCUBE_LOD_STEPS;
}
// Ref: See "Moving Frostbite to PBR" Listing 22

2
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 5.6.0a4
m_EditorVersion: 5.6.0a5

35
.collabignore


# ===========================
# Default Collab Ignore Rules
# ===========================
# OS Generated
# ============
.DS_Store
._*
.Spotlight-V100
.Trashes
Icon?
ehthumbs.db
[Tt]humbs.db
[Dd]esktop.ini
# Visual Studio / MonoDevelop generated
# =====================================
[Ee]xported[Oo]bj/
*.userprefs
*.csproj
*.pidb
*.suo
*.sln
*.user
*.unityproj
*.booproj
# Unity generated
# ===============
/[Tt]emp/
[Oo]bj/
[Bb]uild
/[Ll]ibrary/
sysinfo.txt
*.stackdump

232
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSurfaceData.hlsl


void ADD_IDX(ComputeLayerTexCoord)(FragInput input, bool isTriplanar, inout LayerTexCoord layerTexCoord)
{
// TODO: Do we want to manage local or world triplanar/planar
//float3 position = localTriplanar ? TransformWorldToObject(input.positionWS) : input.positionWS;
float3 position = input.positionWS;
position *= ADD_IDX(_TexWorldScale);
// Handle uv0, uv1 and plnar XZ coordinate based on _CoordWeight weight (exclusif 0..1)
ADD_IDX(layerTexCoord.base).uv = ADD_IDX(_UVMappingMask).x * input.texCoord0 +
ADD_IDX(_UVMappingMask).y * input.texCoord1 +
ADD_IDX(_UVMappingMask).z * input.texCoord3 +
ADD_IDX(_UVMappingMask).w * position.xz;
float2 uvDetails = ADD_IDX(_UVDetailsMappingMask).x * input.texCoord0 +
ADD_IDX(_UVDetailsMappingMask).y * input.texCoord1 +
ADD_IDX(_UVDetailsMappingMask).z * input.texCoord3 +
// Note that if base is planar, detail map is planar
ADD_IDX(_UVMappingMask).w * position.xz;
ADD_IDX(layerTexCoord.details).uv = TRANSFORM_TEX(uvDetails, ADD_IDX(_DetailMap));
// triplanar
ADD_IDX(layerTexCoord.base).isTriplanar = isTriplanar;
ADD_IDX(layerTexCoord.base).uvYZ = position.yz;
ADD_IDX(layerTexCoord.base).uvZX = position.zx;
ADD_IDX(layerTexCoord.base).uvXY = position.xy;
ADD_IDX(layerTexCoord.details).isTriplanar = isTriplanar;
ADD_IDX(layerTexCoord.details).uvYZ = TRANSFORM_TEX(position.yz, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvZX = TRANSFORM_TEX(position.zx, ADD_IDX(_DetailMap));
ADD_IDX(layerTexCoord.details).uvXY = TRANSFORM_TEX(position.xy, ADD_IDX(_DetailMap));
}
void ADD_IDX(ApplyDisplacement)(inout FragInput input, inout LayerTexCoord layerTexCoord)
{
#ifdef _HEIGHTMAP
#ifndef _HEIGHTMAP_AS_DISPLACEMENT
// Transform view vector in tangent space
// Hope the compiler can optimize this in case of multiple layer
float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS);
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
float 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);
ADD_IDX(layerTexCoord.base).uv += offset;
ADD_IDX(layerTexCoord.base).uvYZ += offset;
ADD_IDX(layerTexCoord.base).uvZX += offset;
ADD_IDX(layerTexCoord.base).uvXY += offset;
ADD_IDX(layerTexCoord.details).uv += offset;
ADD_IDX(layerTexCoord.details).uvYZ += offset;
ADD_IDX(layerTexCoord.details).uvZX += offset;
ADD_IDX(layerTexCoord.details).uvXY += offset;
// Only modify tex coord 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;
}
#endif
#endif
}
// Return opacity
float ADD_IDX(GetSurfaceData)(FragInput input, LayerTexCoord layerTexCoord, out SurfaceData surfaceData)
{
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = ADD_IDX(_BaseColor).a;
#else
float alpha = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).a * ADD_IDX(_BaseColor).a;
#endif
// Perform alha test very early to save performance (a killed pixel will not sample textures)
#ifdef _ALPHATEST_ON
clip(alpha - _AlphaCutoff);
#endif
#ifdef _DETAIL_MAP
float detailMask = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_DetailMask), ADD_ZERO_IDX(sampler_DetailMask), ADD_IDX(layerTexCoord.base)).b;
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;
#ifdef _DETAIL_MAP_WITH_NORMAL
// Resample the detail map but this time for the normal map. This call should be optimize by the compiler
// We split both call due to trilinear mapping
float3 detailNormalTS = SAMPLE_LAYER_NORMALMAP_AG(ADD_IDX(_DetailMap), ADD_ZERO_IDX(sampler_DetailMap), ADD_IDX(layerTexCoord.details));
//float detailAO = 0.0;
#else
// TODO: Use heightmap as a derivative with Morten Mikklesen approach, how this work with our abstraction and triplanar ?
float3 detailNormalTS = float3(0.0, 0.0, 1.0);
//float detailAO = detail.b;
#endif
#endif
surfaceData.baseColor = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).rgb * ADD_IDX(_BaseColor).rgb;
#ifdef _DETAIL_MAP
surfaceData.baseColor *= LerpWhiteTo(2.0 * saturate(detailAlbedo * ADD_IDX(_DetailAlbedoScale)), detailMask);
#endif
#ifdef _SPECULAROCCLUSIONMAP
// TODO: Do something. For now just take alpha channel
surfaceData.specularOcclusion = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_SpecularOcclusionMap), ADD_ZERO_IDX(sampler_SpecularOcclusionMap), ADD_IDX(layerTexCoord.base)).a;
#else
// Horizon Occlusion for Normal Mapped Reflections: http://marmosetco.tumblr.com/post/81245981087
//surfaceData.specularOcclusion = saturate(1.0 + horizonFade * dot(r, input.tangentToWorld[2].xyz);
// smooth it
//surfaceData.specularOcclusion *= surfaceData.specularOcclusion;
surfaceData.specularOcclusion = 1.0;
#endif
// TODO: think about using BC5
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));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, BlendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space
// TODO: We are suppose to do * 2 - 1 here. how to deal with triplanar...
float3 normalOS = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_NormalMap), ADD_ZERO_IDX(sampler_NormalMap), ADD_IDX(layerTexCoord.base)).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
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
surfaceData.perceptualSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_BaseColorMap), ADD_ZERO_IDX(sampler_BaseColorMap), ADD_IDX(layerTexCoord.base)).a;
#elif defined(_MASKMAP)
surfaceData.perceptualSmoothness = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), ADD_ZERO_IDX(sampler_MaskMap), ADD_IDX(layerTexCoord.base)).a;
#else
surfaceData.perceptualSmoothness = 1.0;
#endif
surfaceData.perceptualSmoothness *= _Smoothness;
#ifdef _DETAIL_MAP
surfaceData.perceptualSmoothness *= LerpWhiteTo(2.0 * saturate(detailSmoothness * ADD_IDX(_DetailSmoothnessScale)), detailMask);
#endif
// MaskMap is Metallic, Ambient Occlusion, (Optional) - emissive Mask, Optional - Smoothness (in alpha)
#ifdef _MASKMAP
surfaceData.metallic = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), ADD_ZERO_IDX(sampler_MaskMap), ADD_IDX(layerTexCoord.base)).r;
surfaceData.ambientOcclusion = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_MaskMap), ADD_ZERO_IDX(sampler_MaskMap), ADD_IDX(layerTexCoord.base)).g;
#else
surfaceData.metallic = 1.0;
surfaceData.ambientOcclusion = 1.0;
#endif
surfaceData.metallic *= _Metallic;
// This part of the code is not used in case of layered shader but we keep the same macro system for simplicity
#if !defined(LAYERED_LIT_SHADER)
surfaceData.materialId = 0; // TODO
// TODO: think about using BC5
#ifdef _TANGENTMAP
#ifdef _NORMALMAP_TANGENT_SPACE // Normal and tangent use same space
float3 tangentTS = SAMPLE_LAYER_NORMALMAP(ADD_IDX(_TangentMap), ADD_ZERO_IDX(sampler_TangentMap), ADD_IDX(layerTexCoord.base)));
surfaceData.tangentWS = TransformTangentToWorld(tangentTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here! - Require to pass world transform)
surfaceData.tangentWS = SAMPLE_LAYER_TEXTURE2D(ADD_IDX(_TangentMap), ADD_ZERO_IDX(sampler_TangentMap), ADD_IDX(layerTexCoord.base)).rgb;
#endif
#else
surfaceData.tangentWS = normalize(input.tangentToWorld[0].xyz);
#endif
// 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;
#else
surfaceData.anisotropy = 1.0;
#endif
surfaceData.anisotropy *= _Anisotropy;
surfaceData.specular = 0.04;
surfaceData.subSurfaceRadius = 1.0;
surfaceData.thickness = 0.0;
surfaceData.subSurfaceProfile = 0;
surfaceData.coatNormalWS = float3(1.0, 0.0, 0.0);
surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
#else // #if !defined(LAYERED_LIT_SHADER)
// Mandatory to setup value to keep compiler quiet
// Layered shader only support materialId 0
surfaceData.materialId = 0;
surfaceData.tangentWS = input.tangentToWorld[0].xyz;
surfaceData.anisotropy = 0;
surfaceData.specular = 0.04;
surfaceData.subSurfaceRadius = 1.0;
surfaceData.thickness = 0.0;
surfaceData.subSurfaceProfile = 0;
surfaceData.coatNormalWS = float3(1.0, 0.0, 0.0);
surfaceData.coatPerceptualSmoothness = 1.0;
surfaceData.specularColor = float3(0.0, 0.0, 0.0);
#endif // #if !defined(LAYERED_LIT_SHADER)
return alpha;
}

9
Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitSurfaceData.hlsl.meta


fileFormatVersion: 2
guid: b24a503f5b489bb4896bc43d861f7f49
timeCreated: 1479984801
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

68
Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/GGXConvolve.shader


Shader "Hidden/HDRenderLoop/GGXConvolve"
{
SubShader
{
Pass
{
ZWrite Off
ZTest LEqual
Blend One Zero
HLSLPROGRAM
#pragma target 5.0
#pragma only_renderers d3d11 // TEMP: unitl we go futher in dev
#pragma vertex Vert
#pragma fragment Frag
#include "Common.hlsl"
#include "ImageBasedLighting.hlsl"
struct Attributes
{
float3 positionCS : POSITION;
float3 eyeVector : NORMAL;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
float3 eyeVector : TEXCOORD0;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = float4(input.positionCS.xy, UNITY_RAW_FAR_CLIP_VALUE, 1.0);
output.eyeVector = input.eyeVector;
return output;
}
TEXTURECUBE(_MainTex);
SAMPLERCUBE(sampler_MainTex);
float _Level;
float _MipMapCount;
float _InvOmegaP;
half4 Frag(Varyings input) : SV_Target
{
float3 N = input.eyeVector;
float3 V = N;
float perceptualRoughness = mipmapLevelToPerceptualRoughness(_Level);
// We approximate the pre-integration with V == N
float4 val = IntegrateLD( TEXTURECUBE_PARAM(_MainTex, sampler_MainTex),
V,
N,
PerceptualRoughnessToRoughness(perceptualRoughness),
_MipMapCount,
_InvOmegaP,
2048,
false);
return val;
}
ENDHLSL
}
}
}

9
Assets/ScriptableRenderLoop/HDRenderLoop/Sky/Resources/GGXConvolve.shader.meta


fileFormatVersion: 2
guid: 123ed592ad5c2494b8aed301fd609e7b
timeCreated: 1479994507
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

141
Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/Chrome.mat


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: Chrome
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _ALPHACUTOFFENABLE_OFF _DETAIL_MAP_WITH_NORMAL _DISTORTIONDEPTHTEST_OFF
_DISTORTIONONLY_OFF _EMISSION _NORMALMAP_TANGENT_SPACE
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _AnisotropyMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissiveColorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _HeightMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecularOcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubSurfaceRadiusMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TangentMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaCutoff: 0.5
- _AlphaCutoffEnable: 0
- _Anisotropy: 0
- _BlendMode: 0
- _BumpScale: 1
- _CullMode: 2
- _Cutoff: 0.5
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1
- _DetailMapMode: 0
- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DistortionDepthTest: 0
- _DistortionOnly: 0
- _DoubleSidedMode: 0
- _DstBlend: 0
- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _HeightBias: 0
- _HeightMapMode: 0
- _HeightScale: 1
- _MaterialId: 0
- _Metallic: 1
- _Mode: 0
- _NormalMapSpace: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Smoothness: 1
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SubSurfaceRadius: 0
- _SurfaceType: 0
- _UVDetail: 0
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}

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


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