浏览代码

Added support to up to 4 shadow casting lights in the base pass

/main
Felipe Lira 7 年前
当前提交
5a8e42e7
共有 3 个文件被更改,包括 78 次插入47 次删除
  1. 102
      ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs
  2. 18
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl
  3. 5
      ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl

102
ScriptableRenderPipeline/LightweightPipeline/LWRP/LightweightPipeline.cs


using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using UnityEngine.Assertions;
#if UNITY_EDITOR
using UnityEditor.Experimental.Rendering.LightweightPipeline;
#endif

// Lights are culled per-object. This holds the maximum amount of lights that can be shaded per-object.
// The engine fills in the lights indices per-object in unity4_LightIndices0 and unity_4LightIndices1
private static readonly int kMaxPerObjectLights = 4;
private static readonly int kMaxPerObjectLights = 8;
private static readonly int kMaxLocalPixelLightPerPass = 4;
private static readonly int kMaxVertexLights = 4;

private int m_AdditionalShadowmapRTID;
private int m_ScreenSpaceShadowMapRTID;
private Matrix4x4[] m_ShadowMatrices = new Matrix4x4[kMaxCascades + 1];
private Matrix4x4[] m_LocalLightShadowMatrices = new Matrix4x4[4];
private Matrix4x4[] m_LocalLightShadowMatrices = new Matrix4x4[kMaxLocalPixelLightPerPass];
private RenderTargetIdentifier m_CurrCameraColorRT;
private RenderTexture m_DirectionalShadowmapRT;
private RenderTexture m_AdditionalShadowmapRT;

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

DepthPass(ref context, frameRenderingConfiguration);
if (screenspaceShadows)
ShadowCollectPass(visibleLights, ref context, ref lightData, frameRenderingConfiguration);
ShadowCollectPass(frameRenderingConfiguration, ref context);
ForwardPass(visibleLights, frameRenderingConfiguration, ref context, ref lightData, stereoEnabled);

}
}
private bool ShadowPass(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
private void InitializeShadowPass()
m_LocalLightShadowIndex = -1;
m_LocalShadowLightIndices.Clear();
for (int i = 0; i < kMaxLocalPixelLightPerPass; ++i)
m_LocalShadowStrength[i] = 0.0f;
}
private bool ShadowPass(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData)
{
InitializeShadowPass();
bool directionalShadowmapRendered = false;
if (m_Asset.AreShadowsEnabled())

}
if (lightData.pixelAdditionalLightsCount > 0)
RenderAdditionalShadowmapAtlas(visibleLights, ref context);
RenderLocalShadowmapAtlas(visibleLights, ref context);
private void ShadowCollectPass(List<VisibleLight> visibleLights, ref ScriptableRenderContext context, ref LightData lightData, FrameRenderingConfiguration frameRenderingConfiguration)
private void ShadowCollectPass(FrameRenderingConfiguration frameRenderingConfiguration, ref ScriptableRenderContext context)
SetShadowCollectPassKeywords(cmd, visibleLights[lightData.mainLightIndex], ref lightData);
SetShadowCollectPassKeywords(cmd);
// TODO: Support RenderScale for the SSSM target. Should probably move allocation elsewhere, or at
// least propogate RenderTextureDescriptor generation

return -1;
}
private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
private void InitializeLightConstants(List<VisibleLight> lights, int lightIndex, bool castShadows, out Vector4 lightPos, out Vector4 lightColor, out Vector4 lightDistanceAttenuation, out Vector4 lightSpotDir,
out Vector4 lightSpotAttenuation)
{
lightPos = kDefaultLightPosition;

return;
VisibleLight lightData = lights[lightIndex];
float castShadowsProp = castShadows ? 1.0f : 0.0f;
lightPos = new Vector4(dir.x, dir.y, dir.z, 0.0f);
lightPos = new Vector4(dir.x, dir.y, dir.z, castShadowsProp);
lightPos = new Vector4(pos.x, pos.y, pos.z, 1.0f);
lightPos = new Vector4(pos.x, pos.y, pos.z, castShadowsProp);
}
// VisibleLight.finalColor already returns color in active color space

private void SetupMainLightConstants(CommandBuffer cmd, List<VisibleLight> lights, int lightIndex)
{
Vector4 lightPos, lightColor, lightDistanceAttenuation, lightSpotDir, lightSpotAttenuation;
InitializeLightConstants(lights, lightIndex, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
InitializeLightConstants(lights, lightIndex, m_ShadowSampling != LightShadows.None, out lightPos, out lightColor, out lightDistanceAttenuation, out lightSpotDir, out lightSpotAttenuation);
if (lightIndex >= 0)
{

else
{
perObjectLightIndexMap[i] -= directionalLightCount;
InitializeLightConstants(lights, i, out m_LightPositions[localLights],
InitializeLightConstants(lights, i, m_LocalShadowLightIndices.Contains(i), out m_LightPositions[localLights],
out m_LightColors[localLights],
out m_LightDistanceAttenuations[localLights],
out m_LightSpotDirections[localLights],

// Clear to default all light constant data
for (int i = 0; i < kMaxVisibleLights; ++i)
InitializeLightConstants(lights, -1, out m_LightPositions[i],
InitializeLightConstants(lights, -1, false, out m_LightPositions[i],
out m_LightColors[i],
out m_LightDistanceAttenuations[i],
out m_LightSpotDirections[i],

private void SetupLocalLightsShadowReceiverConstants(CommandBuffer cmd, List<VisibleLight> visibleLights, ref ScriptableRenderContext context)
{
VisibleLight shadowLight = visibleLights[m_LocalLightShadowIndex];
m_LocalLightShadowMatrices[0] = m_AddtionalShadowSlices[0].shadowTransform;
m_LocalLightShadowMatrices[1] = Matrix4x4.identity;
m_LocalLightShadowMatrices[2] = Matrix4x4.identity;
m_LocalLightShadowMatrices[3] = Matrix4x4.identity;
for (int i = 0; i < kMaxLocalPixelLightPerPass; ++i)
m_LocalLightShadowMatrices[i] = m_LocalLightShadowSlices[i].shadowTransform;
float invShadowResolution = 1.0f / m_LocalLightShadowResolution;
float invShadowResolution = 1.0f / m_LocalLightShadowAtlasResolution;
cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowData, new Vector4(shadowLight.light.shadowStrength, 0.0f, 0.0f, 0.0f));
cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowData, new Vector4(m_LocalShadowStrength[0], m_LocalShadowStrength[1], m_LocalShadowStrength[2], m_LocalShadowStrength[3]));
cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowmapSize, new Vector4(invShadowResolution, invShadowResolution, m_LocalLightShadowResolution, m_LocalLightShadowResolution));
cmd.SetGlobalVector(LocalShadowConstantBuffer._LocalShadowmapSize, new Vector4(invShadowResolution, invShadowResolution, m_LocalLightShadowAtlasResolution, m_LocalLightShadowAtlasResolution));
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
}

CoreUtils.SetKeyword(cmd, "SOFTPARTICLES_ON", m_RequireDepthTexture && m_Asset.RequireSoftParticles);
}
private void SetShadowCollectPassKeywords(CommandBuffer cmd, VisibleLight shadowLight, ref LightData lightData)
private void SetShadowCollectPassKeywords(CommandBuffer cmd)
{
CoreUtils.SetKeyword(cmd, "_SHADOWS_SOFT", m_ShadowSampling == LightShadows.Soft);
CoreUtils.SetKeyword(cmd, "_SHADOWS_CASCADE", m_Asset.CascadeCount > 1);

return success;
}
private bool RenderAdditionalShadowmapAtlas(List<VisibleLight> visibleLights, ref ScriptableRenderContext context)
private void RenderLocalShadowmapAtlas(List<VisibleLight> visibleLights, ref ScriptableRenderContext context)
int shadowResolution = m_LocalLightShadowResolution;
// TODO: Add support to point light shadows. We make a simplification here that only works
// for spot lights and with max spot shadows per pass.
int sliceResolution = GetMaxTileResolutionInAtlas(m_LocalLightShadowAtlasResolution, m_LocalLightShadowAtlasResolution, kMaxLocalPixelLightPerPass);
RenderTextureDescriptor shadowmapDescriptor = new RenderTextureDescriptor(shadowResolution, shadowResolution, m_ShadowSettings.shadowmapTextureFormat, kShadowBufferBits);
RenderTextureDescriptor shadowmapDescriptor = new RenderTextureDescriptor(m_LocalLightShadowAtlasResolution, m_LocalLightShadowAtlasResolution, m_ShadowSettings.shadowmapTextureFormat, kShadowBufferBits);
shadowmapDescriptor.shadowSamplingMode = ShadowSamplingMode.CompareDepths;
m_AdditionalShadowmapRT = RenderTexture.GetTemporary(shadowmapDescriptor);
m_AdditionalShadowmapRT.filterMode = FilterMode.Bilinear;

CoreUtils.SetRenderTarget(cmd, m_AdditionalShadowmapRT, ClearFlag.Depth, CoreUtils.ConvertSRGBToActiveColorSpace(m_CurrCamera.backgroundColor));
int shadowSliceIndex = 0;
Light light = shadowLight.light;
if (shadowLight.lightType != LightType.Spot)
if (m_LocalShadowLightIndices.Count >= kMaxLocalPixelLightPerPass)
break;
if (shadowLight.lightType != LightType.Spot || light.shadows == LightShadows.None)
continue;
if (!m_CullResults.GetShadowCasterBounds(i, out bounds))

success = m_CullResults.ComputeSpotShadowMatricesAndCullingPrimitives(i, out view, out proj, out settings.splitData);
if (success)
{
Rect shadowSliceRect = new Rect(0.0f, 0.0f, shadowResolution, shadowResolution);
SetupShadowCasterConstants(cmd, ref shadowLight, proj, shadowResolution);
SetupShadowSliceTransform(ref shadowSliceRect, shadowResolution, proj, view, out m_AddtionalShadowSlices[0]);
RenderShadowSlice(cmd, ref context, ref m_AddtionalShadowSlices[0], proj, view, settings);
m_LocalLightShadowIndex = i;
shadowSampling = Math.Max(shadowSampling, (int)shadowLight.light.shadows);
break;
// 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.
Debug.Assert(kMaxLocalPixelLightPerPass == 4 && shadowLight.lightType == LightType.Spot);
int atlasX = (shadowSliceIndex % 2) * sliceResolution;
int atlasY = (shadowSliceIndex / 2) * sliceResolution;
float atlasWidth = (float)m_LocalLightShadowAtlasResolution;
float atlasHeight = (float)m_LocalLightShadowAtlasResolution;
Rect shadowSliceRect = new Rect(atlasX, atlasY, atlasWidth, atlasHeight);
SetupShadowCasterConstants(cmd, ref shadowLight, proj, sliceResolution);
SetupShadowSliceTransform(ref shadowSliceRect, sliceResolution, proj, view, out m_LocalLightShadowSlices[shadowSliceIndex]);
RenderShadowSlice(cmd, ref context, ref m_LocalLightShadowSlices[shadowSliceIndex], proj, view, settings);
m_LocalShadowStrength[shadowSliceIndex] = light.shadowStrength;
m_LocalShadowLightIndices.Add(i);
shadowSampling = Math.Max(shadowSampling, (int)light.shadows);
shadowSliceIndex++;
}
}

m_LocalLightShadowSampling = (LightShadows)Math.Min(shadowSampling, (int)m_Asset.ShadowSetting);
context.ExecuteCommandBuffer(cmd);
cmd.Clear();
return success;
}
private void SetupShadowSliceTransform(ref Rect shadowSliceRect, int shadowResolution, Matrix4x4 proj, Matrix4x4 view, out ShadowSliceData shadowSliceData)

18
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Lighting.hlsl


half3 color;
half attenuation;
half subtractiveModeAttenuation;
half castShadows;
};
///////////////////////////////////////////////////////////////////////////////

half4 GetLightDirectionAndAttenuation(LightInput lightInput, float3 positionWS)
{
half4 directionAndAttenuation;
float3 posToLightVec = lightInput.position.xyz - positionWS * lightInput.position.w;
float3 posToLightVec = lightInput.position.xyz - positionWS;
float distanceSqr = max(dot(posToLightVec, posToLightVec), FLT_MIN);
directionAndAttenuation.xyz = half3(posToLightVec * rsqrt(distanceSqr));

light.attenuation = 1.0;
light.subtractiveModeAttenuation = _MainLightPosition.w;
light.color = _MainLightColor.rgb;
light.castShadows = _MainLightPosition.w;
return light;
}

light.attenuation = directionAndRealtimeAttenuation.w;
light.subtractiveModeAttenuation = lightInput.distanceAttenuation.w;
light.color = lightInput.color;
light.castShadows = lightInput.position.w;
return light;
}

// TODO: we need to expose in SRP api an ability for the pipeline cap the amount of lights
// in the culling. This way we could do the loop branch with an uniform
// This would be helpful to support baking exceeding lights in SH as well
return min(_AdditionalLightCount.x, unity_LightIndicesOffsetAndCount.y);
}

int pixelLightCount = GetPixelLightCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetLight(half(i), inputData.positionWS);
light.attenuation *= LocalLightRealtimeShadowAttenuation(i, inputData.positionWS);
half index = half(i);
Light light = GetLight(index, inputData.positionWS);
light.attenuation *= LocalLightRealtimeShadowAttenuation(index, light.castShadows, inputData.positionWS);
color += LightingPhysicallyBased(brdfData, light, inputData.normalWS, inputData.viewDirectionWS);
}
#endif

int pixelLightCount = GetPixelLightCount();
for (int i = 0; i < pixelLightCount; ++i)
{
Light light = GetLight(half(i), inputData.positionWS);
light.attenuation *= LocalLightRealtimeShadowAttenuation(i, inputData.positionWS);
half index = half(i);
Light light = GetLight(index, inputData.positionWS);
light.attenuation *= LocalLightRealtimeShadowAttenuation(index, light.castShadows, inputData.positionWS);
half3 attenuatedLightColor = light.color * light.attenuation;
diffuseColor += LightingLambert(attenuatedLightColor, light.direction, inputData.normalWS);
specularColor += LightingSpecular(attenuatedLightColor, light.direction, inputData.normalWS, inputData.viewDirectionWS, specularGloss, shininess);

5
ScriptableRenderPipeline/LightweightPipeline/LWRP/ShaderLibrary/Shadows.hlsl


}
half LocalLightRealtimeShadowAttenuation(int lightIndex, float3 positionWS)
half LocalLightRealtimeShadowAttenuation(int lightIndex, half castShadows, float3 positionWS)
{
#if defined(NO_SHADOWS) || !defined(_LOCAL_SHADOWS_ENABLED)
return 1.0h;

return SampleShadowmap(shadowCoord, TEXTURE2D_PARAM(_LocalShadowMapAtlas, sampler_LocalShadowMapAtlas), shadowSamplingData, 0.0);
half attenuation = SampleShadowmap(shadowCoord, TEXTURE2D_PARAM(_LocalShadowMapAtlas, sampler_LocalShadowMapAtlas), shadowSamplingData, 0.0);
return (castShadows < 1.0h) ? 1.0h : attenuation;
#endif
}
正在加载...
取消
保存