浏览代码

Merge branch 'master' into Branch_Batching2

# Conflicts:
#	ProjectSettings/ProjectVersion.txt
/Branch_Batching2
Arnaud Carre 7 年前
当前提交
4fcf88bb
共有 64 个文件被更改,包括 1838 次插入1103 次删除
  1. 2
      Assets/GraphicsTests/Framework/Editor/TestFramework.cs
  2. 2
      Assets/ScriptableRenderPipeline/Core/Shadow/Shadow.cs
  3. 2
      Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs.hlsl
  4. 71
      Assets/ScriptableRenderPipeline/Core/TextureCache.cs
  5. 11
      Assets/ScriptableRenderPipeline/Fptl/FptlLighting.cs
  6. 10
      Assets/ScriptableRenderPipeline/Fptl/LightingConvexHullUtils.hlsl
  7. 16
      Assets/ScriptableRenderPipeline/Fptl/LightingTemplate.hlsl
  8. 24
      Assets/ScriptableRenderPipeline/Fptl/LightingUtils.hlsl
  9. 4
      Assets/ScriptableRenderPipeline/Fptl/ShadowDispatch.hlsl
  10. 26
      Assets/ScriptableRenderPipeline/Fptl/lightlistbuild-bigtile.compute
  11. 26
      Assets/ScriptableRenderPipeline/Fptl/lightlistbuild-clustered.compute
  12. 17
      Assets/ScriptableRenderPipeline/Fptl/lightlistbuild.compute
  13. 11
      Assets/ScriptableRenderPipeline/Fptl/scrbound.compute
  14. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs
  15. 47
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs
  16. 11
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl
  17. 39
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl
  18. 124
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugFullScreen.shader
  19. 40
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugViewTiles.shader
  20. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebugPanel.cs
  21. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs
  22. 231
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs
  23. 12
      Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset
  24. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs
  25. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl
  26. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl
  27. 331
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs
  28. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs.hlsl
  29. 65
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl
  30. 14
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/builddispatchindirect.compute
  31. 4
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/lightlistbuild.compute
  32. 7
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/materialflags.compute
  33. 68
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/shadeopaque.compute
  34. 22
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs
  35. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl
  36. 538
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl
  37. 6
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl
  38. 16
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl
  39. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader
  40. 20
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs
  41. 43
      Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/CameraMotionVectors.shader
  42. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl
  43. 2
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl
  44. 1
      Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl
  45. 15
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Utilities.cs
  46. 3
      Assets/ScriptableRenderPipeline/ShaderLibrary/AreaLighting.hlsl
  47. 6
      Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl
  48. 16
      Assets/ScriptableRenderPipeline/ShaderLibrary/Packing.hlsl
  49. 12
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl
  50. 78
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl
  51. 10
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl
  52. 2
      Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowMoments.hlsl
  53. 195
      Assets/TestScenes/HDTest/BasicProfiling.unity
  54. 287
      Assets/TestScenes/HDTest/CascadedShadowsTest.unity
  55. 2
      ProjectSettings/ProjectVersion.txt
  56. 2
      README.md
  57. 248
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl
  58. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl.meta
  59. 58
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader
  60. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader.meta
  61. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/Resources.meta
  62. 10
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Resources.meta
  63. 9
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl.meta
  64. 39
      Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl

2
Assets/GraphicsTests/Framework/Editor/TestFramework.cs


yield return null;
}
while (Lightmapping.isRunning)
while (UnityEditor.Lightmapping.isRunning)
{
yield return null;
}

2
Assets/ScriptableRenderPipeline/Core/Shadow/Shadow.cs


// For lights with multiple faces, the first shadow data contains
// per light information, so not all fields contain valid data.
// Shader code must make sure to read per face data from per face entries.
sd.texelSizeRcp = new Vector2( m_WidthRcp, m_HeightRcp );
sd.texelSizeRcp = new Vector4( m_WidthRcp, m_HeightRcp, 1.0f / widths[0], 1.0f / heights[0] );
sd.PackShadowType( sr.shadowType, sanitizedAlgo );
sd.payloadOffset = payload.Count();
entries.AddUnchecked( sd );

2
Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs.hlsl


//
// This file was automatically generated from Assets/ScriptableRenderPipeline/core/Shadow/ShadowBase.cs. Please don't edit by hand.
// This file was automatically generated from Assets/ScriptableRenderPipeline/Core/Shadow/ShadowBase.cs. Please don't edit by hand.
//
#ifndef SHADOWBASE_CS_HLSL

71
Assets/ScriptableRenderPipeline/Core/TextureCache.cs


if (!TextureCache.supportsCubemapArrayTextures)
{
if (!m_CubeBlitMaterial) m_CubeBlitMaterial = new Material(Shader.Find("Hidden/CubeToPano"));
if (!m_CubeBlitMaterial) m_CubeBlitMaterial = new Material(Shader.Find("Hidden/CubeToPano")) { hideFlags = HideFlags.HideAndDontSave };
int panoWidthTop = 4 * width;
int panoHeightTop = 2 * width;

m_StagingRTs = new RenderTexture[m_NumPanoMipLevels];
for (int m = 0; m < m_NumPanoMipLevels; m++)
{
m_StagingRTs[m] = new RenderTexture(Mathf.Max(1, panoWidthTop >> m), Mathf.Max(1, panoHeightTop >> m), 0, RenderTextureFormat.ARGBHalf);
m_StagingRTs[m] = new RenderTexture(Mathf.Max(1, panoWidthTop >> m), Mathf.Max(1, panoHeightTop >> m), 0, RenderTextureFormat.ARGBHalf) { hideFlags = HideFlags.HideAndDontSave };
}
if (m_CubeBlitMaterial)

{
protected int m_NumMipLevels;
static int s_GlobalTextureCacheVersion = 0;
int m_TextureCacheVersion = 0;
#if UNITY_EDITOR
static int s_TextureCacheIdGenerator = 0;
int m_TextureCacheId = 0;
#if UNITY_EDITOR
static bool s_ForceReinjectGlobalFirst = false;
static bool s_ForceReinjectGlobalSecond = false;
static int s_GlobalSecondSetByTexCacheID = -1;
// here we receive the in-editor updated textures. These must be reinjected into
// any texture cache which has a stale copy of it. However, we don't have a this-pointer to the texture cache
// so instead we defer this to NewFrame() where we force reinject.
// Ideally we'd build up a list here of textures which are to be reinjected but unfortunately the texture we receive
// is an intermediate one and not the final compressed one. So instead we will have to reinject all in NewFrame().
s_GlobalTextureCacheVersion++;
s_ForceReinjectGlobalFirst = true;
s_ForceReinjectGlobalSecond = false;
s_GlobalSecondSetByTexCacheID = -1;
#endif
#endif
public static bool isMobileBuildTarget
{

{
sliceIndex = m_LocatorInSliceArray[texId];
bFoundAvailOrExistingSlice = true;
#if UNITY_EDITOR
if(m_TextureCacheVersion!=s_GlobalTextureCacheVersion)
{
m_TextureCacheVersion++;
Debug.Assert(m_TextureCacheVersion <= s_GlobalTextureCacheVersion);
bSwapSlice = true; // force a reinject.
}
#endif
//assert(m_SliceArray[sliceIndex].TexID==TexID);
}

//for(int q=1; q<m_numTextures; q++)
// assert(m_SliceArray[m_SortedIdxArray[q-1]].CountLRU>=m_SliceArray[m_SortedIdxArray[q]].CountLRU);
#if UNITY_EDITOR
// one or more textures got updated in editor. Unfortunately we do not know exactly which since
// OnPostprocessTexture() receives intermediate uncompressed textures. So we will have to reinject all slices to force an update.
if(s_ForceReinjectGlobalSecond && s_GlobalSecondSetByTexCacheID==m_TextureCacheId)
{
s_ForceReinjectGlobalSecond = false;
s_GlobalSecondSetByTexCacheID = -1;
}
if(s_ForceReinjectGlobalFirst)
{
s_ForceReinjectGlobalSecond = true;
s_GlobalSecondSetByTexCacheID = m_TextureCacheId;
s_ForceReinjectGlobalFirst = false;
}
if(s_ForceReinjectGlobalSecond)
{
// all texture caches must loop through and force a reinject on all entries when this is true.
for(int i = 0; i < m_NumTextures; i++)
{
var texID = m_SliceArray[i].texId;
if(texID!=g_InvalidTexID)
{
Texture texture = (Texture) EditorUtility.InstanceIDToObject((int) texID);
if(texture!=null) TransferToSlice(i, texture);
}
}
}
#endif
}
protected TextureCache()

#if UNITY_EDITOR
m_TextureCacheId = s_TextureCacheIdGenerator; // assign an ID so we can tell the caches apart
++s_TextureCacheIdGenerator; // static/global
#endif
}
public virtual void TransferToSlice(int sliceIndex, Texture texture)

11
Assets/ScriptableRenderPipeline/Fptl/FptlLighting.cs


cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_ClearVoxelAtomicKernel, "g_LayeredSingleIdxBuffer", s_GlobalLightListAtomic);
cmd.DispatchCompute(buildPerVoxelLightListShader, s_ClearVoxelAtomicKernel, 1, 1, 1);
bool isOrthographic = camera.orthographic;
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_isOrthographic", isOrthographic ? 1 : 0);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_iNrVisibLights", numLights);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, "g_mScrProjection", projscr);
cmd.SetComputeMatrixParam(buildPerVoxelLightListShader, "g_mInvScrProjection", invProjscr);

var cmd = CommandBufferPool.Get("Build light list" );
bool isOrthographic = camera.orthographic;
// generate screen-space AABBs (used for both fptl and clustered).
if (numLights != 0)
{

var projh = temp * proj;
var invProjh = projh.inverse;
cmd.SetComputeIntParam(buildScreenAABBShader, "g_isOrthographic", isOrthographic ? 1 : 0);
cmd.SetComputeIntParam(buildScreenAABBShader, "g_iNrVisibLights", numLights);
cmd.SetComputeMatrixParam(buildScreenAABBShader, "g_mProjection", projh);
cmd.SetComputeMatrixParam(buildScreenAABBShader, "g_mInvProjection", invProjh);

// enable coarse 2D pass on 64x64 tiles (used for both fptl and clustered).
if (enableBigTilePrepass)
{
cmd.SetComputeIntParam(buildPerBigTileLightListShader, "g_isOrthographic", isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerBigTileLightListShader, "g_viDimensions", new int[2] { w, h });
cmd.SetComputeIntParam(buildPerBigTileLightListShader, "g_iNrVisibLights", numLights);
cmd.SetComputeMatrixParam(buildPerBigTileLightListShader, "g_mScrProjection", projscr);

if (usingFptl) // optimized for opaques only
{
cmd.SetComputeIntParam(buildPerTileLightListShader, "g_isOrthographic", isOrthographic ? 1 : 0);
cmd.SetComputeIntParams(buildPerTileLightListShader, "g_viDimensions", new int[2] { w, h });
cmd.SetComputeIntParam(buildPerTileLightListShader, "g_iNrVisibLights", numLights);
cmd.SetComputeMatrixParam(buildPerTileLightListShader, "g_mScrProjection", projscr);

void PushGlobalParams(Camera camera, ScriptableRenderContext loop, Matrix4x4 viewToWorld, Matrix4x4 scrProj, Matrix4x4 incScrProj, int numDirLights)
{
var cmd = CommandBufferPool.Get("Push Global Parameters");
bool isOrthographic = camera.orthographic;
cmd.SetGlobalFloat("g_isOrthographic", (float) (isOrthographic ? 1 : 0));
cmd.SetGlobalFloat("g_widthRT", (float)camera.pixelWidth);
cmd.SetGlobalFloat("g_heightRT", (float)camera.pixelHeight);

10
Assets/ScriptableRenderPipeline/Fptl/LightingConvexHullUtils.hlsl


return float4(vN, -dot(vN,p0));
}
bool DoesSphereOverlapTile(float3 dir, float halfTileSizeAtZDistOne, float3 sphCen, float sphRadiusIn)
bool DoesSphereOverlapTile(float3 dir, float halfTileSizeAtZDistOne, float3 sphCen_in, float sphRadiusIn, bool isOrthographic)
float3 V = dir; // ray direction down center of tile (does not need to be normalized).
float3 V = float3(isOrthographic ? 0.0 : dir.x, isOrthographic ? 0.0 : dir.y, dir.z); // ray direction down center of tile (does not need to be normalized).
float3 sphCen = float3(sphCen_in.x - (isOrthographic ? dir.x : 0.0), sphCen_in.y - (isOrthographic ? dir.y : 0.0), sphCen_in.z);
#if 1
float3 maxZdir = float3(-sphCen.z*sphCen.x, -sphCen.z*sphCen.y, sphCen.x*sphCen.x + sphCen.y*sphCen.y); // cross(sphCen,cross(Zaxis,sphCen))

// enlarge sphere so it overlaps the center of the tile assuming it overlaps the tile to begin with.
#if USE_LEFTHAND_CAMERASPACE
float sphRadius = sphRadiusIn + (sphCen.z+offs)*halfTileSizeAtZDistOne;
float s = sphCen.z+offs;
float sphRadius = sphRadiusIn - (sphCen.z-offs)*halfTileSizeAtZDistOne;
float s = -(sphCen.z-offs);
float sphRadius = sphRadiusIn + (isOrthographic ? 1.0 : s)*halfTileSizeAtZDistOne;
float a = dot(V,V);
float CdotV = dot(sphCen,V);

16
Assets/ScriptableRenderPipeline/Fptl/LightingTemplate.hlsl


DirectionalLight lightData = g_dirLightData[i];
float atten = 1;
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.lightAxisZ).xyz;
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, 0.0.xxx);
float shadow = GetDirectionalShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, normalize(light.dir.xyz));
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, -lightData.lightAxisZ).xyz;
ints += EvalMaterial(light, ind);
}

}
atten *= angularAtt.w*(fProjVec>0.0); // finally apply this to the dist att.
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, 0.0.xxx);
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(normalize(light.dir.xyz), dist));
UnityLight light;
light.dir.xyz = mul((float3x3) g_mViewToWorld, vL).xyz; //unity_CameraToWorld
ints += EvalMaterial(light, ind);

[branch]
if (shadowIdx >= 0)
{
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, vLw);
float shadow = GetPunctualShadowAttenuation(shadowContext, vPw, 0.0.xxx, shadowIdx, float4(vLw, dist));
atten *= shadow;
}

24
Assets/ScriptableRenderPipeline/Fptl/LightingUtils.hlsl


uniform float4x4 g_mInvScrProjection;
uniform uint g_isOrthographic;
uniform uint g_widthRT;
uniform uint g_heightRT;

float fSx = g_mScrProjection[0].x;
//float fCx = g_mScrProjection[2].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
//float fCy = g_mScrProjection[2].y;
float fCy = g_mScrProjection[1].z;
bool isOrthographic = g_isOrthographic!=0;
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
float fCx = isOrthographic ? g_mScrProjection[0].w : g_mScrProjection[0].z;
float fCy = isOrthographic ? g_mScrProjection[1].w : g_mScrProjection[1].z;
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
bool useLeftHandVersion = true;
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
bool useLeftHandVersion = isOrthographic;
float s = useLeftHandVersion ? 1 : (-1);
float2 p = float2( (s*v2ScrPos.x-fCx)/fSx, (s*v2ScrPos.y-fCy)/fSy);
return float3(isOrthographic ? p.xy : (fLinDepth*p.xy), fLinDepth);
}
float GetLinearZFromSVPosW(float posW)

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)
// for perspective projection m22 is zero and m23 is +1/-1 (depends on left/right hand proj)
// however this function must also work for orthographic projection so we keep it like this.
float m22 = g_mInvScrProjection[2].z, m23 = g_mInvScrProjection[2].w;
float m32 = g_mInvScrProjection[3].z, m33 = g_mInvScrProjection[3].w;

4
Assets/ScriptableRenderPipeline/Fptl/ShadowDispatch.hlsl


// example of overriding punctual lights
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
{
// example for choosing the same algo
Texture2DArray tex = shadowContext.tex2DArray[0];

}
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

26
Assets/ScriptableRenderPipeline/Fptl/lightlistbuild-bigtile.compute


#define MAX_NR_BIGTILE_LIGHTS (MAX_NR_BIGTILE_LIGHTS_PLUSONE-1)
uniform int g_isOrthographic;
uniform int g_iNrVisibLights;
uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;

float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
bool isOrthographic = g_isOrthographic!=0;
float fCx = g_mScrProjection[0].z;
float fCy = g_mScrProjection[1].z;
float fCx = isOrthographic ? g_mScrProjection[0].w : g_mScrProjection[0].z;
float fCy = isOrthographic ? g_mScrProjection[1].w : g_mScrProjection[1].z;
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
bool useLeftHandVersion = true;
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
bool useLeftHandVersion = isOrthographic;
float s = useLeftHandVersion ? 1 : (-1);
float2 p = float2( (s*v2ScrPos.x-fCx)/fSx, (s*v2ScrPos.y-fCy)/fSy);
return float3(isOrthographic ? p.xy : (fLinDepth*p.xy), fLinDepth);
}
float GetOnePixDiagWorldDistAtDepthOne()

{
SFiniteLightBound lgtDat = g_data[lightsListLDS[l]];
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius) )
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius, g_isOrthographic!=0) )
lightsListLDS[l]=0xffffffff;
}

int i=iSwizzle + (2*(iSection&0x2)); // offset by 4 at section 2
vP0 = GetTileVertex(uint2(viTilLL.x, viTilUR.y), uint2(viTilUR.x, viTilLL.y), i, fTileFarPlane);
vE0 = iSection == 0 ? vP0 : (((iSwizzle & 0x2) == 0 ? 1.0f : (-1.0f)) * ((int)(iSwizzle & 0x1) == (iSwizzle >> 1) ? float3(1, 0, 0) : float3(0, 1, 0)));
#if USE_LEFTHAND_CAMERASPACE
float3 edgeSectionZero = g_isOrthographic==0 ? vP0 : float3(0.0,0.0,1.0);
#else
float3 edgeSectionZero = g_isOrthographic==0 ? vP0 : float3(0.0,0.0,-1.0);
#endif
vE0 = iSection == 0 ? edgeSectionZero : (((iSwizzle & 0x2) == 0 ? 1.0f : (-1.0f)) * ((int)(iSwizzle & 0x1) == (iSwizzle >> 1) ? float3(1, 0, 0) : float3(0, 1, 0)));
}
void CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR)

26
Assets/ScriptableRenderPipeline/Fptl/lightlistbuild-clustered.compute


#define PERFORM_SPHERICAL_INTERSECTION_TESTS
#define CONV_HULL_TEST_ENABLED
uniform int g_isOrthographic;
uniform int g_iNrVisibLights;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;

float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
bool isOrthographic = g_isOrthographic!=0;
float fCx = g_mScrProjection[0].z;
float fCy = g_mScrProjection[1].z;
float fCx = isOrthographic ? g_mScrProjection[0].w : g_mScrProjection[0].z;
float fCy = isOrthographic ? g_mScrProjection[1].w : g_mScrProjection[1].z;
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
bool useLeftHandVersion = true;
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
bool useLeftHandVersion = isOrthographic;
float s = useLeftHandVersion ? 1 : (-1);
float2 p = float2( (s*v2ScrPos.x-fCx)/fSx, (s*v2ScrPos.y-fCy)/fSy);
return float3(isOrthographic ? p.xy : (fLinDepth*p.xy), fLinDepth);
}
float GetOnePixDiagWorldDistAtDepthOne()

{
SFiniteLightBound lgtDat = g_data[coarseList[l]];
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius) )
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius, g_isOrthographic!=0) )
coarseList[l]=0xffffffff;
}

int i=iSwizzle + (2*(iSection&0x2)); // offset by 4 at section 2
vP0 = GetTileVertex(uint2(viTilLL.x, viTilUR.y), uint2(viTilUR.x, viTilLL.y), i, fTileFarPlane);
vE0 = iSection==0 ? vP0 : (((iSwizzle&0x2)==0 ? 1.0f : (-1.0f))*((iSwizzle&0x1)==(iSwizzle>>1) ? float3(1,0,0) : float3(0,1,0)));
#if USE_LEFTHAND_CAMERASPACE
float3 edgeSectionZero = g_isOrthographic==0 ? vP0 : float3(0.0,0.0,1.0);
#else
float3 edgeSectionZero = g_isOrthographic==0 ? vP0 : float3(0.0,0.0,-1.0);
#endif
vE0 = iSection==0 ? edgeSectionZero : (((iSwizzle&0x2)==0 ? 1.0f : (-1.0f))*((iSwizzle&0x1)==(iSwizzle>>1) ? float3(1,0,0) : float3(0,1,0)));
}
int CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR, float fTileFarPlane)

17
Assets/ScriptableRenderPipeline/Fptl/lightlistbuild.compute


#define PERFORM_SPHERICAL_INTERSECTION_TESTS
uniform int g_isOrthographic;
uniform int g_iNrVisibLights;
uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;

float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
bool isOrthographic = g_isOrthographic!=0;
float fCx = g_mScrProjection[0].z;
float fCy = g_mScrProjection[1].z;
float fCx = isOrthographic ? g_mScrProjection[0].w : g_mScrProjection[0].z;
float fCy = isOrthographic ? g_mScrProjection[1].w : g_mScrProjection[1].z;
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
bool useLeftHandVersion = true;
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
bool useLeftHandVersion = isOrthographic;
float s = useLeftHandVersion ? 1 : (-1);
float2 p = float2( (s*v2ScrPos.x-fCx)/fSx, (s*v2ScrPos.y-fCy)/fSy);
return float3(isOrthographic ? p.xy : (fLinDepth*p.xy), fLinDepth);
}
float GetOnePixDiagWorldDistAtDepthOne()

{
SFiniteLightBound lightData = g_data[prunedList[l]];
if( DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lightData.center.xyz, lightData.radius) )
if( DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lightData.center.xyz, lightData.radius, g_isOrthographic!=0) )
{
unsigned int uIndex;
InterlockedAdd(lightOffsSph, 1, uIndex);

11
Assets/ScriptableRenderPipeline/Fptl/scrbound.compute


#include "ShaderBase.h"
#include "LightDefinitions.cs.hlsl"
uniform int g_isOrthographic;
uniform int g_iNrVisibLights;
uniform float4x4 g_mInvProjection;
uniform float4x4 g_mProjection;

}
else
{
//if((center.z+radius)<0.0)
if( length(center)>radius)
if(g_isOrthographic==0 && length(center)>radius)
{
float2 vMi, vMa;
bool2 bMi, bMa;

vMax.xy = bMa ? min(vMax.xy, vMa) : vMax.xy;
}
else if(g_isOrthographic!=0)
{
float2 vMi = mul(g_mProjection, float4(center.xyz-radius,1)).xy; // no division needed for ortho
float2 vMa = mul(g_mProjection, float4(center.xyz+radius,1)).xy; // no division needed for ortho
vMin.xy = max(vMin.xy, vMi);
vMax.xy = min(vMax.xy, vMa);
}
#if USE_LEFTHAND_CAMERASPACE

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/AdditionalData/HDAdditionalLightData.cs


public bool affectSpecular = true;
public LightArchetype archetype = LightArchetype.Punctual;
public SpotLightShape spotLightShape = SpotLightShape.Cone;
public SpotLightShape spotLightShape = SpotLightShape.Cone; // Note: Only for Spotlight, should be hide for other light
[Range(0.0f, 20.0f)]
public float lightLength = 0.0f; // Area & projector lights

47
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs


public static string kFullScreenDebugMode = "Fullscreen Debug Mode";
public static string kDisplaySkyReflectionDebug = "Display Sky Reflection";
public static string kSkyReflectionMipmapDebug = "Sky Reflection Mipmap";
public static string kTileDebug = "Tile Debug By Category";
public float debugOverlayRatio = 0.33f;

public static int[] debugViewEngineValues = null;
public static GUIContent[] debugViewMaterialVaryingStrings = null;
public static int[] debugViewMaterialVaryingValues = null;
public static GUIContent[] debugViewMaterialPropertiesStrings = null;
public static int[] debugViewMaterialPropertiesValues = null;
public static GUIContent[] debugViewMaterialGBufferStrings = null;
public static int[] debugViewMaterialGBufferValues = null;

materialDebugSettings.SetDebugViewVarying(value);
}
public void SetDebugViewProperties(Attributes.DebugViewProperties value)
{
if (value != 0)
lightingDebugSettings.debugLightingMode = DebugLightingMode.None;
materialDebugSettings.SetDebugViewProperties(value);
}
public void SetDebugViewGBuffer(int value)
{
if (value != 0)

DebugMenuManager.instance.AddDebugItem<int>("Material", "Material",() => materialDebugSettings.debugViewMaterial, (value) => SetDebugViewMaterial((int)value), DebugItemFlag.None, new DebugItemHandlerIntEnum(DebugDisplaySettings.debugViewMaterialStrings, DebugDisplaySettings.debugViewMaterialValues));
DebugMenuManager.instance.AddDebugItem<int>("Material", "Engine",() => materialDebugSettings.debugViewEngine, (value) => SetDebugViewEngine((int)value), DebugItemFlag.None, new DebugItemHandlerIntEnum(DebugDisplaySettings.debugViewEngineStrings, DebugDisplaySettings.debugViewEngineValues));
DebugMenuManager.instance.AddDebugItem<Attributes.DebugViewVarying>("Material", "Attributes",() => materialDebugSettings.debugViewVarying, (value) => SetDebugViewVarying((Attributes.DebugViewVarying)value));
DebugMenuManager.instance.AddDebugItem<Attributes.DebugViewProperties>("Material", "Properties", () => materialDebugSettings.debugViewProperties, (value) => SetDebugViewProperties((Attributes.DebugViewProperties)value));
DebugMenuManager.instance.AddDebugItem<int>("Material", "GBuffer",() => materialDebugSettings.debugViewGBuffer, (value) => SetDebugViewGBuffer((int)value), DebugItemFlag.None, new DebugItemHandlerIntEnum(DebugDisplaySettings.debugViewMaterialGBufferStrings, DebugDisplaySettings.debugViewMaterialGBufferValues));
DebugMenuManager.instance.AddDebugItem<LightingDebugPanel, bool>(kEnableShadowDebug, () => lightingDebugSettings.enableShadows, (value) => lightingDebugSettings.enableShadows = (bool)value);

DebugMenuManager.instance.AddDebugItem<LightingDebugPanel, Color>(kDebugLightingAlbedo, () => lightingDebugSettings.debugLightingAlbedo, (value) => lightingDebugSettings.debugLightingAlbedo = (Color)value);
DebugMenuManager.instance.AddDebugItem<bool>("Lighting", kDisplaySkyReflectionDebug, () => lightingDebugSettings.displaySkyReflection, (value) => lightingDebugSettings.displaySkyReflection = (bool)value);
DebugMenuManager.instance.AddDebugItem<LightingDebugPanel, float>(kSkyReflectionMipmapDebug, () => lightingDebugSettings.skyReflectionMipmap, (value) => lightingDebugSettings.skyReflectionMipmap = (float)value, DebugItemFlag.None, new DebugItemHandlerFloatMinMax(0.0f, 1.0f));
DebugMenuManager.instance.AddDebugItem<LightingDebugPanel, TilePass.TileSettings.TileDebug>(kTileDebug,() => lightingDebugSettings.tileDebugByCategory, (value) => lightingDebugSettings.tileDebugByCategory = (TilePass.TileSettings.TileDebug)value);
DebugMenuManager.instance.AddDebugItem<bool>("Rendering", "Display Opaque",() => renderingDebugSettings.displayOpaqueObjects, (value) => renderingDebugSettings.displayOpaqueObjects = (bool)value);
DebugMenuManager.instance.AddDebugItem<bool>("Rendering", "Display Transparency",() => renderingDebugSettings.displayTransparentObjects, (value) => renderingDebugSettings.displayTransparentObjects = (bool)value);

index = 0;
FillWithPropertiesEnum(typeof(Attributes.DebugViewVarying), debugViewMaterialVaryingStrings, debugViewMaterialVaryingValues, "", ref index);
// Properties debug
var propertiesNames = Enum.GetNames(typeof(Attributes.DebugViewProperties));
debugViewMaterialPropertiesStrings = new GUIContent[propertiesNames.Length];
debugViewMaterialPropertiesValues = new int[propertiesNames.Length];
index = 0;
FillWithPropertiesEnum(typeof(Attributes.DebugViewProperties), debugViewMaterialPropertiesStrings, debugViewMaterialPropertiesValues, "", ref index);
// Gbuffer debug
var gbufferNames = Enum.GetNames(typeof(Attributes.DebugViewGbuffer));
debugViewMaterialGBufferStrings = new GUIContent[gbufferNames.Length + bsdfDataDeferredType.GetFields().Length];

Depth = DebugViewVarying.VertexColorAlpha + 1,
BakeDiffuseLightingWithAlbedoPlusEmissive,
}
// Number must be contiguous
[GenerateHLSL]
public enum DebugViewProperties
{
None = 0,
Tessellation = DebugViewGbuffer.BakeDiffuseLightingWithAlbedoPlusEmissive + 1,
PerPixelDisplacement,
DepthOffset,
Lightmap,
}
}
[Serializable]

public int debugViewEngine { get { return m_DebugViewEngine; } }
public Attributes.DebugViewVarying debugViewVarying { get { return m_DebugViewVarying; } }
public Attributes.DebugViewProperties debugViewProperties { get { return m_DebugViewProperties; } }
Attributes.DebugViewProperties m_DebugViewProperties = Attributes.DebugViewProperties.None;
int m_DebugViewGBuffer = 0; // Can't use GBuffer enum here because the values are actually split between this enum and values from Lit.BSDFData
public int GetDebugMaterialIndex()

// They are all mutually exclusive so return the sum will return the right index.
return m_DebugViewGBuffer + m_DebugViewMaterial + m_DebugViewEngine + (int)m_DebugViewVarying;
return m_DebugViewGBuffer + m_DebugViewMaterial + m_DebugViewEngine + (int)m_DebugViewVarying + (int)m_DebugViewProperties;
}
public void DisableMaterialDebug()

m_DebugViewVarying = Attributes.DebugViewVarying.None;
m_DebugViewProperties = Attributes.DebugViewProperties.None;
m_DebugViewGBuffer = 0;
}

DisableMaterialDebug();
m_DebugViewVarying = value;
}
public void SetDebugViewProperties(Attributes.DebugViewProperties value)
{
if (value != 0)
DisableMaterialDebug();
m_DebugViewProperties = value;
}
public void SetDebugViewGBuffer(int value)
{

public bool IsDebugDisplayEnabled()
{
return (m_DebugViewEngine != 0 || m_DebugViewMaterial != 0 || m_DebugViewVarying != Attributes.DebugViewVarying.None || m_DebugViewGBuffer != 0);
return (m_DebugViewEngine != 0 || m_DebugViewMaterial != 0 || m_DebugViewVarying != Attributes.DebugViewVarying.None || m_DebugViewProperties != Attributes.DebugViewProperties.None || m_DebugViewGBuffer != 0);
}
}

None,
SSAO,
SSAOBeforeFiltering,
MotionVectors,
NanTracker
}
[Serializable]

public bool displaySkyReflection = false;
public float skyReflectionMipmap = 0.0f;
public TilePass.TileSettings.TileDebug tileDebugByCategory = TilePass.TileSettings.TileDebug.None;
public void OnValidate()
{

11
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.cs.hlsl


#define DEBUGVIEWGBUFFER_BAKE_DIFFUSE_LIGHTING_WITH_ALBEDO_PLUS_EMISSIVE (11)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Attributes.DebugViewProperties: static fields
//
#define DEBUGVIEWPROPERTIES_NONE (0)
#define DEBUGVIEWPROPERTIES_TESSELLATION (12)
#define DEBUGVIEWPROPERTIES_PER_PIXEL_DISPLACEMENT (13)
#define DEBUGVIEWPROPERTIES_DEPTH_OFFSET (14)
#define DEBUGVIEWPROPERTIES_LIGHTMAP (15)
//
#define FULLSCREENDEBUGMODE_MOTION_VECTORS (3)
#define FULLSCREENDEBUGMODE_NAN_TRACKER (4)
#endif

39
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugDisplay.hlsl


float4 _DebugLightingAlbedo; // xyz = albedo for diffuse, w unused
float4 _DebugLightingSmoothness; // x == bool override, y == override value
void GetPropertiesDataDebug(uint paramId, inout float3 result, inout bool needLinearToSRGB)
{
switch (paramId)
{
case DEBUGVIEWPROPERTIES_TESSELLATION:
#ifdef TESSELLATION_ON
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
case DEBUGVIEWPROPERTIES_PER_PIXEL_DISPLACEMENT:
#ifdef _PER_PIXEL_DISPLACEMENT // Caution: This define is related to a shader features (But it may become a standard features for HD
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
case DEBUGVIEWPROPERTIES_DEPTH_OFFSET:
#ifdef _DEPTHOFFSET_ON // Caution: This define is related to a shader features (But it may become a standard features for HD
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
case DEBUGVIEWPROPERTIES_LIGHTMAP:
#if defined(LIGHTMAP_ON) || defined (DIRLIGHTMAP_COMBINED) || defined(DYNAMICLIGHTMAP_ON)
result = float3(1.0, 0.0, 0.0);
#else
result = float3(0.0, 0.0, 0.0);
#endif
break;
}
}
#endif

124
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugFullScreen.shader


#include "../../ShaderLibrary/Common.hlsl"
#include "../Debug/DebugDisplay.cs.hlsl"
#include "../ShaderVariables.hlsl"
TEXTURE2D(_DebugFullScreenTexture);
SAMPLER2D(sampler_DebugFullScreenTexture);

return output;
}
// Motion vector debug utilities
// >>>
float DistanceToLine(float2 p, float2 p1, float2 p2)
{
float2 center = (p1 + p2) * 0.5;
float len = length(p2 - p1);
float2 dir = (p2 - p1) / len;
float2 rel_p = p - center;
return dot(rel_p, float2(dir.y, -dir.x));
}
float DistanceToSegment(float2 p, float2 p1, float2 p2)
{
float2 center = (p1 + p2) * 0.5;
float len = length(p2 - p1);
float2 dir = (p2 - p1) / len;
float2 rel_p = p - center;
float dist1 = abs(dot(rel_p, float2(dir.y, -dir.x)));
float dist2 = abs(dot(rel_p, dir)) - 0.5 * len;
return max(dist1, dist2);
}
float DrawArrow(float2 texcoord, float body, float head, float height, float linewidth, float antialias)
{
float w = linewidth / 2.0 + antialias;
float2 start = -float2(body / 2.0, 0.0);
float2 end = float2(body / 2.0, 0.0);
// Head: 3 lines
float d1 = DistanceToLine(texcoord, end, end - head * float2(1.0, -height));
float d2 = DistanceToLine(texcoord, end - head * float2(1.0, height), end);
float d3 = texcoord.x - end.x + head;
// Body: 1 segment
float d4 = DistanceToSegment(texcoord, start, end - float2(linewidth, 0.0));
float d = min(max(max(d1, d2), -d3), d4);
return d;
}
float2 SampleMotionVectors(float2 coords)
{
#if UNITY_UV_STARTS_AT_TOP
coords.y = 1.0 - coords.y;
#endif
float2 mv = SAMPLE_TEXTURE2D(_DebugFullScreenTexture, sampler_DebugFullScreenTexture, coords).xy;
#if UNITY_UV_STARTS_AT_TOP
mv.y *= -1.0;
#endif
return mv;
}
// <<<
float4 Frag(Varyings input) : SV_Target
{
// SSAO

if (_FullScreenDebugMode == FULLSCREENDEBUGMODE_SSAOBEFORE_FILTERING)
{
return 1.0f - SAMPLE_TEXTURE2D(_DebugFullScreenTexture, sampler_DebugFullScreenTexture, input.texcoord).xxxx;
}
if (_FullScreenDebugMode == FULLSCREENDEBUGMODE_NAN_TRACKER)
{
#if UNITY_UV_STARTS_AT_TOP
input.texcoord.y = 1.0 - input.texcoord.y;
#endif
float4 color = SAMPLE_TEXTURE2D(_DebugFullScreenTexture, sampler_DebugFullScreenTexture, input.texcoord);
if (any(isnan(color)) || any(isinf(color)))
{
color = float4(1.0, 0.0, 1.0, 1.0);
}
else
{
// Dim the color buffer so we can see NaNs & Infs better
color.rgb *= 0.25;
}
return color;
}
if (_FullScreenDebugMode == FULLSCREENDEBUGMODE_MOTION_VECTORS)
{
float2 mv = SampleMotionVectors(input.texcoord);
// Background color intensity - keep this low unless you want to make your eyes bleed
const float kIntensity = 0.15;
// Map motion vector direction to color wheel (hue between 0 and 360deg)
float phi = atan2(mv.x, mv.y);
float hue = (phi / PI + 1.0) * 0.5;
float r = abs(hue * 6.0 - 3.0) - 1.0;
float g = 2.0 - abs(hue * 6.0 - 2.0);
float b = 2.0 - abs(hue * 6.0 - 4.0);
float3 color = saturate(float3(r, g, b) * kIntensity);
// Grid subdivisions - should be dynamic
const float kGrid = 64.0;
// Arrow grid (aspect ratio is kept)
float rows = floor(kGrid * _ScreenParams.y / _ScreenParams.x);
float cols = kGrid;
float2 size = _ScreenParams.xy / float2(cols, rows);
float body = min(size.x, size.y) / 1.4142135623730951; // sqrt(2)
float2 texcoord = input.positionCS.xy;
float2 center = (floor(texcoord / size) + 0.5) * size;
texcoord -= center;
// Sample the center of the cell to get the current arrow vector
float2 arrow_coord = center / _ScreenParams.xy;
float2 mv_arrow = SampleMotionVectors(arrow_coord);
// Skip empty motion
float d = 0.0;
if (any(mv_arrow))
{
// Rotate the arrow according to the direction
mv_arrow = normalize(mv_arrow);
float2x2 rot = float2x2(mv_arrow.x, -mv_arrow.y, mv_arrow.y, mv_arrow.x);
texcoord = mul(rot, texcoord);
d = DrawArrow(texcoord, body, 0.25 * body, 0.5, 2.0, 1.0);
d = 1.0 - saturate(d);
}
return float4(color + d.xxx, 1.0);
}
return float4(0.0, 0.0, 0.0, 0.0);

40
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/DebugViewTiles.shader


StructuredBuffer<uint> g_TileList;
Buffer<uint> g_DispatchIndirectBuffer;
struct VSOut
struct Attributes
{
uint vertexID : SV_VertexID;
};
struct Varyings
float4 Pos : SV_POSITION;
int Variant : TEXCOORD0;
float4 positionCS : SV_POSITION;
int variant : TEXCOORD0;
VSOut Vert(uint vertexID : SV_VertexID)
Varyings Vert(uint vertexID : SV_VertexID)
{
uint quadIndex = vertexID / 6;
uint quadVertex = vertexID - quadIndex * 6;

float2 clipCoord = (pixelCoord / _ScreenParams.xy) * 2.0 - 1.0;
clipCoord.y *= -1;
VSOut Out;
Out.Pos = float4(clipCoord, 0, 1.0);
Out.Variant = variant;
return Out;
Varyings output;
output.positionCS = float4(clipCoord, 0, 1.0);
output.variant = variant;
return output;
VSOut Vert(float3 positionOS : POSITION)
Varyings Vert(Attributes input)
VSOut Out;
Out.Pos = TransformWorldToHClip(TransformObjectToWorld(positionOS));
Out.Variant = 0;
return Out;
Varyings output;
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
output.variant = 0; // unused
return output;
}
#endif

return color;
}
float4 Frag(float4 positionCS : SV_POSITION, int Variant : TEXCOORD0) : SV_Target
float4 Frag(Varyings input) : SV_Target
PositionInputs posInput = GetPositionInput(positionCS.xy, _ScreenSize.zw, uint2(positionCS.xy) / GetTileSize());
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw, uint2(input.positionCS.xy) / GetTileSize());
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);

n += count;
}
}
if(n == 0) n = -1;
if (n == 0)
n = -1;
n = Variant;
n = input.variant;
#endif
float4 result = float4(0.0, 0.0, 0.0, 0.0);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Debug/LightingDebugPanel.cs


m_DebugPanel.GetDebugItem(DebugDisplaySettings.kFullScreenDebugMode).handler.OnEditorGUI();
m_DebugPanel.GetDebugItem(DebugDisplaySettings.kTileDebug).handler.OnEditorGUI();
DebugItem displaySkyReflecItem = m_DebugPanel.GetDebugItem(DebugDisplaySettings.kDisplaySkyReflectionDebug);
displaySkyReflecItem.handler.OnEditorGUI();
if ((bool)displaySkyReflecItem.GetValue())

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Editor/HDRenderPipelineInspector.cs


// Tile pass Settings
public readonly GUIContent tileLightLoopSettings = new GUIContent("Tile Light Loop Settings");
public readonly GUIContent enableTileAndCluster = new GUIContent("Enable tile/clustered", "Toggle");
public readonly GUIContent enableSplitLightEvaluation = new GUIContent("Split light and reflection evaluation", "Toggle");
public readonly GUIContent enableComputeLightEvaluation = new GUIContent("Enable Compute Light Evaluation", "Toggle");
public readonly GUIContent enableComputeLightVariants = new GUIContent("Enable Compute Light Variants", "Toggle");
public readonly GUIContent enableComputeMaterialVariants = new GUIContent("Enable Compute Material Variants", "Toggle");

SerializedProperty m_enableClustered;
SerializedProperty m_enableFptlForOpaqueWhenClustered;
SerializedProperty m_enableBigTilePrepass;
SerializedProperty m_tileDebugByCategory;
// Rendering Settings
SerializedProperty m_RenderingUseForwardOnly = null;

// Tile settings
m_enableTileAndCluster = FindProperty(x => x.tileSettings.enableTileAndCluster);
m_enableSplitLightEvaluation = FindProperty(x => x.tileSettings.enableSplitLightEvaluation);
m_enableComputeLightEvaluation = FindProperty(x => x.tileSettings.enableComputeLightEvaluation);
m_enableComputeLightVariants = FindProperty(x => x.tileSettings.enableComputeLightVariants);
m_enableComputeMaterialVariants = FindProperty(x => x.tileSettings.enableComputeMaterialVariants);

m_tileDebugByCategory = FindProperty(x => x.tileSettings.tileDebugByCategory);
// Shadow settings
m_ShadowAtlasWidth = FindProperty(x => x.shadowInitParams.shadowAtlasWidth);

EditorGUI.BeginChangeCheck();
EditorGUILayout.PropertyField(m_enableTileAndCluster, styles.enableTileAndCluster);
EditorGUILayout.PropertyField(m_enableSplitLightEvaluation, styles.enableSplitLightEvaluation);
EditorGUILayout.PropertyField(m_enableComputeLightEvaluation, styles.enableComputeLightEvaluation);
EditorGUILayout.PropertyField(m_enableComputeLightVariants, styles.enableComputeLightVariants);
EditorGUILayout.PropertyField(m_enableComputeMaterialVariants, styles.enableComputeMaterialVariants);

EditorGUILayout.PropertyField(m_tileDebugByCategory, styles.tileDebugByCategory);
if (EditorGUI.EndChangeCheck())
{

231
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipeline.cs


{
public Matrix4x4 viewMatrix;
public Matrix4x4 projMatrix;
public Matrix4x4 nonJitteredProjMatrix;
public Vector4 screenSize;
public Vector4[] frustumPlaneEquations;
public Camera camera;

get { return projMatrix * viewMatrix; }
}
public Matrix4x4 nonJitteredViewProjMatrix
{
get { return nonJitteredProjMatrix * viewMatrix; }
}
public Vector4 invProjParam
{
// Ref: An Efficient Depth Linearization Method for Oblique View Frustums, Eq. 6.

// View-projection matrix from the previous frame.
public Matrix4x4 prevViewProjMatrix;
// We need to keep track of these when camera relative rendering is enabled so we can take
// camera translation into account when generating camera motion vectors
public Vector3 cameraPos;
public Vector3 prevCameraPos;
// The only way to reliably keep track of a frame change right now is to compare the frame
// count Unity gives us. We need this as a single camera could be rendered several times per
// frame and some matrices only have to be computed once. Realistically this shouldn't

Reset();
}
public void Update()
public void Update(PostProcessLayer postProcessLayer)
// If TAA is enabled projMatrix will hold a jittered projection matrix. The original,
// non-jittered projection matrix can be accessed via nonJitteredProjMatrix.
bool taaEnabled = camera.cameraType == CameraType.Game
&& Utilities.IsTemporalAntialiasingActive(postProcessLayer);
Matrix4x4 nonJitteredCameraProj = camera.projectionMatrix;
Matrix4x4 cameraProj = taaEnabled
? postProcessLayer.temporalAntialiasing.GetJitteredProjectionMatrix(camera)
: nonJitteredCameraProj;
Matrix4x4 gpuProj = GL.GetGPUProjectionMatrix(camera.projectionMatrix, true); // Had to change this from 'false'
Matrix4x4 gpuProj = GL.GetGPUProjectionMatrix(cameraProj, true); // Had to change this from 'false'
Matrix4x4 gpuNonJitteredProj = GL.GetGPUProjectionMatrix(nonJitteredCameraProj, true);
Vector3 pos = camera.transform.position;
if (ShaderConfig.s_CameraRelativeRendering != 0)
{

Matrix4x4 gpuVP = gpuProj * gpuView;
Matrix4x4 gpuVP = gpuNonJitteredProj * gpuView;
// A camera could be rendered multiple time per frame, only updates the previous viewproj if needed
// A camera could be rendered multiple times per frame, only updates the previous view proj & pos if needed
prevViewProjMatrix = !m_FirstFrame
? viewProjMatrix
: gpuVP;
if (m_FirstFrame)
{
prevCameraPos = pos;
prevViewProjMatrix = gpuVP;
}
else
{
prevCameraPos = cameraPos;
prevViewProjMatrix = nonJitteredViewProjMatrix;
}
m_FirstFrame = false;
}

nonJitteredProjMatrix = gpuNonJitteredProj;
cameraPos = pos;
screenSize = new Vector4(camera.pixelWidth, camera.pixelHeight, 1.0f / camera.pixelWidth, 1.0f / camera.pixelHeight);
Plane[] planes = GeometryUtility.CalculateFrustumPlanes(viewProjMatrix);

static List<Camera> m_Cleanup = new List<Camera>(); // Recycled to reduce GC pressure
// Grab the HDCamera tied to a given Camera and update it.
public static HDCamera Get(Camera camera)
public static HDCamera Get(Camera camera, PostProcessLayer postProcessLayer)
{
HDCamera hdcam;

m_Cameras.Add(camera, hdcam);
}
hdcam.Update();
hdcam.Update(postProcessLayer);
return hdcam;
}

public void SetupGlobalParams(CommandBuffer cmd)
{
cmd.SetGlobalMatrix("_ViewMatrix", viewMatrix);
cmd.SetGlobalMatrix("_InvViewMatrix", viewMatrix.inverse);
cmd.SetGlobalMatrix("_ProjMatrix", projMatrix);
cmd.SetGlobalMatrix("_InvProjMatrix", projMatrix.inverse);
cmd.SetGlobalMatrix("_ViewProjMatrix", viewProjMatrix);
cmd.SetGlobalMatrix("_InvViewProjMatrix", viewProjMatrix.inverse);
cmd.SetGlobalVector("_InvProjParam", invProjParam);
cmd.SetGlobalVector("_ScreenSize", screenSize);
cmd.SetGlobalMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetGlobalVectorArray("_FrustumPlanes", frustumPlaneEquations);
cmd.SetGlobalMatrix("_ViewMatrix", viewMatrix);
cmd.SetGlobalMatrix("_InvViewMatrix", viewMatrix.inverse);
cmd.SetGlobalMatrix("_ProjMatrix", projMatrix);
cmd.SetGlobalMatrix("_InvProjMatrix", projMatrix.inverse);
cmd.SetGlobalMatrix("_NonJitteredViewProjMatrix", nonJitteredViewProjMatrix);
cmd.SetGlobalMatrix("_ViewProjMatrix", viewProjMatrix);
cmd.SetGlobalMatrix("_InvViewProjMatrix", viewProjMatrix.inverse);
cmd.SetGlobalVector("_InvProjParam", invProjParam);
cmd.SetGlobalVector("_ScreenSize", screenSize);
cmd.SetGlobalMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetGlobalVectorArray("_FrustumPlanes", frustumPlaneEquations);
material.SetMatrix("_ViewMatrix", viewMatrix);
material.SetMatrix("_InvViewMatrix", viewMatrix.inverse);
material.SetMatrix("_ProjMatrix", projMatrix);
material.SetMatrix("_InvProjMatrix", projMatrix.inverse);
material.SetMatrix("_ViewProjMatrix", viewProjMatrix);
material.SetMatrix("_InvViewProjMatrix", viewProjMatrix.inverse);
material.SetVector("_InvProjParam", invProjParam);
material.SetVector("_ScreenSize", screenSize);
material.SetMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
material.SetVectorArray("_FrustumPlanes", frustumPlaneEquations);
material.SetMatrix("_ViewMatrix", viewMatrix);
material.SetMatrix("_InvViewMatrix", viewMatrix.inverse);
material.SetMatrix("_ProjMatrix", projMatrix);
material.SetMatrix("_InvProjMatrix", projMatrix.inverse);
material.SetMatrix("_NonJitteredViewProjMatrix", nonJitteredViewProjMatrix);
material.SetMatrix("_ViewProjMatrix", viewProjMatrix);
material.SetMatrix("_InvViewProjMatrix", viewProjMatrix.inverse);
material.SetVector("_InvProjParam", invProjParam);
material.SetVector("_ScreenSize", screenSize);
material.SetMatrix("_PrevViewProjMatrix", prevViewProjMatrix);
material.SetVectorArray("_FrustumPlanes", frustumPlaneEquations);
cmd.SetComputeMatrixParam(cs, "_ViewMatrix", viewMatrix);
cmd.SetComputeMatrixParam(cs, "_InvViewMatrix", viewMatrix.inverse);
cmd.SetComputeMatrixParam(cs, "_ProjMatrix", projMatrix);
cmd.SetComputeMatrixParam(cs, "_InvProjMatrix", projMatrix.inverse);
cmd.SetComputeMatrixParam(cs, "_ViewProjMatrix", viewProjMatrix);
cmd.SetComputeMatrixParam(cs, "_InvViewProjMatrix", viewProjMatrix.inverse);
cmd.SetComputeVectorParam(cs, "_InvProjParam", invProjParam);
cmd.SetComputeVectorParam(cs, "_ScreenSize", screenSize);
cmd.SetComputeMatrixParam(cs, "_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetComputeVectorArrayParam(cs, "_FrustumPlanes", frustumPlaneEquations);
cmd.SetComputeMatrixParam(cs, "_ViewMatrix", viewMatrix);
cmd.SetComputeMatrixParam(cs, "_InvViewMatrix", viewMatrix.inverse);
cmd.SetComputeMatrixParam(cs, "_ProjMatrix", projMatrix);
cmd.SetComputeMatrixParam(cs, "_InvProjMatrix", projMatrix.inverse);
cmd.SetComputeMatrixParam(cs, "_NonJitteredViewProjMatrix", nonJitteredViewProjMatrix);
cmd.SetComputeMatrixParam(cs, "_ViewProjMatrix", viewProjMatrix);
cmd.SetComputeMatrixParam(cs, "_InvViewProjMatrix", viewProjMatrix.inverse);
cmd.SetComputeVectorParam(cs, "_InvProjParam", invProjParam);
cmd.SetComputeVectorParam(cs, "_ScreenSize", screenSize);
cmd.SetComputeMatrixParam(cs, "_PrevViewProjMatrix", prevViewProjMatrix);
cmd.SetComputeVectorArrayParam(cs, "_FrustumPlanes", frustumPlaneEquations);
}
}

readonly List<RenderPipelineMaterial> m_MaterialList = new List<RenderPipelineMaterial>();
readonly GBufferManager m_gbufferManager = new GBufferManager();
Material m_CopyStencilBuffer;
// Various set of material use in render loop
Material m_FilterAndCombineSubsurfaceScattering;

readonly RenderTargetIdentifier m_DistortionBufferRT;
private RenderTexture m_CameraDepthStencilBuffer = null;
private RenderTexture m_CameraDepthStencilBufferCopy = null;
private RenderTexture m_CameraDepthBufferCopy = null;
private RenderTexture m_CameraStencilBufferCopy = null; // Currently, it's manually copied using a pixel shader, and optimized to only contain the SSS bit
private RenderTargetIdentifier m_CameraDepthStencilBufferCopyRT;
private RenderTargetIdentifier m_CameraDepthBufferCopyRT;
private RenderTargetIdentifier m_CameraStencilBufferCopyRT;
// Post-processing context and screen-space effects (recycled on every frame to avoid GC alloc)
readonly PostProcessRenderContext m_PostProcessContext;

// Currently we use only 2 bits to identify the kind of lighting that is expected from the render pipeline
// Usage is define in LightDefinitions.cs
[Flags]
public enum StencilBits
public enum StencilBitMask
Lighting = 3, // 0
All = 255 // 0xFF
Clear = 0, // 0x0
Lighting = 3, // 0x3 - 2 bit
All = 255 // 0xFF - 8 bit
}
// Detect when windows size is changing

CreateSssMaterials(sssSettings.useDisneySSS);
// <<< Old SSS Model
m_CopyStencilBuffer = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CopyStencilBuffer");
m_CameraMotionVectorsMaterial = Utilities.CreateEngineMaterial("Hidden/HDRenderPipeline/CameraMotionVectors");
InitializeDebugMaterials();

};
#endif
void CreateDepthBuffer(Camera camera)
void CreateDepthStencilBuffer(Camera camera)
{
if (m_CameraDepthStencilBuffer != null)
{

if (NeedDepthBufferCopy())
{
if (m_CameraDepthStencilBufferCopy != null)
if (m_CameraDepthBufferCopy != null)
m_CameraDepthStencilBufferCopy.Release();
m_CameraDepthBufferCopy.Release();
m_CameraDepthStencilBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 24, RenderTextureFormat.Depth);
m_CameraDepthStencilBufferCopy.filterMode = FilterMode.Point;
m_CameraDepthStencilBufferCopy.Create();
m_CameraDepthStencilBufferCopyRT = new RenderTargetIdentifier(m_CameraDepthStencilBufferCopy);
m_CameraDepthBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 24, RenderTextureFormat.Depth);
m_CameraDepthBufferCopy.filterMode = FilterMode.Point;
m_CameraDepthBufferCopy.Create();
m_CameraDepthBufferCopyRT = new RenderTargetIdentifier(m_CameraDepthBufferCopy);
}
if (NeedStencilBufferCopy())
{
if (m_CameraStencilBufferCopy != null)
{
m_CameraStencilBufferCopy.Release();
}
m_CameraStencilBufferCopy = new RenderTexture(camera.pixelWidth, camera.pixelHeight, 0, RenderTextureFormat.R8);
m_CameraStencilBufferCopy.filterMode = FilterMode.Point;
m_CameraStencilBufferCopy.Create();
m_CameraStencilBufferCopyRT = new RenderTargetIdentifier(m_CameraStencilBufferCopy);
}
}

if (resolutionChanged || m_CameraDepthStencilBuffer == null)
{
CreateDepthBuffer(camera);
CreateDepthStencilBuffer(camera);
}
if (resolutionChanged || m_LightLoop.NeedResize())

Shader.SetGlobalInt( "_EnableSSSAndTransmission", m_DebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission ? 1 : 0);
Shader.SetGlobalInt( "_TexturingModeFlags", (int)sssParameters.texturingModeFlags);
Shader.SetGlobalInt( "_TransmissionFlags", (int)sssParameters.transmissionFlags);
cmd.SetGlobalFloatArray( "_ThicknessRemaps", sssParameters.thicknessRemaps);
cmd.SetGlobalVectorArray( "_ThicknessRemaps", sssParameters.thicknessRemaps);
// We are currently supporting two different SSS mode: Jimenez (with 2-Gaussian profile) and Disney
// We have added the ability to switch between each other for subsurface scattering, but for transmittance this is more tricky as we need to add
// shader variant for forward, gbuffer and deferred shader. We want to avoid this.

return SystemInfo.graphicsDeviceType != GraphicsDeviceType.PlayStation4;
}
Texture GetDepthTexture()
bool NeedStencilBufferCopy()
{
// Currently, Unity does not offer a way to bind the stencil buffer as a texture in a compute shader.
// Therefore, it's manually copied using a pixel shader, and optimized to only contain the SSS bit.
return m_DebugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission;
}
RenderTargetIdentifier GetDepthTexture()
{
return NeedDepthBufferCopy() ? m_CameraDepthBufferCopy : m_CameraDepthStencilBuffer;
}
RenderTargetIdentifier GetStencilTexture()
if (NeedDepthBufferCopy())
return m_CameraDepthStencilBufferCopy;
else
return m_CameraDepthStencilBuffer;
return NeedStencilBufferCopy() ? m_CameraStencilBufferCopyRT : m_CameraDepthStencilBufferRT;
}
private void CopyDepthBufferIfNeeded(CommandBuffer cmd)

{
using (new Utilities.ProfilingSample("Copy depth-stencil buffer", cmd))
{
cmd.CopyTexture(m_CameraDepthStencilBufferRT, m_CameraDepthStencilBufferCopyRT);
cmd.CopyTexture(m_CameraDepthStencilBufferRT, m_CameraDepthBufferCopyRT);
}
}

private void PrepareAndBindStencilTexture(CommandBuffer cmd)
{
if (NeedStencilBufferCopy())
{
using (new Utilities.ProfilingSample("Copy StencilBuffer", cmd))
{
Utilities.DrawFullScreen(cmd, m_CopyStencilBuffer, m_CameraStencilBufferCopyRT, m_CameraDepthStencilBufferRT);
}
}
cmd.SetGlobalTexture("_StencilTexture", GetStencilTexture());
}
public void UpdateCommonSettings()
{
var commonSettings = commonSettingsToUse;

renderContext.SetupCameraProperties(camera);
HDCamera hdCamera = HDCamera.Get(camera);
var postProcessLayer = camera.GetComponent<PostProcessLayer>();
HDCamera hdCamera = HDCamera.Get(camera, postProcessLayer);
PushGlobalParams(hdCamera, cmd, m_Asset.sssSettings);
// TODO: Find a correct place to bind these material textures

{
CopyDepthBufferIfNeeded(cmd);
}
// Required for the SSS pass.
PrepareAndBindStencilTexture(cmd);
if (m_DebugDisplaySettings.IsDebugMaterialDisplayEnabled())
{

RenderForward(m_CullResults, camera, renderContext, cmd, true); // Render deferred or forward opaque
RenderForwardOnlyOpaque(m_CullResults, camera, renderContext, cmd);
RenderLightingDebug(hdCamera, cmd, m_CameraColorBufferRT);
RenderLightingDebug(hdCamera, cmd, m_CameraColorBufferRT, m_DebugDisplaySettings);
// If full forward rendering, we did just rendered everything, so we can copy the depth buffer
// If Deferred nothing needs copying anymore.

// Render all type of transparent forward (unlit, lit, complex (hair...)) to keep the sorting between transparent objects.
RenderForward(m_CullResults, camera, renderContext, cmd, false);
PushFullScreenDebugTexture(cmd, m_CameraColorBuffer, camera, renderContext, FullScreenDebugMode.NanTracker);
// Planar and real time cubemap doesn't need post process and render in FP16
if (camera.cameraType == CameraType.Reflection)
{

// Instead we chose to apply distortion at the end after we cumulate distortion vector and desired blurriness. This
RenderDistortion(m_CullResults, camera, renderContext, cmd);
RenderPostProcesses(camera, cmd);
RenderPostProcesses(camera, cmd, postProcessLayer);
}
}

return;
}
RenderTargetIdentifier[] colorRTs = { m_CameraColorBufferRT, m_CameraSubsurfaceBufferRT };
RenderTargetIdentifier[] colorRTs = { m_CameraColorBufferRT, m_CameraSubsurfaceBufferRT };
RenderTargetIdentifier depthTexture = GetDepthTexture();
m_LightLoop.RenderDeferredLighting(hdCamera, cmd, m_DebugDisplaySettings, colorRTs, m_CameraDepthStencilBufferRT, new RenderTargetIdentifier(GetDepthTexture()), true);
m_LightLoop.RenderDeferredLighting(hdCamera, cmd, m_DebugDisplaySettings, colorRTs, m_CameraDepthStencilBufferRT, depthTexture, true);
m_LightLoop.RenderDeferredLighting(hdCamera, cmd, m_DebugDisplaySettings, colorRTs, m_CameraDepthStencilBufferRT, new RenderTargetIdentifier(GetDepthTexture()), false);
m_LightLoop.RenderDeferredLighting(hdCamera, cmd, m_DebugDisplaySettings, colorRTs, m_CameraDepthStencilBufferRT, depthTexture, false);
}
// Combines specular lighting and diffuse lighting with subsurface scattering.

return m_SkyManager.ExportSkyToTexture();
}
void RenderLightingDebug(HDCamera camera, CommandBuffer cmd, RenderTargetIdentifier colorBuffer)
void RenderLightingDebug(HDCamera camera, CommandBuffer cmd, RenderTargetIdentifier colorBuffer, DebugDisplaySettings debugDisplaySettings)
m_LightLoop.RenderLightingDebug(camera, cmd, colorBuffer);
m_LightLoop.RenderLightingDebug(camera, cmd, colorBuffer, debugDisplaySettings);
}
void RenderForward(CullResults cullResults, Camera camera, ScriptableRenderContext renderContext, CommandBuffer cmd, bool renderOpaque)

int w = (int)hdcam.screenSize.x;
int h = (int)hdcam.screenSize.y;
m_CameraMotionVectorsMaterial.SetVector("_CameraPosDiff", hdcam.prevCameraPos - hdcam.cameraPos);
cmd.Blit(BuiltinRenderTextureType.None, m_VelocityBufferRT, m_CameraMotionVectorsMaterial, 0);
Utilities.DrawFullScreen(cmd, m_CameraMotionVectorsMaterial, m_VelocityBufferRT, null, 0);
PushFullScreenDebugTexture(cmd, m_VelocityBuffer, hdcam.camera, renderContext, FullScreenDebugMode.MotionVectors);
}
}

}
}
void RenderPostProcesses(Camera camera, CommandBuffer cmd)
void RenderPostProcesses(Camera camera, CommandBuffer cmd, PostProcessLayer layer)
var postProcessLayer = camera.GetComponent<PostProcessLayer>();
if (postProcessLayer != null && postProcessLayer.enabled)
if (Utilities.IsPostProcessingActive(layer))
{
cmd.SetGlobalTexture("_CameraDepthTexture", GetDepthTexture());
cmd.SetGlobalTexture("_CameraMotionVectorsTexture", m_VelocityBufferRT);

context.sourceFormat = RenderTextureFormat.ARGBHalf;
context.flip = true;
postProcessLayer.Render(context);
layer.Render(context);
}
else
{

12
Assets/ScriptableRenderPipeline/HDRenderPipeline/HDRenderPipelineAsset.asset


tileSettings:
enableTileAndCluster: 1
enableSplitLightEvaluation: 1
enableComputeLightEvaluation: 0
enableComputeLightVariants: 0
enableComputeMaterialVariants: 0
enableComputeLightEvaluation: 1
enableComputeLightVariants: 1
enableComputeMaterialVariants: 1
tileDebugByCategory: 0
shadowInitParams:
shadowAtlasWidth: 4096
shadowAtlasHeight: 4096

reflectionCubemapSize: 128
m_DefaultDiffuseMaterial: {fileID: 0}
m_DefaultShader: {fileID: 0}
m_DefaultDiffuseMaterial: {fileID: 2100000, guid: 73c176f402d2c2f4d929aa5da7585d17,
type: 2}
m_DefaultShader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}

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


ProjectorPyramid,
// AreaLight
Line, // Keep Line lights before Rectangle. This is needed because of a compiler bug (see LightLoop.hlsl)
Line,
// Currently not supported in real time (just use for reference)
Sphere,
Disk,

public struct DirectionalLightData
{
public Vector3 positionWS;
public float unused;
public bool tileCookie;
public Vector3 color;
public int shadowIndex; // -1 if unused

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/LightDefinition.cs.hlsl


#define GPULIGHTTYPE_SPOT (2)
#define GPULIGHTTYPE_POINT (3)
#define GPULIGHTTYPE_PROJECTOR_PYRAMID (4)
#define GPULIGHTTYPE_RECTANGLE (5)
#define GPULIGHTTYPE_LINE (6)
#define GPULIGHTTYPE_LINE (5)
#define GPULIGHTTYPE_RECTANGLE (6)
#define GPULIGHTTYPE_SPHERE (7)
#define GPULIGHTTYPE_DISK (8)
#define GPULIGHTTYPE_HEMISPHERE (9)

struct DirectionalLightData
{
float3 positionWS;
float unused;
bool tileCookie;
float3 color;
int shadowIndex;
float3 forward;

{
return value.positionWS;
}
float GetUnused(DirectionalLightData value)
bool GetTileCookie(DirectionalLightData value)
return value.unused;
return value.tileCookie;
}
float3 GetColor(DirectionalLightData value)
{

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/ShadowDispatch.hlsl


// example of overriding punctual lights
#ifdef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
{
#ifdef SHADOW_DISPATCH_USE_SEPARATE_PUNC_ALGOS
// example for choosing different algos for point and spot lights

return EvalShadow_PunctualDepth( shadowContext, algo, tex, compSamp, positionWS, normalWS, shadowDataIndex, L );
#endif
}
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuation( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

331
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePass.cs


// binding code. This needs to be in sync with ShadowContext.hlsl
ShadowContext.BindDel binder = (ShadowContext sc, CommandBuffer cb, ComputeShader computeShader, int computeKernel) =>
{
{
if(computeShader)
{
// bind buffers
cb.SetComputeBufferParam(computeShader, computeKernel, "_ShadowDatasExp", s_ShadowDataBuffer);
cb.SetComputeBufferParam(computeShader, computeKernel, "_ShadowPayloads", s_ShadowPayloadBuffer);
// bind textures
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_0", tex[0]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_1", tex[1]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_2", tex[2]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_PCF", tex[3]);
if(computeShader)
{
// bind buffers
cb.SetComputeBufferParam(computeShader, computeKernel, "_ShadowDatasExp", s_ShadowDataBuffer);
cb.SetComputeBufferParam(computeShader, computeKernel, "_ShadowPayloads", s_ShadowPayloadBuffer);
// bind textures
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_0", tex[0]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_1", tex[1]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_VSM_2", tex[2]);
cb.SetComputeTextureParam(computeShader, computeKernel, "_ShadowmapExp_PCF", tex[3]);
else
{
// bind buffers
cb.SetGlobalBuffer("_ShadowDatasExp", s_ShadowDataBuffer);
cb.SetGlobalBuffer("_ShadowPayloads", s_ShadowPayloadBuffer);
// bind textures
cb.SetGlobalTexture("_ShadowmapExp_VSM_0", tex[0]);
cb.SetGlobalTexture("_ShadowmapExp_VSM_1", tex[1]);
cb.SetGlobalTexture("_ShadowmapExp_VSM_2", tex[2]);
cb.SetGlobalTexture("_ShadowmapExp_PCF", tex[3]);
else
{
// bind buffers
cb.SetGlobalBuffer("_ShadowDatasExp", s_ShadowDataBuffer);
cb.SetGlobalBuffer("_ShadowPayloads", s_ShadowPayloadBuffer);
// bind textures
cb.SetGlobalTexture("_ShadowmapExp_VSM_0", tex[0]);
cb.SetGlobalTexture("_ShadowmapExp_VSM_1", tex[1]);
cb.SetGlobalTexture("_ShadowmapExp_VSM_2", tex[2]);
cb.SetGlobalTexture("_ShadowmapExp_PCF", tex[3]);
// TODO: Currently samplers are hard coded in ShadowContext.hlsl, so we can't really set them here
};

[GenerateHLSL]
public enum LightFeatureFlags
{
Punctual = 1 << 0,
Area = 1 << 1,
Directional = 1 << 2,
Env = 1 << 3,
Sky = 1 << 4
// Light bit mask must match LightDefinitions.s_LightFeatureMaskFlags value
Punctual = 1 << 8,
Area = 1 << 9,
Directional = 1 << 10,
Env = 1 << 11,
Sky = 1 << 12 // If adding more light be sure to not overflow LightDefinitions.s_LightFeatureMaskFlags
}
[GenerateHLSL]

public static int s_TileSizeClustered = 32;
// feature variants
public static int s_NumFeatureVariants = 16;
public static int s_NumFeatureVariants = 26;
public static uint LIGHTFEATUREFLAGS_MASK = 0xFFF;
public static uint MATERIALFEATUREFLAGS_MASK = 0xF000; // don't use all bits just to be safe from signed and/or float conversions :/
// Following define the maximum number of bits use in each feature category.
public static uint s_LightFeatureMaskFlags = 0xFF00;
public static uint s_MaterialFeatureMaskFlags = 0x00FF; // don't use all bits just to be safe from signed and/or float conversions :/
}
[GenerateHLSL]

public class TileSettings
{
public bool enableTileAndCluster; // For debug / test
public bool enableSplitLightEvaluation;
public bool enableComputeLightEvaluation;
public bool enableComputeLightVariants;
public bool enableComputeMaterialVariants;

public enum TileDebug : int
{
None = 0, Punctual = 1, Area = 2, AreaAndPunctual = 3, Projector = 4, ProjectorAndPunctual = 5, ProjectorAndArea = 6, ProjectorAndAreaAndPunctual = 7,
Environment = 8, EnvironmentAndPunctual = 9, EnvironmentAndArea = 10, EnvironemntAndAreaAndPunctual = 11,
EnvironmentAndProjector = 12, EnvironmentAndProjectorAndPunctual = 13, EnvironmentAndProjectorAndArea = 14, EnvironmentAndProjectorAndAreaAndPunctual = 15,
FeatureVariants = 16
None = 0, Punctual = 1, Area = 2, AreaAndPunctual = 3, Environment = 4, EnvironmentAndPunctual = 5, EnvironmentAndArea = 6, EnvironmentAndAreaAndPunctual = 7,
FeatureVariants = 8
public TileDebug tileDebugByCategory;
enableSplitLightEvaluation = true;
enableComputeLightEvaluation = false;
enableComputeLightVariants = false;
enableComputeMaterialVariants = false;
enableComputeLightEvaluation = true;
enableComputeLightVariants = true;
enableComputeMaterialVariants = true;
enableClustered = true;
enableFptlForOpaqueWhenClustered = true;

specularGlobalDimmer = 1.0f;
tileDebugByCategory = TileDebug.None;
}
}

}
}
Material m_DeferredDirectMaterialSRT = null;
Material m_DeferredDirectMaterialMRT = null;
Material m_DeferredIndirectMaterialSRT = null;
Material m_DeferredIndirectMaterialMRT = null;
Material m_DeferredAllMaterialSRT = null;
Material m_DeferredAllMaterialMRT = null;

string[] tileKeywords = {"LIGHTLOOP_TILE_DIRECT", "LIGHTLOOP_TILE_INDIRECT", "LIGHTLOOP_TILE_ALL"};
m_DeferredDirectMaterialSRT = Utilities.CreateEngineMaterial(m_Resources.deferredShader);
Utilities.SelectKeyword(m_DeferredDirectMaterialSRT, tileKeywords, 0);
m_DeferredDirectMaterialSRT.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredDirectMaterialSRT.DisableKeyword("OUTPUT_SPLIT_LIGHTING");
m_DeferredDirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredDirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
m_DeferredDirectMaterialSRT.SetInt("_SrcBlend", (int)BlendMode.One);
m_DeferredDirectMaterialSRT.SetInt("_DstBlend", (int)BlendMode.Zero);
m_DeferredDirectMaterialMRT = Utilities.CreateEngineMaterial(m_Resources.deferredShader);
Utilities.SelectKeyword(m_DeferredDirectMaterialMRT, tileKeywords, 0);
m_DeferredDirectMaterialMRT.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredDirectMaterialMRT.EnableKeyword("OUTPUT_SPLIT_LIGHTING");
m_DeferredDirectMaterialMRT.SetInt("_StencilRef", (int)StencilLightingUsage.SplitLighting);
m_DeferredDirectMaterialMRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
m_DeferredDirectMaterialMRT.SetInt("_SrcBlend", (int)BlendMode.One);
m_DeferredDirectMaterialMRT.SetInt("_DstBlend", (int)BlendMode.Zero);
m_DeferredIndirectMaterialSRT = Utilities.CreateEngineMaterial(m_Resources.deferredShader);
Utilities.SelectKeyword(m_DeferredIndirectMaterialSRT, tileKeywords, 1);
m_DeferredIndirectMaterialSRT.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredIndirectMaterialSRT.DisableKeyword("OUTPUT_SPLIT_LIGHTING");
m_DeferredIndirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredIndirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
m_DeferredIndirectMaterialSRT.SetInt("_SrcBlend", (int)BlendMode.One);
m_DeferredIndirectMaterialSRT.SetInt("_DstBlend", (int)BlendMode.One); // Additive color & alpha source
m_DeferredIndirectMaterialMRT = Utilities.CreateEngineMaterial(m_Resources.deferredShader);
Utilities.SelectKeyword(m_DeferredIndirectMaterialMRT, tileKeywords, 1);
m_DeferredIndirectMaterialMRT.EnableKeyword("LIGHTLOOP_TILE_PASS");
m_DeferredIndirectMaterialMRT.EnableKeyword("OUTPUT_SPLIT_LIGHTING");
m_DeferredIndirectMaterialMRT.SetInt("_StencilRef", (int)StencilLightingUsage.SplitLighting);
m_DeferredIndirectMaterialMRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
m_DeferredIndirectMaterialMRT.SetInt("_SrcBlend", (int)BlendMode.One);
m_DeferredIndirectMaterialMRT.SetInt("_DstBlend", (int)BlendMode.One); // Additive color & alpha source
m_DeferredAllMaterialSRT = Utilities.CreateEngineMaterial(m_Resources.deferredShader);
Utilities.SelectKeyword(m_DeferredAllMaterialSRT, tileKeywords, 2);
m_DeferredAllMaterialSRT.EnableKeyword("LIGHTLOOP_TILE_PASS");

// enableClustered
Utilities.SafeRelease(s_GlobalLightListAtomic);
Utilities.Destroy(m_DeferredDirectMaterialSRT);
Utilities.Destroy(m_DeferredDirectMaterialMRT);
Utilities.Destroy(m_DeferredIndirectMaterialSRT);
Utilities.Destroy(m_DeferredIndirectMaterialMRT);
Utilities.Destroy(m_DeferredAllMaterialSRT);
Utilities.Destroy(m_DeferredAllMaterialMRT);

if (light.light.cookie != null)
{
directionalLightData.tileCookie = light.light.cookie.wrapMode == TextureWrapMode.Repeat;
directionalLightData.cookieIndex = m_CookieTexArray.FetchSlice(light.light.cookie);
}
// fix up shadow information

}
if (!m_TileSettings.enableComputeMaterialVariants)
{
baseFeatureFlags |= LightDefinitions.MATERIALFEATUREFLAGS_MASK;
baseFeatureFlags |= LightDefinitions.s_MaterialFeatureMaskFlags;
}
cmd.SetComputeIntParam(buildPerTileLightListShader, "g_BaseFeatureFlags", (int)baseFeatureFlags);
cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_TileFeatureFlags", s_TileFeatureFlags);

if (!m_TileSettings.enableComputeLightVariants)
{
buildMaterialFlagsKernel = s_BuildMaterialFlagsWriteKernel;
baseFeatureFlags |= LightDefinitions.LIGHTFEATUREFLAGS_MASK;
baseFeatureFlags |= LightDefinitions.s_LightFeatureMaskFlags;
}
cmd.SetComputeIntParam(buildMaterialFlagsShader, "g_BaseFeatureFlags", (int)baseFeatureFlags);

private void SetupDebugDisplayMode(bool debugDisplayEnable)
{
Utilities.SetKeyword(m_DeferredDirectMaterialSRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_DeferredDirectMaterialMRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_DeferredIndirectMaterialSRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_DeferredIndirectMaterialMRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_DeferredAllMaterialSRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_DeferredAllMaterialMRT, "DEBUG_DISPLAY", debugDisplayEnable);
Utilities.SetKeyword(m_SingleDeferredMaterialSRT, "DEBUG_DISPLAY", debugDisplayEnable);

public void RenderLightingDebug(HDCamera hdCamera, CommandBuffer cmd, RenderTargetIdentifier colorBuffer)
public void RenderLightingDebug(HDCamera hdCamera, CommandBuffer cmd, RenderTargetIdentifier colorBuffer, DebugDisplaySettings debugDisplaySettings)
if (m_TileSettings.tileDebugByCategory == TileSettings.TileDebug.None)
LightingDebugSettings lightingDebug = debugDisplaySettings.lightingDebugSettings;
if (lightingDebug.tileDebugByCategory == TileSettings.TileDebug.None)
return;
using (new Utilities.ProfilingSample("Tiled Lighting Debug", cmd))

// Debug tiles
PushGlobalParams(hdCamera.camera, cmd, null, 0);
if (m_TileSettings.tileDebugByCategory == TileSettings.TileDebug.FeatureVariants)
if (lightingDebug.tileDebugByCategory == TileSettings.TileDebug.FeatureVariants)
m_DebugViewTilesMaterial.SetInt("_ViewTilesFlags", (int)m_TileSettings.tileDebugByCategory);
m_DebugViewTilesMaterial.SetInt("_ViewTilesFlags", (int)lightingDebug.tileDebugByCategory);
m_DebugViewTilesMaterial.SetVector("_MousePixelCoord", mousePixelCoord);
m_DebugViewTilesMaterial.SetBuffer("g_TileList", s_TileList);
m_DebugViewTilesMaterial.SetBuffer("g_DispatchIndirectBuffer", s_DispatchIndirectBuffer);

cmd.DrawProcedural(Matrix4x4.identity, m_DebugViewTilesMaterial, 0, MeshTopology.Triangles, numTiles * 6);
}
}
else if (m_TileSettings.tileDebugByCategory != TileSettings.TileDebug.None)
else if (lightingDebug.tileDebugByCategory != TileSettings.TileDebug.None)
m_DebugViewTilesMaterial.SetInt("_ViewTilesFlags", (int)m_TileSettings.tileDebugByCategory);
m_DebugViewTilesMaterial.SetInt("_ViewTilesFlags", (int)lightingDebug.tileDebugByCategory);
m_DebugViewTilesMaterial.SetVector("_MousePixelCoord", mousePixelCoord);
m_DebugViewTilesMaterial.EnableKeyword(bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");
m_DebugViewTilesMaterial.DisableKeyword(!bUseClusteredForDeferred ? "USE_CLUSTERED_LIGHTLIST" : "USE_FPTL_LIGHTLIST");

cmd.Blit(null, colorBuffer, m_DebugViewTilesMaterial, 0);
Utilities.DrawFullScreen(cmd, m_DebugViewTilesMaterial, 0, colorBuffer);
}
SetGlobalPropertyRedirect(null, 0, null);
}

DebugDisplaySettings debugDisplaySettings,
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer, RenderTargetIdentifier depthStencilTexture,
RenderTargetIdentifier[] colorBuffers, RenderTargetIdentifier depthStencilBuffer, RenderTargetIdentifier depthTexture,
if (m_TileSettings.enableComputeLightEvaluation && outputSplitLighting)
{
// The CS is always in the MRT mode. Do not execute the same shader twice.
return;
}
// TODO: To reduce GC pressure don't do concat string here
using (new Utilities.ProfilingSample((m_TileSettings.enableTileAndCluster ? "TilePass - Deferred Lighting Pass" : "SinglePass - Deferred Lighting Pass") + (outputSplitLighting ? " MRT" : ""), cmd))

if (enableFeatureVariants)
numVariants = LightDefinitions.s_NumFeatureVariants;
int debugViewMaterial = Shader.GetGlobalInt("_DebugViewMaterial");
int debugLightingMode = Shader.GetGlobalInt("_DebugLightingMode");
Vector4 debugLightingAlbedo = Shader.GetGlobalVector("_DebugLightingAlbedo");
Vector4 debugLightingSmoothness = Shader.GetGlobalVector("_DebugLightingSmoothness");
int gbufferTexture0 = Shader.PropertyToID("_GBufferTexture0");
int gbufferTexture1 = Shader.PropertyToID("_GBufferTexture1");
int gbufferTexture2 = Shader.PropertyToID("_GBufferTexture2");
int gbufferTexture3 = Shader.PropertyToID("_GBufferTexture3");
int ambientOcclusionTexture = Shader.PropertyToID("_AmbientOcclusionTexture");
Texture ltcData = Shader.GetGlobalTexture(Shader.PropertyToID("_LtcData"));
Texture preIntegratedFGD = Shader.GetGlobalTexture("_PreIntegratedFGD");
Texture ltcGGXMatrix = Shader.GetGlobalTexture("_LtcGGXMatrix");
Texture ltcDisneyDiffuseMatrix = Shader.GetGlobalTexture("_LtcDisneyDiffuseMatrix");
Texture ltcMultiGGXFresnelDisneyDiffuse = Shader.GetGlobalTexture("_LtcMultiGGXFresnelDisneyDiffuse");
Matrix4x4 invScrProjection = Shader.GetGlobalMatrix("g_mInvScrProjection");
int useTileLightList = Shader.GetGlobalInt("_UseTileLightList");
Vector4 time = Shader.GetGlobalVector("_Time");
Vector4 sinTime = Shader.GetGlobalVector("_SinTime");
Vector4 cosTime = Shader.GetGlobalVector("_CosTime");
Vector4 unity_DeltaTime = Shader.GetGlobalVector("unity_DeltaTime");
Vector4 worldSpaceCameraPos = Shader.GetGlobalVector("_WorldSpaceCameraPos");
Vector4 projectionParams = Shader.GetGlobalVector("_ProjectionParams");
Vector4 screenParams = Shader.GetGlobalVector("_ScreenParams");
Vector4 zbufferParams = Shader.GetGlobalVector("_ZBufferParams");
Vector4 unity_OrthoParams = Shader.GetGlobalVector("unity_OrthoParams");
int envLightSkyEnabled = Shader.GetGlobalInt("_EnvLightSkyEnabled");
int enableSSSAndTransmission = Shader.GetGlobalInt("_EnableSSSAndTransmission");
int texturingModeFlags = Shader.GetGlobalInt("_TexturingModeFlags");
int transmissionFlags = Shader.GetGlobalInt("_TransmissionFlags");
Vector4[] thicknessRemaps = Shader.GetGlobalVectorArray("_ThicknessRemaps");
Vector4[] shapeParams = Shader.GetGlobalVectorArray("_ShapeParams");
Vector4[] transmissionTints = Shader.GetGlobalVectorArray("_TransmissionTints");
for (int variant = 0; variant < numVariants; variant++)
{
int kernel;

// Pass global parameters to compute shader
// TODO: get rid of this by making global parameters visible to compute shaders
PushGlobalParams(camera, cmd, shadeOpaqueShader, kernel);
hdCamera.SetupComputeShader(shadeOpaqueShader, cmd);
cmd.SetComputeIntParam(shadeOpaqueShader, "_DebugViewMaterial", Shader.GetGlobalInt("_DebugViewMaterial"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_DebugLightingAlbedo", Shader.GetGlobalVector("_DebugLightingAlbedo"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_DebugLightingSmoothness", Shader.GetGlobalVector("_DebugLightingSmoothness"));
cmd.SetComputeIntParam(shadeOpaqueShader, "_DebugViewMaterial", debugViewMaterial);
cmd.SetComputeIntParam(shadeOpaqueShader, "_DebugLightingMode", debugLightingMode);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_DebugLightingAlbedo", debugLightingAlbedo);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_DebugLightingSmoothness", debugLightingSmoothness);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_MainDepthTexture", depthStencilTexture);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture0", Shader.PropertyToID("_GBufferTexture0"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture1", Shader.PropertyToID("_GBufferTexture1"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture2", Shader.PropertyToID("_GBufferTexture2"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture3", Shader.PropertyToID("_GBufferTexture3"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_AmbientOcclusionTexture", Shader.PropertyToID("_AmbientOcclusionTexture"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_MainDepthTexture", depthTexture);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture0", gbufferTexture0);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture1", gbufferTexture1);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture2", gbufferTexture2);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_GBufferTexture3", gbufferTexture3);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_AmbientOcclusionTexture", ambientOcclusionTexture);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcData", Shader.GetGlobalTexture(Shader.PropertyToID("_LtcData")));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_PreIntegratedFGD", Shader.GetGlobalTexture("_PreIntegratedFGD"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcGGXMatrix", Shader.GetGlobalTexture("_LtcGGXMatrix"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcDisneyDiffuseMatrix", Shader.GetGlobalTexture("_LtcDisneyDiffuseMatrix"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcMultiGGXFresnelDisneyDiffuse", Shader.GetGlobalTexture("_LtcMultiGGXFresnelDisneyDiffuse"));
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcData", ltcData);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_PreIntegratedFGD", preIntegratedFGD);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcGGXMatrix", ltcGGXMatrix);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcDisneyDiffuseMatrix", ltcDisneyDiffuseMatrix);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "_LtcMultiGGXFresnelDisneyDiffuse", ltcMultiGGXFresnelDisneyDiffuse);
hdCamera.SetupComputeShader(shadeOpaqueShader, cmd);
cmd.SetComputeMatrixParam(shadeOpaqueShader, "g_mInvScrProjection", invScrProjection);
cmd.SetComputeIntParam(shadeOpaqueShader, "_UseTileLightList", useTileLightList);
cmd.SetComputeMatrixParam(shadeOpaqueShader, "g_mInvScrProjection", Shader.GetGlobalMatrix("g_mInvScrProjection"));
cmd.SetComputeIntParam(shadeOpaqueShader, "_UseTileLightList", Shader.GetGlobalInt("_UseTileLightList"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_Time", Shader.GetGlobalVector("_Time"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_SinTime", Shader.GetGlobalVector("_SinTime"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_CosTime", Shader.GetGlobalVector("_CosTime"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "unity_DeltaTime", Shader.GetGlobalVector("unity_DeltaTime"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_WorldSpaceCameraPos", Shader.GetGlobalVector("_WorldSpaceCameraPos"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ProjectionParams", Shader.GetGlobalVector("_ProjectionParams"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ScreenParams", Shader.GetGlobalVector("_ScreenParams"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ZBufferParams", Shader.GetGlobalVector("_ZBufferParams"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "unity_OrthoParams", Shader.GetGlobalVector("unity_OrthoParams"));
cmd.SetComputeIntParam(shadeOpaqueShader, "_EnvLightSkyEnabled", Shader.GetGlobalInt("_EnvLightSkyEnabled"));
cmd.SetComputeVectorParam(shadeOpaqueShader, "_Time", time);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_SinTime", sinTime);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_CosTime", cosTime);
cmd.SetComputeVectorParam(shadeOpaqueShader, "unity_DeltaTime", unity_DeltaTime);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_WorldSpaceCameraPos", worldSpaceCameraPos);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ProjectionParams", projectionParams);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ScreenParams", screenParams);
cmd.SetComputeVectorParam(shadeOpaqueShader, "_ZBufferParams", zbufferParams);
cmd.SetComputeVectorParam(shadeOpaqueShader, "unity_OrthoParams", unity_OrthoParams);
cmd.SetComputeIntParam(shadeOpaqueShader, "_EnvLightSkyEnabled", envLightSkyEnabled);
Texture skyTexture = Shader.GetGlobalTexture("_SkyTexture");
Texture IESArrayTexture = Shader.GetGlobalTexture("_IESArray");

// Since we need the stencil test, the compute path does not currently support SSS.
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "combinedLightingUAV", colorBuffers[0]);
// Set SSS parameters.
cmd.SetComputeIntParam( shadeOpaqueShader, "_EnableSSSAndTransmission", enableSSSAndTransmission);
cmd.SetComputeIntParam( shadeOpaqueShader, "_TexturingModeFlags", texturingModeFlags);
cmd.SetComputeIntParam( shadeOpaqueShader, "_TransmissionFlags", transmissionFlags);
cmd.SetComputeVectorArrayParam(shadeOpaqueShader, "_ThicknessRemaps", thicknessRemaps);
// We are currently supporting two different SSS mode: Jimenez (with 2-Gaussian profile) and Disney
// We have added the ability to switch between each other for subsurface scattering, but for transmittance this is more tricky as we need to add
// shader variant for forward, gbuffer and deferred shader. We want to avoid this.
// So for transmittance we use Disney profile formulation (that we know is more correct) in both case, and in the case of Jimenez we hack the parameters with 2-Gaussian parameters (Ideally we should fit but haven't find good fit) so it approximately match.
// Note: Jimenez SSS is in cm unit whereas Disney is in mm unit making an inconsistency here to compare model side by side
cmd.SetComputeVectorArrayParam(shadeOpaqueShader, "_ShapeParams", shapeParams);
cmd.SetComputeVectorArrayParam(shadeOpaqueShader, "_TransmissionTints", transmissionTints);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "specularLightingUAV", colorBuffers[0]);
cmd.SetComputeTextureParam(shadeOpaqueShader, kernel, "diffuseLightingUAV", colorBuffers[1]);
// always do deferred lighting in blocks of 16x16 (not same as tiled light size)

// Pixel shader evaluation
PushGlobalParams(camera, cmd, null, 0);
if (m_TileSettings.enableSplitLightEvaluation)
if (outputSplitLighting)
if (outputSplitLighting)
{
Utilities.SelectKeyword(m_DeferredDirectMaterialMRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredDirectMaterialMRT, colorBuffers, depthStencilBuffer);
Utilities.SelectKeyword(m_DeferredIndirectMaterialMRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredIndirectMaterialMRT, colorBuffers, depthStencilBuffer);
}
else
{
// If SSS is disable, do lighting for both split lighting and no split lighting
if (!debugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission)
{
m_DeferredDirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.NoLighting);
m_DeferredDirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.NotEqual);
m_DeferredIndirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.NoLighting);
m_DeferredIndirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.NotEqual);
}
else
{
m_DeferredDirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredDirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
m_DeferredIndirectMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredIndirectMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
}
Utilities.SelectKeyword(m_DeferredDirectMaterialSRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredDirectMaterialSRT, colorBuffers[0], depthStencilBuffer);
Utilities.SelectKeyword(m_DeferredIndirectMaterialSRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredIndirectMaterialSRT, colorBuffers[0], depthStencilBuffer);
}
Utilities.SelectKeyword(m_DeferredAllMaterialMRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredAllMaterialMRT, colorBuffers, depthStencilBuffer);
if (outputSplitLighting)
// If SSS is disable, do lighting for both split lighting and no split lighting
if (!debugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission)
Utilities.SelectKeyword(m_DeferredAllMaterialMRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredAllMaterialMRT, colorBuffers, depthStencilBuffer);
m_DeferredAllMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.NoLighting);
m_DeferredAllMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.NotEqual);
// If SSS is disable, do lighting for both split lighting and no split lighting
if (!debugDisplaySettings.renderingDebugSettings.enableSSSAndTransmission)
{
m_DeferredAllMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.NoLighting);
m_DeferredAllMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.NotEqual);
}
else
{
m_DeferredAllMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredAllMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
}
Utilities.SelectKeyword(m_DeferredAllMaterialSRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredAllMaterialSRT, colorBuffers[0], depthStencilBuffer);
m_DeferredAllMaterialSRT.SetInt("_StencilRef", (int)StencilLightingUsage.RegularLighting);
m_DeferredAllMaterialSRT.SetInt("_StencilCmp", (int)CompareFunction.Equal);
Utilities.SelectKeyword(m_DeferredAllMaterialSRT, "USE_CLUSTERED_LIGHTLIST", "USE_FPTL_LIGHTLIST", bUseClusteredForDeferred);
Utilities.DrawFullScreen(cmd, m_DeferredAllMaterialSRT, colorBuffers[0], depthStencilBuffer);
}
}
}

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


//
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightFeatureFlags: static fields
//
#define LIGHTFEATUREFLAGS_PUNCTUAL (1)
#define LIGHTFEATUREFLAGS_AREA (2)
#define LIGHTFEATUREFLAGS_DIRECTIONAL (4)
#define LIGHTFEATUREFLAGS_ENV (8)
#define LIGHTFEATUREFLAGS_SKY (16)
#define LIGHTFEATUREFLAGS_PUNCTUAL (256)
#define LIGHTFEATUREFLAGS_AREA (512)
#define LIGHTFEATUREFLAGS_DIRECTIONAL (1024)
#define LIGHTFEATUREFLAGS_ENV (2048)
#define LIGHTFEATUREFLAGS_SKY (4096)
//
// UnityEngine.Experimental.Rendering.HDPipeline.TilePass.LightDefinitions: static fields

#define USE_LEFT_HAND_CAMERA_SPACE (1)
#define TILE_SIZE_FPTL (16)
#define TILE_SIZE_CLUSTERED (32)
#define NUM_FEATURE_VARIANTS (16)
#define LIGHTFEATUREFLAGS_MASK (4095)
#define MATERIALFEATUREFLAGS_MASK (61440)
#define NUM_FEATURE_VARIANTS (26)
#define LIGHT_FEATURE_MASK_FLAGS (65280)
#define MATERIAL_FEATURE_MASK_FLAGS (255)
// Generated from UnityEngine.Experimental.Rendering.HDPipeline.TilePass.SFiniteLightBound
// PackingRules = Exact

65
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/TilePassLoop.hlsl


{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional(context, V, posInput, prelightData,
GPULIGHTTYPE_DIRECTIONAL, _DirectionalLightDatas[i], bsdfData,
EvaluateBSDF_Directional(context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;

#ifdef PROCESS_AREA_LIGHT
if(featureFlags & LIGHTFEATUREFLAGS_AREA)
{
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
for(i = 0; i < areaLightCount; ++i)
float3 localDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 localSpecularLighting = float3(0.0, 0.0, 0.0);
// COMPILER BEHAVIOR WARNING!
// If rectangle lights are before line lights, the compiler will duplicate light matrices in VGPR because they are used differently between the two types of lights.
// By keeping line lights first we avoid this behavior and save substantial register pressure.
// TODO: This is based on the current Lit.shader and can be different for any other way of implementing area lights, how to be generic and ensure performance ?
i = 0;
uint areaIndex = FetchIndex(areaLightStart, i);
while ( i < areaLightCount && _LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
float3 localDiffuseLighting, localSpecularLighting;
areaIndex = FetchIndex(areaLightStart, i);
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_LINE,
localDiffuseLighting, localSpecularLighting);
uint areaIndex = FetchIndex(areaLightStart, i);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
if(_LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
i++;
}
while (i < areaLightCount) // Rectangle lights are the last area lights so no need to check type
{
areaIndex = FetchIndex(areaLightStart, i);
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[areaIndex], bsdfData, GPULIGHTTYPE_RECTANGLE,
localDiffuseLighting, localSpecularLighting);
i++;
}
}
#endif

diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
#endif
// TODO: currently apply GI at the same time as reflection
#ifdef PROCESS_ENV_LIGHT
// Add indirect diffuse + emissive (if any)
// Apply GI at the same time as reflection
// Add indirect diffuse + emissive (if any) - Ambient occlusion is multiply by emissive which is wrong but not a big deal
diffuseLighting += bakeDiffuseLighting * context.ambientOcclusion;
#endif

{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional(context, V, posInput, prelightData,
GPULIGHTTYPE_DIRECTIONAL, _DirectionalLightDatas[i], bsdfData,
EvaluateBSDF_Directional(context, V, posInput, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;

{
float3 localDiffuseLighting, localSpecularLighting;
if (_LightDatas[i].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
EvaluateBSDF_Area( context, V, posInput, prelightData, _LightDatas[i], bsdfData, _LightDatas[i].lightType,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;

specularLighting += iblSpecularLighting;
// Add indirect diffuse + emissive (if any)
// Add indirect diffuse + emissive (if any) - Ambient occlusion is multiply by emissive which is wrong but not a big deal
diffuseLighting += bakeDiffuseLighting * context.ambientOcclusion;
ApplyDebug(context, posInput.positionWS, diffuseLighting, specularLighting);

14
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/builddispatchindirect.compute


#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "../../Material/Material.hlsl" // This includes Material.hlsl
#include "FeatureFlags.hlsl"
RWBuffer<uint> g_DispatchIndirectBuffer : register( u0 ); // Indirect arguments have to be in a _buffer_, not a structured buffer
RWStructuredBuffer<uint> g_TileList;
StructuredBuffer<uint> g_TileFeatureFlags;

uint tileY = (dispatchThreadId + 0.5f) / (float)g_NumTilesX; // Integer division is extremely expensive, so we better avoid it
uint tileX = dispatchThreadId - tileY * g_NumTilesX;
uint variant = FeatureFlagsToTileVariant(featureFlags);
uint offset;
InterlockedAdd(g_DispatchIndirectBuffer[variant * 3 + 0], 1, offset);
g_TileList[variant * g_NumTiles + offset] = (tileY << 16) | tileX;
// Check if there is no light or no material (mean we are sky/background pixel) / Both test as we can enable/disable light/material classification
if ((featureFlags & LIGHT_FEATURE_MASK_FLAGS) != 0 && (featureFlags & MATERIAL_FEATURE_MASK_FLAGS) != 0)
{
uint variant = FeatureFlagsToTileVariant(featureFlags);
uint offset;
InterlockedAdd(g_DispatchIndirectBuffer[variant * 3 + 0], 1, offset);
g_TileList[variant * g_NumTiles + offset] = (tileY << 16) | tileX;
}
}

4
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/lightlistbuild.compute


if(t == 0)
{
uint featureFlags = ldsFeatureFlags | g_BaseFeatureFlags;
// In case of back
featureFlags &= ~(LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_AREA | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | 0xFFFFF); // list of features that are not enabled on background
// There is no stencil usage with compute path, featureFlags set to 0 is use to have fast rejection of tile in this case. It will still execute but will do nothing
featureFlags = 0;
}
g_TileFeatureFlags[tileIDX.y * nrTilesX + tileIDX.x] = featureFlags;

7
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/materialflags.compute


#define UNITY_MATERIAL_LIT // Need to be define before including Material.hlsl
#include "../../Material/Material.hlsl" // This includes Material.hlsl
#include "FeatureFlags.hlsl"
#define USE_MATERIAL_FEATURE_FLAGS
#define NR_THREADS 64

}
GroupMemoryBarrierWithGroupSync();
uint materialFeatureFlags = g_BaseFeatureFlags;
uint materialFeatureFlags = g_BaseFeatureFlags; // Contain all lightFeatures or 0 (depends if we enable light classification or not)
[unroll]
for(int i = 0; i < 4; i++)
{

if (FetchDepth(g_depth_tex, uCrd) < VIEWPORT_SCALE_Z)
if (FetchDepth(g_depth_tex, uCrd) < VIEWPORT_SCALE_Z) // This test is we are the sky/background or not
{
PositionInputs posInput = GetPositionInput(uCrd, invScreenSize);
FETCH_GBUFFER(gbuffer, _GBufferTexture, posInput.unPositionSS);

{
#ifdef USE_OR
g_TileFeatureFlags[tileIDX.y * nrTilesX + tileIDX.x] |= ldsFeatureFlags;
#else
#else // Use in case we have disabled light classification
g_TileFeatureFlags[tileIDX.y * nrTilesX + tileIDX.x] = ldsFeatureFlags;
#endif
}

68
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/shadeopaque.compute


#pragma kernel ShadeOpaque_Indirect_Fptl_Variant13 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant13 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=13
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant14 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant14 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=14
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant15 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant15 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=15
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant16 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant16 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=16
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant17 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant17 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=17
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant18 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant18 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=18
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant19 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant19 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=19
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant20 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant20 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=20
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant21 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant21 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=21
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant22 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant22 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=22
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant23 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant23 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=23
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant24 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant24 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=24
#pragma kernel ShadeOpaque_Indirect_Fptl_Variant25 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Fptl_Variant25 USE_FPTL_LIGHTLIST USE_INDIRECT VARIANT=25
// TODO: We should remove these variant for cluster opaque and only keep tile opaque.
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant0 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant0 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=0
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant1 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant1 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=1
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant2 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant2 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=2

#pragma kernel ShadeOpaque_Indirect_Clustered_Variant13 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant13 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=13
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant14 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant14 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=14
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant15 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant15 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=15
//#pragma #pragma enable_d3d11_debug_symbols
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant16 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant16 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=16
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant17 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant17 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=17
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant18 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant18 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=18
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant19 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant19 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=19
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant20 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant20 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=20
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant21 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant21 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=21
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant22 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant22 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=22
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant23 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant23 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=23
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant24 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant24 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=24
#pragma kernel ShadeOpaque_Indirect_Clustered_Variant25 SHADE_OPAQUE_ENTRY=ShadeOpaque_Indirect_Clustered_Variant25 USE_CLUSTERED_LIGHTLIST USE_INDIRECT VARIANT=25
// Split lighting is required for the SSS pass.
// Not currently possible since we need to access the stencil buffer from the compute shader.
// #pragma multi_compile _ OUTPUT_SPLIT_LIGHTING
#define LIGHTLOOP_TILE_PASS 1
#define LIGHTLOOP_TILE_DIRECT 1

//#pragma enable_d3d11_debug_symbols
//-------------------------------------------------------------------------------------
// Include
//-------------------------------------------------------------------------------------

#include "../../ShaderConfig.cs.hlsl"
#include "../../ShaderVariables.hlsl"
#include "../../Lighting/Lighting.hlsl" // This include Material.hlsl
#include "../../Lighting/TilePass/FeatureFlags.hlsl"
//-------------------------------------------------------------------------------------
// variable declaration
//-------------------------------------------------------------------------------------

#ifdef OUTPUT_SPLIT_LIGHTING
RWTexture2D<float4> specularLightingUAV;
RWTexture2D<float3> diffuseLightingUAV;
#else
RWTexture2D<float4> combinedLightingUAV;
#endif
RWTexture2D<float3> diffuseLightingUAV;
RWTexture2D<float4> specularLightingUAV;
CBUFFER_START(UnityShadeOpaque)
uint g_TileListOffset;

#endif
float depth = LOAD_TEXTURE2D(_MainDepthTexture, posInput.unPositionSS).x;
// For indirect case: we can still overlap inside a tile with the sky/background, reject it
// Can't rely on stencil as we are in compute shader
// TODO : if we have depth bounds test we could remove such a test ?
if (depth == UNITY_RAW_FAR_CLIP_VALUE)
{
return;
}
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float3 V = GetWorldSpaceNormalizeViewDir(posInput.positionWS);

float3 specularLighting;
LightLoop(V, posInput, preLightData, bsdfData, bakeDiffuseLighting, featureFlags, diffuseLighting, specularLighting);
#ifdef OUTPUT_SPLIT_LIGHTING
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = diffuseLighting;
#else
combinedLightingUAV[pixelCoord] = float4(diffuseLighting + specularLighting, 1.0);
#endif
if (_EnableSSSAndTransmission != 0 && bsdfData.materialId == MATERIALID_LIT_SSS)
{
// We SSSSS is enabled with use split lighting.
// SSSSS algorithm need to know which pixels contribute to SSS and which doesn't. We could use the stencil for that but it mean that it will increase the cost of SSSSS
// A simpler solution is to add a slight contribution here that isn't visible (here we chose fp16 min (which is also fp11 and fp10 min).
// The SSSSS algorithm will check if diffuse lighting is black and discard the pixel if it is the case
diffuseLighting.r = max(diffuseLighting.r, HFLT_MIN);
specularLightingUAV[pixelCoord] = float4(specularLighting, 1.0);
diffuseLightingUAV[pixelCoord] = diffuseLighting;
}
else
{
specularLightingUAV[pixelCoord] = float4(diffuseLighting + specularLighting, 1.0);
}
}

22
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs


LitStandard = 1,
LitUnused0 = 2,
LitUnused1 = 3,
LitAniso = 4, // Should be the last as it is not setup by the users but generated based on anisotropy property
LitSpecular = 5, // Should be the last as it is not setup by the users but generated based on anisotropy property and specular
// We don't store any materialId for aniso but instead deduce it from LitStandard + value of specular + anisotropy parameters
// Consequence is that when querying materialId alone, it will read 2 RT and not only one. This may be a performance hit when only materialId is desired (like in material classification pass)
// Alternative is to use a materialId slot, if any are available.
LitAniso = 4,
// LitSpecular (DiffuseColor/SpecularColor) is an alternate parametrization for LitStandard (BaseColor/Metal/Specular), but it is the same shading model
// We don't want any specific materialId for it, instead we use LitStandard as materialId. However for UI purpose we still define this value here.
LitSpecular = 5,
// If change, be sure it match what is done in Lit.hlsl: MaterialFeatureFlagsFromGBuffer
// Material bit mask must match LightDefinitions.s_MaterialFeatureMaskFlags value
LitSSS = 1 << 12,
LitStandard = 1 << 13,
LitAniso = 1 << 14,
LitSpecular = 1 << 15
}
LitSSS = 1 << MaterialId.LitSSS,
LitStandard = 1 << MaterialId.LitStandard,
LitUnused0 = 1 << MaterialId.LitUnused0,
LitUnused1 = 1 << MaterialId.LitUnused1,
LitAniso = 1 << MaterialId.LitAniso,
};
[GenerateHLSL]
public enum SpecularValue

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.cs.hlsl


//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+MaterialFeatureFlags: static fields
//
#define MATERIALFEATUREFLAGS_LIT_SSS (4096)
#define MATERIALFEATUREFLAGS_LIT_STANDARD (8192)
#define MATERIALFEATUREFLAGS_LIT_ANISO (16384)
#define MATERIALFEATUREFLAGS_LIT_SPECULAR (32768)
#define MATERIALFEATUREFLAGS_LIT_SSS (1)
#define MATERIALFEATUREFLAGS_LIT_STANDARD (2)
#define MATERIALFEATUREFLAGS_LIT_UNUSED0 (4)
#define MATERIALFEATUREFLAGS_LIT_UNUSED1 (8)
#define MATERIALFEATUREFLAGS_LIT_ANISO (16)
//
// UnityEngine.Experimental.Rendering.HDPipeline.Lit+SpecularValue: static fields

538
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Lit.hlsl


uint _EnableSSSAndTransmission; // Globally toggles subsurface and transmission scattering on/off
uint _TexturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
uint _TransmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
float _ThicknessRemaps[SSS_N_PROFILES][2]; // Remap: 0 = start, 1 = end - start
// Use float4 to avoid any packing issue between compute and pixel shaders
float4 _ThicknessRemaps[SSS_N_PROFILES]; // R: start, G = end - start, BA unused
// Ligth and material classification for the deferred rendering path
// Configure what kind of combination is supported
//-----------------------------------------------------------------------------
// Lighting architecture and material are suppose to be decoupled files.
// However as we use material classification it is hard to be fully separated
// the dependecy is define in this include where there is shared define for material and lighting in case of deferred material.
// If a user do a lighting architecture without material classification, this can be remove
#include "../../Lighting/TilePass/TilePass.cs.hlsl"
// Combination need to be define in increasing "comlexity" order as define by FeatureFlagsToTileVariant
static const uint kFeatureVariantFlags[NUM_FEATURE_VARIANTS] =
{
// Standard
/* 0 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 1 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 2 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 4 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_STANDARD,
// SSS
// SSS is a superset of material standard. With foliage or crowd SSS and standard can overlap a lot, better to have a dedicated combination
/* 5 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 6 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 7 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 8 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_SSS | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 9 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_SSS,
// Specular/Aniso
/* 10 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 11 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 12 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 13 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_ANISO,
/* 14 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_ANISO,
// Future usage
/* 15 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_UNUSED0,
/* 16 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_UNUSED0,
/* 17 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_UNUSED0,
/* 18 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_UNUSED0,
/* 19 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_UNUSED0,
// Future usage
/* 20 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_UNUSED1,
/* 21 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_UNUSED1,
/* 22 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_UNUSED1,
/* 23 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_UNUSED1,
/* 24 */ LIGHT_FEATURE_MASK_FLAGS | MATERIALFEATUREFLAGS_LIT_UNUSED1,
/* 25 */ LIGHT_FEATURE_MASK_FLAGS | MATERIAL_FEATURE_MASK_FLAGS, // Catch all case with MATERIAL_FEATURE_MASK_FLAGS is needed in case we disable material classification
};
uint FeatureFlagsToTileVariant(uint featureFlags)
{
for (int i = 0; i < NUM_FEATURE_VARIANTS; i++)
{
if ((featureFlags & kFeatureVariantFlags[i]) == featureFlags)
return i;
}
return NUM_FEATURE_VARIANTS - 1;
}
// This function need to return a compile time value, else there is no optimization
uint TileVariantToFeatureFlags(uint variant)
{
return kFeatureVariantFlags[variant];
}
//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material
//-----------------------------------------------------------------------------

bsdfData.fresnel0 = 0.04; // Should be 0.028 for the skin
bsdfData.subsurfaceProfile = subsurfaceProfile;
bsdfData.subsurfaceRadius = subsurfaceRadius;
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile][0] +
_ThicknessRemaps[subsurfaceProfile][1] * thickness;
bsdfData.thickness = _ThicknessRemaps[subsurfaceProfile].x +
_ThicknessRemaps[subsurfaceProfile].y * thickness;
uint transmissionMode = BitFieldExtract(_TransmissionFlags, 2u, 2u * subsurfaceProfile);

#if defined(SHADERPASS) && (SHADERPASS == SHADERPASS_LIGHT_TRANSPORT) // In case of GI pass don't modify the diffuseColor
if (0)
#else
if (_EnableSSSAndTransmission > 0) // If we globally disable SSS effect, don't modify diffuseColor
if (_EnableSSSAndTransmission != 0) // If we globally disable SSS effect, don't modify diffuseColor
#endif
{
// We modify the albedo here as this code is used by all lighting (including light maps and GI).

bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
bsdfData.materialId = surfaceData.materialId;
// IMPORTANT: In case of foward or gbuffer pass we know what we are, we don't need to check specular or aniso to know the materialId, this is because we have static compile shader feature for it
// IMPORTANT: In case of foward or gbuffer pass we must know what we are statically, so compiler can do compile time optimization
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, surfaceData.metallic, bsdfData);
}
else if (bsdfData.materialId == MATERIALID_LIT_SPECULAR)
{
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = surfaceData.specularColor;
if (surfaceData.specular == SPECULARVALUE_SPECULAR_COLOR)
{
bsdfData.diffuseColor = surfaceData.baseColor;
bsdfData.fresnel0 = surfaceData.specularColor;
}
else
{
FillMaterialIdStandardData(surfaceData.baseColor, surfaceData.specular, surfaceData.metallic, bsdfData);
}
}
else if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{

if (surfaceData.materialId == MATERIALID_LIT_STANDARD)
{
// Encode specular on two bit for the enum
outGBuffer2 = float4(0.0, 0.0, 0.0, PackFloatInt8bit(surfaceData.metallic, surfaceData.specular, 4.0));
}
else if (surfaceData.materialId == MATERIALID_LIT_SPECULAR)
{
outGBuffer1.a = PackMaterialId(MATERIALID_LIT_STANDARD); // We save 1bit in gbuffer1 to store it in gbuffer2 instead
// Encode specular on two bit for the enum, must match encoding of MATERIALID_LIT_STANDARD
// TODO: encoding here could be optimize as we know what is the value of surfaceData.specular => (0.75294)
outGBuffer2 = float4(surfaceData.specularColor, PackFloatInt8bit(0.0, surfaceData.specular, 4.0));
// Note: we encode two parametrization at the same time, specularColor and metal/specular
if (surfaceData.specular == SPECULARVALUE_SPECULAR_COLOR)
{
outGBuffer2 = float4(surfaceData.specularColor, PackFloatInt8bit(0.0, surfaceData.specular, 4.0)); // As all is static, Pack function should produce the result compile time
}
else
{
// Note: it is important to setup anisotropy field to 0 else materialId will be anisotropic
outGBuffer2 = float4(float3(0.0, 0.0, 0.0), PackFloatInt8bit(surfaceData.metallic, surfaceData.specular, 4.0));
}
}
else if (surfaceData.materialId == MATERIALID_LIT_ANISO)
{

bsdfData.roughness = PerceptualRoughnessToRoughness(bsdfData.perceptualRoughness);
int supportsStandard = (featureFlags & (MATERIALFEATUREFLAGS_LIT_STANDARD | MATERIALFEATUREFLAGS_LIT_ANISO | MATERIALFEATUREFLAGS_LIT_SPECULAR)) != 0;
// The material features system for material classification must allow compile time optimization (i.e everything should be static)
// Note that as we store materialId for Aniso based on content of RT2 we need to add few extra condition.
// The code is also call from MaterialFeatureFlagsFromGBuffer, so must work fully dynamic if featureFlags is 0xFFFFFFFF
int supportsStandard = (featureFlags & (MATERIALFEATUREFLAGS_LIT_STANDARD | MATERIALFEATUREFLAGS_LIT_ANISO)) != 0;
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a); // only fetch materialid if it is not statically known from feature flags
// only fetch materialid if it is not statically known from feature flags
bsdfData.materialId = UnpackMaterialId(inGBuffer1.a);
}
else
{

bsdfData.materialId = MATERIALID_LIT_SSS;
}
if (supportsStandard && bsdfData.materialId == MATERIALID_LIT_STANDARD)
if (bsdfData.materialId == MATERIALID_LIT_STANDARD)
{
float metallic;
int specular;

if (((featureFlags & MATERIALFEATUREFLAGS_LIT_SPECULAR) && (featureFlags & MATERIALFEATUREFLAGS_LIT_STANDARD) == 0)
|| specular == SPECULARVALUE_SPECULAR_COLOR)
if (featureFlags & (MATERIAL_FEATURE_MASK_FLAGS) == MATERIALFEATUREFLAGS_LIT_STANDARD)
bsdfData.materialId = MATERIALID_LIT_SPECULAR;
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
if (specular == SPECULARVALUE_SPECULAR_COLOR)
{
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
}
else
{
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);
}
else if ( ((featureFlags & MATERIALFEATUREFLAGS_LIT_ANISO) && (featureFlags & MATERIALFEATUREFLAGS_LIT_STANDARD) == 0)
|| anisotropy > 0)
else if (featureFlags & (MATERIAL_FEATURE_MASK_FLAGS) == MATERIALFEATUREFLAGS_LIT_ANISO)
{
bsdfData.materialId = MATERIALID_LIT_ANISO;
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);

else
else // either MATERIAL_FEATURE_MASK_FLAGS or MATERIALFEATUREFLAGS_LIT_STANDARD | MATERIALFEATUREFLAGS_LIT_ANISO
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);
if (specular == SPECULARVALUE_SPECULAR_COLOR)
{
bsdfData.diffuseColor = baseColor;
bsdfData.fresnel0 = inGBuffer2.rgb;
}
else if (anisotropy > 0)
{
bsdfData.materialId = MATERIALID_LIT_ANISO;
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);
float3 tangentWS = UnpackNormalOctEncode(float2(inGBuffer2.rg * 2.0 - 1.0));
FillMaterialIdAnisoData(bsdfData.roughness, bsdfData.normalWS, tangentWS, anisotropy, bsdfData);
}
else
{
FillMaterialIdStandardData(baseColor, specular, metallic, bsdfData);
}
else // if (supportsSSS && bsdfData.materialId == MATERIALID_LIT_SSS)
else // bsdfData.materialId == MATERIALID_LIT_SSS
{
float subsurfaceRadius = inGBuffer2.x;
float thickness = inGBuffer2.y;

#endif
)
{
BSDFData bsdfData;
float3 unused;
DecodeFromGBuffer(
float4 inGBuffer0, inGBuffer1, inGBuffer2, inGBuffer3;
inGBuffer0 = DecodeGBuffer0(inGBufferU0);
uint packedGBuffer1 = inGBufferU0.z | inGBufferU0.w << 16;
inGBuffer1 = UnpackR10G10B10A2(packedGBuffer1);
inGBuffer2.x = UnpackUIntToFloat(inGBufferU1.x, 8, 0);
inGBuffer2.y = UnpackUIntToFloat(inGBufferU1.x, 8, 8);
inGBuffer2.z = UnpackUIntToFloat(inGBufferU1.y, 8, 0);
inGBuffer2.w = UnpackUIntToFloat(inGBufferU1.y, 8, 8);
uint packedGBuffer3 = inGBufferU1.z | inGBufferU1.w << 16;
inGBuffer3.xyz = UnpackR11G11B10f(packedGBuffer1);
inGBuffer3.w = 0.0;
inGBufferU0, inGBufferU1,
#else
inGBuffer0, inGBuffer1, inGBuffer2, inGBuffer3,
int materialId = UnpackMaterialId(inGBuffer1.a);
uint featureFlags = 0;
if (materialId == MATERIALID_LIT_STANDARD)
{
float metallic;
int specular;
UnpackFloatInt8bit(inGBuffer2.a, 4.0, metallic, specular);
float anisotropy = inGBuffer2.b;
if (specular == SPECULARVALUE_SPECULAR_COLOR)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_SPECULAR;
}
else if (anisotropy > 0.0)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_ANISO;
}
else
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_STANDARD;
}
}
else if (materialId == MATERIALID_LIT_SSS)
{
featureFlags |= MATERIALFEATUREFLAGS_LIT_SSS;
}
0xFFFFFFFF,
bsdfData,
unused
);
return featureFlags;
return (1 << bsdfData.materialId); // This match all the MATERIALFEATUREFLAGS_LIT_XXX flag
}

preLightData.ggxLambdaV = GetSmithJointGGXLambdaV(NdotV, bsdfData.roughness);
// GGX aniso
preLightData.TdotV = 0;
preLightData.BdotV = 0;
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
preLightData.TdotV = dot(bsdfData.tangentWS, V);

void EvaluateBSDF_Directional(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput, PreLightData preLightData,
int lightType, DirectionalLightData lightData, BSDFData bsdfData,
DirectionalLightData lightData, BSDFData bsdfData,
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane.
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU.
float3 lightToSurface = positionWS - lightData.positionWS;
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
float3 positionLS = mul(lightToSurface, transpose(lightToWorld));
float2 positionNDC = positionLS.xy;
// Clip only box projector lights.
float clipFactor = 1;
// Static branch.
if (lightType == GPULIGHTTYPE_PROJECTOR_BOX)
{
bool isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1;
clipFactor = isInBounds ? 1 : 0;
}
float attenuation = clipFactor;
float illuminance = saturate(NdotL * attenuation);
float illuminance = saturate(NdotL);
diffuseLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure
specularLighting = float3(0, 0, 0); // TODO: check whether using 'out' instead of 'inout' increases the VGPR pressure

[branch] if (lightData.cookieIndex >= 0)
{
// Compute the NDC position (in [-1, 1]^2) by projecting 'positionWS' onto the near plane.
// 'lightData.right' and 'lightData.up' are pre-scaled on CPU.
float3 lightToSurface = positionWS - lightData.positionWS;
float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
float3 positionLS = mul(lightToSurface, transpose(lightToWorld));
float2 positionNDC = positionLS.xy;
float clipFactor = 1.0f;
if (lightData.tileCookie)
{
// Tile the texture if the 'repeat' wrap mode is enabled.
coord = frac(coord);
}
else
{
bool isInBounds = Max3(abs(positionNDC.x), abs(positionNDC.y), 1 - positionLS.z) <= 1;
clipFactor = isInBounds ? 1 : 0;
}
cookie = c.rgb * c.a;
cookie = c.rgb * c.a * clipFactor;
}
[branch] if (illuminance > 0.0)

// (we reuse the illumination) with the reversed normal of the current sample.
// We apply wrapped lighting instead of the regular Lambertian diffuse
// to compensate for these approximations.
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT) * attenuation;
illuminance = ComputeWrappedDiffuseLighting(NdotL, SSS_WRAP_LIGHT);
// For low thickness, we can reuse the shadowing status for the back of the object.
shadow = bsdfData.useThinObjectMode ? shadow : 1;

float3 cookie = float3(1, 1, 1);
float shadow = 1;
// TODO: measure impact of having all these dynamic branch here and the gain (or not) of testing illuminace > 0
//[branch] if (lightData.IESIndex >= 0 && illuminance > 0.0)
//{
// float3x3 lightToWorld = float3x3(lightData.right, lightData.up, lightData.forward);
// float2 sphericalCoord = GetIESTextureCoordinate(lightToWorld, L);
// illuminance *= SampleIES(lightLoopContext, lightData.IESIndex, sphericalCoord, 0).r;
//}
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L, posInput.unPositionSS);
float4 L_dist = { normalize( L.xyz ), length( unL ) };
shadow = GetPunctualShadowAttenuation(lightLoopContext.shadowContext, positionWS + offset, bsdfData.normalWS, lightData.shadowIndex, L_dist, posInput.unPositionSS);
shadow = lerp(1.0, shadow, lightData.shadowDimmer);
illuminance *= shadow;

}
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Line - Reference
//-----------------------------------------------------------------------------
void IntegrateBSDF_LineRef(float3 V, float3 positionWS,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting,
int sampleCount = 128)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
const float len = lightData.size.x;
const float3 T = lightData.right;
const float3 P1 = lightData.positionWS - T * (0.5 * len);
const float dt = len * rcp(sampleCount);
const float off = 0.5 * dt;
// Uniformly sample the line segment with the Pdf = 1 / len.
const float invPdf = len;
for (int i = 0; i < sampleCount; ++i)
{
// Place the sample in the middle of the interval.
float t = off + i * dt;
float3 sPos = P1 + t * T;
float3 unL = sPos - positionWS;
float dist2 = dot(unL, unL);
float3 L = normalize(unL);
float sinLT = length(cross(L, T));
float NdotL = saturate(dot(bsdfData.normalWS, L));
if (NdotL > 0)
{
float3 lightDiff, lightSpec;
BSDF(V, L, positionWS, preLightData, bsdfData, lightDiff, lightSpec);
diffuseLighting += lightDiff * (sinLT / dist2 * NdotL);
specularLighting += lightSpec * (sinLT / dist2 * NdotL);
}
}
// The factor of 2 is due to the fact: Integral{0, 2 PI}{max(0, cos(x))dx} = 2.
float normFactor = 2.0 * invPdf * rcp(sampleCount);
diffuseLighting *= normFactor * lightData.diffuseScale * lightData.color;
specularLighting *= normFactor * lightData.specularScale * lightData.color;
}
#include "LitReference.hlsl"
//-----------------------------------------------------------------------------
// EvaluateBSDF_Line - Approximation with Linearly Transformed Cosines

}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area - Reference
//-----------------------------------------------------------------------------
void IntegrateBSDF_AreaRef(float3 V, float3 positionWS,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting,
uint sampleCount = 512)
{
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
for (uint i = 0; i < sampleCount; ++i)
{
float3 P = float3(0.0, 0.0, 0.0); // Sample light point. Random point on the light shape in local space.
float3 Ns = float3(0.0, 0.0, 0.0); // Unit surface normal at P
float lightPdf = 0.0; // Pdf of the light sample
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
// Lights in Unity point backward.
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(-lightData.forward, 0.0), float4(lightData.positionWS, 1.0));
switch (lightData.lightType)
{
case GPULIGHTTYPE_SPHERE:
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_HEMISPHERE:
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_CYLINDER:
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_RECTANGLE:
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_DISK:
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
// case GPULIGHTTYPE_LINE: handled by a separate function.
}
// Get distance
float3 unL = P - positionWS;
float sqrDist = dot(unL, unL);
float3 L = normalize(unL);
// Cosine of the angle between the light direction and the normal of the light's surface.
float cosLNs = saturate(dot(-L, Ns));
// We calculate area reference light with the area integral rather than the solid angle one.
float illuminance = cosLNs * saturate(dot(bsdfData.normalWS, L)) / (sqrDist * lightPdf);
float3 localDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 localSpecularLighting = float3(0.0, 0.0, 0.0);
if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, localDiffuseLighting, localSpecularLighting);
localDiffuseLighting *= lightData.color * illuminance * lightData.diffuseScale;
localSpecularLighting *= lightData.color * illuminance * lightData.specularScale;
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
diffuseLighting /= float(sampleCount);
specularLighting /= float(sampleCount);
}
//-----------------------------------------------------------------------------
void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
void EvaluateBSDF_Rect( LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
{
float3 positionWS = posInput.positionWS;

#endif // LIT_DISPLAY_REFERENCE_AREA
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Env - Reference
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateLambertIBLRef(LightLoopContext lightLoopContext,
float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
void EvaluateBSDF_Area(LightLoopContext lightLoopContext,
float3 V, PositionInputs posInput,
PreLightData preLightData, LightData lightData, BSDFData bsdfData, int GPULightType,
out float3 diffuseLighting, out float3 specularLighting)
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
if (GPULightType == GPULIGHTTYPE_LINE)
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += bsdfData.diffuseColor * LambertNoPI() * weightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
float3 IntegrateDisneyDiffuseIBLRef(LightLoopContext lightLoopContext,
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
{
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float3 L;
float NdotL;
float weightOverPdf;
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
acc += bsdfData.diffuseColor * disneyDiffuse * weightOverPdf * val.rgb;
}
EvaluateBSDF_Line(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return acc / sampleCount;
}
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateSpecularGGXIBLRef(LightLoopContext lightLoopContext,
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
{
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
else
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
// GGX BRDF
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
ImportanceSampleAnisoGGX(u, V, localToWorld, bsdfData.roughnessT, bsdfData.roughnessB, NdotV, L, VdotH, NdotL, weightOverPdf);
}
else
{
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
}
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
float3 FweightOverPdf = F_Schlick(bsdfData.fresnel0, VdotH) * weightOverPdf;
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
acc += FweightOverPdf * val.rgb;
}
EvaluateBSDF_Rect(lightLoopContext, V, posInput, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return acc / sampleCount;
}
//-----------------------------------------------------------------------------

6
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitDataInternal.hlsl


#ifdef _DETAIL_MAP_IDX
#ifdef SURFACE_GRADIENT
normalTS += detailNormalTS;
normalTS += detailNormalTS * detailMask;
#else
normalTS = lerp(normalTS, BlendNormalRNM(normalTS, detailNormalTS), detailMask);
#endif

#elif defined(_MATID_ANISO)
surfaceData.materialId = MATERIALID_LIT_ANISO;
#elif defined(_MATID_SPECULAR)
surfaceData.materialId = MATERIALID_LIT_SPECULAR;
surfaceData.materialId = MATERIALID_LIT_STANDARD; // Specular is not a different BRDF, it is just different parametrization, do'nt do a separate matId for it
#else // Default
surfaceData.materialId = MATERIALID_LIT_STANDARD;
#endif

#endif
surfaceData.anisotropy *= ADD_IDX(_Anisotropy);
// This surfaceData.specular must be static to allow the compiler to optimize the code when converting / encoding the values
// To save 1bit space in GBuffer we don't store specular as materialID but in the enum of the specular value
surfaceData.specular = SPECULARVALUE_SPECULAR_COLOR;
#else
surfaceData.specular = SPECULARVALUE_REGULAR;

16
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitTessellation.hlsl


// Thus the following code play with both.
#if defined(SHADERPASS) && (SHADERPASS != SHADERPASS_SHADOWS)
bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes); // _FrustumPlanes are primary camera planes
bool frustumCulledCurrentView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes); // _FrustumPlanes are primary camera planes
bool frustumCulledMainView = false;
bool frustumCulled = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes); // unity_CameraWorldClipPlanes is set by legacy Unity in case of shadow and contain shadow view plan
bool frustumCulledCurrentView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])unity_CameraWorldClipPlanes); // unity_CameraWorldClipPlanes is set by legacy Unity in case of shadow and contain shadow view plan
// In the case of shadow, we don't want to tessellate anything that is not seen by the main view frustum. It can result in minor popping of tessellation into a shadow but we can't afford it anyway.
bool frustumCulledMainView = WorldViewFrustumCull(p0, p1, p2, maxDisplacement, (float4[4])_FrustumPlanes);
#endif
bool faceCull = false;

}
#endif
if (frustumCulled || faceCull)
if (frustumCulledCurrentView || faceCull)
}
// See comment above:
// During shadow passes, we decide that anything outside the main view frustum should not be tessellated.
if (frustumCulledMainView)
{
return float4(1.0, 1.0, 1.0, 1.0);
}
// We use the parameters of the primary (scene view) camera in order

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CombineSubsurfaceScattering.shader


{
Stencil
{
Ref 1 // StencilBits.SSS
Ref 1 // StencilLightingUsage.SplitLighting
Comp Equal
Pass Keep
}

20
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SubsurfaceScatteringProfile.cs


// PDF(r, s) = s * (Exp[-r * s] + Exp[-r * s / 3]) / 4
// CDF(r, s) = 1 - 1/4 * Exp[-r * s] - 3/4 * Exp[-r * s / 3]
// ------------------------------------------------------------------------------------
// N.b.: computation of normalized weights, and multiplication by the surface albedo
// of the actual geometry is performed at runtime (in the shader).
m_FilterKernelNearField[i].x = r;

// Set in BuildKernel().
get { return m_FilterKernelNearField; }
}
public Vector2[] filterKernelFarField
{
// Set in BuildKernel().

// Below are the cached values.
[NonSerialized] public uint texturingModeFlags; // 1 bit/profile; 0 = PreAndPostScatter, 1 = PostScatter
[NonSerialized] public uint transmissionFlags; // 2 bit/profile; 0 = inf. thick, 1 = thin, 2 = regular
[NonSerialized] public float[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[NonSerialized] public Vector4[] thicknessRemaps; // Remap: 0 = start, 1 = end - start
[NonSerialized] public float[] worldScales; // Size of the world unit in meters
[NonSerialized] public Vector4[] shapeParams; // RGB = S = 1 / D, A = filter radius
[NonSerialized] public Vector4[] transmissionTints; // RGB = color, A = unused

{
texturingModeFlags = transmissionFlags = 0;
const int thicknessRemapsLen = SssConstants.SSS_N_PROFILES * 2;
if (thicknessRemaps == null || thicknessRemaps.Length != thicknessRemapsLen)
if (thicknessRemaps == null || thicknessRemaps.Length != SssConstants.SSS_N_PROFILES)
thicknessRemaps = new float[thicknessRemapsLen];
thicknessRemaps = new Vector4[SssConstants.SSS_N_PROFILES];
}
if (worldScales == null || worldScales.Length != SssConstants.SSS_N_PROFILES)

texturingModeFlags |= (uint)profiles[i].texturingMode << i;
transmissionFlags |= (uint)profiles[i].transmissionMode << i * 2;
thicknessRemaps[2 * i] = profiles[i].thicknessRemap.x;
thicknessRemaps[2 * i + 1] = profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x;
thicknessRemaps[i] = new Vector4(profiles[i].thicknessRemap.x, profiles[i].thicknessRemap.y - profiles[i].thicknessRemap.x, 0.0f, 0.0f);
worldScales[i] = profiles[i].worldScale;
shapeParams[i] = profiles[i].shapeParameter;
shapeParams[i].w = profiles[i].maxRadius;

if (useDisneySSS)
{
EditorGUILayout.PropertyField(m_ScatteringDistance, styles.sssProfileScatteringDistance);
GUI.enabled = false;
EditorGUILayout.PropertyField(m_MaxRadius, styles.sssProfileMaxRadius);
GUI.enabled = true;

m_ProfileMaterial.SetFloat("_MaxRadius", rMax);
// <<< Old SSS Model
EditorGUI.DrawPreviewTexture(GUILayoutUtility.GetRect(256, 256), m_ProfileImage, m_ProfileMaterial, ScaleMode.ScaleToFit, 1.0f);
EditorGUILayout.Space();
EditorGUILayout.LabelField(styles.sssTransmittancePreview0, styles.centeredMiniBoldLabel);
EditorGUILayout.LabelField(styles.sssTransmittancePreview1, EditorStyles.centeredGreyMiniLabel);

43
Assets/ScriptableRenderPipeline/HDRenderPipeline/RenderPipelineResources/CameraMotionVectors.shader


#include "../../ShaderLibrary/Common.hlsl"
#include "../ShaderVariables.hlsl"
#include "../ShaderConfig.cs.hlsl"
PackedVaryingsType Vert(AttributesMesh inputMesh)
float4 _CameraPosDiff;
struct Attributes
VaryingsType varyingsType;
varyingsType.vmesh = VertMesh(inputMesh);
return PackVaryingsType(varyingsType);
uint vertexID : SV_VertexID;
};
struct Varyings
{
float4 positionCS : SV_POSITION;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
return output;
float4 Frag(PackedVaryingsToPS packedInput) : SV_Target
float4 Frag(Varyings input) : SV_Target
PositionInputs posInput = GetPositionInput(packedInput.vmesh.positionCS.xy, _ScreenSize.zw);
PositionInputs posInput = GetPositionInput(input.positionCS.xy, _ScreenSize.zw);
float3 vPos = ComputeViewSpacePosition(posInput.positionSS, depth, _InvProjMatrix);
float4 worldPos = mul(unity_CameraToWorld, float4(vPos, 1.0));
UpdatePositionInput(depth, _InvViewProjMatrix, _ViewProjMatrix, posInput);
float4 worldPos = float4(posInput.positionWS, 1.0);
float4 prevPos = worldPos;
#if (SHADEROPTIONS_CAMERA_RELATIVE_RENDERING != 0)
prevPos -= _CameraPosDiff;
#endif
float4 prevClipPos = mul(_PrevViewProjMatrix, worldPos);
float4 curClipPos = mul(_ViewProjMatrix, worldPos);
float4 prevClipPos = mul(_PrevViewProjMatrix, prevPos);
float4 curClipPos = mul(_NonJitteredViewProjMatrix, worldPos);
#if UNITY_UV_STARTS_AT_TOP
previousPositionCS.y = 1.0 - previousPositionCS.y;
positionCS.y = 1.0 - positionCS.y;
#endif
return float4(positionCS - previousPositionCS, 0.0, 1.0);
}

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassForward.hlsl


float3 result = float3(1.0, 0.0, 1.0);
bool needLinearToSRGB = false;
GetPropertiesDataDebug(_DebugViewMaterial, result, needLinearToSRGB);
GetVaryingsDataDebug(_DebugViewMaterial, input, result, needLinearToSRGB);
GetBuiltinDataDebug(_DebugViewMaterial, builtinData, result, needLinearToSRGB);
GetSurfaceDataDebug(_DebugViewMaterial, surfaceData, result, needLinearToSRGB);

2
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderPass/ShaderPassVelocity.hlsl


// It is not possible to correctly generate the motion vector for tesselated geometry as tessellation parameters can change
// from one frame to another (adaptative, lod) + in Unity we only receive information for one non tesselated vertex.
// So motion vetor will be based on interpolate previous position at vertex level instead.
varyingsType.vpass.positionCS = mul(_ViewProjMatrix, mul(unity_ObjectToWorld, float4(inputMesh.positionOS, 1.0)));
varyingsType.vpass.positionCS = mul(_NonJitteredViewProjMatrix, mul(unity_ObjectToWorld, float4(inputMesh.positionOS, 1.0)));
varyingsType.vpass.previousPositionCS = mul(_PrevViewProjMatrix, mul(unity_MatrixPreviousM, unity_MotionVectorsParams.x ? float4(inputPass.previousPositionOS, 1.0) : float4(inputMesh.positionOS, 1.0)));
return PackVaryingsType(varyingsType);

1
Assets/ScriptableRenderPipeline/HDRenderPipeline/ShaderVariables.hlsl


CBUFFER_START(UnityPerPass)
float4x4 _PrevViewProjMatrix;
float4x4 _ViewProjMatrix;
float4x4 _NonJitteredViewProjMatrix;
float4x4 _ViewMatrix;
float4x4 _ProjMatrix;
float4x4 _InvViewProjMatrix;

15
Assets/ScriptableRenderPipeline/HDRenderPipeline/Utilities.cs


using UnityEngine.Rendering;
using UnityObject = UnityEngine.Object;
using System.Reflection;
using UnityEngine.Rendering.PostProcessing;
namespace UnityEngine.Experimental.Rendering.HDPipeline
{

{
SetRenderTarget(cmd, buffer, ClearFlag.ClearColor, Color.black, 0, (CubemapFace)i);
}
}
// Post-processing misc
public static bool IsPostProcessingActive(PostProcessLayer layer)
{
return layer != null
&& layer.enabled;
}
public static bool IsTemporalAntialiasingActive(PostProcessLayer layer)
{
return IsPostProcessingActive(layer)
&& layer.antialiasingMode == PostProcessLayer.Antialiasing.TemporalAntialiasing
&& layer.temporalAntialiasing.IsSupported();
}
// Miscellanous

3
Assets/ScriptableRenderPipeline/ShaderLibrary/AreaLighting.hlsl


float a = cosOmega * acos(x) - z; // y*ArcCos[-y*Sqrt[(1/x-1)/(1-y^2)]]-Sqrt[(1-y^2)*(x/(1-x))-y^2]*(1/x-1)
float b = atan(y); // ArcTan[Sqrt[(1-y^2)*(x/(1-x))-y^2]]
// Replacing max() with saturate() results in a 12 cycle SGPR forwarding stall on PS4.
return max(INV_PI * (a * sinSqSigma + b), 0); // (a/Pi)*x+(b/Pi)
return saturate(INV_PI * (a * sinSqSigma + b));
}
#endif
#endif

6
Assets/ScriptableRenderPipeline/ShaderLibrary/Common.hlsl


// headers from ShaderLibrary do not include "common.hlsl", this should be included in the .shader using it (or Material.hlsl)
// Rules: When doing an array for constant buffer variables, we always use float4 to avoid any packing issue, particularly between compute shader and pixel shaders
// i.e don't use SetGlobalFloatArray or SetComputeFloatParams
// The array can be alias in hlsl. Exemple:
// uniform float4 packedArray[3];
// static float unpackedArray[12] = (float[12]packedArray;
// Include language header
#if defined(SHADER_API_D3D11)

16
Assets/ScriptableRenderPipeline/ShaderLibrary/Packing.hlsl


return normalize(n);
}
float2 PackNormalHemiOctEncode(float3 n)
{
float l1norm = dot(abs(n), 1.0);
float2 res = n.xy * (1.0 / l1norm);
return float2(res.x + res.y, res.x - res.y);
}
float3 UnpackNormalHemiOctEncode(float2 f)
{
float2 val = float2(f.x + f.y, f.x - f.y) * 0.5;
float3 n = float3(val, 1.0 - dot(abs(val), 1.0));
return normalize(n);
}
// Tetrahedral encoding - Looks like Tetra encoding 10:10 + 2 is similar to oct 11:11, as oct is cheaper prefer it
// To generate the basisNormal below we use these 4 vertex of a regular tetrahedron
// v0 = float3(1.0, 0.0, -1.0 / sqrt(2.0));

12
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/Shadow.hlsl


// shadow sampling prototypes
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L );
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS );
// shadow sampling prototypes with screenspace info
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L );
float GetDirectionalShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS );

// default dispatchers for the individual shadow types (with and without screenspace support)
// point/spot light shadows
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuationDefault( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, normalWS, shadowDataIndex, L );
}

// if shadow dispatch is empty we'll fall back to default shadow sampling implementations
#ifndef SHADOW_DISPATCH_USE_CUSTOM_PUNCTUAL
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L, float2 unPositionSS )
float GetPunctualShadowAttenuation( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float4 L, float2 unPositionSS )
{
return GetPunctualShadowAttenuationDefault( shadowContext, positionWS, normalWS, shadowDataIndex, L, unPositionSS );
}

78
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithms.hlsl


//
// Point shadows
//
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
float EvalShadow_PointDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
ShadowData sd = shadowContext.shadowDatas[index];
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
ShadowData sd = shadowContext.shadowDatas[index + faceIndex];
sd = shadowContext.shadowDatas[index + faceIndex];
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
// get the algorithm

}
#define EvalShadow_PointDepth_( _samplerType ) \
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
float EvalShadow_PointDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
ShadowData sd = shadowContext.shadowDatas[index]; \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
int faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
int faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \
sd = shadowContext.shadowDatas[index + faceIndex]; \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

ShadowData sd = shadowContext.shadowDatas[index]; \
uint payloadOffset = GetPayloadOffset( sd ); \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

//
// Punctual shadows for Point and Spot
//
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
float EvalShadow_PunctualDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float4 L )
ShadowData sd = shadowContext.shadowDatas[index];
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType );
UnpackShadowType( sd.shadowType, shadowType );
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1;
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
float3 lpos = positionWS + L.xyz * L.w;
positionWS = biased_posWS;
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1;
else
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias );
ShadowData sd = shadowContext.shadowDatas[index + faceIndex];
sd = shadowContext.shadowDatas[index + faceIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );
// sample the texture according to the given algorithm

UnpackShadowType( sd.shadowType, shadowType, shadowAlgorithm );
return SampleShadow_SelectAlgorithm( shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx );
}
return SampleShadow_SelectAlgorithm(shadowContext, sd, payloadOffset, posTC, sd.bias, slice, shadowAlgorithm, texIdx, sampIdx);
}
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
float EvalShadow_PunctualDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float4 L ) \
ShadowData sd = shadowContext.shadowDatas[index]; \
UnpackShadowType( shadowContext.shadowDatas[index].shadowType, shadowType ); \
UnpackShadowType( sd.shadowType, shadowType ); \
faceIndex = EvalShadow_GetCubeFaceID( L ) + 1; \
float3 biased_posWS = positionWS + EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
float3 lpos = positionWS + L.xyz * L.w; \
positionWS = biased_posWS; \
faceIndex = EvalShadow_GetCubeFaceID( lpos - biased_posWS ) + 1; \
else \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L.xyz ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
ShadowData sd = shadowContext.shadowDatas[index + faceIndex]; \
sd = shadowContext.shadowDatas[index + faceIndex]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

float EvalShadow_CascadedDepth( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int index, float3 L )
{
ShadowData sd = shadowContext.shadowDatas[index];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres );

ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex];
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );

#define EvalShadow_CascadedDepth_( _samplerType ) \
float EvalShadow_CascadedDepth( ShadowContext shadowContext, uint shadowAlgorithm, Texture2DArray tex, _samplerType samp, float3 positionWS, float3 normalWS, int index, float3 L ) \
{ \
ShadowData sd = shadowContext.shadowDatas[index]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
\
/* load the right shadow data for the current face */ \
float4 dirShadowSplitSpheres[4]; \
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, index, dirShadowSplitSpheres ); \

\
ShadowData sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* normal based bias */ \
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias ); \
sd = shadowContext.shadowDatas[index + 1 + shadowSplitIndex]; \
/* get shadowmap texcoords */ \
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS ); \
/* sample the texture */ \

10
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowAlgorithmsCustom.hlsl


float EvalShadow_CascadedMoment( ShadowContext shadowContext, float3 positionWS, float3 normalWS, int shadowDataIndex, float3 L )
{
ShadowData sd = shadowContext.shadowDatas[shadowDataIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// load the right shadow data for the current face
float4 dirShadowSplitSpheres[4];
uint payloadOffset = EvalShadow_LoadSplitSpheres( shadowContext, shadowDataIndex, dirShadowSplitSpheres );

ShadowData sd = shadowContext.shadowDatas[shadowDataIndex + 1 + shadowSplitIndex];
// normal based bias
positionWS += EvalShadow_NormalBias( normalWS, saturate( dot( normalWS, L ) ), sd.texelSizeRcp.zw, sd.normalBias );
// get the shadowmap data for the correct cascade
sd = shadowContext.shadowDatas[shadowDataIndex + 1 + shadowSplitIndex];
// get shadowmap texcoords
float3 posTC = EvalShadow_GetTexcoords( sd, positionWS );

2
Assets/ScriptableRenderPipeline/ShaderLibrary/Shadow/ShadowMoments.hlsl


float mD = depth - moments.x;
float p = variance / (variance + mD * mD);
p = saturate( p / (1.0f - lightLeakBias) );
p = saturate( (p - lightLeakBias) / (1.0f - lightLeakBias) );
return max( p, depth <= moments.x );
}

195
Assets/TestScenes/HDTest/BasicProfiling.unity


affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &31226894

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &119724878

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &290893317

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &578289780

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1028064555

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!1 &1224712456

affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1369123404

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 1
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1418455419

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1685118384

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1736085185

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1866152053

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1955890979

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

affectDiffuse: 1
affectSpecular: 1
archetype: 0
spotLightShape: 0
lightLength: 0
lightWidth: 0
--- !u!108 &1964619977

m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_FalloffTable:
m_Table[0]: 0
m_Table[1]: 0
m_Table[2]: 0
m_Table[3]: 0
m_Table[4]: 0
m_Table[5]: 0
m_Table[6]: 0
m_Table[7]: 0
m_Table[8]: 0
m_Table[9]: 0
m_Table[10]: 0
m_Table[11]: 0
m_Table[12]: 0
m_ColorTemperature: 6570
m_UseColorTemperature: 0
m_ShadowRadius: 0

287
Assets/TestScenes/HDTest/CascadedShadowsTest.unity
文件差异内容过多而无法显示
查看文件

2
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 2017.2.0b1
m_EditorVersion: 2017.3.0a2

2
README.md


SRP depends on PostProcessing submodule. Perform the following instructions to get a working copy of SRP:
* git clone https://github.com/Unity-Technologies/ScriptableRenderLoop
* git checkout unity-2017.1b5 (or the latest tag)
* git submodule update --init --recursive
* git submodule update --init --recursive --remote
## For Unity 5.6 beta users

248
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl


//-----------------------------------------------------------------------------
// EvaluateBSDF_Line - Reference
//-----------------------------------------------------------------------------
void IntegrateBSDF_LineRef(float3 V, float3 positionWS,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting,
int sampleCount = 128)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
const float len = lightData.size.x;
const float3 T = lightData.right;
const float3 P1 = lightData.positionWS - T * (0.5 * len);
const float dt = len * rcp(sampleCount);
const float off = 0.5 * dt;
// Uniformly sample the line segment with the Pdf = 1 / len.
const float invPdf = len;
for (int i = 0; i < sampleCount; ++i)
{
// Place the sample in the middle of the interval.
float t = off + i * dt;
float3 sPos = P1 + t * T;
float3 unL = sPos - positionWS;
float dist2 = dot(unL, unL);
float3 L = normalize(unL);
float sinLT = length(cross(L, T));
float NdotL = saturate(dot(bsdfData.normalWS, L));
if (NdotL > 0)
{
float3 lightDiff, lightSpec;
BSDF(V, L, positionWS, preLightData, bsdfData, lightDiff, lightSpec);
diffuseLighting += lightDiff * (sinLT / dist2 * NdotL);
specularLighting += lightSpec * (sinLT / dist2 * NdotL);
}
}
// The factor of 2 is due to the fact: Integral{0, 2 PI}{max(0, cos(x))dx} = 2.
float normFactor = 2.0 * invPdf * rcp(sampleCount);
diffuseLighting *= normFactor * lightData.diffuseScale * lightData.color;
specularLighting *= normFactor * lightData.specularScale * lightData.color;
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area - Reference
//-----------------------------------------------------------------------------
void IntegrateBSDF_AreaRef(float3 V, float3 positionWS,
PreLightData preLightData, LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting,
uint sampleCount = 512)
{
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
for (uint i = 0; i < sampleCount; ++i)
{
float3 P = float3(0.0, 0.0, 0.0); // Sample light point. Random point on the light shape in local space.
float3 Ns = float3(0.0, 0.0, 0.0); // Unit surface normal at P
float lightPdf = 0.0; // Pdf of the light sample
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
// Lights in Unity point backward.
float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(-lightData.forward, 0.0), float4(lightData.positionWS, 1.0));
switch (lightData.lightType)
{
case GPULIGHTTYPE_SPHERE:
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_HEMISPHERE:
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_CYLINDER:
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_RECTANGLE:
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
break;
case GPULIGHTTYPE_DISK:
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
break;
// case GPULIGHTTYPE_LINE: handled by a separate function.
}
// Get distance
float3 unL = P - positionWS;
float sqrDist = dot(unL, unL);
float3 L = normalize(unL);
// Cosine of the angle between the light direction and the normal of the light's surface.
float cosLNs = saturate(dot(-L, Ns));
// We calculate area reference light with the area integral rather than the solid angle one.
float illuminance = cosLNs * saturate(dot(bsdfData.normalWS, L)) / (sqrDist * lightPdf);
float3 localDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 localSpecularLighting = float3(0.0, 0.0, 0.0);
if (illuminance > 0.0)
{
BSDF(V, L, positionWS, preLightData, bsdfData, localDiffuseLighting, localSpecularLighting);
localDiffuseLighting *= lightData.color * illuminance * lightData.diffuseScale;
localSpecularLighting *= lightData.color * illuminance * lightData.specularScale;
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
diffuseLighting /= float(sampleCount);
specularLighting /= float(sampleCount);
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Env - Reference
// ----------------------------------------------------------------------------
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateLambertIBLRef(LightLoopContext lightLoopContext,
float3 V, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
{
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float3 L;
float NdotL;
float weightOverPdf;
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
acc += bsdfData.diffuseColor * LambertNoPI() * weightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
float3 IntegrateDisneyDiffuseIBLRef(LightLoopContext lightLoopContext,
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
{
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float3 L;
float NdotL;
float weightOverPdf;
// for Disney we still use a Cosine importance sampling, true Disney importance sampling imply a look up table
ImportanceSampleLambert(u, localToWorld, L, NdotL, weightOverPdf);
if (NdotL > 0.0)
{
float3 H = normalize(L + V);
float LdotH = dot(L, H);
// Note: we call DisneyDiffuse that require to multiply by Albedo / PI. Divide by PI is already taken into account
// in weightOverPdf of ImportanceSampleLambert call.
float disneyDiffuse = DisneyDiffuse(NdotV, NdotL, LdotH, bsdfData.perceptualRoughness);
// diffuse Albedo is apply here as describe in ImportanceSampleLambert function
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
acc += bsdfData.diffuseColor * disneyDiffuse * weightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}
// Ref: Moving Frostbite to PBR (Appendix A)
float3 IntegrateSpecularGGXIBLRef(LightLoopContext lightLoopContext,
float3 V, PreLightData preLightData, EnvLightData lightData, BSDFData bsdfData,
uint sampleCount = 4096)
{
float3x3 localToWorld = float3x3(bsdfData.tangentWS, bsdfData.bitangentWS, bsdfData.normalWS);
float NdotV = max(preLightData.NdotV, MIN_N_DOT_V);
float3 acc = float3(0.0, 0.0, 0.0);
// Add some jittering on Hammersley2d
float2 randNum = InitRandom(V.xy * 0.5 + 0.5);
for (uint i = 0; i < sampleCount; ++i)
{
float2 u = Hammersley2d(i, sampleCount);
u = frac(u + randNum);
float VdotH;
float NdotL;
float3 L;
float weightOverPdf;
// GGX BRDF
if (bsdfData.materialId == MATERIALID_LIT_ANISO)
{
ImportanceSampleAnisoGGX(u, V, localToWorld, bsdfData.roughnessT, bsdfData.roughnessB, NdotV, L, VdotH, NdotL, weightOverPdf);
}
else
{
ImportanceSampleGGX(u, V, localToWorld, bsdfData.roughness, NdotV, L, VdotH, NdotL, weightOverPdf);
}
if (NdotL > 0.0)
{
// Fresnel component is apply here as describe in ImportanceSampleGGX function
float3 FweightOverPdf = F_Schlick(bsdfData.fresnel0, VdotH) * weightOverPdf;
float4 val = SampleEnv(lightLoopContext, lightData.envIndex, L, 0);
acc += FweightOverPdf * val.rgb;
}
}
return acc / sampleCount;
}

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/LitReference.hlsl.meta


fileFormatVersion: 2
guid: 0406917314064054eb0ef42f727a8889
timeCreated: 1500913760
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

58
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader


Shader "Hidden/HDRenderPipeline/CopyStencilBuffer"
{
SubShader
{
Pass
{
Stencil
{
Ref 1 // StencilLightingUsage.SplitLighting
Comp Equal
Pass Keep
}
Cull Off
ZTest Always
ZWrite Off
Blend Off
HLSLPROGRAM
#pragma target 4.5
#pragma only_renderers d3d11 ps4 metal // TEMP: until we go further in dev
// #pragma enable_d3d11_debug_symbols
#pragma vertex Vert
#pragma fragment Frag
#include "../../../../ShaderLibrary/Common.hlsl"
#include "../../../ShaderConfig.cs.hlsl"
#include "../../../ShaderVariables.hlsl"
#include "../../../Lighting/LightDefinition.cs.hlsl"
struct Attributes
{
uint vertexID : SV_VertexID;
};
struct Varyings
{
float4 positionCS : SV_Position;
};
Varyings Vert(Attributes input)
{
Varyings output;
output.positionCS = GetFullScreenTriangleVertexPosition(input.vertexID);
return output;
}
// Should use HiS and therefore be faster than a GPU memcpy().
float4 Frag(Varyings input) : SV_Target // use SV_StencilRef in D3D 11.3+
{
return float4(STENCILLIGHTINGUSAGE_SPLIT_LIGHTING, 0, 0, 0);
}
ENDHLSL
}
}
Fallback Off
}

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/Resources/CopyStencilBuffer.shader.meta


fileFormatVersion: 2
guid: 7fd941b2d9d2a39429de64bde023932c
timeCreated: 1499946987
licenseType: Pro
ShaderImporter:
externalObjects: {}
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Material/Lit/SSSProfile/Resources.meta


fileFormatVersion: 2
guid: 59a5ca19094a8c64099eded20685322f
folderAsset: yes
timeCreated: 1500627638
licenseType: Pro
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

10
Assets/ScriptableRenderPipeline/HDRenderPipeline/Resources.meta


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

9
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl.meta


fileFormatVersion: 2
guid: 0ef495ee49d152b419e9fd62aa24523f
timeCreated: 1489679489
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

39
Assets/ScriptableRenderPipeline/HDRenderPipeline/Lighting/TilePass/FeatureFlags.hlsl


#ifndef __FEATURE_FLAGS_H__
#define __FEATURE_FLAGS_H__
static const uint FeatureVariantFlags[NUM_FEATURE_VARIANTS] =
{
/* 0 */ 0 | MATERIALFEATUREFLAGS_MASK, // TODO: ask Runes if this is really needed ? In case of material only, it mean debug and we don't care about performance
/* 1 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 2 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 3 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 5 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 6 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 7 */ LIGHTFEATUREFLAGS_MASK | MATERIALFEATUREFLAGS_LIT_STANDARD,
/* 8 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | MATERIALFEATUREFLAGS_MASK,
/* 9 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_MASK,
/* 10 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | MATERIALFEATUREFLAGS_MASK,
/* 11 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_MASK,
/* 12 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | MATERIALFEATUREFLAGS_MASK,
/* 13 */ LIGHTFEATUREFLAGS_SKY | LIGHTFEATUREFLAGS_DIRECTIONAL | LIGHTFEATUREFLAGS_AREA | LIGHTFEATUREFLAGS_PUNCTUAL | LIGHTFEATUREFLAGS_ENV | MATERIALFEATUREFLAGS_MASK,
/* 14 */ LIGHTFEATUREFLAGS_MASK | MATERIALFEATUREFLAGS_MASK,
/* 15 */ 0xFFFFFFFF // shouldn't be needed
};
uint FeatureFlagsToTileVariant(uint featureFlags)
{
for(int i = 0; i < NUM_FEATURE_VARIANTS; i++)
{
if((featureFlags & FeatureVariantFlags[i]) == featureFlags)
return i;
}
return NUM_FEATURE_VARIANTS - 1;
}
uint TileVariantToFeatureFlags(uint variant)
{
return FeatureVariantFlags[variant];
}
#endif
正在加载...
取消
保存