浏览代码

HDRenderLoop: Add support of directional split shadow

/main
sebastienlagarde 8 年前
当前提交
ca83feb0
共有 8 个文件被更改,包括 165 次插入23 次删除
  1. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.asset.meta
  2. 68
      Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs
  3. 14
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs
  4. 36
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/LightDefinition.cs.hlsl
  5. 15
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.cs
  6. 49
      Assets/ScriptableRenderLoop/HDRenderLoop/Lighting/SinglePass/SinglePass.hlsl
  7. 2
      Assets/ScriptableRenderLoop/HDRenderLoop/Material/Lit/Lit.hlsl
  8. 2
      ProjectSettings/ProjectVersion.txt

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


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

68
Assets/ScriptableRenderLoop/HDRenderLoop/HDRenderLoop.cs


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;

public class LightList
{
public List<DirectionalLightData> directionalLights;
public List<DirectionalShadowData> directionalShadows;
public List<PunctualShadowData> punctualShadows;
public List<PunctualShadowData> punctualShadows;
public Vector4[] directionalShadowSplitSphereSqr;
public void Clear()
{
directionalLights.Clear();
directionalShadows.Clear();
punctualLights.Clear();
punctualShadows.Clear();
areaLights.Clear();
envLights.Clear();
}
LightList m_lightList;
// Detect when windows size is changing
int m_WidthOnRecord;

m_SinglePassLightLoop.Rebuild();
// m_TilePassLightLoop = new TilePass.LightLoop();
// m_TilePassLightLoop.Rebuild();
m_lightList = new LightList();
m_lightList.directionalLights = new List<DirectionalLightData>();
m_lightList.punctualLights = new List<LightData>();
m_lightList.areaLights = new List<LightData>();
m_lightList.envLights = new List<EnvLightData>();
m_lightList.punctualShadows = new List<PunctualShadowData>();
m_lightList.directionalShadows = new List<DirectionalShadowData>();
m_lightList.directionalShadowSplitSphereSqr = new Vector4[k_MaxCascadeCount];
}
void OnDisable()

}
// Function to prepare light structure for GPU lighting
void ConvertLightForGPU(CullResults cullResults, ref ShadowOutput shadowOutput, out LightList lightList)
void ConvertLightForGPU(CullResults cullResults, 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)
{

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.directionalLights.Add(directionalLightData);

renderLoop.SetupCameraProperties(camera); // Need to recall SetupCameraProperties after m_ShadowPass.Render
LightList lightList;
ConvertLightForGPU(cullResults, ref shadows, out lightList);
PushGlobalParams(camera, renderLoop, lightList);
ConvertLightForGPU(cullResults, ref shadows, ref m_lightList);
PushGlobalParams(camera, renderLoop, m_lightList);
// build per tile light lists
//var numLights = 0; // GenerateSourceLightBuffers(camera, cullResults);

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


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;
}
//

15
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();

public void PushGlobalParams(Camera camera, RenderLoop loop, HDRenderLoop.LightList lightList)
{
s_DirectionalLights.SetData(lightList.directionalLights.ToArray());
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);
}
//-----------------------------------------------------------------------------

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


[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;
}

2
ProjectSettings/ProjectVersion.txt


m_EditorVersion: 5.6.0a2
m_EditorVersion: 5.6.0a4
正在加载...
取消
保存