浏览代码

Fixed issue in the order of local light shadow indices. Shadow info gets stored into a shadow bitmask. Refactored to make both lit and shadow pass use the lightData struct.

/main
Felipe Lira 6 年前
当前提交
5e96c7f1
共有 1 个文件被更改,包括 99 次插入77 次删除
  1. 176
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs

176
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


public int pixelAdditionalLightsCount;
public int totalAdditionalLightsCount;
public int mainLightIndex;
public int localShadowMask;
public List<VisibleLight> visibleLights;
public List<int> localLightIndices;
}
public enum MixedLightingSetup

private ShadowSettings m_ShadowSettings = ShadowSettings.Default;
private ShadowSliceData[] m_ShadowCascadeSlices = new ShadowSliceData[kMaxCascades];
private ShadowSliceData[] m_LocalLightShadowSlices = new ShadowSliceData[kMaxPerObjectLights];
private List<int> m_LocalShadowLightIndices = new List<int>(kMaxLocalPixelLightPerPass);
List<int> m_LocalLightIndices = new List<int>(kMaxLocalPixelLightPerPass);
// Pipeline pass names
private static readonly ShaderPassName m_DepthPrepass = new ShaderPassName("DepthOnly");

LightData lightData;
InitializeLightData(visibleLights, out lightData);
bool screenspaceShadows = ShadowPass(visibleLights, ref context, ref lightData);
bool screenspaceShadows = ShadowPass(ref lightData, ref context);
FrameRenderingConfiguration frameRenderingConfiguration;
SetupFrameRenderingConfiguration(out frameRenderingConfiguration, screenspaceShadows, stereoEnabled, sceneViewCamera);

if (screenspaceShadows)
ShadowCollectPass(frameRenderingConfiguration, ref context);
ForwardPass(visibleLights, frameRenderingConfiguration, ref context, ref lightData, stereoEnabled);
ForwardPass(frameRenderingConfiguration, ref lightData, ref context);
cmd.name = "After Camera Render";
#if UNITY_EDITOR

m_AdditionalShadowmapRT = null;
m_ShadowSampling = LightShadows.None;
m_LocalLightShadowSampling = LightShadows.None;
m_LocalShadowLightIndices.Clear();
{
m_LocalLightShadowMatrices[i] = Matrix4x4.identity;
}
private bool ShadowPass(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
private bool ShadowPass(ref LightData lightData, ref ScriptableRenderContext context)
bool directionalShadowmapRendered = false;
if (m_Asset.AreShadowsEnabled())
{
if (lightData.mainLightIndex != -1)
{
VisibleLight mainLight = visibleLights[lightData.mainLightIndex];
if (mainLight.lightType == LightType.Directional && mainLight.light.shadows != LightShadows.None)
directionalShadowmapRendered = RenderDirectionalCascadeShadowmap(ref mainLight, lightData.mainLightIndex, ref context);
}
if (lightData.pixelAdditionalLightsCount > 0)
RenderLocalShadowmapAtlas(visibleLights, ref context);
}
if (!m_Asset.AreShadowsEnabled())
return false;
bool directionalShadowmapRendered = RenderDirectionalCascadeShadowmap(ref lightData, ref context);
RenderLocalShadowmapAtlas(ref lightData, ref context);
return directionalShadowmapRendered && m_ShadowSettings.screenSpace;
}

StopStereoRendering(ref context, frameRenderingConfiguration);
}
private void ForwardPass(List<VisibleLight> visibleLights, FrameRenderingConfiguration frameRenderingConfiguration, ref ScriptableRenderContext context, ref LightData lightData, bool stereoEnabled)
private void ForwardPass(FrameRenderingConfiguration frameRenderingConfiguration, ref LightData lightData, ref ScriptableRenderContext context)
SetupShaderConstants(visibleLights, ref context, ref lightData);
SetupShaderConstants(ref lightData, ref context);
RendererConfiguration rendererSettings = GetRendererSettings(ref lightData);

cmd.GetTemporaryRT(CameraRenderTargetID.copyColor, colorRTDesc, FilterMode.Point);
}
private void SetupShaderConstants(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
private void SetupShaderConstants(ref LightData lightData, ref ScriptableRenderContext context)
SetupShaderLightConstants(cmd, visibleLights, ref lightData);
SetShaderKeywords(cmd, ref lightData, visibleLights);
SetupShaderLightConstants(cmd, ref lightData);
SetShaderKeywords(cmd, ref lightData);
context.ExecuteCommandBuffer(cmd);
CommandBufferPool.Release(cmd);
}

m_LocalLightIndices.Clear();
for (int i = 0; i < visibleLights.Count && i < kMaxLocalPixelLightPerPass; ++i)
if (visibleLights[i].lightType != LightType.Directional)
m_LocalLightIndices.Add(i);
// Clear to default all light constant data
for (int i = 0; i < kMaxVisibleLights; ++i)
InitializeLightConstants(visibleLights, -1, false, out m_LightPositions[i],
out m_LightColors[i],
out m_LightDistanceAttenuations[i],
out m_LightSpotDirections[i],
out m_LightSpotAttenuations[i]);
int visibleLightsCount = Math.Min(visibleLights.Count, m_Asset.MaxPixelLights);
lightData.mainLightIndex = GetMainLight(visibleLights);

lightData.pixelAdditionalLightsCount = additionalPixelLightsCount;
lightData.totalAdditionalLightsCount = additionalPixelLightsCount + vertexLightCount;
lightData.localShadowMask = 0x0;
lightData.visibleLights = visibleLights;
lightData.localLightIndices = m_LocalLightIndices;
m_MixedLightingSetup = MixedLightingSetup.None;
}

Shader.SetGlobalVector(PerFrameBuffer._SubtractiveShadowColor, CoreUtils.ConvertSRGBToActiveColorSpace(RenderSettings.subtractiveShadowColor));
}
private void SetupShaderLightConstants(CommandBuffer cmd, List<VisibleLight> lights, ref LightData lightData)
private void SetupShaderLightConstants(CommandBuffer cmd, ref LightData lightData)
SetupMainLightConstants(cmd, lights, lightData.mainLightIndex);
SetupAdditionalListConstants(cmd, lights, ref lightData);
SetupMainLightConstants(cmd, ref lightData);
SetupAdditionalListConstants(cmd, ref lightData);
private void SetupMainLightConstants(CommandBuffer cmd, List<VisibleLight> lights, int lightIndex)
private void SetupMainLightConstants(CommandBuffer cmd, ref LightData lightData)
InitializeLightConstants(lights, lightIndex, m_ShadowSampling != LightShadows.None, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
List<VisibleLight> lights = lightData.visibleLights;
InitializeLightConstants(lightData.visibleLights, lightData.mainLightIndex, m_ShadowSampling != LightShadows.None, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
if (lightIndex >= 0)
if (lightData.mainLightIndex >= 0)
LightType mainLightType = lights[lightIndex].lightType;
Light mainLight = lights[lightIndex].light;
VisibleLight mainLight = lights[lightData.mainLightIndex];
Light mainLightRef = mainLight.light;
if (LightweightUtils.IsSupportedCookieType(mainLightType) && mainLight.cookie != null)
if (LightweightUtils.IsSupportedCookieType(mainLight.lightType) && mainLightRef.cookie != null)
LightweightUtils.GetLightCookieMatrix(lights[lightIndex], out lightCookieMatrix);
cmd.SetGlobalTexture(PerCameraBuffer._MainLightCookie, mainLight.cookie);
LightweightUtils.GetLightCookieMatrix(mainLight, out lightCookieMatrix);
cmd.SetGlobalTexture(PerCameraBuffer._MainLightCookie, mainLightRef.cookie);
cmd.SetGlobalMatrix(PerCameraBuffer._WorldToLight, lightCookieMatrix);
}
}

}
private void SetupAdditionalListConstants(CommandBuffer cmd, List<VisibleLight> lights, ref LightData lightData)
private void SetupAdditionalListConstants(CommandBuffer cmd, ref LightData lightData)
List<VisibleLight> lights = lightData.visibleLights;
if (lightData.totalAdditionalLightsCount > 0)
{
// We need to update per-object light list with the proper map to our global additional light buffer

int directionalLightCount = 0;
int localLights = 0;
for (int i = 0; i < lights.Count && localLights < kMaxVisibleLights; ++i)
int localLightsCount = 0;
for (int i = 0; i < lights.Count && localLightsCount < kMaxVisibleLights; ++i)
{
VisibleLight light = lights[i];
if (light.lightType == LightType.Directional)

else
{
perObjectLightIndexMap[i] -= directionalLightCount;
InitializeLightConstants(lights, i, m_LocalShadowLightIndices.Contains(i), out m_LightPositions[localLights],
out m_LightColors[localLights],
out m_LightDistanceAttenuations[localLights],
out m_LightSpotDirections[localLights],
out m_LightSpotAttenuations[localLights]);
localLights++;
bool castShadows = (lightData.localShadowMask & (1 << i)) != 0 &&
lightData.localLightIndices.Contains(i);
InitializeLightConstants(lights, i, castShadows, out m_LightPositions[localLightsCount],
out m_LightColors[localLightsCount],
out m_LightDistanceAttenuations[localLightsCount],
out m_LightSpotDirections[localLightsCount],
out m_LightSpotAttenuations[localLightsCount]);
localLightsCount++;
}
}
m_CullResults.SetLightIndexMap(perObjectLightIndexMap);

else
{
cmd.SetGlobalVector(PerCameraBuffer._AdditionalLightCount, Vector4.zero);
// Clear to default all light constant data
for (int i = 0; i < kMaxVisibleLights; ++i)
InitializeLightConstants(lights, -1, false, out m_LightPositions[i],
out m_LightColors[i],
out m_LightDistanceAttenuations[i],
out m_LightSpotDirections[i],
out m_LightSpotAttenuations[i]);
}
cmd.SetGlobalVectorArray(PerCameraBuffer._AdditionalLightPosition, m_LightPositions);

cmd.Clear();
}
private void SetupLocalLightsShadowReceiverConstants(CommandBuffer cmd, List<VisibleLight> visibleLights, ref ScriptableRenderContext context)
private void SetupLocalLightsShadowReceiverConstants(CommandBuffer cmd, ref ScriptableRenderContext context)
{
for (int i = 0; i < kMaxLocalPixelLightPerPass; ++i)
m_LocalLightShadowMatrices[i] = m_LocalLightShadowSlices[i].shadowTransform;

cmd.Clear();
}
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData, List<VisibleLight> visibleLights)
private void SetShaderKeywords(CommandBuffer cmd, ref LightData lightData)
int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;
List<VisibleLight> visibleLights = lightData.visibleLights;
int vertexLightsCount = lightData.totalAdditionalLightsCount - lightData.pixelAdditionalLightsCount;
CoreUtils.SetKeyword(cmd, "_SHADOWS_ENABLED", m_ShadowSampling != LightShadows.None);
CoreUtils.SetKeyword(cmd, "_LOCAL_SHADOWS_ENABLED", m_LocalLightShadowSampling != LightShadows.None);

CoreUtils.SetKeyword(cmd, "_SHADOWS_CASCADE", m_Asset.CascadeCount > 1);
}
private bool RenderDirectionalCascadeShadowmap(ref VisibleLight shadowLight, int shadowLightIndex, ref ScriptableRenderContext context)
private bool RenderDirectionalCascadeShadowmap(ref LightData lightData, ref ScriptableRenderContext context)
int shadowLightIndex = lightData.mainLightIndex;
if (shadowLightIndex == -1)
return false;
VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex];
Light light = shadowLight.light;
Debug.Assert(shadowLight.lightType == LightType.Directional);
if (light.shadows == LightShadows.None)
return false;
CommandBuffer cmd = CommandBufferPool.Get("Prepare Directional Shadowmap");
m_ShadowCasterCascadesCount = m_ShadowSettings.directionalLightCascadeCount;

if (success)
{
m_ShadowSampling = (m_Asset.ShadowSetting != ShadowType.SOFT_SHADOWS) ? LightShadows.Hard : shadowLight.light.shadows;
m_ShadowSampling = (m_Asset.ShadowSetting != ShadowType.SOFT_SHADOWS) ? LightShadows.Hard : light.shadows;
// In order to avoid shader variants explosion we only do hard shadows when sampling shadowmap in the lit pass.
// GLES2 platform is forced to hard single cascade shadows.

return success;
}
private void RenderLocalShadowmapAtlas(List<VisibleLight> visibleLights, ref ScriptableRenderContext context)
private void RenderLocalShadowmapAtlas(ref LightData lightData, ref ScriptableRenderContext context)
CommandBuffer cmd = CommandBufferPool.Get("Prepare Local Lights Shadowmap");
Matrix4x4 view, proj;
Bounds bounds;
bool success = false;
List<int> localLightIndices = lightData.localLightIndices;
List<VisibleLight> visibleLights = lightData.visibleLights;
for (int i = 0; i < visibleLights.Count; ++i)
int shadowCastingLightsCount = 0;
for (int i = 0; i < localLightIndices.Count; ++i)
VisibleLight shadowLight = visibleLights[i];
if (m_LocalShadowLightIndices.Count >= kMaxLocalPixelLightPerPass)
break;
VisibleLight shadowLight = visibleLights[localLightIndices[i]];
m_LocalShadowLightIndices.Add(i);
shadowCastingLightsCount++;
if (m_LocalShadowLightIndices.Count == 0)
if (shadowCastingLightsCount == 0)
CommandBuffer cmd = CommandBufferPool.Get("Prepare Local Lights Shadowmap");
Matrix4x4 view, proj;
Bounds bounds;
int sliceResolution = GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, m_LocalShadowLightIndices.Count);
int sliceResolution = GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount);
int shadowSampling = 0;
RenderTextureDescriptor shadowmapDescriptor = new RenderTextureDescriptor(m_LocalLightShadowAtlasResolution, m_LocalLightShadowAtlasResolution, m_ShadowSettings.shadowmapTextureFormat, kShadowBufferBits);

// LightweightPipeline.SetRenderTarget is meant to be used with camera targets, not shadowmaps
CoreUtils.SetRenderTarget(cmd, m_AdditionalShadowmapRT, ClearFlag.Depth, CoreUtils.ConvertSRGBToActiveColorSpace(m_CurrCamera.backgroundColor));
for (int i = 0; i < m_LocalShadowLightIndices.Count; ++i)
for (int i = 0; i < localLightIndices.Count; ++i)
int shadowLightIndex = m_LocalShadowLightIndices[i];
int shadowLightIndex = localLightIndices[i];
if (shadowLight.lightType != LightType.Spot || shadowLight.light.shadows == LightShadows.None)
continue;
success = m_CullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData);
if (success)
if (m_CullResults.ComputeSpotShadowMatricesAndCullingPrimitives(shadowLightIndex, out view, out proj, out settings.splitData))
{
// This way of computing the shadow slice only work for spots and with most 4 shadow casting lights per pass
// Change this when point lights are supported.

RenderShadowSlice(cmd, ref context, ref m_LocalLightShadowSlices[i], proj, view, settings);
m_LocalShadowStrength[i] = light.shadowStrength;
shadowSampling = Math.Max(shadowSampling, (int)light.shadows);
lightData.localShadowMask |= (1 << shadowLightIndex);
if (success)
SetupLocalLightsShadowReceiverConstants(cmd, visibleLights, ref context);
SetupLocalLightsShadowReceiverConstants(cmd, ref context);
m_LocalLightShadowSampling = (LightShadows)Math.Min(shadowSampling, (int)m_Asset.ShadowSetting);
context.ExecuteCommandBuffer(cmd);

正在加载...
取消
保存