浏览代码

Merge pull request #34 from Unity-Technologies/Refactor-lightloop

Refactor lightloop
/main
GitHub 8 年前
当前提交
8337fa69
共有 21 个文件被更改,包括 1130 次插入888 次删除
  1. 13
      Assets/ScriptableRenderLoop/HDRenderLoop/Debug/Resources/DebugViewTiles.shader
  2. 21
      Assets/ScriptableRenderLoop/HDRenderLoop/Editor/HDRenderLoopInspector.cs
  3. 1
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset
  4. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta
  5. 472
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  6. 16
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs
  7. 52
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl
  8. 10
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Lighting.hlsl
  9. 5
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-bigtile.compute
  10. 17
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild-clustered.compute
  11. 42
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/Resources/lightlistbuild.compute
  12. 919
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs
  13. 67
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs.hlsl
  14. 174
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.hlsl
  15. 147
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePassLoop.hlsl
  16. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  17. 3
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.shader
  18. 34
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightLoop.cs
  19. 12
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightLoop.cs.meta
  20. 9
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass.meta

13
Assets/ScriptableRenderLoop/HDRenderLoop/Debug/Resources/DebugViewTiles.shader


#endif
int n = 0;
for(int category = 0; category < NR_LIGHT_CATEGORIES; category++)
for (int category = 0; category < LIGHTCATEGORY_COUNT; category++)
uint start;
uint count;
GetCountAndStart(coord, category, linearDepth, start, count);
n += count;
if (mask & _ViewTilesFlags)
{
uint start;
uint count;
GetCountAndStart(coord, category, linearDepth, start, count);
n += count;
}
}
if (n > 0)

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


public readonly GUIContent useForwardRenderingOnly = new GUIContent("Use Forward Rendering Only");
public readonly GUIContent useDepthPrepass = new GUIContent("Use Depth Prepass");
public readonly GUIContent useSinglePassLightLoop = new GUIContent("Use single Pass light loop");
public bool isDebugViewMaterialInit = false;
public GUIContent[] debugViewMaterialStrings = null;

public readonly GUIContent shadowsCascades = new GUIContent("Cascade values");
public readonly GUIContent tileLightLoopSettings = new GUIContent("Tile Light Loop settings");
public readonly string[] tileLightLoopDebugTileFlagStrings = new string[] { "Direct Light", "Reflection Light", "Area Light"};
public readonly GUIContent directIndirectSinglePass = new GUIContent("Enable direct and indirect lighting in single pass", "Toggle");
public readonly string[] tileLightLoopDebugTileFlagStrings = new string[] { "Punctual Light", "Area Light", "Env Light"};
public readonly GUIContent splitLightEvaluation = new GUIContent("Split light and reflection evaluation", "Toggle");
public readonly GUIContent disableTileAndCluster = new GUIContent("Disable Tile/clustered", "Toggle");
public readonly GUIContent textureSettings = new GUIContent("texture Settings");

debugParameters.displayTransparentObjects = EditorGUILayout.Toggle(styles.displayTransparentObjects, debugParameters.displayTransparentObjects);
debugParameters.useForwardRenderingOnly = EditorGUILayout.Toggle(styles.useForwardRenderingOnly, debugParameters.useForwardRenderingOnly);
debugParameters.useDepthPrepass = EditorGUILayout.Toggle(styles.useDepthPrepass, debugParameters.useDepthPrepass);
debugParameters.useSinglePassLightLoop = EditorGUILayout.Toggle(styles.useSinglePassLightLoop, debugParameters.useSinglePassLightLoop);
if (EditorGUI.EndChangeCheck())
{

EditorGUILayout.Space();
if (renderLoop.tilePassLightLoop != null)
// TODO: we should call a virtual method or something similar to setup the UI, inspector should not know about it
TilePass.LightLoop tilePass = renderLoop.lightLoop as TilePass.LightLoop;
if (tilePass != null)
renderLoop.tilePassLightLoop.debugViewTilesFlags = EditorGUILayout.MaskField("DebugView Tiles", renderLoop.tilePassLightLoop.debugViewTilesFlags, styles.tileLightLoopDebugTileFlagStrings);
renderLoop.tilePassLightLoop.enableDirectIndirectSinglePass = EditorGUILayout.Toggle(styles.directIndirectSinglePass, renderLoop.tilePassLightLoop.enableDirectIndirectSinglePass);
renderLoop.tilePassLightLoop.enableBigTilePrepass = EditorGUILayout.Toggle(styles.bigTilePrepass, renderLoop.tilePassLightLoop.enableBigTilePrepass);
renderLoop.tilePassLightLoop.enableClustered = EditorGUILayout.Toggle(styles.clustered, renderLoop.tilePassLightLoop.enableClustered);
tilePass.debugViewTilesFlags = EditorGUILayout.MaskField("DebugView Tiles", tilePass.debugViewTilesFlags, styles.tileLightLoopDebugTileFlagStrings);
tilePass.enableSplitLightEvaluation = EditorGUILayout.Toggle(styles.splitLightEvaluation, tilePass.enableSplitLightEvaluation);
tilePass.enableBigTilePrepass = EditorGUILayout.Toggle(styles.bigTilePrepass, tilePass.enableBigTilePrepass);
tilePass.enableClustered = EditorGUILayout.Toggle(styles.clustered, tilePass.enableClustered);
tilePass.disableTileAndCluster = EditorGUILayout.Toggle(styles.disableTileAndCluster, tilePass.disableTileAndCluster);
if (EditorGUI.EndChangeCheck())
{

1
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset


spotCookieSize: 128
pointCookieSize: 512
reflectionCubemapSize: 128
m_Dirty: 0

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


fileFormatVersion: 2
guid: 2400b74f5ce370c4481e5dc417d03703
timeCreated: 1480436907
timeCreated: 1481084818
licenseType: Pro
NativeFormatImporter:
userData:

472
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


public bool enableTonemap = true;
public float exposure = 0;
public bool useSinglePassLightLoop = true;
}
DebugParameters m_DebugParameters = new DebugParameters();

ShadowRenderPass m_ShadowPass;
public const int k_MaxDirectionalLightsOnSCreen = 3;
public const int k_MaxPunctualLightsOnSCreen = 512;
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;

RenderTargetIdentifier m_CameraDepthBufferRT;
RenderTargetIdentifier m_VelocityBufferRT;
RenderTargetIdentifier m_DistortionBufferRT;
public class LightList
{
public List<DirectionalLightData> directionalLights;
public List<DirectionalShadowData> directionalShadows;
public List<LightData> punctualLights;
public List<PunctualShadowData> punctualShadows;
public List<LightData> areaLights;
public List<EnvLightData> envLights;
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;
// TODO: Find a way to automatically create/iterate through lightloop
// This must be init externally else The value can't be set in the inspector... (as it will recreate the class with default value)
SinglePass.LightLoop m_SinglePassLightLoop = new SinglePass.LightLoop();
TilePass.LightLoop m_TilePassLightLoop = new TilePass.LightLoop();
public TilePass.LightLoop tilePassLightLoop
// This must be allocate outside of Rebuild() else the option in the class can't be set in the inspector (as it will in this case recreate the class with default value)
BaseLightLoop m_lightLoop = new TilePass.LightLoop();
public BaseLightLoop lightLoop
get { return m_TilePassLightLoop; }
get { return m_lightLoop; }
TextureCacheCubemap m_CubeReflTexArray;
TextureCache2D m_CookieTexArray;
TextureCacheCubemap m_CubeCookieTexArray;
public void OnValidate()
{

m_DistortionBufferRT = new RenderTargetIdentifier(m_DistortionBuffer);
m_LitRenderLoop.Rebuild();
m_CookieTexArray = new TextureCache2D();
m_CookieTexArray.AllocTextureArray(8, m_TextureSettings.spotCookieSize, m_TextureSettings.spotCookieSize, TextureFormat.RGBA32, true);
m_CubeCookieTexArray = new TextureCacheCubemap();
m_CubeCookieTexArray.AllocTextureArray(4, m_TextureSettings.pointCookieSize, TextureFormat.RGBA32, true);
m_CubeReflTexArray = new TextureCacheCubemap();
m_CubeReflTexArray.AllocTextureArray(32, m_TextureSettings.reflectionCubemapSize, TextureFormat.BC6H, true);
// Init various light loop
m_SinglePassLightLoop.Rebuild();
tilePassLightLoop.Rebuild();
m_lightList = new LightList();
m_lightList.Allocate();
m_lightLoop.Rebuild(m_TextureSettings);
m_Dirty = false;
}

public override void Cleanup()
{
m_LitRenderLoop.Cleanup();
m_SinglePassLightLoop.Cleanup();
m_TilePassLightLoop.Cleanup();
m_lightLoop.Cleanup();
if (m_CubeReflTexArray != null)
{
m_CubeReflTexArray.Release();
m_CubeReflTexArray = null;
}
if (m_CookieTexArray != null)
{
m_CookieTexArray.Release();
m_CookieTexArray = null;
}
if (m_CubeCookieTexArray != null)
{
m_CubeCookieTexArray.Release();
m_CubeCookieTexArray = null;
}
if (m_SkyRenderer != null)
{
m_SkyRenderer.Cleanup();

#endif
}
void NewFrame()
{
m_CookieTexArray.NewFrame();
m_CubeCookieTexArray.NewFrame();
m_CubeReflTexArray.NewFrame();
}
// We clear only the depth buffer, no need to clear the various color buffer as we overwrite them.
// Clear depth/stencil and init buffers
// We clear only the depth buffer, no need to clear the various color buffer as we overwrite them.
// Clear depth/stencil and init buffers
cmd.name = "";
cmd.name = "";
// Init buffer
// With scriptable render loop we must allocate ourself depth and color buffer (We must be independent of backbuffer for now, hope to fix that later).

// TEMP: As we are in development and have not all the setup pass we still clear the color in emissive buffer and gbuffer, but this will be removed later.
// Clear HDR target
using (new Utilities.ProfilingSample("Clear HDR target", renderLoop))
using (new Utilities.ProfilingSample("Clear HDR target", renderLoop))
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
Utilities.SetRenderTarget(renderLoop, m_CameraColorBufferRT, m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
using (new Utilities.ProfilingSample("Clear GBuffer", renderLoop))
using (new Utilities.ProfilingSample("Clear GBuffer", renderLoop))
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
Utilities.SetRenderTarget(renderLoop, m_gbufferManager.GetGBuffers(), m_CameraDepthBufferRT, ClearFlag.ClearColor, Color.black);
}
// END TEMP

if (debugParameters.useDepthPrepass)
return;
using (new Utilities.ProfilingSample("Depth Prepass", renderLoop))
using (new Utilities.ProfilingSample("Forward opaque depth", renderLoop))
// or use the new MAterial.SetPassEnable ?
Utilities.SetRenderTarget(renderLoop, m_CameraDepthBufferRT);
RenderOpaqueRenderList(cull, camera, renderLoop, "DepthOnly");
}

// Bind material data
m_LitRenderLoop.Bind();
if (debugParameters.useSinglePassLightLoop)
{
m_SinglePassLightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBuffer);
}
else
{
tilePassLightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBufferRT);
}
m_lightLoop.RenderDeferredLighting(camera, renderLoop, m_CameraColorBuffer);
}
void RenderSky(Camera camera, RenderLoop renderLoop)

void RenderForward(CullResults cullResults, Camera camera, RenderLoop renderLoop)
void RenderForward(CullResults cullResults, Camera camera, RenderLoop renderLoop, bool renderOpaque)
// TODO: Currently we can't render opaque object forward when deferred is enabled
// miss option
if (!debugParameters.useForwardRenderingOnly && renderOpaque)
return;
using (new Utilities.ProfilingSample("Forward Pass", renderLoop))
{
// Bind material data

if (debugParameters.useForwardRenderingOnly)
m_lightLoop.RenderForward(camera, renderLoop, renderOpaque);
if (renderOpaque)
RenderTransparentRenderList(cullResults, camera, renderLoop, "Forward", Utilities.kRendererConfigurationBakedLighting);
else
{
RenderTransparentRenderList(cullResults, camera, renderLoop, "Forward", Utilities.kRendererConfigurationBakedLighting);
}
}
}

}
}
void PrepareLightsForGPU(CullResults cullResults, Camera camera, ref ShadowOutput shadowOutput, ref LightList lightList)
void PrepareLightsForGPU(CullResults cullResults, Camera camera, ref ShadowOutput shadowOutput)
lightList.Clear();
for (int lightIndex = 0, numLights = cullResults.visibleLights.Length; lightIndex < numLights; ++lightIndex)
{
var light = cullResults.visibleLights[lightIndex];
// We only process light with additional data
var additionalData = light.light.GetComponent<AdditionalLightData>();
if (additionalData == null)
{
Debug.LogWarning("Light entity detected without additional data, will not be taken into account " + light.light.name);
continue;
}
// Linear intensity calculation (different Unity 5.5)
var lightColorR = light.light.intensity * Mathf.GammaToLinearSpace(light.light.color.r);
var lightColorG = light.light.intensity * Mathf.GammaToLinearSpace(light.light.color.g);
var lightColorB = light.light.intensity * Mathf.GammaToLinearSpace(light.light.color.b);
if (light.lightType == LightType.Directional)
{
if (lightList.directionalLights.Count >= k_MaxDirectionalLightsOnSCreen)
continue;
var directionalLightData = new DirectionalLightData();
// Light direction for directional and is opposite to the forward direction
directionalLightData.direction = -light.light.transform.forward;
directionalLightData.up = light.light.transform.up;
directionalLightData.right = light.light.transform.right;
directionalLightData.positionWS = light.light.transform.position;
directionalLightData.color = new Vector3(lightColorR, lightColorG, lightColorB);
directionalLightData.diffuseScale = additionalData.affectDiffuse ? 1.0f : 0.0f;
directionalLightData.specularScale = additionalData.affectSpecular ? 1.0f : 0.0f;
directionalLightData.invScaleX = 1.0f / light.light.transform.localScale.x;
directionalLightData.invScaleY = 1.0f / light.light.transform.localScale.y;
directionalLightData.cosAngle = 0.0f;
directionalLightData.sinAngle = 0.0f;
directionalLightData.shadowIndex = -1;
directionalLightData.cookieIndex = -1;
if (light.light.cookie != null)
{
directionalLightData.tileCookie = (light.light.cookie.wrapMode == TextureWrapMode.Repeat);
directionalLightData.cookieIndex = m_CookieTexArray.FetchSlice(light.light.cookie);
}
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.directionalLights.Add(directionalLightData);
lightList.directionalCullIndices.Add(lightIndex);
continue;
}
// Note: LightType.Area is offline only, use for baking, no need to test it
var lightData = new LightData();
// Test whether we should treat this punctual light as an area light.
// It's a temporary hack until the proper UI support is added.
if (additionalData.archetype != LightArchetype.Punctual)
{
// Early out if we reach the maximum
if (lightList.areaLights.Count >= k_MaxAreaLightsOnSCreen)
continue;
if (additionalData.archetype == LightArchetype.Rectangle)
{
lightData.lightType = GPULightType.Rectangle;
}
else
{
lightData.lightType = GPULightType.Line;
}
}
else
{
if (lightList.punctualLights.Count >= k_MaxPunctualLightsOnSCreen)
continue;
switch (light.lightType)
{
case LightType.Directional: lightData.lightType = GPULightType.Directional; break;
case LightType.Spot: lightData.lightType = GPULightType.Spot; break;
case LightType.Point: lightData.lightType = GPULightType.Point; break;
}
}
lightData.positionWS = light.light.transform.position;
lightData.invSqrAttenuationRadius = 1.0f / (light.range * light.range);
lightData.color = new Vector3(lightColorR, lightColorG, lightColorB);
lightData.forward = light.light.transform.forward; // Note: Light direction is oriented backward (-Z)
lightData.up = light.light.transform.up;
lightData.right = light.light.transform.right;
if (lightData.lightType == GPULightType.Spot)
{
var spotAngle = light.spotAngle;
var innerConePercent = additionalData.GetInnerSpotPercent01();
var cosSpotOuterHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * Mathf.Deg2Rad), 0.0f, 1.0f);
var sinSpotOuterHalfAngle = Mathf.Sqrt(1.0f - cosSpotOuterHalfAngle * cosSpotOuterHalfAngle);
var cosSpotInnerHalfAngle = Mathf.Clamp(Mathf.Cos(spotAngle * 0.5f * innerConePercent * Mathf.Deg2Rad), 0.0f, 1.0f); // inner cone
var val = Mathf.Max(0.001f, (cosSpotInnerHalfAngle - cosSpotOuterHalfAngle));
lightData.angleScale = 1.0f / val;
lightData.angleOffset = -cosSpotOuterHalfAngle * lightData.angleScale;
// TODO: find a proper place to store the cotangent.
lightData.size.x = cosSpotOuterHalfAngle / sinSpotOuterHalfAngle;
}
else
{
// 1.0f, 2.0f are neutral value allowing GetAngleAnttenuation in shader code to return 1.0
lightData.angleScale = 1.0f;
lightData.angleOffset = 2.0f;
}
lightData.diffuseScale = additionalData.affectDiffuse ? 1.0f : 0.0f;
lightData.specularScale = additionalData.affectSpecular ? 1.0f : 0.0f;
lightData.shadowDimmer = additionalData.shadowDimmer;
lightData.IESIndex = -1;
lightData.cookieIndex = -1;
lightData.shadowIndex = -1;
if (light.light.cookie != null)
{
// TODO: add texture atlas support for cookie textures.
switch (light.lightType)
{
case LightType.Spot:
lightData.cookieIndex = m_CookieTexArray.FetchSlice(light.light.cookie);
break;
case LightType.Point:
lightData.cookieIndex = m_CubeCookieTexArray.FetchSlice(light.light.cookie);
break;
}
}
// Setup shadow data arrays
bool hasShadows = light.light.shadows != LightShadows.None && shadowOutput.GetShadowSliceCountLightIndex(lightIndex) != 0;
bool hasNotReachMaxLimit = lightList.punctualShadows.Count + (lightData.lightType == GPULightType.Point ? 6 : 1) <= k_MaxShadowOnScreen;
if (hasShadows && hasNotReachMaxLimit) // Note < MaxShadows should be check at shadowOutput creation
{
// When we have a point light, we assumed that there is 6 consecutive PunctualShadowData
lightData.shadowIndex = lightList.punctualShadows.Count;
for (int sliceIndex = 0; sliceIndex < shadowOutput.GetShadowSliceCountLightIndex(lightIndex); ++sliceIndex)
{
PunctualShadowData punctualShadowData = new PunctualShadowData();
int shadowSliceIndex = shadowOutput.GetShadowSliceIndex(lightIndex, sliceIndex);
punctualShadowData.worldToShadow = shadowOutput.shadowSlices[shadowSliceIndex].shadowTransform.transpose; // Transpose for hlsl reading ?
punctualShadowData.lightType = lightData.lightType;
punctualShadowData.bias = light.light.shadowBias;
lightList.punctualShadows.Add(punctualShadowData);
}
}
if (additionalData.archetype == LightArchetype.Punctual)
{
lightList.punctualLights.Add(lightData);
lightList.punctualCullIndices.Add(lightIndex);
}
else
{
lightData.twoSided = additionalData.isDoubleSided;
lightData.size = new Vector2(additionalData.areaLightLength,
additionalData.areaLightWidth);
// Area and line lights are both currently stored as area lights on the GPU.
lightList.areaLights.Add(lightData);
lightList.areaCullIndices.Add(lightIndex);
}
}
for (int probeIndex = 0, numProbes = cullResults.visibleReflectionProbes.Length; probeIndex < numProbes; probeIndex++)
{
var probe = cullResults.visibleReflectionProbes[probeIndex];
// If probe have not been rendered discard
if (probe.texture == null)
continue;
if (lightList.envLights.Count >= k_MaxEnvLightsOnSCreen)
continue;
var envLightData = new EnvLightData();
// CAUTION: localToWorld is the transform for the widget of the reflection probe. i.e the world position of the point use to do the cubemap capture (mean it include the local offset)
envLightData.positionWS = probe.localToWorld.GetColumn(3);
envLightData.envShapeType = EnvShapeType.None;
// TODO: Support sphere in the interface
if (probe.boxProjection != 0)
{
envLightData.envShapeType = EnvShapeType.Box;
}
// remove scale from the matrix (Scale in this matrix is use to scale the widget)
envLightData.right = probe.localToWorld.GetColumn(0);
envLightData.right.Normalize();
envLightData.up = probe.localToWorld.GetColumn(1);
envLightData.up.Normalize();
envLightData.forward = probe.localToWorld.GetColumn(2);
envLightData.forward.Normalize();
// Artists prefer to have blend distance inside the volume!
// So we let the current UI but we assume blendDistance is an inside factor instead
// Blend distance can't be larger than the max radius
// probe.bounds.extents is BoxSize / 2
float maxBlendDist = Mathf.Min(probe.bounds.extents.x, Mathf.Min(probe.bounds.extents.y, probe.bounds.extents.z));
float blendDistance = Mathf.Min(maxBlendDist, probe.blendDistance);
envLightData.innerDistance = probe.bounds.extents - new Vector3(blendDistance, blendDistance, blendDistance);
envLightData.envIndex = m_CubeReflTexArray.FetchSlice(probe.texture);
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);
}
if (debugParameters.useSinglePassLightLoop)
{
m_SinglePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
}
else
{
tilePassLightLoop.PrepareLightsForGPU(cullResults, camera, m_lightList);
}
m_lightLoop.PrepareLightsForGPU(cullResults, camera, ref shadowOutput);
}
void Resize(Camera camera)

// For now consider we have only one camera that go to this code, the main one.
m_SkyRenderer.Resize(m_SkyParameters); // TODO: Also a bad naming, here we just want to realloc texture if skyparameters change (usefull for lookdev)
if (camera.pixelWidth != m_WidthOnRecord || camera.pixelHeight != m_HeightOnRecord || tilePassLightLoop.NeedResize())
if (camera.pixelWidth != m_WidthOnRecord || camera.pixelHeight != m_HeightOnRecord || m_lightLoop.NeedResize())
tilePassLightLoop.ReleaseResolutionDependentBuffers();
m_lightLoop.ReleaseResolutionDependentBuffers();
tilePassLightLoop.AllocResolutionDependentBuffers(camera.pixelWidth, camera.pixelHeight);
m_lightLoop.AllocResolutionDependentBuffers(camera.pixelWidth, camera.pixelHeight);
// update recorded window resolution
m_WidthOnRecord = camera.pixelWidth;

public void PushGlobalParams(Camera camera, RenderLoop renderLoop, HDRenderLoop.LightList lightList)
public void PushGlobalParams(Camera camera, RenderLoop renderLoop)
Shader.SetGlobalTexture("_CookieTextures", m_CookieTexArray.GetTexCache());
Shader.SetGlobalTexture("_CookieCubeTextures", m_CubeCookieTexArray.GetTexCache());
Shader.SetGlobalTexture("_EnvTextures", m_CubeReflTexArray.GetTexCache());
if (m_SkyRenderer.IsSkyValid(m_SkyParameters))
{
m_SkyRenderer.SetGlobalSkyTexture();

Shader.SetGlobalInt("_EnvLightSkyEnabled", 0);
}
if (debugParameters.useSinglePassLightLoop)
{
m_SinglePassLightLoop.PushGlobalParams(camera, renderLoop, lightList);
}
else
{
tilePassLightLoop.PushGlobalParams(camera, renderLoop, lightList);
}
m_lightLoop.PushGlobalParams(camera, renderLoop);
}
public override void Render(Camera[] cameras, RenderLoop renderLoop)

}
// Do anything we need to do upon a new frame.
NewFrame();
m_lightLoop.NewFrame();
// Set Frame constant buffer
// TODO...

RenderDepthPrepass(cullResults, camera, renderLoop);
RenderGBuffer(cullResults, camera, renderLoop);
RenderGBuffer(cullResults, camera, renderLoop);
// For tile lighting with forward opaque
// Forward opaque with deferred tile require that we fill the depth buffer
// correctly to build the light list.
// TODO: avoid double lighting by tagging stencil or gbuffer that we must not lit.
// TODO: ask Morten why this pass is not before GBuffer ? Will make more sense and avoid
// to do gbuffer pass on unseen mesh.
// TODO: how do we select only the object that must be render forward ?
// this is all object with gbuffer pass disabled ?
//RenderForwardOpaqueDepth(cullResults, camera, renderLoop);
if (debugParameters.debugViewMaterial != 0)

using (new Utilities.ProfilingSample("Build Light list", renderLoop))
{
PrepareLightsForGPU(cullResults, camera, ref shadows, ref m_lightList);
if (!debugParameters.useSinglePassLightLoop)
tilePassLightLoop.BuildGPULightLists(camera, renderLoop, m_lightList, m_CameraDepthBufferRT);
m_lightLoop.PrepareLightsForGPU(cullResults, camera, ref shadows);
m_lightLoop.BuildGPULightLists(camera, renderLoop, m_CameraDepthBufferRT);
PushGlobalParams(camera, renderLoop, m_lightList);
PushGlobalParams(camera, renderLoop);
RenderForward(cullResults, camera, renderLoop, true);
RenderForward(cullResults, camera, renderLoop); // Note: We want to render forward opaque before RenderSky, then RenderTransparent - can only do that once we have material.SetPass feature...
RenderForward(cullResults, camera, renderLoop, false);
RenderForwardUnlit(cullResults, camera, renderLoop);
RenderVelocity(cullResults, camera, renderLoop); // Note we may have to render velocity earlier if we do temporalAO, temporal volumetric etc... Mean we will not take into account forward opaque in case of deferred rendering ?

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


[GenerateHLSL]
public struct DirectionalLightData
{
public Vector3 direction;
public Vector3 forward;
public float diffuseScale;
public Vector3 up;

// TODO: we may have to add various parameters here for shadow - was suppose to be coupled with a light loop
// A point light is 6x PunctualShadowData
[GenerateHLSL]
public struct PunctualShadowData
public struct ShadowData
{
// World to ShadowMap matrix
// Include scale and bias for shadow atlas if any

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]

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


// PackingRules = Exact
struct DirectionalLightData
{
float3 direction;
float3 forward;
float diffuseScale;
float3 up;
float invScaleY;

int cookieIndex;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.PunctualShadowData
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.ShadowData
struct PunctualShadowData
struct ShadowData
{
float4x4 worldToShadow;
int lightType;

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

//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.DirectionalLightData
//
float3 GetDirection(DirectionalLightData value)
float3 GetForward(DirectionalLightData value)
return value.direction;
return value.forward;
}
float GetDiffuseScale(DirectionalLightData value)
{

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.PunctualShadowData
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.ShadowData
float4x4 GetWorldToShadow(PunctualShadowData value)
float4x4 GetWorldToShadow(ShadowData value)
int GetLightType(PunctualShadowData value)
int GetLightType(ShadowData value)
float GetBias(PunctualShadowData value)
float GetBias(ShadowData value)
float GetQuality(PunctualShadowData value)
float GetQuality(ShadowData value)
float GetUnused(PunctualShadowData value)
float GetUnused(ShadowData value)
}
//
// 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;
}
//

10
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/Lighting.hlsl


#define HAS_LIGHTLOOP // Allow to not define LightLoop related function in Material.hlsl
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl"
#ifdef LIGHTLOOP_SINGLE_PASS
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.hlsl"
#elif defined(LIGHTLOOP_TILE_PASS)
#if defined(LIGHTLOOP_SINGLE_PASS) || defined(LIGHTLOOP_TILE_PASS)
#include "Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.hlsl"
#endif

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

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


uniform float4x4 g_mScrProjection;
uniform float g_fNearPlane;
uniform float g_fFarPlane;
uniform int _EnvLightIndexShift;
StructuredBuffer<LightShapeData> _LightShapeData : register(t2);
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );

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

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


uniform int g_iNrVisibLights;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform int _EnvLightIndexShift;
uniform float g_fClustScale;
uniform float g_fClustBase;

Texture2D g_depth_tex : register( t0 );
#endif
StructuredBuffer<float3> g_vBoundsBuffer : register( t1 );
StructuredBuffer<LightShapeData> _LightShapeData : register(t2);
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#ifdef USE_TWO_PASS_TILED_LIGHTING

InterlockedAdd(g_LayeredSingleIdxBuffer[0], (uint) iSpaceAvail, start); // alloc list memory
}
int categoryListCount[NR_LIGHT_CATEGORIES]={0,0,0}; // direct light count and reflection lights
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
int categoryListCount[LIGHTCATEGORY_COUNT]={0,0,0}; // direct light count and reflection lights
uint offs = start;
for(int ll=0; ll<iNrCoarseLights; ll+=4)
{

{
if(offs<(start+iSpaceAvail) && i<nrClusters && CheckIntersection(l, i, viTilLL.xy, viTilUR.xy, suggestedBase) )
{
uint lightCategory = _LightShapeData[coarseList[l]].lightCategory;
uint lightCategory = _LightVolumeData[coarseList[l]].lightCategory;
g_vLayeredLightList[offs++] = _LightShapeData[coarseList[l]].lightIndex; // reflection lights will be last since we sorted
g_vLayeredLightList[offs++] = coarseList[l] - shiftIndex[lightCategory]; // reflection lights will be last since we sorted
}
}

uint localOffs=0;
offs = i*nrTilesX*nrTilesY + tileIDX.y*nrTilesX + tileIDX.x;
for(int category=0; category<NR_LIGHT_CATEGORIES; category++)
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{
int numLights = min(categoryListCount[category],31); // only allow 5 bits
if(i<nrClusters)

GroupMemoryBarrierWithGroupSync();
#endif
const int idxCoarse = coarseList[l];
[branch]if (_LightShapeData[idxCoarse].lightVolume != SPHERE_VOLUME) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
[branch]if (_LightVolumeData[idxCoarse].lightVolume != LIGHTVOLUMETYPE_SPHERE) // don't bother doing edge tests for sphere lights since these have camera aligned bboxes.
{
SFiniteLightBound lgtDat = g_data[idxCoarse];

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


uniform uint2 g_viDimensions;
uniform float4x4 g_mInvScrProjection;
uniform float4x4 g_mScrProjection;
uniform int _EnvLightIndexShift;
StructuredBuffer<LightShapeData> _LightShapeData : register(t2);
StructuredBuffer<LightVolumeData> _LightVolumeData : register(t2);
StructuredBuffer<SFiniteLightBound> g_data : register( t3 );
#ifdef USE_TWO_PASS_TILED_LIGHTING

#endif
groupshared int ldsNrLightsFinal;
groupshared int ldsCategoryListCount[NR_LIGHT_CATEGORIES]; // since NR_LIGHT_CATEGORIES is 3
groupshared int ldsCategoryListCount[LIGHTCATEGORY_COUNT]; // since LIGHTCATEGORY_COUNT is 3
#ifdef PERFORM_SPHERICAL_INTERSECTION_TESTS
groupshared uint lightOffsSph;

#endif
//
if(t<NR_LIGHT_CATEGORIES) ldsCategoryListCount[t]=0;
if(t<LIGHTCATEGORY_COUNT) ldsCategoryListCount[t]=0;
#if !defined(SHADER_API_XBOXONE) && !defined(SHADER_API_PSSL)
GroupMemoryBarrierWithGroupSync();

int nrLightsCombinedList = min(ldsNrLightsFinal,MAX_NR_COARSE_ENTRIES);
for(int i=t; i<nrLightsCombinedList; i+=NR_THREADS)
{
InterlockedAdd(ldsCategoryListCount[_LightShapeData[prunedList[i]].lightCategory], 1);
InterlockedAdd(ldsCategoryListCount[_LightVolumeData[prunedList[i]].lightCategory], 1);
}

int localOffs=0;
int offs = tileIDX.y*nrTilesX + tileIDX.x;
for(int category=0; category<NR_LIGHT_CATEGORIES; category++)
// All our cull data are in the same list, but at render time envLights are separated so we need to shit the index
// to make it work correctly
int shiftIndex[LIGHTCATEGORY_COUNT] = {0, 0, _EnvLightIndexShift}; // 3 for now, will throw an error if we change LIGHTCATEGORY_COUNT
for(int category=0; category<LIGHTCATEGORY_COUNT; category++)
{
int nrLightsFinal = ldsCategoryListCount[category];
int nrLightsFinalClamped = nrLightsFinal<MAX_NR_PRUNED_ENTRIES ? nrLightsFinal : MAX_NR_PRUNED_ENTRIES;

for(int l=(int) t; l<(int) nrDWords; l += NR_THREADS)
{
// We remap the prunedList index to the original LightData / EnvLightData indices
uint uLow = l==0 ? nrLightsFinalClamped : _LightShapeData[prunedList[2*l-1+localOffs]].lightIndex;
uint uHigh = _LightShapeData[prunedList[2 * l + 0 + localOffs]].lightIndex;
uint uLow = l==0 ? nrLightsFinalClamped : prunedList[2*l-1+localOffs] - shiftIndex[category];
uint uHigh = prunedList[2 * l + 0 + localOffs] - shiftIndex[category];
g_vLightList[16*offs + l] = (uLow&0xffff) | (uHigh<<16);
}

{
// fetch light
int idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uint uLightVolume = l<iNrCoarseLights ? _LightShapeData[idxCoarse].lightVolume : 0;
uint uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
while(l<iNrCoarseLights && uLightVolume==SPOT_VOLUME)
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_CONE)
LightShapeData lightData = _LightShapeData[idxCoarse];
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// TODO: Change by SebL
const bool bIsSpotDisc = true; // (lightData.flags&IS_CIRCULAR_SPOT_SHAPE) != 0;

uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightShapeData[idxCoarse].lightVolume : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
while(l<iNrCoarseLights && uLightVolume==SPHERE_VOLUME)
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_SPHERE)
LightShapeData lightData = _LightShapeData[idxCoarse];
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;

uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightShapeData[idxCoarse].lightVolume : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
while(l<iNrCoarseLights && uLightVolume==BOX_VOLUME)
while(l<iNrCoarseLights && uLightVolume==LIGHTVOLUMETYPE_BOX)
LightShapeData lightData = _LightShapeData[idxCoarse];
LightVolumeData lightData = _LightVolumeData[idxCoarse];
// serially check 4 pixels
uint uVal = 0;

uLightsFlags[l<32 ? 0 : 1] |= (uVal<<(l&31));
++l; idxCoarse = l<iNrCoarseLights ? coarseList[l] : 0;
uLightVolume = l<iNrCoarseLights ? _LightShapeData[idxCoarse].lightVolume : 0;
uLightVolume = l<iNrCoarseLights ? _LightVolumeData[idxCoarse].lightVolume : 0;
if(uLightVolume >=MAX_VOLUME_TYPES) ++l;
if(uLightVolume >=LIGHTVOLUMETYPE_COUNT) ++l;
}
InterlockedOr(ldsDoesLightIntersect[0], uLightsFlags[0]);

919
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/TilePass/TilePass.cs
文件差异内容过多而无法显示
查看文件

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


#ifndef TILEPASS_CS_HLSL
#define TILEPASS_CS_HLSL
//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeType: static fields
//
#define LIGHTVOLUMETYPE_CONE (0)
#define LIGHTVOLUMETYPE_SPHERE (1)
#define LIGHTVOLUMETYPE_BOX (2)
#define LIGHTVOLUMETYPE_COUNT (3)
//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightCategory: static fields
//
#define LIGHTCATEGORY_PUNCTUAL (0)
#define LIGHTCATEGORY_AREA (1)
#define LIGHTCATEGORY_ENV (2)
#define LIGHTCATEGORY_COUNT (3)
//
// UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightDefinitions: static fields
//
#define MAX_NR_LIGHTS_PER_CAMERA (1024)

#define HAS_COOKIE_TEXTURE (2)
#define IS_BOX_PROJECTED (4)
#define HAS_SHADOW (8)
#define MAX_VOLUME_TYPES (3)
#define SPOT_VOLUME (0)
#define SPHERE_VOLUME (1)
#define BOX_VOLUME (2)
#define DIRECTIONAL_VOLUME (3)
#define NR_LIGHT_CATEGORIES (3)
#define DIRECT_LIGHT_CATEGORY (0)
#define REFLECTION_LIGHT_CATEGORY (1)
#define AREA_LIGHT_CATEGORY (2)
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.TilePass.SFiniteLightBound
// PackingRules = Exact

float radius;
};
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightShapeData
// Generated from UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeData
struct LightShapeData
struct LightVolumeData
uint lightIndex;
uint lightVolume;
uint lightVolume;
uint lightCategory;
uint lightCategory;
float unused;
float3 boxInvRange;
float unused2;
};

}
//
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightShapeData
// Accessors for UnityEngine.Experimental.ScriptableRenderLoop.TilePass.LightVolumeData
float3 GetLightPos(LightShapeData value)
float3 GetLightPos(LightVolumeData value)
uint GetLightIndex(LightShapeData value)
uint GetLightVolume(LightVolumeData value)
return value.lightIndex;
return value.lightVolume;
float3 GetLightAxisX(LightShapeData value)
float3 GetLightAxisX(LightVolumeData value)
uint GetLightVolume(LightShapeData value)
uint GetLightCategory(LightVolumeData value)
return value.lightVolume;
return value.lightCategory;
float3 GetLightAxisY(LightShapeData value)
float3 GetLightAxisY(LightVolumeData value)
float GetRadiusSq(LightShapeData value)
float GetRadiusSq(LightVolumeData value)
float3 GetLightAxisZ(LightShapeData value)
float3 GetLightAxisZ(LightVolumeData value)
float GetCotan(LightShapeData value)
float GetCotan(LightVolumeData value)
float3 GetBoxInnerDist(LightShapeData value)
float3 GetBoxInnerDist(LightVolumeData value)
uint GetLightCategory(LightShapeData value)
float GetUnused(LightVolumeData value)
return value.lightCategory;
return value.unused;
float3 GetBoxInvRange(LightShapeData value)
float3 GetBoxInvRange(LightVolumeData value)
float GetUnused2(LightShapeData value)
float GetUnused2(LightVolumeData value)
{
return value.unused2;
}

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


Buffer<float> g_logBaseBuffer;
//#endif
// TODO: Need to correctly define the shadow framework, WIP
#include "../SinglePass/SinglePass.hlsl"
StructuredBuffer<DirectionalLightData> _DirectionalLightDatas;
StructuredBuffer<LightData> _LightDatas;
StructuredBuffer<EnvLightData> _EnvLightDatas;
StructuredBuffer<ShadowData> _ShadowDatas;
// Use texture atlas for shadow map
//TEXTURE2D(_ShadowAtlas);
//SAMPLER2D_SHADOW(sampler_ShadowAtlas);
//SAMPLER2D(sampler_ManualShadowAtlas); // TODO: settings sampler individually is not supported in shader yet...
TEXTURE2D(g_tShadowBuffer) // TODO: No choice, the name is hardcoded in ShadowrenderPass.cs for now. Need to change this!
SAMPLER2D_SHADOW(samplerg_tShadowBuffer);
// Use texture array for IES
TEXTURE2D_ARRAY(_IESArray);
SAMPLER2D(sampler_IESArray);
// Used by directional and spot lights
TEXTURE2D_ARRAY(_CookieTextures);
SAMPLER2D(sampler_CookieTextures);
// Used by point lights
TEXTURECUBE_ARRAY(_CookieCubeTextures);
SAMPLERCUBE(sampler_CookieCubeTextures);
// Use texture array for reflection
TEXTURECUBE_ARRAY(_EnvTextures);
SAMPLERCUBE(sampler_EnvTextures);
TEXTURECUBE(_SkyTexture);
SAMPLERCUBE(sampler_SkyTexture); // NOTE: Sampler could be share here with _EnvTextures. Don't know if the shader compiler will complain...
CBUFFER_START(UnityPerLightLoop)
uint _DirectionalLightCount;
uint _PunctualLightCount;
uint _AreaLightCount;
uint _EnvLightCount;
float4 _DirShadowSplitSpheres[4]; // TODO: share this max between C# and hlsl
int _EnvLightSkyEnabled; // TODO: make it a bool
CBUFFER_END
struct LightLoopContext
{
int sampleShadow;
int sampleReflection;
};
//-----------------------------------------------------------------------------
// Shadow sampling function
// ----------------------------------------------------------------------------
float GetPunctualShadowAttenuation(LightLoopContext lightLoopContext, float3 positionWS, int index, float3 L, float2 unPositionSS)
{
int faceIndex = 0;
if (_ShadowDatas[index].lightType == GPULIGHTTYPE_POINT)
{
GetCubeFaceID(L, faceIndex);
}
ShadowData shadowData = _ShadowDatas[index + faceIndex];
// 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.001;
#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);
}
// 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 _ShadowDatas
uint shadowSplitIndex = GetSplitSphereIndexForDirshadows(positionWS, _DirShadowSplitSpheres);
ShadowData shadowData = _ShadowDatas[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);
}
//-----------------------------------------------------------------------------
// Cookie sampling functions
// ----------------------------------------------------------------------------
// Used by directional and spot lights.
// Returns the color in the RGB components, and the transparency (lack of occlusion) in A.
float4 SampleCookie2D(LightLoopContext lightLoopContext, float2 coord, int index)
{
return SAMPLE_TEXTURE2D_ARRAY_LOD(_CookieTextures, sampler_CookieTextures, coord, index, 0);
}
// Used by point lights.
// Returns the color in the RGB components, and the transparency (lack of occlusion) in A.
float4 SampleCookieCube(LightLoopContext lightLoopContext, float3 coord, int index)
{
return SAMPLE_TEXTURECUBE_ARRAY_LOD(_CookieCubeTextures, sampler_CookieCubeTextures, coord, index, 0);
}
//-----------------------------------------------------------------------------
// IES sampling function
// ----------------------------------------------------------------------------
// sphericalTexCoord is theta and phi spherical coordinate
float4 SampleIES(LightLoopContext lightLoopContext, int index, float2 sphericalTexCoord, float lod)
{
return SAMPLE_TEXTURE2D_ARRAY_LOD(_IESArray, sampler_IESArray, sphericalTexCoord, index, 0);
}
//-----------------------------------------------------------------------------
// Reflection proble / Sky sampling function
// ----------------------------------------------------------------------------
#define SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES 0
#define SINGLE_PASS_CONTEXT_SAMPLE_SKY 1
// Note: index is whatever the lighting architecture want, it can contain information like in which texture to sample (in case we have a compressed BC6H texture and an uncompressed for real time reflection ?)
// EnvIndex can also be use to fetch in another array of struct (to atlas information etc...).
float4 SampleEnv(LightLoopContext lightLoopContext, int index, float3 texCoord, float lod)
{
// This code will be inlined as lightLoopContext is hardcoded in the light loop
if (lightLoopContext.sampleReflection == SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES)
{
return SAMPLE_TEXTURECUBE_ARRAY_LOD(_EnvTextures, sampler_EnvTextures, texCoord, index, lod);
}
else // SINGLE_PASS_SAMPLE_SKY
{
return SAMPLE_TEXTURECUBE_LOD(_SkyTexture, sampler_SkyTexture, texCoord, lod);
}
}

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


// LightLoop
// ----------------------------------------------------------------------------
#ifdef LIGHTLOOP_TILE_PASS
// Calculate the offset in global light index light for current light category
int GetTileOffset(Coordinate coord, uint lightCategory)
{

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

#ifdef PROCESS_PUNCTUAL_LIGHT
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
GetCountAndStart(coord, DIRECT_LIGHT_CATEGORY, linearDepth, punctualLightStart, punctualLightCount);
GetCountAndStart(coord, LIGHTCATEGORY_PUNCTUAL, linearDepth, punctualLightStart, punctualLightCount);
EvaluateBSDF_Punctual( context, V, positionWS, prelightData, _PunctualLightList[FetchIndex(punctualLightStart, i)], bsdfData,
EvaluateBSDF_Punctual( context, V, positionWS, prelightData, _LightDatas[FetchIndex(punctualLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;

#ifdef PROCESS_AREA_LIGHT
// TODO: Area lights are where the sorting is important (Morten approach with while loop)
// TODO: Convert the for loop below to a while on each type as we know we are sorted!
GetCountAndStart(coord, AREA_LIGHT_CATEGORY, linearDepth, areaLightStart, areaLightCount);
GetCountAndStart(coord, LIGHTCATEGORY_AREA, linearDepth, areaLightStart, areaLightCount);
if(_AreaLightList[i].lightType == GPULIGHTTYPE_LINE)
uint areaIndex = FetchIndex(areaLightStart, i);
if(_LightDatas[areaIndex].lightType == GPULIGHTTYPE_LINE)
EvaluateBSDF_Line(context, V, positionWS, prelightData, _AreaLightList[FetchIndex(areaLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Line( context, V, positionWS, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Area(context, V, positionWS, prelightData, _AreaLightList[FetchIndex(areaLightStart, i)], bsdfData,
localDiffuseLighting, localSpecularLighting);
EvaluateBSDF_Area( context, V, positionWS, prelightData, _LightDatas[areaIndex], bsdfData,
localDiffuseLighting, localSpecularLighting);
}

#endif
#ifdef PROCESS_ENV_LIGHT
uint envLightStart;
uint envLightCount;
GetCountAndStart(coord, REFLECTION_LIGHT_CATEGORY, linearDepth, envLightStart, envLightCount);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, positionWS, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
uint envLightStart;
uint envLightCount;
GetCountAndStart(coord, LIGHTCATEGORY_ENV, linearDepth, envLightStart, envLightCount);
EvaluateBSDF_Env(context, V, positionWS, prelightData, _EnvLightList[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
EvaluateBSDF_Env(context, V, positionWS, prelightData, _EnvLightDatas[FetchIndex(envLightStart, i)], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}

#endif
// Currently do lightmap with indirect specula
// TODO: test what is the most appropriate here...
#ifdef PROCESS_ENV_LIGHT
// TODO: HACK: to avoid the message Fragment program 'Frag': sampler 'sampler_PreIntegratedFGD' has no matching texture and will be undefined.
// we sample the GI during direct lighting, so FGD texture is used...
#ifdef LIGHTLOOP_TILE_DIRECT
#else // LIGHTLOOP_SINGLE_PASS
// bakeDiffuseLighting is part of the prototype so a user is able to implement a "base pass" with GI and multipass direct light (aka old unity rendering path)
void LightLoop( float3 V, float3 positionWS, Coordinate coord, PreLightData prelightData, BSDFData bsdfData, float3 bakeDiffuseLighting,
out float3 diffuseLighting,
out float3 specularLighting)
{
LightLoopContext context;
ZERO_INITIALIZE(LightLoopContext, context);
diffuseLighting = float3(0.0, 0.0, 0.0);
specularLighting = float3(0.0, 0.0, 0.0);
uint i = 0; // Declare once to avoid the D3D11 compiler warning.
for (i = 0; i < _DirectionalLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Directional( context, V, positionWS, prelightData, _DirectionalLightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
for (i = 0; i < _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
EvaluateBSDF_Punctual( context, V, positionWS, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// Area are store with punctual, just offset the index
for (i = _PunctualLightCount; i < _AreaLightCount + _PunctualLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
if (_LightDatas[i].lightType == GPULIGHTTYPE_LINE)
{
EvaluateBSDF_Line( context, V, positionWS, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
else
{
EvaluateBSDF_Area( context, V, positionWS, prelightData, _LightDatas[i], bsdfData,
localDiffuseLighting, localSpecularLighting);
}
diffuseLighting += localDiffuseLighting;
specularLighting += localSpecularLighting;
}
// TODO: Check the reflection hierarchy, for the current system (matching legacy unity) we must sort from bigger solid angle to lower (lower override bigger). So begging by sky
// TODO: Change the way it is done by reversing the order, from smaller solid angle to bigger, so we can early out when the weight is 1.
float3 iblDiffuseLighting = float3(0.0, 0.0, 0.0);
float3 iblSpecularLighting = float3(0.0, 0.0, 0.0);
// Only apply sky IBL if the sky texture is available.
if (_EnvLightSkyEnabled)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
// The sky is a single cubemap texture separate from the reflection probe texture array (different resolution and compression)
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_SKY;
EnvLightData envLightSky = InitSkyEnvLightData(0); // The sky data are generated on the fly so the compiler can optimize the code
EvaluateBSDF_Env(context, V, positionWS, prelightData, envLightSky, bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
for (i = 0; i < _EnvLightCount; ++i)
{
float3 localDiffuseLighting, localSpecularLighting;
float2 weight;
context.sampleReflection = SINGLE_PASS_CONTEXT_SAMPLE_REFLECTION_PROBES;
EvaluateBSDF_Env(context, V, positionWS, prelightData, _EnvLightDatas[i], bsdfData, localDiffuseLighting, localSpecularLighting, weight);
iblDiffuseLighting = lerp(iblDiffuseLighting, localDiffuseLighting, weight.x); // Should be remove by the compiler if it is smart as all is constant 0
iblSpecularLighting = lerp(iblSpecularLighting, localSpecularLighting, weight.y);
}
diffuseLighting += iblDiffuseLighting;
specularLighting += iblSpecularLighting;
// Add indirect diffuse + emissive (if any)
diffuseLighting += bakeDiffuseLighting;
}
#endif

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


out float3 diffuseLighting,
out float3 specularLighting)
{
float3 L = lightData.direction;
float3 L = -lightData.forward; // Lights are pointing backward in Unity
float illuminance = saturate(dot(bsdfData.normalWS, L));
diffuseLighting = float3(0.0, 0.0, 0.0);

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


#define SHADERPASS SHADERPASS_FORWARD
// TEMP until pragma work in include
// #include "../../Lighting/Forward.hlsl"
// LIGHTLOOP_TILE_PASS
#pragma multi_compile LIGHTLOOP_SINGLE_PASS
#pragma multi_compile LIGHTLOOP_SINGLE_PASS LIGHTLOOP_TILE_PASS
//#pragma multi_compile SHADOWFILTERING_FIXED_SIZE_PCF
#include "../../Lighting/Lighting.hlsl"

34
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightLoop.cs


using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Experimental.Rendering;
using System;
namespace UnityEngine.Experimental.ScriptableRenderLoop
{
public class BaseLightLoop
{
// TODO: We should rather put the texture settings in LightLoop, but how do we serialize it ?
public virtual void Rebuild(TextureSettings textureSettings) {}
public virtual void Cleanup() {}
public virtual bool NeedResize() { return false; }
public virtual void AllocResolutionDependentBuffers(int width, int height) { }
public virtual void ReleaseResolutionDependentBuffers() {}
public virtual void NewFrame() {}
public virtual void PrepareLightsForGPU(CullResults cullResults, Camera camera, ref ShadowOutput shadowOutput) { }
// TODO: this should not be aprt of the interface but for now make something working
public virtual void BuildGPULightLists(Camera camera, RenderLoop loop, RenderTargetIdentifier cameraDepthBufferRT) { }
public virtual void PushGlobalParams(Camera camera, RenderLoop loop) {}
public virtual void RenderDeferredLighting(Camera camera, RenderLoop renderLoop, RenderTargetIdentifier cameraColorBufferRT) {}
public virtual void RenderForward(Camera camera, RenderLoop renderLoop, bool renderOpaque) {}
}
}

12
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightLoop.cs.meta


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

9
Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass.meta


fileFormatVersion: 2
guid: dfb6e7f2aee22e147834de3e01b7c03c
folderAsset: yes
timeCreated: 1477266406
licenseType: Pro
DefaultImporter:
userData:
assetBundleName:
assetBundleVariant:
正在加载...
取消
保存