123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255 |
- using System;
- namespace UnityEngine.Rendering.Universal.Internal
- {
- /// <summary>
- /// Renders a shadow map for the main Light.
- /// </summary>
- public class MainLightShadowCasterPass : ScriptableRenderPass
- {
- private static class MainLightShadowConstantBuffer
- {
- public static int _WorldToShadow;
- public static int _ShadowParams;
- public static int _CascadeShadowSplitSpheres0;
- public static int _CascadeShadowSplitSpheres1;
- public static int _CascadeShadowSplitSpheres2;
- public static int _CascadeShadowSplitSpheres3;
- public static int _CascadeShadowSplitSphereRadii;
- public static int _ShadowOffset0;
- public static int _ShadowOffset1;
- public static int _ShadowOffset2;
- public static int _ShadowOffset3;
- public static int _ShadowmapSize;
- }
- const int k_MaxCascades = 4;
- const int k_ShadowmapBufferBits = 16;
- int m_ShadowmapWidth;
- int m_ShadowmapHeight;
- int m_ShadowCasterCascadesCount;
- bool m_SupportsBoxFilterForShadows;
- RenderTargetHandle m_MainLightShadowmap;
- RenderTexture m_MainLightShadowmapTexture;
- Matrix4x4[] m_MainLightShadowMatrices;
- ShadowSliceData[] m_CascadeSlices;
- Vector4[] m_CascadeSplitDistances;
- const string m_ProfilerTag = "Render Main Shadowmap";
- ProfilingSampler m_ProfilingSampler = new ProfilingSampler(m_ProfilerTag);
- public MainLightShadowCasterPass(RenderPassEvent evt)
- {
- renderPassEvent = evt;
- m_MainLightShadowMatrices = new Matrix4x4[k_MaxCascades + 1];
- m_CascadeSlices = new ShadowSliceData[k_MaxCascades];
- m_CascadeSplitDistances = new Vector4[k_MaxCascades];
- MainLightShadowConstantBuffer._WorldToShadow = Shader.PropertyToID("_MainLightWorldToShadow");
- MainLightShadowConstantBuffer._ShadowParams = Shader.PropertyToID("_MainLightShadowParams");
- MainLightShadowConstantBuffer._CascadeShadowSplitSpheres0 = Shader.PropertyToID("_CascadeShadowSplitSpheres0");
- MainLightShadowConstantBuffer._CascadeShadowSplitSpheres1 = Shader.PropertyToID("_CascadeShadowSplitSpheres1");
- MainLightShadowConstantBuffer._CascadeShadowSplitSpheres2 = Shader.PropertyToID("_CascadeShadowSplitSpheres2");
- MainLightShadowConstantBuffer._CascadeShadowSplitSpheres3 = Shader.PropertyToID("_CascadeShadowSplitSpheres3");
- MainLightShadowConstantBuffer._CascadeShadowSplitSphereRadii = Shader.PropertyToID("_CascadeShadowSplitSphereRadii");
- MainLightShadowConstantBuffer._ShadowOffset0 = Shader.PropertyToID("_MainLightShadowOffset0");
- MainLightShadowConstantBuffer._ShadowOffset1 = Shader.PropertyToID("_MainLightShadowOffset1");
- MainLightShadowConstantBuffer._ShadowOffset2 = Shader.PropertyToID("_MainLightShadowOffset2");
- MainLightShadowConstantBuffer._ShadowOffset3 = Shader.PropertyToID("_MainLightShadowOffset3");
- MainLightShadowConstantBuffer._ShadowmapSize = Shader.PropertyToID("_MainLightShadowmapSize");
- m_MainLightShadowmap.Init("_MainLightShadowmapTexture");
- m_SupportsBoxFilterForShadows = Application.isMobilePlatform || SystemInfo.graphicsDeviceType == GraphicsDeviceType.Switch;
- }
- public bool Setup(ref RenderingData renderingData)
- {
- if (!renderingData.shadowData.supportsMainLightShadows)
- return false;
- Clear();
- int shadowLightIndex = renderingData.lightData.mainLightIndex;
- if (shadowLightIndex == -1)
- return false;
- VisibleLight shadowLight = renderingData.lightData.visibleLights[shadowLightIndex];
- Light light = shadowLight.light;
- if (light.shadows == LightShadows.None)
- return false;
- if (shadowLight.lightType != LightType.Directional)
- {
- Debug.LogWarning("Only directional lights are supported as main light.");
- }
- Bounds bounds;
- if (!renderingData.cullResults.GetShadowCasterBounds(shadowLightIndex, out bounds))
- return false;
- m_ShadowCasterCascadesCount = renderingData.shadowData.mainLightShadowCascadesCount;
- int shadowResolution = ShadowUtils.GetMaxTileResolutionInAtlas(renderingData.shadowData.mainLightShadowmapWidth,
- renderingData.shadowData.mainLightShadowmapHeight, m_ShadowCasterCascadesCount);
- m_ShadowmapWidth = renderingData.shadowData.mainLightShadowmapWidth;
- m_ShadowmapHeight = (m_ShadowCasterCascadesCount == 2) ?
- renderingData.shadowData.mainLightShadowmapHeight >> 1 :
- renderingData.shadowData.mainLightShadowmapHeight;
- for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
- {
- bool success = ShadowUtils.ExtractDirectionalLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData,
- shadowLightIndex, cascadeIndex, m_ShadowmapWidth, m_ShadowmapHeight, shadowResolution, light.shadowNearPlane,
- out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex], out m_CascadeSlices[cascadeIndex].viewMatrix, out m_CascadeSlices[cascadeIndex].projectionMatrix);
- if (!success)
- return false;
- }
- return true;
- }
- public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor)
- {
- m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth,
- m_ShadowmapHeight, k_ShadowmapBufferBits);
- ConfigureTarget(new RenderTargetIdentifier(m_MainLightShadowmapTexture));
- ConfigureClear(ClearFlag.All, Color.black);
- }
- /// <inheritdoc/>
- public override void Execute(ScriptableRenderContext context, ref RenderingData renderingData)
- {
- RenderMainLightCascadeShadowmap(ref context, ref renderingData.cullResults, ref renderingData.lightData, ref renderingData.shadowData);
- }
- /// <inheritdoc/>
- public override void FrameCleanup(CommandBuffer cmd)
- {
- if (cmd == null)
- throw new ArgumentNullException("cmd");
- if (m_MainLightShadowmapTexture)
- {
- RenderTexture.ReleaseTemporary(m_MainLightShadowmapTexture);
- m_MainLightShadowmapTexture = null;
- }
- }
- void Clear()
- {
- m_MainLightShadowmapTexture = null;
- for (int i = 0; i < m_MainLightShadowMatrices.Length; ++i)
- m_MainLightShadowMatrices[i] = Matrix4x4.identity;
- for (int i = 0; i < m_CascadeSplitDistances.Length; ++i)
- m_CascadeSplitDistances[i] = new Vector4(0.0f, 0.0f, 0.0f, 0.0f);
- for (int i = 0; i < m_CascadeSlices.Length; ++i)
- m_CascadeSlices[i].Clear();
- }
- void RenderMainLightCascadeShadowmap(ref ScriptableRenderContext context, ref CullingResults cullResults, ref LightData lightData, ref ShadowData shadowData)
- {
- int shadowLightIndex = lightData.mainLightIndex;
- if (shadowLightIndex == -1)
- return;
- VisibleLight shadowLight = lightData.visibleLights[shadowLightIndex];
- CommandBuffer cmd = CommandBufferPool.Get(m_ProfilerTag);
- using (new ProfilingScope(cmd, m_ProfilingSampler))
- {
- var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex);
- for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex)
- {
- var splitData = settings.splitData;
- splitData.cullingSphere = m_CascadeSplitDistances[cascadeIndex];
- settings.splitData = splitData;
- Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].resolution);
- ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias);
- ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_CascadeSlices[cascadeIndex],
- ref settings, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].viewMatrix);
- }
- bool softShadows = shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows;
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, true);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1);
- CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows);
- SetupMainLightShadowReceiverConstants(cmd, shadowLight, softShadows);
- }
- context.ExecuteCommandBuffer(cmd);
- CommandBufferPool.Release(cmd);
- }
- void SetupMainLightShadowReceiverConstants(CommandBuffer cmd, VisibleLight shadowLight, bool softShadows)
- {
- Light light = shadowLight.light;
- int cascadeCount = m_ShadowCasterCascadesCount;
- for (int i = 0; i < cascadeCount; ++i)
- m_MainLightShadowMatrices[i] = m_CascadeSlices[i].shadowTransform;
- // We setup and additional a no-op WorldToShadow matrix in the last index
- // because the ComputeCascadeIndex function in Shadows.hlsl can return an index
- // out of bounds. (position not inside any cascade) and we want to avoid branching
- Matrix4x4 noOpShadowMatrix = Matrix4x4.zero;
- noOpShadowMatrix.m22 = (SystemInfo.usesReversedZBuffer) ? 1.0f : 0.0f;
- for (int i = cascadeCount; i <= k_MaxCascades; ++i)
- m_MainLightShadowMatrices[i] = noOpShadowMatrix;
- float invShadowAtlasWidth = 1.0f / m_ShadowmapWidth;
- float invShadowAtlasHeight = 1.0f / m_ShadowmapHeight;
- float invHalfShadowAtlasWidth = 0.5f * invShadowAtlasWidth;
- float invHalfShadowAtlasHeight = 0.5f * invShadowAtlasHeight;
- float softShadowsProp = softShadows ? 1.0f : 0.0f;
- cmd.SetGlobalTexture(m_MainLightShadowmap.id, m_MainLightShadowmapTexture);
- cmd.SetGlobalMatrixArray(MainLightShadowConstantBuffer._WorldToShadow, m_MainLightShadowMatrices);
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowParams, new Vector4(light.shadowStrength, softShadowsProp, 0.0f, 0.0f));
- if (m_ShadowCasterCascadesCount > 1)
- {
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._CascadeShadowSplitSpheres0,
- m_CascadeSplitDistances[0]);
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._CascadeShadowSplitSpheres1,
- m_CascadeSplitDistances[1]);
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._CascadeShadowSplitSpheres2,
- m_CascadeSplitDistances[2]);
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._CascadeShadowSplitSpheres3,
- m_CascadeSplitDistances[3]);
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._CascadeShadowSplitSphereRadii, new Vector4(
- m_CascadeSplitDistances[0].w * m_CascadeSplitDistances[0].w,
- m_CascadeSplitDistances[1].w * m_CascadeSplitDistances[1].w,
- m_CascadeSplitDistances[2].w * m_CascadeSplitDistances[2].w,
- m_CascadeSplitDistances[3].w * m_CascadeSplitDistances[3].w));
- }
- if (softShadows)
- {
- if (m_SupportsBoxFilterForShadows)
- {
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowOffset0,
- new Vector4(-invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowOffset1,
- new Vector4(invHalfShadowAtlasWidth, -invHalfShadowAtlasHeight, 0.0f, 0.0f));
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowOffset2,
- new Vector4(-invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowOffset3,
- new Vector4(invHalfShadowAtlasWidth, invHalfShadowAtlasHeight, 0.0f, 0.0f));
- }
- // Currently only used when !SHADER_API_MOBILE but risky to not set them as it's generic
- // enough so custom shaders might use it.
- cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowmapSize, new Vector4(invShadowAtlasWidth,
- invShadowAtlasHeight,
- m_ShadowmapWidth, m_ShadowmapHeight));
- }
- }
- };
- }
|