浏览代码

Merge branch 'master' of https://github.com/Unity-Technologies/ScriptableRenderLoop

# Conflicts:
#	Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
/main
Julien Ignace 8 年前
当前提交
442892e0
共有 34 个文件被更改,包括 2754 次插入339 次删除
  1. 10
      Assets/ScriptableRenderLoop/AdditionalLightData.cs
  2. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta
  3. 182
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  4. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs
  5. 36
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl
  6. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.cs
  7. 49
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.hlsl
  8. 10
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild.compute
  9. 413
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs
  10. 21
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs.hlsl
  11. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/LayeredLit/LayeredLit.shader
  12. 81
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Editor/LitUI.cs
  13. 192
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  14. 29
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.shader
  15. 60
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/LitData.hlsl
  16. 4
      Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs
  17. 32
      Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl
  18. 20
      Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl
  19. 18
      Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl
  20. 3
      Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl
  21. 8
      Assets/ScriptableRenderLoop/fptl/FptlLighting.cs
  22. 702
      Assets/TestScenes/HDTest/HDRenderLoopTest.unity
  23. 2
      ProjectSettings/ProjectVersion.txt
  24. 90
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ClusteredUtils.hlsl
  25. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ClusteredUtils.hlsl.meta
  26. 267
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute
  27. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute.meta
  28. 553
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-clustered.compute
  29. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-clustered.compute.meta
  30. 30
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ShaderBase.hlsl
  31. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ShaderBase.hlsl.meta
  32. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Shaders.meta
  33. 192
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/test details.mat
  34. 8
      Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/test details.mat.meta

10
Assets/ScriptableRenderLoop/AdditionalLightData.cs


namespace UnityEngine.Experimental.ScriptableRenderLoop
{
//@TODO: We should continously move these values
public enum LightArchetype {Punctual, Rectangle, Line};
//@TODO: We should continuously move these values
public const int DefaultShadowResolution = 512;
public int shadowResolution = DefaultShadowResolution;

public bool affectDiffuse = true;
public bool affectSpecular = true;
// Area Light Hack
public bool treatAsAreaLight = false;
public bool isDoubleSided = false;
public LightArchetype archetype = LightArchetype.Punctual;
public bool isDoubleSided = false;
[RangeAttribute(0.0f, 20.0f)]
public float areaLightLength = 0.0f;

2
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta


fileFormatVersion: 2
guid: 2400b74f5ce370c4481e5dc417d03703
timeCreated: 1479345431
timeCreated: 1479691644
licenseType: Pro
NativeFormatImporter:
userData:

182
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


UnityEditor.AssetDatabase.CreateAsset(instance, k_HDRenderLoopPath);
}
[UnityEditor.MenuItem("HDRenderLoop/Add \"Additional Light Data\" (if not present)")]
static void AddAdditionalLightData()
{
Light[] lights = FindObjectsOfType(typeof(Light)) as Light[];
foreach (Light light in lights)
{
// Do not add a component if there already is one.
if (light.GetComponent<AdditionalLightData>() == null)
{
light.gameObject.AddComponent<AdditionalLightData>();
}
}
}
#endif
SkyRenderer m_SkyRenderer = null;

public const int k_MaxAreaLightsOnSCreen = 128;
public const int k_MaxEnvLightsOnSCreen = 64;
public const int k_MaxShadowOnScreen = 16;
public const int k_MaxCascadeCount = 4; //Should be not less than m_Settings.directionalLightCascadeCount;
[SerializeField]
TextureSettings m_TextureSettings = TextureSettings.Default;

Material m_DebugViewMaterialGBuffer;
// Various buffer
int s_CameraColorBuffer;
int s_CameraDepthBuffer;
int s_VelocityBuffer;
int s_DistortionBuffer;
int m_CameraColorBuffer;
int m_CameraDepthBuffer;
int m_VelocityBuffer;
int m_DistortionBuffer;
RenderTargetIdentifier s_CameraColorBufferRT;
RenderTargetIdentifier s_CameraDepthBufferRT;

public class LightList
{
public List<DirectionalLightData> directionalLights;
public List<DirectionalShadowData> directionalShadows;
public List<PunctualShadowData> punctualShadows;
public List<PunctualShadowData> punctualShadows;
public Vector4[] directionalShadowSplitSphereSqr;
// Index mapping list to go from GPU lights (above) to CPU light (in cullResult)
public List<int> directionalCullIndices;
public List<int> punctualCullIndices;
public List<int> areaCullIndices;
public List<int> envCullIndices;
public void Clear()
{
directionalLights.Clear();
directionalShadows.Clear();
punctualLights.Clear();
punctualShadows.Clear();
areaLights.Clear();
envLights.Clear();
directionalCullIndices.Clear();
punctualCullIndices.Clear();
areaCullIndices.Clear();
envCullIndices.Clear();
}
public void Allocate()
{
directionalLights = new List<DirectionalLightData>();
punctualLights = new List<LightData>();
areaLights = new List<LightData>();
envLights = new List<EnvLightData>();
punctualShadows = new List<PunctualShadowData>();
directionalShadows = new List<DirectionalShadowData>();
directionalShadowSplitSphereSqr = new Vector4[k_MaxCascadeCount];
directionalCullIndices = new List<int>();
punctualCullIndices = new List<int>();
areaCullIndices = new List<int>();
envCullIndices = new List<int>();
}
LightList m_lightList;
// Detect when windows size is changing
int m_WidthOnRecord;

SinglePass.LightLoop m_SinglePassLightLoop;
// TilePass.LightLoop m_TilePassLightLoop;
TilePass.LightLoop m_TilePassLightLoop;
// TODO: Find a way to automatically create/iterate through deferred material
Lit.RenderLoop m_LitRenderLoop;

public override void Rebuild()
{
s_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
s_CameraDepthBuffer = Shader.PropertyToID("_CameraDepthTexture");
m_CameraColorBuffer = Shader.PropertyToID("_CameraColorTexture");
m_CameraDepthBuffer = Shader.PropertyToID("_CameraDepthTexture");
s_CameraColorBufferRT = new RenderTargetIdentifier(s_CameraColorBuffer);
s_CameraDepthBufferRT = new RenderTargetIdentifier(s_CameraDepthBuffer);

}
#pragma warning disable 162 // warning CS0162: Unreachable code detected
s_VelocityBuffer = Shader.PropertyToID("_VelocityTexture");
m_VelocityBuffer = Shader.PropertyToID("_VelocityTexture");
if (ShaderConfig.VelocityInGbuffer == 1)
{
// If velocity is in GBuffer then it is in the last RT. Assign a different name to it.

s_VelocityBufferRT = new RenderTargetIdentifier(s_VelocityBuffer);
#pragma warning restore 162
s_DistortionBuffer = Shader.PropertyToID("_DistortionTexture");
m_DistortionBuffer = Shader.PropertyToID("_DistortionTexture");
s_DistortionBufferRT = new RenderTargetIdentifier(s_DistortionBuffer);
m_LitRenderLoop.Rebuild();

// Init various light loop
m_SinglePassLightLoop = new SinglePass.LightLoop();
m_SinglePassLightLoop.Rebuild();
// m_TilePassLightLoop = new TilePass.LightLoop();
// m_TilePassLightLoop.Rebuild();
m_TilePassLightLoop = new TilePass.LightLoop();
m_TilePassLightLoop.Rebuild();
m_lightList = new LightList();
m_lightList.Allocate();
}
void OnDisable()

//m_TilePassLightLoop.OnDisable();
m_TilePassLightLoop.OnDisable();
Utilities.Destroy(m_DeferredMaterial);
Utilities.Destroy(m_FinalPassMaterial);
Utilities.Destroy(m_DebugViewMaterialGBuffer);

int w = camera.pixelWidth;
int h = camera.pixelHeight;
cmd.GetTemporaryRT(s_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
cmd.GetTemporaryRT(s_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
cmd.GetTemporaryRT(m_CameraColorBuffer, w, h, 0, FilterMode.Point, RenderTextureFormat.ARGBHalf, RenderTextureReadWrite.Linear);
cmd.GetTemporaryRT(m_CameraDepthBuffer, w, h, 24, FilterMode.Point, RenderTextureFormat.Depth);
if (!debugParameters.useForwardRenderingOnly)
{
m_gbufferManager.InitGBuffers(w, h, cmd);

{
rendererConfiguration = rendererConfiguration,
sorting = { sortOptions = SortOptions.SortByMaterialThenMesh }
};
};
settings.inputFilter.SetQueuesOpaque();
renderLoop.DrawRenderers(ref settings);
}

if (!debugParameters.useDepthPrepass)
return;
// TODO: Must do opaque then alpha masked for performance!
// TODO: Must do opaque then alpha masked for performance!
// TODO: front to back for opaque and by materal for opaque tested when we split in two
Utilities.SetRenderTarget(renderLoop, s_CameraDepthBufferRT, "Depth Prepass");
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");

void RenderSky(Camera camera, RenderLoop renderLoop)
{
m_SkyRenderer.RenderSky(camera, m_SkyParameters, s_CameraColorBufferRT, s_CameraDepthBufferRT, renderLoop);
}
}
void RenderForward(CullResults cullResults, Camera camera, RenderLoop renderLoop)
{

int h = camera.pixelHeight;
var cmd = new CommandBuffer { name = "Velocity Pass" };
cmd.GetTemporaryRT(s_VelocityBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetVelocityBufferFormat(), Builtin.RenderLoop.GetVelocityBufferReadWrite());
cmd.GetTemporaryRT(m_VelocityBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetVelocityBufferFormat(), Builtin.RenderLoop.GetVelocityBufferReadWrite());
cmd.SetRenderTarget(s_VelocityBufferRT, s_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();

int h = camera.pixelHeight;
var cmd = new CommandBuffer { name = "Distortion Pass" };
cmd.GetTemporaryRT(s_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetDistortionBufferFormat(), Builtin.RenderLoop.GetDistortionBufferReadWrite());
cmd.GetTemporaryRT(m_DistortionBuffer, w, h, 0, FilterMode.Point, Builtin.RenderLoop.GetDistortionBufferFormat(), Builtin.RenderLoop.GetDistortionBufferReadWrite());
cmd.SetRenderTarget(s_DistortionBufferRT, s_CameraDepthBufferRT);
renderLoop.ExecuteCommandBuffer(cmd);
cmd.Dispose();

}
// Function to prepare light structure for GPU lighting
void ConvertLightForGPU(CullResults cullResults, ref ShadowOutput shadowOutput, out LightList lightList)
void PrepareLightsForGPU(CullResults cullResults, Camera camera, ref ShadowOutput shadowOutput, ref LightList lightList)
// Init light list
lightList = new LightList();
lightList.directionalLights = new List<DirectionalLightData>();
lightList.punctualLights = new List<LightData>();
lightList.areaLights = new List<LightData>();
lightList.envLights = new List<EnvLightData>();
lightList.punctualShadows = new List<PunctualShadowData>();
lightList.Clear();
for (int lightIndex = 0, numLights = cullResults.visibleLights.Length; lightIndex < numLights; ++lightIndex)
{

if (light.lightType == LightType.Directional)
{
if (lightList.areaLights.Count >= k_MaxDirectionalLightsOnSCreen)
if (lightList.directionalLights.Count >= k_MaxDirectionalLightsOnSCreen)
continue;
var directionalLightData = new DirectionalLightData();

directionalLightData.sinAngle = 0.0f;
directionalLightData.shadowIndex = -1;
// TODO: shadow
bool hasDirectionalShadows = light.light.shadows != LightShadows.None && shadowOutput.GetShadowSliceCountLightIndex(lightIndex) != 0;
bool hasDirectionalNotReachMaxLimit = lightList.directionalShadows.Count == 0; // Only one cascade shadow allowed
if (hasDirectionalShadows && hasDirectionalNotReachMaxLimit) // Note < MaxShadows should be check at shadowOutput creation
{
// When we have a point light, we assumed that there is 6 consecutive PunctualShadowData
directionalLightData.shadowIndex = 0;
for (int sliceIndex = 0; sliceIndex < shadowOutput.GetShadowSliceCountLightIndex(lightIndex); ++sliceIndex)
{
DirectionalShadowData directionalShadowData = new DirectionalShadowData();
int shadowSliceIndex = shadowOutput.GetShadowSliceIndex(lightIndex, sliceIndex);
directionalShadowData.worldToShadow = shadowOutput.shadowSlices[shadowSliceIndex].shadowTransform.transpose; // Transpose for hlsl reading ?
directionalShadowData.bias = light.light.shadowBias;
lightList.directionalShadows.Add(directionalShadowData);
}
// Fill split information for shaders
for (int s = 0; s < k_MaxCascadeCount; ++s)
{
lightList.directionalShadowSplitSphereSqr[s] = shadowOutput.directionalShadowSplitSphereSqr[s];
}
}
lightList.directionalCullIndices.Add(lightIndex);
continue;
}

// Early out if we reach the maximum
if (additionalData.treatAsAreaLight)
if (additionalData.archetype != LightArchetype.Punctual)
// Early out if we reach the maximum
if (additionalData.archetype == LightArchetype.Rectangle)
{
}
else
{
lightData.lightType = GPULightType.Line;
}
}
else
{

lightData.size = new Vector2(additionalData.areaLightLength, additionalData.areaLightWidth);
lightData.twoSided = additionalData.isDoubleSided;
if (additionalData.treatAsAreaLight)
if (additionalData.archetype == LightArchetype.Punctual)
lightList.areaLights.Add(lightData);
lightList.punctualLights.Add(lightData);
lightList.punctualCullIndices.Add(lightIndex);
lightList.punctualLights.Add(lightData);
// Area and line lights are both currently stored as area lights on the GPU.
lightList.areaLights.Add(lightData);
lightList.areaCullIndices.Add(lightIndex);
}
}

envLightData.offsetLS = probe.center; // center is misnamed, it is the offset (in local space) from center of the bounding box to the cubemap capture point
envLightData.blendDistance = blendDistance;
lightList.envLights.Add(envLightData);
lightList.envCullIndices.Add(probeIndex);
// build per tile light lists
m_SinglePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
m_TilePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
{ /*
{
if (camera.pixelWidth != m_WidthOnRecord || camera.pixelHeight != m_HeightOnRecord || m_TilePassLightLoop.NeedResize())
{
if (m_WidthOnRecord > 0 && m_HeightOnRecord > 0)

m_WidthOnRecord = camera.pixelWidth;
m_HeightOnRecord = camera.pixelHeight;
}
*/
}
public void PushGlobalParams(Camera camera, RenderLoop renderLoop, HDRenderLoop.LightList lightList)

Shader.SetGlobalTexture("_EnvTextures", m_CubeReflTexArray.GetTexCache());
m_SinglePassLightLoop.PushGlobalParams(camera, renderLoop, lightList);
// m_TilePassLightLoop.PushGlobalParams(camera, renderLoop, lightList);
m_TilePassLightLoop.PushGlobalParams(camera, renderLoop, lightList);
}
public override void Render(Camera[] cameras, RenderLoop renderLoop)

renderLoop.SetupCameraProperties(camera); // Need to recall SetupCameraProperties after m_ShadowPass.Render
LightList lightList;
ConvertLightForGPU(cullResults, ref shadows, out lightList);
PushGlobalParams(camera, renderLoop, lightList);
PrepareLightsForGPU(cullResults, camera, ref shadows, ref m_lightList);
m_TilePassLightLoop.BuildGPULightLists(camera, renderLoop, m_lightList, m_CameraDepthBuffer);
PushGlobalParams(camera, renderLoop, m_lightList);
// build per tile light lists
//var numLights = 0; // GenerateSourceLightBuffers(camera, cullResults);
//m_tilePassLightLoop.BuildPerTileLightLists(camera, loop, numLights, projscr, invProjscr);
RenderDeferredLighting(camera, renderLoop);

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


public int IESIndex;
public int cookieIndex;
public GPULightType lightType;
public GPULightType lightType;
// Area Light specific
public Vector2 size;
public bool twoSided;

public float cosAngle; // Distance to disk
public float sinAngle; // Disk radius
public int shadowIndex;
public float unsued;
public float unused;
};

public float bias;
public float quality;
public float unused;
};
[GenerateHLSL]
public struct DirectionalShadowData
{
// World to ShadowMap matrix
// Include scale and bias for shadow atlas if any
public Matrix4x4 worldToShadow;
public float bias;
public float quality;
public Vector2 unused2;
};
[GenerateHLSL]

36
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl


float cosAngle;
float sinAngle;
int shadowIndex;
float unsued;
float unused;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.PunctualShadowData

float bias;
float quality;
float unused;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.DirectionalShadowData
// PackingRules = Exact
struct DirectionalShadowData
{
float4x4 worldToShadow;
float bias;
float quality;
float2 unused2;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.EnvLightData

{
return value.shadowIndex;
}
float GetUnsued(DirectionalLightData value)
float GetUnused(DirectionalLightData value)
return value.unsued;
return value.unused;
}
//

float GetUnused(PunctualShadowData value)
{
return value.unused;
}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.DirectionalShadowData
//
float4x4 GetWorldToShadow(DirectionalShadowData value)
{
return value.worldToShadow;
}
float GetBias(DirectionalShadowData value)
{
return value.bias;
}
float GetQuality(DirectionalShadowData value)
{
return value.quality;
}
float2 GetUnused2(DirectionalShadowData value)
{
return value.unused2;
}
//

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


static ComputeBuffer s_EnvLightList;
static ComputeBuffer s_AreaLightList;
static ComputeBuffer s_PunctualShadowList;
static ComputeBuffer s_DirectionalShadowList;
if (s_DirectionalShadowList != null)
s_DirectionalShadowList.Release();
if (s_PunctualLightList != null)
s_PunctualLightList.Release();

ClearComputeBuffers();
s_DirectionalLights = new ComputeBuffer(HDRenderLoop.k_MaxDirectionalLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DirectionalLightData)));
s_DirectionalShadowList = new ComputeBuffer(HDRenderLoop.k_MaxCascadeCount, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DirectionalShadowData)));
s_PunctualLightList = new ComputeBuffer(HDRenderLoop.k_MaxPunctualLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_AreaLightList = new ComputeBuffer(HDRenderLoop.k_MaxAreaLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(LightData)));
s_EnvLightList = new ComputeBuffer(HDRenderLoop.k_MaxEnvLightsOnSCreen, System.Runtime.InteropServices.Marshal.SizeOf(typeof(EnvLightData)));

{
s_DirectionalLights.Release();
s_DirectionalLights = null;
s_DirectionalShadowList.Release();
s_DirectionalShadowList = null;
s_PunctualLightList.Release();
s_PunctualLightList = null;
s_AreaLightList.Release();

s_PunctualShadowList = null;
}
public void PrepareLightsForGPU(CullResults cullResults, Camera camera, HDRenderLoop.LightList lightList) {}
s_DirectionalShadowList.SetData(lightList.directionalShadows.ToArray());
s_PunctualLightList.SetData(lightList.punctualLights.ToArray());
s_AreaLightList.SetData(lightList.areaLights.ToArray());
s_EnvLightList.SetData(lightList.envLights.ToArray());

Shader.SetGlobalInt("_DirectionalLightCount", lightList.directionalLights.Count);
Shader.SetGlobalBuffer("_DirectionalShadowList", s_DirectionalShadowList);
Shader.SetGlobalBuffer("_PunctualLightList", s_PunctualLightList);
Shader.SetGlobalInt("_PunctualLightCount", lightList.punctualLights.Count);
Shader.SetGlobalBuffer("_AreaLightList", s_AreaLightList);

Shader.SetGlobalInt("_EnvLightCount", lightList.envLights.Count);
Shader.SetGlobalInt("_EnvLightCount", lightList.envLights.Count);
Shader.SetGlobalVectorArray("_DirShadowSplitSpheres", lightList.directionalShadowSplitSphereSqr);
}
}
}

49
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.hlsl


StructuredBuffer<DirectionalLightData> _DirectionalLightList;
StructuredBuffer<DirectionalShadowData> _DirectionalShadowList;
StructuredBuffer<PunctualShadowData> _PunctualShadowList;
StructuredBuffer<PunctualShadowData> _PunctualShadowList;
//TEXTURE2D_ARRAY(_ShadowArray);
//SAMPLER2D_SHADOW(sampler_ShadowArray);

int _EnvLightCount;
EnvLightData _EnvLightSky;
float4 _ShadowMapSize;
float4 _DirShadowSplitSpheres[4]; // TODO share this max between C# and hlsl
CBUFFER_END
struct LightLoopContext

// float3 shadowPosDY = ddy_fine(positionTXS);
return SAMPLE_TEXTURE2D_SHADOW(g_tShadowBuffer, samplerg_tShadowBuffer, positionTXS);
}
// Gets the cascade weights based on the world position of the fragment and the positions of the split spheres for each cascade.
// Returns an invalid split index if past shadowDistance (ie 4 is invalid for cascade)
uint GetSplitSphereIndexForDirshadows(float3 positionWS, float4 dirShadowSplitSpheres[4])
{
float3 fromCenter0 = positionWS.xyz - dirShadowSplitSpheres[0].xyz;
float3 fromCenter1 = positionWS.xyz - dirShadowSplitSpheres[1].xyz;
float3 fromCenter2 = positionWS.xyz - dirShadowSplitSpheres[2].xyz;
float3 fromCenter3 = positionWS.xyz - dirShadowSplitSpheres[3].xyz;
float4 distances2 = float4(dot(fromCenter0, fromCenter0), dot(fromCenter1, fromCenter1), dot(fromCenter2, fromCenter2), dot(fromCenter3, fromCenter3));
float4 dirShadowSplitSphereSqRadii;
dirShadowSplitSphereSqRadii.x = dirShadowSplitSpheres[0].w;
dirShadowSplitSphereSqRadii.y = dirShadowSplitSpheres[1].w;
dirShadowSplitSphereSqRadii.z = dirShadowSplitSpheres[2].w;
dirShadowSplitSphereSqRadii.w = dirShadowSplitSpheres[3].w;
float4 weights = float4(distances2 < dirShadowSplitSphereSqRadii);
weights.yzw = saturate(weights.yzw - weights.xyz);
return uint(4.0 - dot(weights, float4(4.0, 3.0, 2.0, 1.0)));
}
float GetDirectionalShadowAttenuation(LightLoopContext lightLoopContext, float3 positionWS, int index, float3 L, float2 unPositionSS)
{
// Note Index is 0 for now, but else we need to provide the correct index in _DirShadowSplitSpheres and _DirectionalShadowList
uint shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _DirShadowSplitSpheres);
DirectionalShadowData shadowData = _DirectionalShadowList[shadowSplitIndex];
// Note: scale and bias of shadow atlas are included in ShadowTransform but could be apply here.
float4 positionTXS = mul(float4(positionWS, 1.0), shadowData.worldToShadow);
positionTXS.xyz /= positionTXS.w;
// positionTXS.z -= shadowData.bias; // Apply a linear bias
positionTXS.z -= 0.003;
#if UNITY_REVERSED_Z
positionTXS.z = 1.0 - positionTXS.z;
#endif
// float3 shadowPosDX = ddx_fine(positionTXS);
// float3 shadowPosDY = ddy_fine(positionTXS);
return SAMPLE_TEXTURE2D_SHADOW(g_tShadowBuffer, samplerg_tShadowBuffer, positionTXS);
}
//-----------------------------------------------------------------------------

10
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild.compute


#pragma kernel TileLightListGen LIGHTLISTGEN=TileLightListGen
#pragma kernel TileLightListGen_SrcBigTile LIGHTLISTGEN=TileLightListGen_SrcBigTile USE_TWO_PASS_TILED_LIGHTING
float FetchDepth(Texture2D depthTexture, uint2 pixCoord)
{
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0)).x;
}
#include "../ShaderBase.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#include "../SortingComputeUtils.hlsl"
#endif

while(l<iNrCoarseLights && uLgtType==SPOT_LIGHT)
{
SFiniteLightData lightData = g_vLightData[idxCoarse];
const bool bIsSpotDisc = (lightData.flags&IS_CIRCULAR_SPOT_SHAPE)!=0;
// TODO: Change by SebL
const bool bIsSpotDisc = true; // (lightData.flags&IS_CIRCULAR_SPOT_SHAPE) != 0;
// serially check 4 pixels
uint uVal = 0;

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


using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.Rendering;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop

public struct SFiniteLightData
{
public Vector3 lightPos;
public int flags;
public Vector3 lightAxisX;
public uint lightType;

public Vector3 lightAxisZ; // spot +Z axis
public float cotan;
public Vector3 color;
public uint lightModel; // DIRECT_LIGHT=0, REFLECTION_LIGHT=1
public float unusued;
public uint lightModel; // DIRECT_LIGHT=0, REFLECTION_LIGHT=1
public Vector3 boxInvRange;
public float unused2;

return "LIGHTLOOP_SINGLE_PASS";
}
/*
public const int MaxNumLights = HDRenderLoop.k_MaxPunctualLightsOnSCreen + HDRenderLoop.k_MaxAreaLightsOnSCreen + HDRenderLoop.k_MaxEnvLightsOnSCreen;
public const int MaxNumLights = 1024;
ComputeShader buildScreenAABBShader;
ComputeShader buildPerTileLightListShader; // FPTL
ComputeShader buildPerBigTileLightListShader;
ComputeShader buildPerVoxelLightListShader; // clustered
static ComputeShader buildScreenAABBShader;
static ComputeShader buildPerTileLightListShader; // FPTL
static ComputeShader buildPerBigTileLightListShader;
static ComputeShader buildPerVoxelLightListShader; // clustered
private static int s_GenAABBKernel;
private static int s_GenListPerTileKernel;

private static ComputeBuffer s_ConvexBoundsBuffer;
private static ComputeBuffer s_AABBBoundsBuffer;
private static ComputeBuffer s_LightList;
private static ComputeBuffer s_DirLightList;
private static ComputeBuffer s_BigTileLightList; // used for pre-pass coarse culling on 64x64 tiles
private static int s_GenListPerBigTileKernel;

public bool disableFptlWhenClustered = false; // still useful on opaques
public bool enableBigTilePrepass = true;
public bool enableBigTilePrepass = false; // SebL - TODO: I get a crash when enabling this
public bool enableDrawLightBoundsDebug = false;
public bool enableDrawTileDebug = false;
public bool enableComputeLightEvaluation = false;

// clustered light list specific buffers and data end
const int k_TileSize = 16;
*/
SFiniteLightBound[] m_boundData;
SFiniteLightData[] m_lightData;
int m_lightCount;
/*
*/
return true;
}
}

/*
ReleaseResolutionDependentBuffers();
if (s_AABBBoundsBuffer != null)

if (s_LightDataBuffer != null)
s_LightDataBuffer.Release();
if (s_DirLightList != null)
s_DirLightList.Release();
*/
/*
ClearComputeBuffers();
buildScreenAABBShader = Resources.Load<ComputeShader>("scrbound");

s_AABBBoundsBuffer = new ComputeBuffer(2 * MaxNumLights, 3 * sizeof(float));
s_ConvexBoundsBuffer = new ComputeBuffer(MaxNumLights, System.Runtime.InteropServices.Marshal.SizeOf(typeof(SFiniteLightBound)));
s_LightDataBuffer = new ComputeBuffer(MaxNumLights, System.Runtime.InteropServices.Marshal.SizeOf(typeof(SFiniteLightData)));
s_DirLightList = new ComputeBuffer(MaxNumDirLights, System.Runtime.InteropServices.Marshal.SizeOf(typeof(DirectionalLight)));
buildScreenAABBShader.SetBuffer(s_GenAABBKernel, "g_data", s_ConvexBoundsBuffer);
buildPerTileLightListShader.SetBuffer(s_GenListPerTileKernel, "g_vBoundsBuffer", s_AABBBoundsBuffer);
buildPerTileLightListShader.SetBuffer(s_GenListPerTileKernel, "g_vLightData", s_LightDataBuffer);

s_GlobalLightListAtomic = new ComputeBuffer(1, sizeof(uint));
}
if (enableBigTilePrepass)
{
s_GenListPerBigTileKernel = buildPerBigTileLightListShader.FindKernel("BigTileLightListGen");

}
*/
m_boundData = new SFiniteLightBound[MaxNumLights];
m_lightData = new SFiniteLightData[MaxNumLights];
m_lightCount = 0;
{/*
{
// TODO: do something for Resources.Load<ComputeShader> ?
s_AABBBoundsBuffer.Release();

s_DirLightList.Release();
*/
/*
public bool NeedResize()
{
return s_LightList == null || (s_BigTileLightList == null && enableBigTilePrepass) || (s_PerVoxelLightLists == null && enableClustered);

s_BigTileLightList = new ComputeBuffer(LightDefinitions.MAX_NR_BIGTILE_LIGHTS_PLUSONE * nrBigTiles, sizeof(uint));
}
}
*/
// TEMP: These functions should be implemented C++ side, for now do it in C#
private static void SetMatrixCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4 mat)
{
var data = new float[16];
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[4 * c + r] = mat[r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
private static void SetMatrixArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Matrix4x4[] matArray)
{
int numMatrices = matArray.Length;
var data = new float[numMatrices * 16];
for (int n = 0; n < numMatrices; n++)
for (int c = 0; c < 4; c++)
for (int r = 0; r < 4; r++)
data[16 * n + 4 * c + r] = matArray[n][r, c];
cmd.SetComputeFloatParams(shadercs, name, data);
}
/*
int GenerateSourceLightBuffers(Camera camera, CullResults inputs)
private static void SetVectorArrayCS(CommandBuffer cmd, ComputeShader shadercs, string name, Vector4[] vecArray)
{
int numVectors = vecArray.Length;
var data = new float[numVectors * 4];
for (int n = 0; n < numVectors; n++)
for (int i = 0; i < 4; i++)
data[4 * n + i] = vecArray[n][i];
cmd.SetComputeFloatParams(shadercs, name, data);
}
static Matrix4x4 GetFlipMatrix()
{
Matrix4x4 flip = Matrix4x4.identity;
bool isLeftHand = ((int)LightDefinitions.USE_LEFTHAND_CAMERASPACE) != 0;
if (isLeftHand) flip.SetColumn(2, new Vector4(0.0f, 0.0f, -1.0f, 0.0f));
return flip;
}
static Matrix4x4 WorldToCamera(Camera camera)
{
return GetFlipMatrix() * camera.worldToCameraMatrix;
}
static Matrix4x4 CameraProjection(Camera camera)
var probes = inputs.visibleReflectionProbes;
//ReflectionProbe[] probes = Object.FindObjectsOfType<ReflectionProbe>();
return camera.projectionMatrix * GetFlipMatrix();
}
public void PrepareLightsForGPU(CullResults cullResults, Camera camera, HDRenderLoop.LightList lightList)
{
// Use for first space screen AABB
// Use for the second pass (fine pruning)
// first pass. Figure out how much we have of each and establish offsets
foreach (var cl in inputs.visibleLights)
// TODO manage area lights
foreach (var punctualLight in lightList.punctualLights)
var volType = cl.lightType == LightType.Spot ? LightDefinitions.SPOT_LIGHT : (cl.lightType == LightType.Point ? LightDefinitions.SPHERE_LIGHT : -1);
if (volType >= 0) ++numEntries[LightDefinitions.DIRECT_LIGHT, volType];
var volType = punctualLight.lightType == GPULightType.Spot ? LightDefinitions.SPOT_LIGHT : (punctualLight.lightType == GPULightType.Point ? LightDefinitions.SPHERE_LIGHT : -1);
if (volType >= 0)
++numEntries[LightDefinitions.DIRECT_LIGHT, volType];
foreach (var rl in probes)
// TODO: manage sphere_light
foreach (var envLight in lightList.envLights)
if (rl.texture != null) ++numEntries[LightDefinitions.REFLECTION_LIGHT, volType];
++numEntries[LightDefinitions.REFLECTION_LIGHT, volType];
}
// add decals here too similar to the above

{
offsets[m, 0] = m == 0 ? 0 : (numEntries[m - 1, numVolTypes - 1] + offsets[m - 1, numVolTypes - 1]);
for (var v = 1; v < numVolTypes; v++) offsets[m, v] = numEntries[m, v - 1] + offsets[m, v - 1];
for (var v = 1; v < numVolTypes; v++)
{
offsets[m, v] = numEntries[m, v - 1] + offsets[m, v - 1];
}
var numLights = inputs.visibleLights.Length;
var numProbes = probes.Length;
var numVolumes = numLights + numProbes;
var lightData = new SFiniteLightData[numVolumes];
var boundData = new SFiniteLightBound[numVolumes];
bool isNegDeterminant = Vector3.Dot(worldToView.GetColumn(0), Vector3.Cross(worldToView.GetColumn(1), worldToView.GetColumn(2))) < 0.0f; // 3x3 Determinant.
uint shadowLightIndex = 0;
foreach (var cl in inputs.visibleLights)
for (int lightIndex = 0; lightIndex < lightList.punctualLights.Count; lightIndex++)
var range = cl.range;
LightData punctualLightData = lightList.punctualLights[lightIndex];
VisibleLight light = cullResults.visibleLights[lightList.punctualCullIndices[lightIndex]];
var lightToWorld = cl.localToWorld;
var range = light.range;
var lightToWorld = light.localToWorld;
// Fill bounds
var light = new SFiniteLightData();
var lightData = new SFiniteLightData();
int index = -1;
bound.boxAxisX.Set(1, 0, 0);
bound.boxAxisY.Set(0, 1, 0);
bound.boxAxisZ.Set(0, 0, 1);
bound.scaleXY.Set(1.0f, 1.0f);
bound.radius = range;
light.flags = 0;
light.recipRange = 1.0f / range;
light.color.Set(cl.finalColor.r, cl.finalColor.g, cl.finalColor.b);
light.sliceIndex = 0;
light.lightModel = (uint)LightDefinitions.DIRECT_LIGHT;
light.shadowLightIndex = shadowLightIndex;
shadowLightIndex++;
lightData.lightModel = (uint)LightDefinitions.DIRECT_LIGHT;
var bHasCookie = cl.light.cookie != null;
var bHasShadow = cl.light.shadows != LightShadows.None;
var idxOut = 0;
if (cl.lightType == LightType.Spot)
if (punctualLightData.lightType == GPULightType.Spot || punctualLightData.lightType == GPULightType.ProjectorPyramid)
var isCircularSpot = !bHasCookie;
if (!isCircularSpot) // square spots always have cookie
{
light.sliceIndex = m_CookieTexArray.FetchSlice(cl.light.cookie);
}
Vector3 lightDir = lightToWorld.GetColumn(2); // Z axis in world space
// represents a left hand coordinate system in world space

const float degToRad = (float)(pi / 180.0);
var sa = cl.light.spotAngle;
var sa = light.light.spotAngle;
var cs = Mathf.Cos(0.5f * sa * degToRad);
var si = Mathf.Sin(0.5f * sa * degToRad);

var squeeze = true;//sa < 0.7f * 90.0f; // arb heuristic
var fS = squeeze ? ta : si;
bound.center = worldToView.MultiplyPoint(lightPos + ((0.5f * range) * lightDir)); // use mid point of the spot as the center of the bounding volume for building screen-space AABB for tiled lighting.
light.lightAxisX = vx;
light.lightAxisY = vy;
light.lightAxisZ = vz;
// scale axis to match box or base of pyramid
bound.boxAxisX = (fS * range) * vx;

fAltDx *= range; fAltDy *= range;
var altDist = Mathf.Sqrt(fAltDy * fAltDy + (isCircularSpot ? 1.0f : 2.0f) * fAltDx * fAltDx);
var altDist = Mathf.Sqrt(fAltDy * fAltDy + (punctualLightData.lightType == GPULightType.Spot ? 1.0f : 2.0f) * fAltDx * fAltDx);
// fill up ldata
light.lightType = (uint)LightDefinitions.SPOT_LIGHT;
light.lightPos = worldToView.MultiplyPoint(lightPos);
light.radiusSq = range * range;
light.penumbra = cs;
light.cotan = cota;
light.flags |= (isCircularSpot ? LightDefinitions.IS_CIRCULAR_SPOT_SHAPE : 0);
light.flags |= (bHasCookie ? LightDefinitions.HAS_COOKIE_TEXTURE : 0);
light.flags |= (bHasShadow ? LightDefinitions.HAS_SHADOW : 0);
lightData.lightAxisX = vx;
lightData.lightAxisY = vy;
lightData.lightAxisZ = vz;
lightData.lightType = (uint)LightDefinitions.SPOT_LIGHT;
lightData.lightPos = worldToView.MultiplyPoint(lightPos);
lightData.radiusSq = range * range;
lightData.cotan = cota;
idxOut = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
index = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
else if (cl.lightType == LightType.Point)
else // if (punctualLightData.lightType == GPULightType.Point)
if (bHasCookie)
{
light.sliceIndex = m_CubeCookieTexArray.FetchSlice(cl.light.cookie);
}
bool isNegDeterminant = Vector3.Dot(worldToView.GetColumn(0), Vector3.Cross(worldToView.GetColumn(1), worldToView.GetColumn(2))) < 0.0f; // 3x3 Determinant.
bound.center = worldToView.MultiplyPoint(lightPos);
bound.boxAxisX.Set(range, 0, 0);

Vector3 vz = lightToView.GetColumn(2);
// fill up ldata
light.lightType = (uint)LightDefinitions.SPHERE_LIGHT;
light.lightPos = bound.center;
light.radiusSq = range * range;
light.lightAxisX = vx;
light.lightAxisY = vy;
light.lightAxisZ = vz;
light.flags |= (bHasCookie ? LightDefinitions.HAS_COOKIE_TEXTURE : 0);
light.flags |= (bHasShadow ? LightDefinitions.HAS_SHADOW : 0);
lightData.lightAxisX = vx;
lightData.lightAxisY = vy;
lightData.lightAxisZ = vz;
lightData.lightType = (uint)LightDefinitions.SPHERE_LIGHT;
lightData.lightPos = bound.center;
lightData.radiusSq = range * range;
idxOut = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
}
else
{
//Assert(false);
index = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
// next light
if (cl.lightType == LightType.Spot || cl.lightType == LightType.Point)
{
boundData[idxOut] = bound;
lightData[idxOut] = light;
}
m_boundData[index] = bound;
m_lightData[index] = lightData;
var numLightsOut = offsets[LightDefinitions.DIRECT_LIGHT, numVolTypes - 1] + numEntries[LightDefinitions.DIRECT_LIGHT, numVolTypes - 1];
// probe.m_BlendDistance
// Vector3f extents = 0.5*Abs(probe.m_BoxSize);
// C center of rendered refl box <-- GetComponent (Transform).GetPosition() + m_BoxOffset;
// cube map capture point: GetComponent (Transform).GetPosition()
// shader parameter min and max are C+/-(extents+blendDistance)
foreach (var rl in probes)
for (int envIndex = 0; envIndex < lightList.envLights.Count; envIndex++)
var cubemap = rl.texture;
EnvLightData envLightData = lightList.envLights[envIndex];
VisibleReflectionProbe probe = cullResults.visibleReflectionProbes[lightList.envCullIndices[envIndex]];
// always a box for now
if (cubemap == null)
continue;
var bound = new SFiniteLightBound();
var lightData = new SFiniteLightData();
var bndData = new SFiniteLightBound();
var lgtData = new SFiniteLightData();
var idxOut = 0;
lgtData.flags = 0;
var bnds = rl.bounds;
var boxOffset = rl.center; // reflection volume offset relative to cube map capture point
var blendDistance = rl.blendDistance;
float imp = rl.importance;
var bnds = probe.bounds;
var boxOffset = probe.center; // reflection volume offset relative to cube map capture point
var blendDistance = probe.blendDistance;
var mat = rl.localToWorld;
//Matrix4x4 mat = rl.transform.localToWorldMatrix;
Vector3 cubeCapturePos = mat.GetColumn(3); // cube map capture position in world space
// implicit in CalculateHDRDecodeValues() --> float ints = rl.intensity;
var boxProj = (rl.boxProjection != 0);
var decodeVals = rl.hdr;
//Vector4 decodeVals = rl.CalculateHDRDecodeValues();
var mat = probe.localToWorld;
// C is reflection volume center in world space (NOT same as cube map capture point)
var e = bnds.extents; // 0.5f * Vector3.Max(-boxSizes[p], boxSizes[p]);

//Vector3 posForShaderParam = bnds.center - boxOffset; // gives same as rl.GetComponent<Transform>().position;
var posForShaderParam = cubeCapturePos; // same as commented out line above when rot is identity
var combinedExtent = e + new Vector3(blendDistance, blendDistance, blendDistance);
var combinedExtent = e + new Vector3(blendDistance, blendDistance, blendDistance);
Vector3 vx = mat.GetColumn(0);
Vector3 vy = mat.GetColumn(1);

var Cw = worldToView.MultiplyPoint(C);
if (boxProj) lgtData.flags |= LightDefinitions.IS_BOX_PROJECTED;
bound.center = Cw;
bound.boxAxisX = combinedExtent.x * vx;
bound.boxAxisY = combinedExtent.y * vy;
bound.boxAxisZ = combinedExtent.z * vz;
bound.scaleXY.Set(1.0f, 1.0f);
bound.radius = combinedExtent.magnitude;
lgtData.lightPos = Cw;
lgtData.lightAxisX = vx;
lgtData.lightAxisY = vy;
lgtData.lightAxisZ = vz;
lgtData.localCubeCapturePoint = -boxOffset;
lgtData.probeBlendDistance = blendDistance;
lgtData.lightIntensity = decodeVals.x;
lgtData.decodeExp = decodeVals.y;
lgtData.sliceIndex = m_CubeReflTexArray.FetchSlice(cubemap);
lightData.lightPos = Cw;
lightData.lightAxisX = vx;
lightData.lightAxisY = vy;
lightData.lightAxisZ = vz;
lgtData.boxInnerDist = e;
lgtData.boxInvRange.Set(1.0f / delta.x, 1.0f / delta.y, 1.0f / delta.z);
bndData.center = Cw;
bndData.boxAxisX = combinedExtent.x * vx;
bndData.boxAxisY = combinedExtent.y * vy;
bndData.boxAxisZ = combinedExtent.z * vz;
bndData.scaleXY.Set(1.0f, 1.0f);
bndData.radius = combinedExtent.magnitude;
// fill up ldata
lgtData.lightType = (uint)LightDefinitions.BOX_LIGHT;
lgtData.lightModel = (uint)LightDefinitions.REFLECTION_LIGHT;
lightData.boxInnerDist = e;
lightData.boxInvRange.Set(1.0f / delta.x, 1.0f / delta.y, 1.0f / delta.z);
idxOut = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
boundData[idxOut] = bndData;
lightData[idxOut] = lgtData;
int index = numEntries2nd[i, j] + offsets[i, j]; ++numEntries2nd[i, j];
m_boundData[index] = bound;
var numProbesOut = offsets[LightDefinitions.REFLECTION_LIGHT, numVolTypes - 1] + numEntries[LightDefinitions.REFLECTION_LIGHT, numVolTypes - 1];
// Sanity check
{
}
s_ConvexBoundsBuffer.SetData(boundData);
s_LightDataBuffer.SetData(lightData);
m_lightCount = lightList.punctualLights.Count + lightList.envLights.Count;
s_ConvexBoundsBuffer.SetData(m_boundData); // TODO: check with Vlad what is happening here, do we copy 1024 element always ? Could we setup the size we want to copy ?
}
void VoxelLightListGeneration(CommandBuffer cmd, Camera camera, Matrix4x4 projscr, Matrix4x4 invProjscr, int cameraDepthBuffer)
{
// clear atomic offset index
cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_ClearVoxelAtomicKernel, "g_LayeredSingleIdxBuffer", s_GlobalLightListAtomic);
cmd.DispatchCompute(buildPerVoxelLightListShader, s_ClearVoxelAtomicKernel, 1, 1, 1);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_iNrVisibLights", m_lightCount);
SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mScrProjection", projscr);
SetMatrixCS(cmd, buildPerVoxelLightListShader, "g_mInvScrProjection", invProjscr);
cmd.SetComputeIntParam(buildPerVoxelLightListShader, "g_iLog2NumClusters", k_Log2NumClusters);
//Vector4 v2_near = invProjscr * new Vector4(0.0f, 0.0f, 0.0f, 1.0f);
//Vector4 v2_far = invProjscr * new Vector4(0.0f, 0.0f, 1.0f, 1.0f);
//float nearPlane2 = -(v2_near.z/v2_near.w);
//float farPlane2 = -(v2_far.z/v2_far.w);
var nearPlane = camera.nearClipPlane;
var farPlane = camera.farClipPlane;
cmd.SetComputeFloatParam(buildPerVoxelLightListShader, "g_fNearPlane", nearPlane);
cmd.SetComputeFloatParam(buildPerVoxelLightListShader, "g_fFarPlane", farPlane);
const float C = (float)(1 << k_Log2NumClusters);
var geomSeries = (1.0 - Mathf.Pow(k_ClustLogBase, C)) / (1 - k_ClustLogBase); // geometric series: sum_k=0^{C-1} base^k
m_ClustScale = (float)(geomSeries / (farPlane - nearPlane));
cmd.SetComputeFloatParam(buildPerVoxelLightListShader, "g_fClustScale", m_ClustScale);
cmd.SetComputeFloatParam(buildPerVoxelLightListShader, "g_fClustBase", k_ClustLogBase);
return numLightsOut + numProbesOut;
}
cmd.SetComputeTextureParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_depth_tex", new RenderTargetIdentifier(cameraDepthBuffer));
cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_vLayeredLightList", s_PerVoxelLightLists);
cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_LayeredOffset", s_PerVoxelOffset);
cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_LayeredSingleIdxBuffer", s_GlobalLightListAtomic);
if (enableBigTilePrepass) cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_vBigTileLightList", s_BigTileLightList);
if (k_UseDepthBuffer)
{
cmd.SetComputeBufferParam(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, "g_logBaseBuffer", s_PerTileLogBaseTweak);
}
void BuildPerTileLightLists(Camera camera, RenderLoop loop, int numLights, Matrix4x4 projscr, Matrix4x4 invProjscr)
var numTilesX = (camera.pixelWidth + 15) / 16;
var numTilesY = (camera.pixelHeight + 15) / 16;
cmd.DispatchCompute(buildPerVoxelLightListShader, s_GenListPerVoxelKernel, numTilesX, numTilesY, 1);
}
public void BuildGPULightLists(Camera camera, RenderLoop loop, HDRenderLoop.LightList lightList, int cameraDepthBuffer)
{
var w = camera.pixelWidth;
var h = camera.pixelHeight;

var numBigTilesY = (h + 63) / 64;
// camera to screen matrix (and it's inverse)
var proj = CameraProjection(camera);
var temp = new Matrix4x4();
temp.SetRow(0, new Vector4(0.5f * w, 0.0f, 0.0f, 0.5f * w));
temp.SetRow(1, new Vector4(0.0f, 0.5f * h, 0.0f, 0.5f * h));
temp.SetRow(2, new Vector4(0.0f, 0.0f, 0.5f, 0.5f));
temp.SetRow(3, new Vector4(0.0f, 0.0f, 0.0f, 1.0f));
var projscr = temp * proj;
var invProjscr = projscr.inverse;
var proj = CameraProjection(camera);
var temp = new Matrix4x4();
temp.SetRow(0, new Vector4(1.0f, 0.0f, 0.0f, 0.0f));
temp.SetRow(1, new Vector4(0.0f, 1.0f, 0.0f, 0.0f));
temp.SetRow(2, new Vector4(0.0f, 0.0f, 0.5f, 0.5f));

cmd.SetComputeIntParam(buildScreenAABBShader, "g_iNrVisibLights", numLights);
cmd.SetComputeIntParam(buildScreenAABBShader, "g_iNrVisibLights", m_lightCount);
cmd.DispatchCompute(buildScreenAABBShader, s_GenAABBKernel, (numLights + 7) / 8, 1, 1);
cmd.DispatchCompute(buildScreenAABBShader, s_GenAABBKernel, (m_lightCount + 7) / 8, 1, 1);
}
// enable coarse 2D pass on 64x64 tiles (used for both fptl and clustered).

cmd.SetComputeIntParam(buildPerBigTileLightListShader, "g_iNrVisibLights", numLights);
cmd.SetComputeIntParam(buildPerBigTileLightListShader, "g_iNrVisibLights", m_lightCount);
SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mScrProjection", projscr);
SetMatrixCS(cmd, buildPerBigTileLightListShader, "g_mInvScrProjection", invProjscr);
cmd.SetComputeFloatParam(buildPerBigTileLightListShader, "g_fNearPlane", camera.nearClipPlane);

if (usingFptl) // optimized for opaques only
{
cmd.SetComputeIntParams(buildPerTileLightListShader, "g_viDimensions", new int[2] { w, h });
cmd.SetComputeIntParam(buildPerTileLightListShader, "g_iNrVisibLights", numLights);
cmd.SetComputeIntParam(buildPerTileLightListShader, "g_iNrVisibLights", m_lightCount);
cmd.SetComputeTextureParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_depth_tex", new RenderTargetIdentifier(s_CameraDepthTexture));
cmd.SetComputeTextureParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_depth_tex", new RenderTargetIdentifier(cameraDepthBuffer));
cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_vLightList", s_LightList);
if (enableBigTilePrepass) cmd.SetComputeBufferParam(buildPerTileLightListShader, s_GenListPerTileKernel, "g_vBigTileLightList", s_BigTileLightList);
cmd.DispatchCompute(buildPerTileLightListShader, s_GenListPerTileKernel, numTilesX, numTilesY, 1);

{
VoxelLightListGeneration(cmd, camera, numLights, projscr, invProjscr);
VoxelLightListGeneration(cmd, camera, projscr, invProjscr, cameraDepthBuffer);
*/
}
}
}

21
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs.hlsl


struct SFiniteLightData
{
float3 lightPos;
int flags;
float3 lightAxisX;
uint lightType;
float3 lightAxisY;

float3 color;
uint lightModel;
float unusued;
uint lightModel;
float3 boxInvRange;
float unused2;
};

{
return value.lightPos;
}
int GetFlags(SFiniteLightData value)
{
return value.flags;
}
float3 GetLightAxisX(SFiniteLightData value)
{
return value.lightAxisX;

{
return value.cotan;
}
float3 GetColor(SFiniteLightData value)
float3 GetBoxInnerDist(SFiniteLightData value)
return value.color;
return value.boxInnerDist;
}
float3 GetBoxInnerDist(SFiniteLightData value)
{
return value.boxInnerDist;
}
float GetUnusued(SFiniteLightData value)
{
return value.unusued;
}
float3 GetBoxInvRange(SFiniteLightData value)
{

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


PROP_DECL_TEX2D(_MaskMap);
PROP_DECL_TEX2D(_SpecularOcclusionMap);
PROP_DECL_TEX2D(_NormalMap);
PROP_DECL_TEX2D(_Heightmap);
PROP_DECL_TEX2D(_HeightMap);
PROP_DECL(float, _HeightScale);
PROP_DECL(float, _HeightBias);
PROP_DECL(float3, _EmissiveColor);

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


Parallax,
Displacement,
}
public enum DetailMapMode
{
DetailWithNormal,
DetailWithAOHeight,
}
private static class Styles
{

public static GUIContent uvSetLabel = new GUIContent("UV Set");
public static string detailText = "Inputs Detail";
public static string lightingText = "Inputs Lighting";
public static GUIContent alphaCutoffEnableText = new GUIContent("Alpha Cutoff Enable", "Threshold for alpha cutoff");
public static GUIContent alphaCutoffText = new GUIContent("Alpha Cutoff", "Threshold for alpha cutoff");

public static GUIContent smoothnessMapChannelText = new GUIContent("Smoothness Source", "Smoothness texture and channel");
public static GUIContent emissiveColorModeText = new GUIContent("Emissive Color Usage", "Use emissive color or emissive mask");
public static GUIContent detailMapModeText = new GUIContent("Detail Map with Normal", "Detail Map with AO / Height");
public static string InputsText = "Inputs";

public static GUIContent normalMapText = new GUIContent("Normal Map", "Normal Map (BC5) - DXT5 for test");
public static GUIContent normalMapSpaceText = new GUIContent("Normal/Tangent Map space", "");
public static GUIContent heightMapText = new GUIContent("Height Map", "Height Map");
public static GUIContent heightMapText = new GUIContent("Height Map (R)", "Height Map");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map", "Anisotropy (R)");
public static GUIContent anisotropyMapText = new GUIContent("Anisotropy Map (G)", "Anisotropy");
public static GUIContent detailMapNormalText = new GUIContent("Detail Map A(R) Ny(G) S(B) Nx(A)", "Detail Map");
public static GUIContent detailMapAOHeightText = new GUIContent("Detail Map A(R) AO(G) S(B) H(A)", "Detail Map");
public static GUIContent detailMaskText = new GUIContent("Detail Mask (B)", "Mask for detailMap");
public static GUIContent detailAlbedoScaleText = new GUIContent("Detail AlbedoScale", "Detail Albedo Scale factor");
public static GUIContent detailNormalScaleText = new GUIContent("Detail NormalScale", "Normal Scale factor");
public static GUIContent detailSmoothnessScaleText = new GUIContent("Detail SmoothnessScale", "Smoothness Scale factor");
public static GUIContent detailHeightScaleText = new GUIContent("Detail HeightScale", "Height Scale factor");
public static GUIContent detailAOScaleText = new GUIContent("Detail AOScale", "AO Scale factor");
public static GUIContent emissiveText = new GUIContent("Emissive Color", "Emissive");
public static GUIContent emissiveIntensityText = new GUIContent("Emissive Intensity", "Emissive");

MaterialProperty surfaceType = null;
MaterialProperty blendMode = null;
MaterialProperty UVDetail = null;
MaterialProperty detailMapMode = null;
MaterialProperty baseColor = null;
MaterialProperty baseColorMap = null;

MaterialProperty anisotropy = null;
MaterialProperty anisotropyMap = null;
MaterialProperty heightMapMode = null;
MaterialProperty detailMap = null;
MaterialProperty detailMask = null;
MaterialProperty detailAlbedoScale = null;
MaterialProperty detailNormalScale = null;
MaterialProperty detailSmoothnessScale = null;
MaterialProperty detailHeightScale = null;
MaterialProperty detailAOScale = null;
MaterialProperty emissiveColor = null;
MaterialProperty emissiveColorMap = null;
MaterialProperty emissiveIntensity = null;

protected const string kSurfaceType = "_SurfaceType";
protected const string kBlendMode = "_BlendMode";
protected const string kUVDetail = "_UVDetail";
protected const string kAlphaCutoff = "_AlphaCutoff";
protected const string kAlphaCutoffEnabled = "_AlphaCutoffEnable";
protected const string kDoubleSidedMode = "_DoubleSidedMode";

protected const string kHeightMapMode = "_HeightMapMode";
protected const string kDetailMapMode = "_DetailMapMode";
protected const string kNormalMap = "_NormalMap";
protected const string kMaskMap = "_MaskMap";

protected const string kTangentMap = "_TangentMap";
protected const string kAnisotropyMap = "_AnisotropyMap";
protected const string kDetailMap = "_DetailMap";
protected const string kDetailMask = "_DetailMask";
protected const string kDetailAlbedoScale = "_DetailAlbedoScale";
protected const string kDetailNormalScale = "_DetailNormalScale";
protected const string kDetailSmoothnessScale = "_DetailSmoothnessScale";
protected const string kDetailHeightScale = "_DetailHeightScale";
protected const string kDetailAOScale = "_DetailAOScale";
UVDetail = FindProperty(kUVDetail, props);
alphaCutoff = FindProperty(kAlphaCutoff, props);
alphaCutoffEnable = FindProperty(kAlphaCutoffEnabled, props);
doubleSidedMode = FindProperty(kDoubleSidedMode, props);

heightMapMode = FindProperty(kHeightMapMode, props);
detailMapMode = FindProperty(kDetailMapMode, props);
}
public void FindInputProperties(MaterialProperty[] props)

emissiveColor = FindProperty("_EmissiveColor", props);
emissiveColorMap = FindProperty(kEmissiveColorMap, props);
emissiveIntensity = FindProperty("_EmissiveIntensity", props);
detailMap = FindProperty(kDetailMap, props);
detailMask = FindProperty(kDetailMask, props);
detailAlbedoScale = FindProperty(kDetailAlbedoScale, props);
detailNormalScale = FindProperty(kDetailNormalScale, props);
detailSmoothnessScale = FindProperty(kDetailSmoothnessScale, props);
detailHeightScale = FindProperty(kDetailHeightScale, props);
detailAOScale = FindProperty(kDetailAOScale, props);
}
public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] props)

m_MaterialEditor.ShaderProperty(emissiveColorMode, Styles.emissiveColorModeText.text);
m_MaterialEditor.ShaderProperty(normalMapSpace, Styles.normalMapSpaceText.text);
m_MaterialEditor.ShaderProperty(heightMapMode, Styles.heightMapModeText.text);
m_MaterialEditor.ShaderProperty(detailMapMode, Styles.detailMapModeText.text);
EditorGUI.indentLevel--;
}

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

m_MaterialEditor.TexturePropertySingleLine(Styles.anisotropyMapText, anisotropyMap);
EditorGUILayout.Space();
GUILayout.Label(Styles.detailText, EditorStyles.boldLabel);
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMaskText, detailMask);
m_MaterialEditor.ShaderProperty(UVDetail, Styles.uvSetLabel.text);
if (useDetailMapWithNormal)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMapNormalText, detailMap);
}
else
{
m_MaterialEditor.TexturePropertySingleLine(Styles.detailMapAOHeightText, detailMap);
}
m_MaterialEditor.TextureScaleOffsetProperty(detailMap);
EditorGUI.indentLevel++;
m_MaterialEditor.ShaderProperty(detailAlbedoScale, Styles.detailAlbedoScaleText);
m_MaterialEditor.ShaderProperty(detailNormalScale, Styles.detailNormalScaleText);
m_MaterialEditor.ShaderProperty(detailSmoothnessScale, Styles.detailSmoothnessScaleText);
m_MaterialEditor.ShaderProperty(detailHeightScale, Styles.detailHeightScaleText);
m_MaterialEditor.ShaderProperty(detailAOScale, Styles.detailAOScaleText);
EditorGUI.indentLevel--;
EditorGUILayout.Space();
GUILayout.Label(Styles.lightingText, EditorStyles.boldLabel);
if (!useEmissiveMask)
{
m_MaterialEditor.TexturePropertySingleLine(Styles.emissiveText, emissiveColorMap, emissiveColor);

protected virtual void SetupKeywordsForInputMaps(Material material)
{
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap));
SetKeyword(material, "_NORMALMAP", material.GetTexture(kNormalMap) || material.GetTexture(kDetailMap)); // With details map, we always use a normal map and Unity provide a default (0, 0, 1) normal map for ir
SetKeyword(material, "_MASKMAP", material.GetTexture(kMaskMap));
SetKeyword(material, "_SPECULAROCCLUSIONMAP", material.GetTexture(kspecularOcclusionMap));
SetKeyword(material, "_EMISSIVE_COLOR_MAP", material.GetTexture(kEmissiveColorMap));

SetKeyword(material, "_DETAIL_MAP", material.GetTexture(kDetailMap));
}
protected virtual void SetupEmissionGIFlags(Material material)

SetKeyword(material, "_SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A", ((SmoothnessMapChannel)material.GetFloat(kSmoothnessTextureChannelProp)) == SmoothnessMapChannel.AlbedoAlpha);
SetKeyword(material, "_EMISSIVE_COLOR", ((EmissiveColorMode)material.GetFloat(kEmissiveColorMode)) == EmissiveColorMode.UseEmissiveColor);
SetKeyword(material, "_HEIGHTMAP_AS_DISPLACEMENT", (HeightmapMode)material.GetFloat(kHeightMapMode) == HeightmapMode.Displacement);
SetKeyword(material, "_DETAIL_MAP_WITH_NORMAL", (DetailMapMode)material.GetFloat(kDetailMapMode) == DetailMapMode.DetailWithNormal);
SetupKeywordsForInputMaps(material);
SetupEmissionGIFlags(material);

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


#endif
// Reference Lambert diffuse / GGX Specular for IBL and area lights
#ifdef HAS_LIGHTLOOP // Both reference define below need to be define only if LightLoop is present, else we get a compile error
#endif
// Use Lambert diffuse instead of Disney diffuse
// #define LIT_DIFFUSE_LAMBERT_BRDF
// Use optimization of Precomputing LambdaV

// TODO: I haven't configure this sampler in the code, we should be able to do it (but Unity don't allow it for now...)
// By default Unity provide MIG_MAG_LINEAR_POINT sampler, so it fit with our need.
#ifdef LIT_DISPLAY_REFERENCE_IBL
// When reference mode is enabled, then we need to chose another sampler not related to cubemap code...
SAMPLER2D(sampler_LtcGGXMatrix);
#define SRL_BilinearSampler sampler_LtcGGXMatrix // Used for all textures
#else
#endif
// TODO: This one should be set into a constant Buffer at pass frequency (with _Screensize)
TEXTURE2D(_PreIntegratedFGD);

//-----------------------------------------------------------------------------
// Helper functions/variable specific to this material

[branch] if (lightData.shadowIndex >= 0 && illuminance > 0.0f)
{
float shadowAttenuation = GetPunctualShadowAttenuation(lightLoopContext, positionWS, lightData.shadowIndex, L, preLightData.unPositionSS);
float shadowAttenuation = GetDirectionalShadowAttenuation(lightLoopContext, positionWS, lightData.shadowIndex, L, preLightData.unPositionSS);
illuminance *= shadowAttenuation;
}

float4x4 localToWorld = float4x4(float4(lightData.right, 0.0), float4(lightData.up, 0.0), float4(lightData.forward, 0.0), float4(lightData.positionWS, 1.0));
if (lightData.lightType == GPULIGHTTYPE_SPHERE)
SampleSphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.lightType == GPULIGHTTYPE_HEMISPHERE)
SampleHemisphere(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.lightType == GPULIGHTTYPE_CYLINDER)
SampleCylinder(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (lightData.lightType == GPULIGHTTYPE_RECTANGLE)
SampleRectangle(u, localToWorld, lightData.size.x, lightData.size.y, lightPdf, P, Ns);
else if (lightData.lightType == GPULIGHTTYPE_DISK)
SampleDisk(u, localToWorld, lightData.size.x, lightPdf, P, Ns);
else if (lightData.lightType == GPULIGHTTYPE_LINE)
// SampleLine(u, localToWorld, areaLight.lightRadius0, lightPdf, P, Ns);
; // TODO
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;

}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area
// EvaluateBSDFLine - Reference
//-----------------------------------------------------------------------------
void IntegrateBSDFLineRef(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 dir = lightData.right;
const float3 p1 = lightData.positionWS - lightData.right * (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 * dir;
float3 unL = sPos - positionWS;
float dist2 = dot(unL, unL);
float3 L = normalize(unL);
float sinLD = length(cross(L, dir));
float NdotL = saturate(dot(bsdfData.normalWS, L));
float3 lightDiff, lightSpec;
BSDF(V, L, positionWS, preLightData, bsdfData, lightDiff, lightSpec);
diffuseLighting += lightDiff * (sinLD / dist2 * NdotL);
specularLighting += lightSpec * (sinLD / 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_Line | Approximation with Linearly Transformed Cosines
//-----------------------------------------------------------------------------
void EvaluateBSDF_Line( LightLoopContext lightLoopContext,
float3 V, float3 positionWS, PreLightData preLightData,
LightData lightData, BSDFData bsdfData,
out float3 diffuseLighting, out float3 specularLighting)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
float len = lightData.size.x;
float3 dir = lightData.right;
// TODO: precompute half-length. Same as for LTC area lights.
// In fact, why not store both endpoints? Saves us 7 cycles.
float3 p1 = lightData.positionWS - lightData.right * (0.5 * len);
float3 p2 = lightData.positionWS + lightData.right * (0.5 * len);
// Translate both points s.t. the shaded point is at the origin of the coordinate system.
p1 -= positionWS;
p2 -= positionWS;
// Construct an orthonormal basis (local coordinate system) around N.
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
float3x3 basis;
basis[0] = normalize(V - bsdfData.normalWS * preLightData.NdotV);
basis[1] = normalize(cross(bsdfData.normalWS, basis[0]));
basis[2] = bsdfData.normalWS;
// Transform (rotate) both endpoints into the local coordinate system (left-handed).
p1 = mul(p1, transpose(basis));
p2 = mul(p2, transpose(basis));
// Terminate the algorithm if both points are below the horizon.
if (p1.z <= 0.0 && p2.z <= 0.0) return;
if (p2.z <= 0.0)
{
// Convention: 'p2' is above the horizon.
swap(p1, p2);
dir = -dir;
}
// Clip the part of the light below the horizon.
if (p1.z <= 0.0)
{
// p = p1 + t * dir; p.z == 0.
float t = -p1.z / dir.z;
p1 = float3(p1.xy + t * dir.xy, 0.0);
// Set the length of the visible part of the light.
len -= t;
}
// Compute the direction to the point on the line orthogonal to 'dir'.
// Its length is the shortest distance to the line.
float3 p0 = p1 - dot(p1, dir) * dir;
float dist = length(p0);
// Compute the parameterization: distances from 'l1' and 'l2' to 'l0'.
float l1 = dot(p1 - p0, dir);
float l2 = l1 + len;
// Integrate the clamped cosine over the line segment.
float irradiance = LineIrradiance(l1, l2, dist, p0.z, dir.z);
// Only Lambertian for now. TODO: Disney Diffuse and GGX.
diffuseLighting = (lightData.diffuseScale * irradiance * INV_PI) * bsdfData.diffuseColor * lightData.color;
}
//-----------------------------------------------------------------------------
// EvaluateBSDF_Area | Approximation with Linearly Transformed Cosines
//-----------------------------------------------------------------------------
void EvaluateBSDF_Area( LightLoopContext lightLoopContext,

{
#ifdef LIT_DISPLAY_REFERENCE_AREA
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
if (lightData.lightType == GPULIGHTTYPE_LINE)
{
IntegrateBSDFLineRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
}
else
{
IntegrateGGXAreaRef(V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
}
if (lightData.lightType == GPULIGHTTYPE_LINE)
{
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
// EvaluateBSDF_Line(lightLoopContext, V, positionWS, preLightData, lightData, bsdfData, diffuseLighting, specularLighting);
return;
}
// TODO: store 4 points and save 24 cycles.
float3 p0 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * halfHeight;
float3 p1 = lightData.positionWS + lightData.right * -halfWidth + lightData.up * -halfHeight;
float3 p2 = lightData.positionWS + lightData.right * halfWidth + lightData.up * -halfHeight;

0.0, 1.0, 0.0,
0.0, 0.0, 1.0};
ltcValue = LTCEvaluate(V, bsdfData.normalWS, identity3x3, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
identity3x3);
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.ltcXformDisneyDiffuse, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformDisneyDiffuse);
#endif
if (ltcValue == 0.0)

float3 fresnelTerm = bsdfData.fresnel0 * preLightData.ltcGGXFresnelMagnitudeDiff
+ (float3)preLightData.ltcGGXFresnelMagnitude;
ltcValue = LTCEvaluate(V, bsdfData.normalWS, preLightData.ltcXformGGX, L, lightData.twoSided);
ltcValue = LTCEvaluate(L, V, bsdfData.normalWS, preLightData.NdotV, lightData.twoSided,
preLightData.ltcXformGGX);
ltcValue *= lightData.specularScale;
specularLighting = fresnelTerm * lightData.color * ltcValue;
}

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


_Anisotropy("Anisotropy", Range(0.0, 1.0)) = 0
_AnisotropyMap("AnisotropyMap", 2D) = "white" {}
_DetailMap("DetailMap", 2D) = "black" {}
_DetailMask("DetailMask", 2D) = "white" {}
_DetailAlbedoScale("_DetailAlbedoScale", Range(-2.0, 2.0)) = 1
_DetailNormalScale("_DetailNormalScale", Range(0.0, 2.0)) = 1
_DetailSmoothnessScale("_DetailSmoothnessScale", Range(-2.0, 2.0)) = 1
_DetailHeightScale("_DetailHeightScale", Range(-2.0, 2.0)) = 1
_DetailAOScale("_DetailAOScale", Range(-2.0, 2.0)) = 1
[Enum(UV0, 0, UV1, 1)] _UVDetail("UV Set for detailMap", Float) = 0
_SubSurfaceRadius("SubSurfaceRadius", Range(0.0, 1.0)) = 0
_SubSurfaceRadiusMap("SubSurfaceRadiusMap", 2D) = "white" {}
//_Thickness("Thickness", Range(0.0, 1.0)) = 0

[Enum(Mask Alpha, 0, BaseColor Alpha, 1)] _SmoothnessTextureChannel("Smoothness texture channel", Float) = 1
[Enum(Use Emissive Color, 0, Use Emissive Mask, 1)] _EmissiveColorMode("Emissive color mode", Float) = 1
[Enum(None, 0, DoubleSided, 1, DoubleSidedLigthingFlip, 2, DoubleSidedLigthingMirror, 3)] _DoubleSidedMode("Double sided mode", Float) = 0
[Enum(DetailMapNormal, 0, DetailMapAOHeight, 1)] _DetailMapMode("DetailMap mode", Float) = 0
}
HLSLINCLUDE

#pragma shader_feature _HEIGHTMAP_AS_DISPLACEMENT
#pragma shader_feature _TANGENTMAP
#pragma shader_feature _ANISOTROPYMAP
#pragma shader_feature _DETAIL_MAP
#pragma shader_feature _DETAIL_MAP_WITH_NORMAL
#pragma multi_compile LIGHTMAP_OFF LIGHTMAP_ON
#pragma multi_compile DIRLIGHTMAP_OFF DIRLIGHTMAP_COMBINED

TEXTURE2D(_NormalMap);
SAMPLER2D(sampler_NormalMap);
TEXTURE2D(_Heightmap);
SAMPLER2D(sampler_Heightmap);
TEXTURE2D(_DetailMask);
SAMPLER2D(sampler_DetailMask);
TEXTURE2D(_DetailMap);
SAMPLER2D(sampler_DetailMap);
float4 _DetailMap_ST;
float _UVDetail;
float _DetailAlbedoScale;
float _DetailNormalScale;
float _DetailSmoothnessScale;
float _DetailHeightScale;
float _DetailAOScale;
TEXTURE2D(_HeightMap);
SAMPLER2D(sampler_HeightMap);
float _HeightScale;
float _HeightBias;

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


return float2(0.0, 0.0);
#endif
}
float3 LerpWhiteTo(float3 b, float t)
{
float oneMinusT = 1.0 - t;
return float3(oneMinusT, oneMinusT, oneMinusT) + b * t;
}
// Transforms 2D UV by scale/bias property
#define TRANSFORM_TEX(tex,name) ((tex.xy) * name##_ST.xy + name##_ST.zw)
#if !defined(LAYERED_LIT_SHADER)

float3 V = GetWorldSpaceNormalizeViewDir(input.positionWS); // This should be remove by the compiler as we usually cal it before.
float height = SAMPLE_TEXTURE2D(_HeightMap, sampler_HeightMap, input.texCoord0).r * _HeightScale + _HeightBias;
// Transform view vector in tangent space
TransformWorldToTangent(V, input.tangentToWorld);
float3 viewDirTS = TransformWorldToTangent(V, input.tangentToWorld);
float2 offset = ParallaxOffset(viewDirTS, height);
input.texCoord0 += offset;
input.texCoord1 += offset;

#ifdef _DETAIL_MAP
float2 texCoordDetail = TRANSFORM_TEX(_UVDetail ? input.texCoord1 : input.texCoord0, _DetailMap);
float detailMask = SAMPLE_TEXTURE2D(_DetailMask, sampler_DetailMask, input.texCoord0).b;
float4 detail = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail);
float detailAlbedo = detail.r;
float detailSmoothness = detail.b;
#ifdef _DETAIL_MAP_WITH_NORMAL
float3 detailNormalTS = UnpackNormalAG(detail, _DetailNormalScale);
//float detailAO = 0.0;
#else
// TODO: Use heightmap as a derivative with Morten Mikklesen approach
// Or reconstruct
float U = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0.005, 0)).a;
float V = SAMPLE_TEXTURE2D(_DetailMap, sampler_DetailMap, texCoordDetail + float2(0, 0.005)).a;
float dHdU = U - detail.a; //create bump map U offset
float dHdV = V - detail.a; //create bump map V offset
//float3 detailNormal = 1 - float3(dHdU, dHdV, 0.05); //create the tangent space normal
float3 detailNormalTS = float3(0.0, 0.0, 1.0);
//float3 detailNormal = UnpackNormalAG(unifiedDetail.r).a;
//float detailAO = detail.b;
#endif
#endif
#ifdef _DETAIL_MAP
surfaceData.baseColor *= LerpWhiteTo(2.0 * saturate(detailAlbedo * _DetailAlbedoScale), detailMask);
#endif
#ifdef _SMOOTHNESS_TEXTURE_ALBEDO_CHANNEL_A
float alpha = _BaseColor.a;
#else

#ifdef _NORMALMAP
#ifdef _NORMALMAP_TANGENT_SPACE
float3 normalTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0));
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space (TODO: We need to apply the world rotation here! - Require to pass world transform)
surfaceData.normalWS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).rgb;
float3 normalTS = UnpackNormalAG(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0));
#ifdef _DETAIL_MAP
normalTS = lerp(normalTS, blendNormal(normalTS, detailNormalTS), detailMask);
#endif
surfaceData.normalWS = TransformTangentToWorld(normalTS, input.tangentToWorld);
#else // Object space
float3 normalOS = SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, input.texCoord0).rgb;
surfaceData.normalWS = TransformObjectToWorldDir(normalOS);
#ifdef _DETAIL_MAP
float3 detailNormalWS = TransformTangentToWorld(detailNormalTS, input.tangentToWorld);
surfaceData.normalWS = lerp(surfaceData.normalWS, blendNormal(surfaceData.normalWS, detailNormalWS), detailMask);
#endif
#endif
#else
surfaceData.normalWS = vertexNormalWS;

surfaceData.perceptualSmoothness = 1.0;
#endif
surfaceData.perceptualSmoothness *= _Smoothness;
#ifdef _DETAIL_MAP
surfaceData.perceptualSmoothness *= LerpWhiteTo(2.0 * saturate(detailSmoothness * _DetailSmoothnessScale), detailMask);
#endif
surfaceData.materialId = 0;

// TODO: Is there anything todo regarding flip normal but for the tangent ?
#ifdef _ANISOTROPYMAP
surfaceData.anisotropy = SAMPLE_TEXTURE2D(_AnisotropyMap, sampler_AnisotropyMap, input.texCoord0).r;
surfaceData.anisotropy = SAMPLE_TEXTURE2D(_AnisotropyMap, sampler_AnisotropyMap, input.texCoord0).g;
#else
surfaceData.anisotropy = 1.0;
#endif

4
Assets/ScriptableRenderLoop/RenderPasses/ShadowRenderPass.cs


if (lightType == LightType.Spot)
{
var settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputeSpotShadowsMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData);
bool needRendering = cullResults.ComputeSpotShadowMatricesAndCullingPrimitives(lightIndex, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref packedShadows.shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)
RenderShadowSplit(ref shadowSlices[shadowSliceIndex], lightDirection, proj, view, ref loop, settings);

for (int s = 0; s < shadowSliceCount; ++s, shadowSliceIndex++)
{
var settings = new DrawShadowsSettings(cullResults, lightIndex);
bool needRendering = cullResults.ComputePointShadowsMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData);
bool needRendering = cullResults.ComputePointShadowMatricesAndCullingPrimitives(lightIndex, (CubemapFace)s, 2.0f, out view, out proj, out settings.splitData);
SetupShadowSplitMatrices(ref shadowSlices[shadowSliceIndex], proj, view);
if (needRendering)

32
Assets/ScriptableRenderLoop/ShaderLibrary/AreaLighting.hlsl


return twoSided ? abs(sum) : max(sum, 0.0);
}
float LTCEvaluate(float3 V, float3 N, float3x3 minV, float4x3 L, bool twoSided)
float LTCEvaluate(float4x3 L, float3 V, float3 N, float NdotV, bool twoSided, float3x3 minV)
// TODO: it could be stored in PreLightData. All LTC lights compute it more than once!
basis[0] = normalize(V - N * dot(V, N));
basis[0] = normalize(V - N * NdotV);
basis[1] = normalize(cross(N, basis[0]));
basis[2] = N;

// Polygon radiance in transformed configuration - specular
return PolygonRadiance(L, twoSided);
}
float LineFpo(float rcpD, float rcpDL, float l)
{
// Compute: l / d / (d * d + l * l) + 1.0 / (d * d) * atan(l / d).
return l * rcpDL + rcpD * rcpD * atan(l * rcpD);
}
float LineFwt(float sqL, float rcpDL)
{
// Compute: l * l / d / (d * d + l * l).
return sqL * rcpDL;
}
// Computes the integral of the clamped cosine over the line segment.
// 'dist' is the shortest distance to the line. 'l1' and 'l2' define the integration interval.
float LineIrradiance(float l1, float l2, float dist, float pointZ, float tangentZ)
{
float sqD = dist * dist;
float sqL1 = l1 * l1;
float sqL2 = l2 * l2;
float rcpD = rcp(dist);
float rcpDL1 = rcpD * rcp(sqD + sqL1);
float rcpDL2 = rcpD * rcp(sqD + sqL2);
float intP0 = LineFpo(rcpD, rcpDL2, l2) - LineFpo(rcpD, rcpDL1, l1);
float intWt = LineFwt(sqL2, rcpDL2) - LineFwt(sqL1, rcpDL1);
return intP0 * pointZ + intWt * tangentZ;
}
#endif // UNITY_AREA_LIGHTING_INCLUDED

20
Assets/ScriptableRenderLoop/ShaderLibrary/Common.hlsl


}
#endif // INTRINSIC_MINMAX3
void swap(inout float a, inout float b)
{
float t = a; a = b; b = t;
}
void swap(inout float2 a, inout float2 b)
{
float2 t = a; a = b; b = t;
}
void swap(inout float3 a, inout float3 b)
{
float3 t = a; a = b; b = t;
}
void swap(inout float4 a, inout float4 b)
{
float4 t = a; a = b; b = t;
}
#ifndef INTRINSIC_CUBEMAP_FACE_ID
// TODO: implement this. Is the reference implementation of cubemapID provide by AMD the reverse of our ?
/*

18
Assets/ScriptableRenderLoop/ShaderLibrary/CommonMaterial.hlsl


return viewDirTS.xy * height;
}
// ref http://blog.selfshadow.com/publications/blending-in-detail/
// ref https://gist.github.com/selfshadow/8048308
// Reoriented Normal Mapping
// Blending when n1 and n2 are already 'unpacked' and normalised
float3 blendNormalRNM(float3 n1, float3 n2)
{
float3 t = n1.xyz + float3(0.0, 0.0, 1.0);
float3 u = n2.xyz * float3(-1.0, -1.0, 1.0);
float3 r = (t / t.z) * dot(t, u) - u;
return r;
}
float3 blendNormal(float3 n1, float3 n2)
{
return normalize(float3(n1.xy * n2.z + n2.xy * n1.z, n1.z * n2.z));
}
#endif // UNITY_COMMON_MATERIAL_INCLUDED

3
Assets/ScriptableRenderLoop/ShaderLibrary/Packing.hlsl


return normalize(n);
}
float3 UnpackNormalAG(float4 packedNormal)
float3 UnpackNormalAG(float4 packedNormal, float scale = 1.0)
normal.xy *= scale;
normal.z = sqrt(1.0 - saturate(dot(normal.xy, normal.xy)));
return normal;
}

8
Assets/ScriptableRenderLoop/fptl/FptlLighting.cs


cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_spotCookieTextures", m_CookieTexArray.GetTexCache());
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_pointCookieTextures", m_CubeCookieTexArray.GetTexCache());
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_reflCubeTextures", m_CubeReflTexArray.GetTexCache());
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_reflRootCubeTexture", ReflectionProbe.GetDefaultTexture());
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_reflRootCubeTexture", ReflectionProbe.defaultTexture);
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "g_tShadowBuffer", new RenderTargetIdentifier(m_shadowBufferID));
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "unity_NHxRoughness", m_NHxRoughnessTexture);
cmd.SetComputeTextureParam(deferredComputeShader, kernel, "_LightTextureB0", m_LightAttentuationTexture);

cmd.SetComputeBufferParam(deferredComputeShader, kernel, "g_dirLightData", s_DirLightList);
var defdecode = ReflectionProbe.GetDefaultTextureHDRDecodeValues();
var defdecode = ReflectionProbe.defaultTextureHDRDecodeValues;
cmd.SetComputeFloatParam(deferredComputeShader, "_reflRootHdrDecodeMult", defdecode.x);
cmd.SetComputeFloatParam(deferredComputeShader, "_reflRootHdrDecodeExp", defdecode.y);

cmd.SetGlobalTexture("_pointCookieTextures", m_CubeCookieTexArray.GetTexCache());
cmd.SetGlobalTexture("_reflCubeTextures", m_CubeReflTexArray.GetTexCache());
var topCube = ReflectionProbe.GetDefaultTexture();
var defdecode = ReflectionProbe.GetDefaultTextureHDRDecodeValues();
var topCube = ReflectionProbe.defaultTexture;
var defdecode = ReflectionProbe.defaultTextureHDRDecodeValues;
cmd.SetGlobalTexture("_reflRootCubeTexture", topCube);
cmd.SetGlobalFloat("_reflRootHdrDecodeMult", defdecode.x);
cmd.SetGlobalFloat("_reflRootHdrDecodeExp", defdecode.y);

702
Assets/TestScenes/HDTest/HDRenderLoopTest.unity


m_AmbientGroundColor: {r: 0.047, g: 0.043, b: 0.035, a: 1}
m_AmbientIntensity: 1
m_AmbientMode: 0
m_SkyboxMaterial: {fileID: 10304, guid: 0000000000000000f000000000000000, type: 0}
m_SkyboxMaterial: {fileID: 0}
m_HaloStrength: 0.5
m_FlareStrength: 1
m_FlareFadeSpeed: 3

m_Father: {fileID: 1546103598}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &393109612
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 393109613}
- component: {fileID: 393109616}
- component: {fileID: 393109615}
- component: {fileID: 393109614}
m_Layer: 0
m_Name: Quad (4)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &393109613
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 393109612}
m_LocalRotation: {x: 0, y: -0.17364825, z: 0, w: 0.9848078}
m_LocalPosition: {x: -2.5, y: 0, z: 6}
m_LocalScale: {x: 2, y: 10.000004, z: 1.0000005}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 5
m_LocalEulerAnglesHint: {x: 0, y: -20, z: 0}
--- !u!23 &393109614
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 393109612}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 2e59d95585e72d64ba03c9a2d2d400e4, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &393109615
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 393109612}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &393109616
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 393109612}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &406744987
GameObject:
m_ObjectHideFlags: 0

m_Father: {fileID: 1370166355}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &417938708
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 417938709}
- component: {fileID: 417938712}
- component: {fileID: 417938711}
- component: {fileID: 417938710}
m_Layer: 0
m_Name: Quad (3)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &417938709
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 417938708}
m_LocalRotation: {x: 0, y: -0.13052624, z: 0, w: 0.9914449}
m_LocalPosition: {x: 0, y: 0, z: 6.9}
m_LocalScale: {x: 2, y: 10.000004, z: 1.0000005}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 4
m_LocalEulerAnglesHint: {x: 0, y: -15, z: 0}
--- !u!23 &417938710
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 417938708}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 1a5c63b3aa502e6419f403dd3f0f0410, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &417938711
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 417938708}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &417938712
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 417938708}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &423936818
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 423936819}
- component: {fileID: 423936822}
- component: {fileID: 423936821}
- component: {fileID: 423936820}
m_Layer: 0
m_Name: Quad (1)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &423936819
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423936818}
m_LocalRotation: {x: 0, y: -0.043619405, z: 0, w: 0.9990483}
m_LocalPosition: {x: 5, y: 0, z: 7.9}
m_LocalScale: {x: 2, y: 10.000004, z: 1.0000005}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 2
m_LocalEulerAnglesHint: {x: 0, y: -5, z: 0}
--- !u!23 &423936820
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423936818}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 444534c618931b84ab4770dc517021df, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &423936821
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423936818}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &423936822
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 423936818}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &426381625
GameObject:
m_ObjectHideFlags: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

- target: {fileID: 2374582, guid: e641a36bceddbf24a89656e94dafb3e5, type: 2}
propertyPath: m_Materials.Array.data[0]
value:
objectReference: {fileID: 2100000, guid: 87c86082ee14fbd4b8426a8794f2060d, type: 2}
objectReference: {fileID: 2100000, guid: 5dd25721c8df9b24b90a773fca15e636, type: 2}
m_RemovedComponents: []
m_ParentPrefab: {fileID: 100100000, guid: e641a36bceddbf24a89656e94dafb3e5, type: 2}
m_IsPrefabParent: 0

m_Father: {fileID: 1683234571}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &710116620
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 710116623}
- component: {fileID: 710116622}
- component: {fileID: 710116621}
m_Layer: 0
m_Name: Test - LTC Line Light
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!114 &710116621
MonoBehaviour:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 710116620}
m_Enabled: 1
m_EditorHideFlags: 0
m_Script: {fileID: 11500000, guid: 7a68c43fe1f2a47cfa234b5eeaa98012, type: 3}
m_Name:
m_EditorClassIdentifier:
shadowResolution: 512
shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
archetype: 2
isDoubleSided: 1
areaLightLength: 16
areaLightWidth: 0
--- !u!108 &710116622
Light:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 710116620}
m_Enabled: 1
serializedVersion: 7
m_Type: 2
m_Color: {r: 1, g: 1, b: 1, a: 1}
m_Intensity: 1
m_Range: 10
m_SpotAngle: 30
m_CookieSize: 10
m_Shadows:
m_Type: 0
m_Resolution: -1
m_CustomResolution: -1
m_Strength: 1
m_Bias: 0.05
m_NormalBias: 0.4
m_NearPlane: 0.2
m_Cookie: {fileID: 0}
m_DrawHalo: 0
m_Flare: {fileID: 0}
m_RenderMode: 0
m_CullingMask:
serializedVersion: 2
m_Bits: 4294967295
m_Lightmapping: 4
m_AreaSize: {x: 1, y: 1}
m_BounceIntensity: 1
m_ShadowRadius: 0
m_ShadowAngle: 0
--- !u!4 &710116623
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 710116620}
m_LocalRotation: {x: 0.7071068, y: 0, z: 0, w: 0.7071068}
m_LocalPosition: {x: -125, y: 8, z: 15}
m_LocalScale: {x: 1, y: 1, z: 1}
m_Children:
- {fileID: 740109895}
- {fileID: 2110631287}
- {fileID: 423936819}
- {fileID: 782545121}
- {fileID: 417938709}
- {fileID: 393109613}
- {fileID: 1126074680}
m_Father: {fileID: 0}
m_RootOrder: 26
m_LocalEulerAnglesHint: {x: 90, y: 0, z: 0}
--- !u!1 &733865593
GameObject:
m_ObjectHideFlags: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
--- !u!1 &740109894
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 740109895}
- component: {fileID: 740109900}
- component: {fileID: 740109899}
- component: {fileID: 740109898}
m_Layer: 0
m_Name: LightQuad
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &740109895
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 740109894}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 0, y: 0, z: 0}
m_LocalScale: {x: 16, y: 0.1, z: 1}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 0
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &740109898
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 740109894}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 492d83e00e5c35841bcdbcea025f2c50, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &740109899
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 740109894}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &740109900
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 740109894}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1001 &744696321
Prefab:
m_ObjectHideFlags: 0

m_RemovedComponents: []
m_ParentPrefab: {fileID: 100100000, guid: e641a36bceddbf24a89656e94dafb3e5, type: 2}
m_IsPrefabParent: 0
--- !u!1 &782545120
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 782545121}
- component: {fileID: 782545124}
- component: {fileID: 782545123}
- component: {fileID: 782545122}
m_Layer: 0
m_Name: Quad (2)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &782545121
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 782545120}
m_LocalRotation: {x: 0, y: -0.08715578, z: 0, w: 0.9961947}
m_LocalPosition: {x: 2.5, y: 0, z: 7.5}
m_LocalScale: {x: 2, y: 10.000004, z: 1.0000005}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 3
m_LocalEulerAnglesHint: {x: 0, y: -10, z: 0}
--- !u!23 &782545122
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 782545120}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: dcad493d968f31e4ba561145c394919b, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &782545123
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 782545120}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &782545124
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 782545120}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &785457124
GameObject:
m_ObjectHideFlags: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 1
archetype: 1
isDoubleSided: 1
areaLightLength: 16
areaLightWidth: 2

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

m_Father: {fileID: 0}
m_RootOrder: 23
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1126074679
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 1126074680}
- component: {fileID: 1126074683}
- component: {fileID: 1126074682}
- component: {fileID: 1126074681}
m_Layer: 0
m_Name: Quad (5)
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &1126074680
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1126074679}
m_LocalRotation: {x: 0, y: -0.21643952, z: 0, w: 0.97629607}
m_LocalPosition: {x: -5, y: 0, z: 4.9}
m_LocalScale: {x: 2, y: 10.000004, z: 1.0000005}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 6
m_LocalEulerAnglesHint: {x: 0, y: -25, z: 0}
--- !u!23 &1126074681
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1126074679}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 65143432471e8af4db8443b42a8f1b3c, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &1126074682
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1126074679}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &1126074683
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1126074679}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &1137604041
GameObject:
m_ObjectHideFlags: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 1
archetype: 1
isDoubleSided: 1
areaLightLength: 4
areaLightWidth: 2

m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 7af9798eeefeae34c83aca56762a2938, type: 2}
- {fileID: 2100000, guid: f03665895dc89b84487310c5216b8458, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0

shadowDimmer: 1
affectDiffuse: 1
affectSpecular: 1
treatAsAreaLight: 0
archetype: 0
isDoubleSided: 0
areaLightLength: 0
areaLightWidth: 0

m_StereoConvergence: 10
m_StereoSeparation: 0.022
m_StereoMirrorMode: 0
--- !u!1 &2110631286
GameObject:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
serializedVersion: 5
m_Component:
- component: {fileID: 2110631287}
- component: {fileID: 2110631290}
- component: {fileID: 2110631289}
- component: {fileID: 2110631288}
m_Layer: 0
m_Name: Quad
m_TagString: Untagged
m_Icon: {fileID: 0}
m_NavMeshLayer: 0
m_StaticEditorFlags: 0
m_IsActive: 1
--- !u!4 &2110631287
Transform:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2110631286}
m_LocalRotation: {x: 0, y: 0, z: 0, w: 1}
m_LocalPosition: {x: 7.5, y: 0, z: 8}
m_LocalScale: {x: 2, y: 10, z: 1}
m_Children: []
m_Father: {fileID: 710116623}
m_RootOrder: 1
m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!23 &2110631288
MeshRenderer:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2110631286}
m_Enabled: 1
m_CastShadows: 1
m_ReceiveShadows: 1
m_MotionVectors: 1
m_LightProbeUsage: 1
m_ReflectionProbeUsage: 1
m_Materials:
- {fileID: 2100000, guid: 7af9798eeefeae34c83aca56762a2938, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 1
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_SelectedEditorRenderState: 3
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
--- !u!64 &2110631289
MeshCollider:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2110631286}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Convex: 0
m_InflateMesh: 0
m_SkinWidth: 0.01
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!33 &2110631290
MeshFilter:
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 2110631286}
m_Mesh: {fileID: 10210, guid: 0000000000000000e000000000000000, type: 0}
--- !u!1 &2117217831
GameObject:
m_ObjectHideFlags: 0

2
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 5.6.0a2
m_EditorVersion: 5.6.0a4

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


#ifndef __CLUSTEREDUTILS_H__
#define __CLUSTEREDUTILS_H__
#ifndef FLT_EPSILON
#define FLT_EPSILON 1.192092896e-07f
#endif
float GetScaleFromBase(float base)
{
const float C = (float)(1 << g_iLog2NumClusters);
const float geomSeries = (1.0 - pow(base, C)) / (1 - base); // geometric series: sum_k=0^{C-1} base^k
return geomSeries / (g_fFarPlane - g_fNearPlane);
}
int SnapToClusterIdxFlex(float z_in, float suggestedBase, bool logBasePerTile)
{
#if USE_LEFTHAND_CAMERASPACE
float z = z_in;
#else
float z = -z_in;
#endif
float userscale = g_fClustScale;
if (logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
// using the inverse of the geometric series
const float dist = max(0, z - g_fNearPlane);
return (int)clamp(log2(dist * userscale * (suggestedBase - 1.0f) + 1) / log2(suggestedBase), 0.0, (float)((1 << g_iLog2NumClusters) - 1));
}
int SnapToClusterIdx(float z_in, float suggestedBase)
{
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
bool logBasePerTile = true; // resolved compile time
#else
bool logBasePerTile = false;
#endif
return SnapToClusterIdxFlex(z_in, suggestedBase, logBasePerTile);
}
float ClusterIdxToZFlex(int k, float suggestedBase, bool logBasePerTile)
{
float res;
float userscale = g_fClustScale;
if (logBasePerTile)
userscale = GetScaleFromBase(suggestedBase);
float dist = (pow(suggestedBase, (float)k) - 1.0) / (userscale * (suggestedBase - 1.0f));
res = dist + g_fNearPlane;
#if USE_LEFTHAND_CAMERASPACE
return res;
#else
return -res;
#endif
}
float ClusterIdxToZ(int k, float suggestedBase)
{
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
bool logBasePerTile = true; // resolved compile time
#else
bool logBasePerTile = false;
#endif
return ClusterIdxToZFlex(k, suggestedBase, logBasePerTile);
}
// generate a log-base value such that half of the clusters are consumed from near plane to max. opaque depth of tile.
float SuggestLogBase50(float tileFarPlane)
{
const float C = (float)(1 << g_iLog2NumClusters);
float normDist = clamp((tileFarPlane - g_fNearPlane) / (g_fFarPlane - g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow((1.0 + sqrt(max(0.0, 1.0 - 4.0 * normDist * (1.0 - normDist)))) / (2.0 * normDist), 2.0 / C); //
return max(g_fClustBase, suggested_base);
}
// generate a log-base value such that (approximately) a quarter of the clusters are consumed from near plane to max. opaque depth of tile.
float SuggestLogBase25(float tileFarPlane)
{
const float C = (float)(1 << g_iLog2NumClusters);
float normDist = clamp((tileFarPlane - g_fNearPlane) / (g_fFarPlane - g_fNearPlane), FLT_EPSILON, 1.0);
float suggested_base = pow((1 / 2.3) * max(0.0, (0.8 / normDist) - 1), 4.0 / (C * 2)); // approximate inverse of d*x^4 + (-x) + (1-d) = 0 - d is normalized distance
return max(g_fClustBase, suggested_base);
}
#endif

9
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ClusteredUtils.hlsl.meta


fileFormatVersion: 2
guid: 54f8006db9236c148af831b7fcaadc0c
timeCreated: 1479691314
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

267
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute


#pragma kernel BigTileLightListGen
#include "../TilePass.cs.hlsl"
#include "../LightingConvexHullUtils.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#include "../SortingComputeUtils.hlsl"
#endif
#define EXACT_EDGE_TESTS
#define PERFORM_SPHERICAL_INTERSECTION_TESTS
#define MAX_NR_BIGTILE_LIGHTS (MAX_NR_BIGTILE_LIGHTS_PLUSONE-1)
uniform int g_iNrVisibLights;
uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform float g_fNearPlane;
uniform float g_fFarPlane;
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<SFiniteLightData> g_vLightData : register( t2 );
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#define NR_THREADS 64
// output buffer
RWBuffer<uint> g_vLightList : register( u0 );
// 2kB (room for roughly 30 wavefronts)
groupshared unsigned int lightsListLDS[MAX_NR_BIGTILE_LIGHTS_PLUSONE];
groupshared uint lightOffs;
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
float fCy = g_mScrProjection[1].z;
#if USE_LEFTHAND_CAMERASPACE
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
#endif
}
float GetOnePixDiagWorldDistAtDepthOne()
{
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
return length( float2(1.0/fSx,1.0/fSy) );
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
void SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate);
#endif
#ifdef EXACT_EDGE_TESTS
void CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR);
#endif
[numthreads(NR_THREADS, 1, 1)]
void BigTileLightListGen(uint threadID : SV_GroupIndex, uint3 u3GroupID : SV_GroupID)
{
uint2 tileIDX = u3GroupID.xy;
uint t=threadID;
uint iWidth = g_viDimensions.x;
uint iHeight = g_viDimensions.y;
uint nrBigTilesX = (iWidth+63)/64;
uint nrBigTilesY = (iHeight+63)/64;
if(t==0) lightOffs = 0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
uint2 viTilLL = 64*tileIDX;
uint2 viTilUR = min( viTilLL+uint2(64,64), uint2(iWidth, iHeight) ); // not width and height minus 1 since viTilUR represents the end of the tile corner.
float2 vTileLL = float2(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight);
float2 vTileUR = float2(viTilUR.x/(float) iWidth, viTilUR.y/(float) iHeight);
// build coarse list using AABB
for(int l=(int) t; l<(int) g_iNrVisibLights; l += NR_THREADS)
{
const float2 vMi = g_vBoundsBuffer[l].xy;
const float2 vMa = g_vBoundsBuffer[l+g_iNrVisibLights].xy;
if( all(vMa>vTileLL) && all(vMi<vTileUR))
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(lightOffs, uInc, uIndex);
if(uIndex<MAX_NR_BIGTILE_LIGHTS) lightsListLDS[uIndex] = l; // add to light list
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int iNrCoarseLights = min(lightOffs,MAX_NR_BIGTILE_LIGHTS);
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(64/2,64/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifdef EXACT_EDGE_TESTS
CullByExactEdgeTests(t, iNrCoarseLights, viTilLL.xy, viTilUR.xy);
#endif
// sort lights
SORTLIST(lightsListLDS, iNrCoarseLights, MAX_NR_BIGTILE_LIGHTS_PLUSONE, t, NR_THREADS);
lightOffs = 0;
GroupMemoryBarrierWithGroupSync();
for(int i=t; i<iNrCoarseLights; i+=NR_THREADS) if(lightsListLDS[i]<g_iNrVisibLights) InterlockedAdd(lightOffs, 1);
GroupMemoryBarrierWithGroupSync();
iNrCoarseLights = lightOffs;
int offs = tileIDX.y*nrBigTilesX + tileIDX.x;
for(int i=t; i<(iNrCoarseLights+1); i+=NR_THREADS)
g_vLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*offs + i] = t==0 ? iNrCoarseLights : lightsListLDS[i-1];
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
void SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate)
{
#if USE_LEFTHAND_CAMERASPACE
float3 V = GetViewPosFromLinDepth( screenCoordinate, 1.0);
#else
float3 V = GetViewPosFromLinDepth( screenCoordinate, -1.0);
#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float halfTileSizeAtZDistOne = 32*onePixDiagDist; // scale by half a tile
for(int l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{
SFiniteLightBound lgtDat = g_data[lightsListLDS[l]];
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius) )
lightsListLDS[l]=0xffffffff;
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
}
#endif
#ifdef EXACT_EDGE_TESTS
float3 GetTileVertex(uint2 viTilLL, uint2 viTilUR, int i, float fTileFarPlane)
{
float x = (i&1)==0 ? viTilLL.x : viTilUR.x;
float y = (i&2)==0 ? viTilLL.y : viTilUR.y;
float z = (i&4)==0 ? g_fNearPlane : fTileFarPlane;
#if !USE_LEFTHAND_CAMERASPACE
z = -z;
#endif
return GetViewPosFromLinDepth( float2(x, y), z);
}
void GetFrustEdge(out float3 vP0, out float3 vE0, const int e0, uint2 viTilLL, uint2 viTilUR, float fTileFarPlane)
{
int iSection = e0>>2; // section 0 is side edges, section 1 is near edges and section 2 is far edges
int iSwizzle = e0&0x3;
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)));
}
void CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR)
{
const bool bOnlyNeedFrustumSideEdges = true;
const int nrFrustEdges = bOnlyNeedFrustumSideEdges ? 4 : 8; // max 8 since we never need to test 4 far edges of frustum since they are identical vectors to near edges and plane is placed at vP0 on light hull.
const int totNrEdgePairs = 12*nrFrustEdges;
for(int l=0; l<iNrCoarseLights; l++)
{
const int idxCoarse = lightsListLDS[l];
[branch]if(idxCoarse<(uint) g_iNrVisibLights && g_vLightData[idxCoarse].lightType!=SPHERE_LIGHT) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
{
SFiniteLightBound lgtDat = g_data[idxCoarse];
const float3 boxX = lgtDat.boxAxisX.xyz;
const float3 boxY = lgtDat.boxAxisY.xyz;
const float3 boxZ = -lgtDat.boxAxisZ.xyz; // flip axis (so it points away from the light direction for a spot-light)
const float3 center = lgtDat.center.xyz;
const float2 scaleXY = lgtDat.scaleXY;
for(int i=threadID; i<totNrEdgePairs; i+=NR_THREADS)
{
int e0 = (int) (((uint)i)/((uint) nrFrustEdges)); // should become a shift right
int e1 = i - e0*nrFrustEdges;
int idx_cur=0, idx_twin=0;
float3 vP0, vE0;
GetHullEdge(idx_cur, idx_twin, vP0, vE0, e0, boxX, boxY, boxZ, center, scaleXY);
float3 vP1, vE1;
GetFrustEdge(vP1, vE1, e1, viTilLL, viTilUR, g_fFarPlane);
// potential separation plane
float3 vN = cross(vE0, vE1);
int positive=0, negative=0;
for(int k=1; k<8; k++) // only need to test 7 verts (technically just 6).
{
int j = (idx_cur+k)&0x7;
float3 vPh = GetHullVertex(boxX, boxY, boxZ, center, scaleXY, j);
float fSignDist = idx_twin==j ? 0.0 : dot(vN, vPh-vP0);
if(fSignDist>0) ++positive; else if(fSignDist<0) ++negative;
}
int resh = (positive>0 && negative>0) ? 0 : (positive>0 ? 1 : (negative>0 ? (-1) : 0));
positive=0; negative=0;
for(int j=0; j<8; j++)
{
float3 vPf = GetTileVertex(viTilLL, viTilUR, j, g_fFarPlane);
float fSignDist = dot(vN, vPf-vP0);
if(fSignDist>0) ++positive; else if(fSignDist<0) ++negative;
}
int resf = (positive>0 && negative>0) ? 0 : (positive>0 ? 1 : (negative>0 ? (-1) : 0));
bool bFoundSepPlane = (resh*resf)<0;
if(bFoundSepPlane) lightsListLDS[l]=0xffffffff;
}
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
}
#endif

9
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute.meta


fileFormatVersion: 2
guid: 5ee1f9d6e09abe045b2f5e0b784b9072
timeCreated: 1479689024
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

553
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-clustered.compute


#pragma kernel TileLightListGen_NoDepthRT LIGHTLISTGEN=TileLightListGen_NoDepthRT
#pragma kernel TileLightListGen_DepthRT LIGHTLISTGEN=TileLightListGen_DepthRT ENABLE_DEPTH_TEXTURE_BACKPLANE
#pragma kernel TileLightListGen_DepthRT_MSAA LIGHTLISTGEN=TileLightListGen_DepthRT_MSAA ENABLE_DEPTH_TEXTURE_BACKPLANE MSAA_ENABLED
#pragma kernel TileLightListGen_NoDepthRT_SrcBigTile LIGHTLISTGEN=TileLightListGen_NoDepthRT_SrcBigTile USE_TWO_PASS_TILED_LIGHTING
#pragma kernel TileLightListGen_DepthRT_SrcBigTile LIGHTLISTGEN=TileLightListGen_DepthRT_SrcBigTile ENABLE_DEPTH_TEXTURE_BACKPLANE USE_TWO_PASS_TILED_LIGHTING
#pragma kernel TileLightListGen_DepthRT_MSAA_SrcBigTile LIGHTLISTGEN=TileLightListGen_DepthRT_MSAA_SrcBigTile ENABLE_DEPTH_TEXTURE_BACKPLANE MSAA_ENABLED USE_TWO_PASS_TILED_LIGHTING
#pragma kernel ClearAtomic
#include "../ShaderBase.hlsl"
#include "../TilePass.cs.hlsl"
#include "../LightingConvexHullUtils.hlsl"
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
#include "../SortingComputeUtils.hlsl"
#endif
//#define EXACT_EDGE_TESTS
#define PERFORM_SPHERICAL_INTERSECTION_TESTS
#define CONV_HULL_TEST_ENABLED
uniform int g_iNrVisibLights;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform float g_fClustScale;
uniform float g_fClustBase;
uniform float g_fNearPlane;
uniform float g_fFarPlane;
uniform int g_iLog2NumClusters; // numClusters = (1<<g_iLog2NumClusters)
#include "../ClusteredUtils.hlsl"
#ifdef MSAA_ENABLED
Texture2DMS<float> g_depth_tex : register( t0 );
#else
Texture2D g_depth_tex : register( t0 );
#endif
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<SFiniteLightData> g_vLightData : register( t2 );
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#ifdef USE_TWO_PASS_TILED_LIGHTING
Buffer<uint> g_vBigTileLightList : register( t4 );
#endif
#define NR_THREADS 64
// output buffer
RWBuffer<uint> g_vLayeredLightList : register( u0 );
RWBuffer<uint> g_LayeredOffset : register( u1 );
RWBuffer<uint> g_LayeredSingleIdxBuffer : register( u2 );
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
RWBuffer<float> g_logBaseBuffer : register( u3 );
#endif
#define MAX_NR_COARSE_ENTRIES 128
groupshared unsigned int coarseList[MAX_NR_COARSE_ENTRIES];
groupshared unsigned int clusterIdxs[MAX_NR_COARSE_ENTRIES/2];
groupshared float4 lightPlanes[4*6];
groupshared uint lightOffs;
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
groupshared int ldsZMax;
#endif
#ifdef EXACT_EDGE_TESTS
groupshared uint ldsIsLightInvisible;
groupshared uint lightOffs2;
#endif
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
groupshared uint lightOffsSph;
#endif
float GetLinearDepth(float zDptBufSpace) // 0 is near 1 is far
{
float3 vP = float3(0.0f,0.0f,zDptBufSpace);
float4 v4Pres = mul(g_mInvScrProjection, float4(vP,1.0));
return v4Pres.z / v4Pres.w;
}
float3 GetViewPosFromLinDepth(float2 v2ScrPos, float fLinDepth)
{
float fSx = g_mScrProjection[0].x;
float fCx = g_mScrProjection[0].z;
float fSy = g_mScrProjection[1].y;
float fCy = g_mScrProjection[1].z;
#if USE_LEFTHAND_CAMERASPACE
return fLinDepth*float3( ((v2ScrPos.x-fCx)/fSx), ((v2ScrPos.y-fCy)/fSy), 1.0 );
#else
return fLinDepth*float3( -((v2ScrPos.x+fCx)/fSx), -((v2ScrPos.y+fCy)/fSy), 1.0 );
#endif
}
float GetOnePixDiagWorldDistAtDepthOne()
{
float fSx = g_mScrProjection[0].x;
float fSy = g_mScrProjection[1].y;
return length( float2(1.0/fSx,1.0/fSy) );
}
#ifdef EXACT_EDGE_TESTS
int CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR, float fTileFarPlane);
#endif
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate);
#endif
// returns 1 for intersection and 0 for none
float4 FetchPlane(int l, int p);
bool CheckIntersection(int l, int k, uint2 viTilLL, uint2 viTilUR, float suggestedBase)
{
unsigned int val = (clusterIdxs[l>>1]>>(16*(l&1)))&0xffff;
bool bIsHit = ((val>>0)&0xff)<=((uint) k) && ((uint) k)<=((val>>8)&0xff);
if(bIsHit)
{
#ifdef CONV_HULL_TEST_ENABLED
float depthAtNearZ = ClusterIdxToZ(k, suggestedBase);
float depthAtFarZ = ClusterIdxToZ(k+1, suggestedBase);
for(int p=0; p<6; p++)
{
float4 plane = lightPlanes[6*(l&3)+p];
bool bAllInvisib = true;
for(int i=0; i<8; i++)
{
float x = (i&1)==0 ? viTilLL.x : viTilUR.x;
float y = (i&2)==0 ? viTilLL.y : viTilUR.y;
float z = (i&4)==0 ? depthAtNearZ : depthAtFarZ;
float3 vP = GetViewPosFromLinDepth( float2(x, y), z);
bAllInvisib = bAllInvisib && dot(plane, float4(vP,1.0))>0;
}
if(bAllInvisib) bIsHit = false;
}
#endif
}
return bIsHit;
}
bool CheckIntersectionBasic(int l, int k)
{
unsigned int val = (clusterIdxs[l>>1]>>(16*(l&1)))&0xffff;
return ((val>>0)&0xff)<=((uint) k) && ((uint) k)<=((val>>8)&0xff);
}
[numthreads(NR_THREADS, 1, 1)]
void LIGHTLISTGEN(uint threadID : SV_GroupIndex, uint3 u3GroupID : SV_GroupID)
{
uint2 tileIDX = u3GroupID.xy;
uint t=threadID;
uint iWidth;
uint iHeight;
#ifdef MSAA_ENABLED
uint iNumSamplesMSAA;
g_depth_tex.GetDimensions(iWidth, iHeight, iNumSamplesMSAA);
#else
g_depth_tex.GetDimensions(iWidth, iHeight);
#endif
uint nrTilesX = (iWidth+15)/16;
uint nrTilesY = (iHeight+15)/16;
uint2 viTilLL = 16*tileIDX;
uint2 viTilUR = min( viTilLL+uint2(16,16), uint2(iWidth, iHeight) ); // not width and height minus 1 since viTilUR represents the end of the tile corner.
if(t==0)
{
lightOffs = 0;
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
ldsZMax = 0;
#endif
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
float dpt_ma=1.0;
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
// establish min and max depth first
dpt_ma=0.0;
for(int idx=t; idx<256; idx+=NR_THREADS)
{
uint2 uPixCrd = min( uint2(viTilLL.x+(idx&0xf), viTilLL.y+(idx>>4)), uint2(iWidth-1, iHeight-1) );
#ifdef MSAA_ENABLED
for(int i=0; i<iNumSamplesMSAA; i++)
{
const float fDpth = FetchDepthMSAA(g_depth_tex, uPixCrd, i);
#else
const float fDpth = FetchDepth(g_depth_tex, uPixCrd);
#endif
if(fDpth<VIEWPORT_SCALE_Z) // if not skydome
{
dpt_ma = max(fDpth, dpt_ma);
}
#ifdef MSAA_ENABLED
}
#endif
}
InterlockedMax(ldsZMax, asuint(dpt_ma) );
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
dpt_ma = asfloat(ldsZMax);
#endif
float3 vTileLL = float3(viTilLL.x/(float) iWidth, viTilLL.y/(float) iHeight, 0.0);
float3 vTileUR = float3(viTilUR.x/(float) iWidth, viTilUR.y/(float) iHeight, 1.0);
// build coarse list using AABB
#ifdef USE_TWO_PASS_TILED_LIGHTING
int NrBigTilesX = (nrTilesX+3)>>2;
const int bigTileIdx = (tileIDX.y>>2)*NrBigTilesX + (tileIDX.x>>2); // map the idx to 64x64 tiles
int nrBigTileLights = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+0];
for(int l0=(int) t; l0<(int) nrBigTileLights; l0 += NR_THREADS)
{
int l = g_vBigTileLightList[MAX_NR_BIGTILE_LIGHTS_PLUSONE*bigTileIdx+l0+1];
#else
for(int l=(int) t; l<(int) g_iNrVisibLights; l += NR_THREADS)
{
#endif
const float3 vMi = g_vBoundsBuffer[l];
const float3 vMa = g_vBoundsBuffer[l+g_iNrVisibLights];
if( all(vMa.xy>vTileLL.xy) && all(vMi.xy<vTileUR.xy))
{
unsigned int uInc = 1;
unsigned int uIndex;
InterlockedAdd(lightOffs, uInc, uIndex);
if(uIndex<MAX_NR_COARSE_ENTRIES) coarseList[uIndex] = l; // add to light list
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int iNrCoarseLights = min(lightOffs,MAX_NR_COARSE_ENTRIES);
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
iNrCoarseLights = SphericalIntersectionTests( t, iNrCoarseLights, float2(min(viTilLL.xy+uint2(16/2,16/2), uint2(iWidth-1, iHeight-1))) );
#endif
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
#if USE_LEFTHAND_CAMERASPACE
float fTileFarPlane = GetLinearDepth(dpt_ma);
#else
float fTileFarPlane = -GetLinearDepth(dpt_ma);
#endif
float suggestedBase = SuggestLogBase50(fTileFarPlane);
#else
float fTileFarPlane = g_fFarPlane;
float suggestedBase = g_fClustBase;
#endif
#ifdef EXACT_EDGE_TESTS
iNrCoarseLights = CullByExactEdgeTests(t, iNrCoarseLights, viTilLL.xy, viTilUR.xy, fTileFarPlane);
#endif
// sort lights (gives a more efficient execution in both deferred and tiled forward lighting).
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
SORTLIST(coarseList, iNrCoarseLights, MAX_NR_COARSE_ENTRIES, t, NR_THREADS);
#endif
//////////// cell specific code
{
for(int l=(int) t; l<((iNrCoarseLights+1)>>1); l += NR_THREADS)
{
const int l0 = coarseList[2*l+0], l1 = coarseList[min(2*l+1,iNrCoarseLights)];
const unsigned int clustIdxMi0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0].z), suggestedBase));
const unsigned int clustIdxMa0 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l0+g_iNrVisibLights].z), suggestedBase));
const unsigned int clustIdxMi1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1].z), suggestedBase));
const unsigned int clustIdxMa1 = (const unsigned int) min(255,SnapToClusterIdx(GetLinearDepth(g_vBoundsBuffer[l1+g_iNrVisibLights].z), suggestedBase));
clusterIdxs[l] = (clustIdxMa1<<24) | (clustIdxMi1<<16) | (clustIdxMa0<<8) | (clustIdxMi0<<0);
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
int nrClusters = (1<<g_iLog2NumClusters);
//////////////////////////////////////////////////////////
uint start = 0;
int i=(int) t;
int iSpaceAvail = 0;
int iSum = 0;
if(i<nrClusters)
{
for(int l=0; l<iNrCoarseLights; l++)
{
iSum += (CheckIntersectionBasic(l, i) ? 1 : 0);
}
iSpaceAvail = min(iSum,MAX_NR_COARSE_ENTRIES); // combined storage for both direct lights and reflection
InterlockedAdd(g_LayeredSingleIdxBuffer[0], (uint) iSpaceAvail, start); // alloc list memory
}
int modelListCount[NR_LIGHT_MODELS]={0,0}; // direct light count and reflection lights
uint offs = start;
for(int ll=0; ll<iNrCoarseLights; ll+=4)
{
int p = i>>2;
int m = i&3;
if(i<24) lightPlanes[6*m+p] = FetchPlane(min(iNrCoarseLights-1,ll+m), p);
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
for(int l=ll; l<min(iNrCoarseLights,(ll+4)); l++)
{
if(offs<(start+iSpaceAvail) && i<nrClusters && CheckIntersection(l, i, viTilLL.xy, viTilUR.xy, suggestedBase) )
{
uint lightModel = g_vLightData[ coarseList[l] ].lightModel;
++modelListCount[ lightModel==REFLECTION_LIGHT ? 1 : 0];
g_vLayeredLightList[offs++] = coarseList[l]; // reflection lights will be last since we sorted
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
}
uint localOffs=0;
offs = i*nrTilesX*nrTilesY + tileIDX.y*nrTilesX + tileIDX.x;
for(int m=0; m<NR_LIGHT_MODELS; m++)
{
int numLights = min(modelListCount[m],31); // only allow 5 bits
if(i<nrClusters)
{
g_LayeredOffset[offs] = (start+localOffs) | (((uint) numLights)<<27);
offs += (nrClusters*nrTilesX*nrTilesY);
localOffs += modelListCount[m]; // use unclamped count for localOffs
}
}
#ifdef ENABLE_DEPTH_TEXTURE_BACKPLANE
g_logBaseBuffer[tileIDX.y*nrTilesX + tileIDX.x] = suggestedBase;
#endif
}
float4 FetchPlane(int l, int p)
{
SFiniteLightBound lgtDat = g_data[coarseList[l]];
const float3 boxX = lgtDat.boxAxisX.xyz;
const float3 boxY = lgtDat.boxAxisY.xyz;
const float3 boxZ = -lgtDat.boxAxisZ.xyz; // flip axis (so it points away from the light direction for a spot-light)
const float3 center = lgtDat.center.xyz;
const float radius = lgtDat.radius;
const float2 scaleXY = lgtDat.scaleXY;
return GetPlaneEq(boxX, boxY, boxZ, center, scaleXY, p);
}
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
int SphericalIntersectionTests(uint threadID, int iNrCoarseLights, float2 screenCoordinate)
{
#if USE_LEFTHAND_CAMERASPACE
float3 V = GetViewPosFromLinDepth( screenCoordinate, 1.0);
#else
float3 V = GetViewPosFromLinDepth( screenCoordinate, -1.0);
#endif
float onePixDiagDist = GetOnePixDiagWorldDistAtDepthOne();
float halfTileSizeAtZDistOne = 8*onePixDiagDist; // scale by half a tile
for(int l=threadID; l<iNrCoarseLights; l+=NR_THREADS)
{
SFiniteLightBound lgtDat = g_data[coarseList[l]];
if( !DoesSphereOverlapTile(V, halfTileSizeAtZDistOne, lgtDat.center.xyz, lgtDat.radius) )
coarseList[l]=0xffffffff;
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
// to greedy to double buffer coarseList lds on this so serializing removal of gaps.
if(threadID==0)
{
int offs = 0;
for(int l=0; l<iNrCoarseLights; l++)
{ if(coarseList[l]!=0xffffffff) coarseList[offs++] = coarseList[l]; }
lightOffsSph = offs;
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
return lightOffsSph;
}
#endif
#ifdef EXACT_EDGE_TESTS
float3 GetTileVertex(uint2 viTilLL, uint2 viTilUR, int i, float fTileFarPlane)
{
float x = (i&1)==0 ? viTilLL.x : viTilUR.x;
float y = (i&2)==0 ? viTilLL.y : viTilUR.y;
float z = (i&4)==0 ? g_fNearPlane : fTileFarPlane;
#if !USE_LEFTHAND_CAMERASPACE
z = -z;
#endif
return GetViewPosFromLinDepth( float2(x, y), z);
}
void GetFrustEdge(out float3 vP0, out float3 vE0, const int e0, uint2 viTilLL, uint2 viTilUR, float fTileFarPlane)
{
int iSection = e0>>2; // section 0 is side edges, section 1 is near edges and section 2 is far edges
int iSwizzle = e0&0x3;
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)));
}
int CullByExactEdgeTests(uint threadID, int iNrCoarseLights, uint2 viTilLL, uint2 viTilUR, float fTileFarPlane)
{
if(threadID==0) lightOffs2 = 0;
const bool bOnlyNeedFrustumSideEdges = true;
const int nrFrustEdges = bOnlyNeedFrustumSideEdges ? 4 : 8; // max 8 since we never need to test 4 far edges of frustum since they are identical vectors to near edges and plane is placed at vP0 on light hull.
const int totNrEdgePairs = 12*nrFrustEdges;
for(int l=0; l<iNrCoarseLights; l++)
{
if(threadID==0) ldsIsLightInvisible=0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
const int idxCoarse = coarseList[l];
[branch]if(g_vLightData[idxCoarse].lightType!=SPHERE_LIGHT) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
{
SFiniteLightBound lgtDat = g_data[idxCoarse];
const float3 boxX = lgtDat.boxAxisX.xyz;
const float3 boxY = lgtDat.boxAxisY.xyz;
const float3 boxZ = -lgtDat.boxAxisZ.xyz; // flip axis (so it points away from the light direction for a spot-light)
const float3 center = lgtDat.center.xyz;
const float2 scaleXY = lgtDat.scaleXY;
for(int i=threadID; i<totNrEdgePairs; i+=NR_THREADS)
{
int e0 = (int) (((uint)i)/((uint) nrFrustEdges)); // should become a shift right
int e1 = i - e0*nrFrustEdges;
int idx_cur=0, idx_twin=0;
float3 vP0, vE0;
GetHullEdge(idx_cur, idx_twin, vP0, vE0, e0, boxX, boxY, boxZ, center, scaleXY);
float3 vP1, vE1;
GetFrustEdge(vP1, vE1, e1, viTilLL, viTilUR, fTileFarPlane);
// potential separation plane
float3 vN = cross(vE0, vE1);
int positive=0, negative=0;
for(int k=1; k<8; k++) // only need to test 7 verts (technically just 6).
{
int j = (idx_cur+k)&0x7;
float3 vPh = GetHullVertex(boxX, boxY, boxZ, center, scaleXY, j);
float fSignDist = idx_twin==j ? 0.0 : dot(vN, vPh-vP0);
if(fSignDist>0) ++positive; else if(fSignDist<0) ++negative;
}
int resh = (positive>0 && negative>0) ? 0 : (positive>0 ? 1 : (negative>0 ? (-1) : 0));
positive=0; negative=0;
for(int j=0; j<8; j++)
{
float3 vPf = GetTileVertex(viTilLL, viTilUR, j, fTileFarPlane);
float fSignDist = dot(vN, vPf-vP0);
if(fSignDist>0) ++positive; else if(fSignDist<0) ++negative;
}
int resf = (positive>0 && negative>0) ? 0 : (positive>0 ? 1 : (negative>0 ? (-1) : 0));
bool bFoundSepPlane = (resh*resf)<0;
if(bFoundSepPlane) InterlockedOr(ldsIsLightInvisible, 1);
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
if(threadID==0 && ldsIsLightInvisible==0)
{
coarseList[lightOffs2++] = coarseList[l];
}
}
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();
#endif
return lightOffs2;
}
#endif
[numthreads(1, 1, 1)]
void ClearAtomic(uint threadID : SV_GroupIndex, uint3 u3GroupID : SV_GroupID)
{
g_LayeredSingleIdxBuffer[0]=0;
}

9
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-clustered.compute.meta


fileFormatVersion: 2
guid: 0bb1b7e0ddcd5c44baf3ddc7456eb196
timeCreated: 1479689584
licenseType: Pro
ComputeShaderImporter:
currentAPIMask: 4
userData:
assetBundleName:
assetBundleVariant:

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


#ifndef __SHADERBASE_H__
#define __SHADERBASE_H__
#ifdef SHADER_API_PSSL
#ifndef Texture2DMS
#define Texture2DMS MS_Texture2D
#endif
#ifndef SampleCmpLevelZero
#define SampleCmpLevelZero SampleCmpLOD0
#endif
#ifndef firstbithigh
#define firstbithigh FirstSetBit_Hi
#endif
#endif
float FetchDepth(Texture2D depthTexture, uint2 pixCoord)
{
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0)).x;
}
float FetchDepthMSAA(Texture2DMS<float> depthTexture, uint2 pixCoord, uint sampleIdx)
{
return 1 - depthTexture.Load(uint3(pixCoord.xy, 0), sampleIdx).x;
}
#endif

9
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/ShaderBase.hlsl.meta


fileFormatVersion: 2
guid: 3c90176b54c922b4e9cf65c9ec9cb750
timeCreated: 1479691479
licenseType: Pro
ShaderImporter:
defaultTextures: []
userData:
assetBundleName:
assetBundleVariant:

9
Assets/ScriptableRenderLoop/HDRenderLoop/Shaders.meta


fileFormatVersion: 2
guid: fafbb144d7f66074785b7727293d89c5
folderAsset: yes
timeCreated: 1474297943
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:

192
Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/test details.mat


%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 6
m_ObjectHideFlags: 0
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0}
m_Name: test details
m_Shader: {fileID: 4800000, guid: 6e4ae4064600d784cac1e41a9e6f2e59, type: 3}
m_ShaderKeywords: _ALPHACUTOFFENABLE_OFF _DETAIL_MAP _DETAIL_MAP_WITH_NORMAL _DISTORTIONDEPTHTEST_OFF
_DISTORTIONONLY_OFF _EMISSION _NORMALMAP _NORMALMAP_TANGENT_SPACE
m_LightmapFlags: 1
m_CustomRenderQueue: -1
stringTagMap: {}
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _AmbientOcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _AnisotropyMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BaseColorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _BumpMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _CoatCoverageMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _CoatRoughnessMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailAlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailMap:
m_Texture: {fileID: 2800000, guid: d896c388b98bb614ebe6bb48e0f56dcf, type: 3}
m_Scale: {x: 0.99, y: 1}
m_Offset: {x: 1.52, y: 1}
- _DetailMask:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailNormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DetailsMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DiffuseLightingMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _DiffuseMap:
m_Texture: {fileID: 2800000, guid: d734753529ca78148a43944515a64bc5, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _EmissiveColorMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _HeightMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MainTex:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MaskMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MetallicGlossMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _MettalicMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OcclusionMap:
m_Texture: {fileID: 2800000, guid: fe2ed6aee0b5acd42bc15ee53e939e03, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ParallaxMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SmoothnessMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SpecularOcclusionMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _SubSurfaceRadiusMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _TangentMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _ThicknessMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Floats:
- _AlphaCutoff: 0.5
- _AlphaCutoffEnable: 0
- _Anisotropy: 0
- _BlendMode: 0
- _BumpScale: 1
- _CoatCoverage: 0
- _CoatRoughness: 0
- _CullMode: 2
- _Cutoff: 0.5
- _DetailAOScale: 1
- _DetailAlbedoScale: 1
- _DetailHeightScale: 1
- _DetailMapMode: 0
- _DetailNormalMapScale: 1
- _DetailNormalScale: 1
- _DetailSmoothnessScale: 1
- _DistortionDepthTest: 0
- _DistortionOnly: 0
- _DoubleSided: 1
- _DoubleSidedLigthing: 1
- _DoubleSidedMode: 0
- _DstBlend: 0
- _EmissiveColorMode: 1
- _EmissiveIntensity: 0
- _GlossMapScale: 1
- _Glossiness: 0.5
- _GlossyReflections: 1
- _HeightBias: 0
- _HeightMapMode: 0
- _HeightScale: 1
- _MaterialID: 0
- _MaterialId: 0
- _Metalic: 0
- _Metallic: 0
- _Mettalic: 0
- _Mode: 0
- _NormalMapSpace: 0
- _OcclusionStrength: 1
- _Parallax: 0.02
- _Smoothness: 0.524
- _SmoothnessTextureChannel: 0
- _SpecularHighlights: 1
- _SrcBlend: 1
- _SubSurfaceProfile: 0
- _SubSurfaceRadius: 0
- _SurfaceType: 0
- _Thickness: 0
- _UVDetail: 0
- _UVSec: 0
- _ZWrite: 1
m_Colors:
- _BaseColor: {r: 0.5588235, g: 0.5588235, b: 0.5588235, a: 1}
- _Color: {r: 1, g: 1, b: 1, a: 1}
- _DiffuseColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
- _EmissiveColor: {r: 0, g: 0, b: 0, a: 1}
- _SpecColor: {r: 0.04, g: 0.04, b: 0.04, a: 1}

8
Assets/TestScenes/HDTest/Material/HDRenderLoopMaterials/test details.mat.meta


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