void LateUpdate() { //求阴影产生物体的包围盒 Bounds b = new Bounds(); for (int i = 0; i < _shadowCasterList.Count; i++) { if (_shadowCasterList[i] != null) { b.Encapsulate(_shadowCasterList[i].bounds); } } b.extents += Vector3.one * boundsOffset; // Bounds bc = new Bounds(); // for (int i = 0; i < _boxCasterList.Count; i++) // { // if (_boxCasterList[i] != null) // { // bc.Encapsulate(_boxCasterList[i].bounds); // } // } // bc.extents += Vector3.one * boundsOffset; #if UNITY_EDITOR _boundsCollider.center = b.center; _boundsCollider.size = b.size; #endif //根据mainCamera来更新lightCamera和projector的位置,和设置参数 ShadowUtils.SetLightCamera(b, _lightCamera); _projector.aspectRatio = _lightCamera.aspect; _projector.orthographicSize = _lightCamera.orthographicSize; _projector.nearClipPlane = _lightCamera.nearClipPlane; _projector.farClipPlane = _lightCamera.farClipPlane; }
void LateUpdate() { //求阴影产生物体的包围盒 /*Bounds b = new Bounds(); * for (int i = 0; i < _shadowCasterList.Count; i++) * { * if(_shadowCasterList[i] != null) * { * b.Encapsulate(_shadowCasterList[i].bounds); * } * } * b.extents += Vector3.one * boundsOffset; #if UNITY_EDITOR * _boundsCollider.center = b.center; * _boundsCollider.size = b.size; #endif * //根据mainCamera来更新lightCamera和projector的位置,和设置参数 * ShadowUtils.SetLightCamera(b, _lightCamera);*/ if (_mainCamera == null) { _mainCamera = Camera.main; } if (_mainCamera == null) { return; } ShadowUtils.SetLightCamera(_mainCamera, _lightCamera); _projector.aspectRatio = _lightCamera.aspect; _projector.orthographicSize = _lightCamera.orthographicSize; _projector.nearClipPlane = _lightCamera.nearClipPlane; _projector.farClipPlane = _lightCamera.farClipPlane; }
/// <summary> /// Creates a new <c>MainLightShadowCasterPass</c> instance. /// </summary> /// <param name="evt">The <c>RenderPassEvent</c> to use.</param> /// <seealso cref="RenderPassEvent"/> public MainLightShadowCasterPass(RenderPassEvent evt) { base.profilingSampler = new ProfilingSampler(nameof(MainLightShadowCasterPass)); 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_MainLightShadowmapID = Shader.PropertyToID("_MainLightShadowmapTexture"); m_EmptyLightShadowmapTexture = ShadowUtils.AllocShadowRT(1, 1, k_ShadowmapBufferBits, 1, 0, name: "_EmptyLightShadowmapTexture"); }
public void Set(float v0, float v1, float v2, float v3) { p0 = ShadowUtils.Asint(v0); p1 = ShadowUtils.Asint(v1); p2 = ShadowUtils.Asint(v2); p3 = ShadowUtils.Asint(v3); }
public static void drawShadow(Canvas canvas, Path path, Color color, float elevation, bool transparentOccluder, float dpr) { float kAmbientAlpha = 0.039f; float kSpotAlpha = ShadowUtils.kUseFastShadow ? 0.1f : 0.25f; float kLightHeight = 600f; float kLightRadius = 800f; Rect bounds = path.getBounds(); float shadow_x = (bounds.left + bounds.right) / 2f; float shadow_y = bounds.top - 600.0f; _inAmbient = color.withAlpha((int)(kAmbientAlpha * color.alpha)); _inSpot = color.withAlpha((int)(kSpotAlpha * color.alpha)); _ambientColor = null; _spotColor = null; ShadowUtils.computeTonalColors(_inAmbient, _inSpot, ref _ambientColor, ref _spotColor); _zPlane.Set(0, 0, dpr * elevation); _devLight.Set(shadow_x, shadow_y, dpr * kLightHeight); ShadowUtils.drawShadow( canvas, path, _zPlane, _devLight, dpr * kLightRadius, _ambientColor, _spotColor, 0 ); }
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); }
public static void drawShadow(Canvas canvas, Path path, Color color, float elevation, bool transparentOccluder, float dpr) { Rect bounds = path.getBounds(); float shadow_x = (bounds.left + bounds.right) / 2f; float shadow_y = bounds.top - 600.0f; uiColor uicolor = uiColor.fromColor(color); uiColor inAmbient = uicolor.withAlpha((int)(kAmbientAlpha * uicolor.alpha)); uiColor inSpot = uicolor.withAlpha((int)(kSpotAlpha * uicolor.alpha)); uiColor?ambientColor = null; uiColor?spotColor = null; ShadowUtils.computeTonalColors(inAmbient, inSpot, ref ambientColor, ref spotColor); ShadowUtils.drawShadow( canvas, path, new Vector3(0, 0, dpr * elevation), new Vector3(shadow_x, shadow_y, dpr * kLightHeight), dpr * kLightRadius, ambientColor.Value, spotColor.Value, 0 ); }
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); }
private void Loaded() { //The control was drawn. //This means we can add the drop shadow ShadowUtils.CreateDropShadow(this); if (Parent != null) { Parent.Invalidate(); } }
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { base.Configure(cmd, cameraTextureDescriptor); if (m_CharacterShadowmapTexture == null) { m_CharacterShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); m_CharacterShadowmapTexture.name = "CharacterShadowmapTexture"; } ConfigureTarget(new RenderTargetIdentifier(m_CharacterShadowmapTexture)); ConfigureClear(ClearFlag.All, Color.black); }
// Start is called before the first frame update void Start() { //bits = 0,16,24라는데...24비트로 했을 때만 스텐실 버퍼가 생긴다함 //rawImage.texture = testRenderTexture; //testRenderTexture = ShadowUtils.GetTemporaryShadowTexture(1920, 1080, 24); rawImage.texture = testRenderTexture; testRenderTexture = ShadowUtils.GetTemporaryShadowTexture(1920, 1080, 24); RenderTexture.ReleaseTemporary(testRenderTexture); }
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); if (test_pcfDefine && (test_pcfDefine.forcePoint || test_pcfDefine.pt == PCFType.UE4Manual2x2PCF || test_pcfDefine.pt == PCFType.UE4Manual3x3PCF_NoGather)) { m_MainLightShadowmapTexture.filterMode = FilterMode.Point; } ConfigureTarget(new RenderTargetIdentifier(m_MainLightShadowmapTexture)); ConfigureClear(ClearFlag.All, Color.black); }
void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullingResults cullResults, ref LightData lightData, ref ShadowData shadowData) { NativeArray <VisibleLight> visibleLights = lightData.visibleLights; bool additionalLightHasSoftShadows = false; CommandBuffer cmd = CommandBufferPool.Get(k_RenderAdditionalLightShadows); using (new ProfilingSample(cmd, k_RenderAdditionalLightShadows)) { int shadowmapWidth = shadowData.additionalLightsShadowmapWidth; int shadowmapHeight = shadowData.additionalLightsShadowmapHeight; m_AdditionalLightsShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(shadowmapWidth, shadowmapHeight, k_ShadowmapBufferBits); SetRenderTarget(cmd, m_AdditionalLightsShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); for (int i = 0; i < m_AdditionalShadowCastingLightIndices.Count; ++i) { int shadowLightIndex = m_AdditionalShadowCastingLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; if (m_AdditionalShadowCastingLightIndices.Count > 1) { ShadowUtils.ApplySliceTransform(ref m_AdditionalLightSlices[i], shadowmapWidth, shadowmapHeight); } var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref m_AdditionalLightSlices[i], ref settings, m_AdditionalLightSlices[i].projectionMatrix, m_AdditionalLightSlices[i].viewMatrix); additionalLightHasSoftShadows |= shadowLight.light.shadows == LightShadows.Soft; } SetupAdditionalLightsShadowReceiverConstants(cmd, ref shadowData); } // We share soft shadow settings for main light and additional lights to save keywords. // So we check here if pipeline supports soft shadows and either main light or any additional light has soft shadows // to enable the keyword. // TODO: In PC and Consoles we can upload shadow data per light and branch on shader. That will be more likely way faster. bool mainLightHasSoftShadows = shadowData.supportsMainLightShadows && lightData.mainLightIndex != -1 && visibleLights[lightData.mainLightIndex].light.shadows == LightShadows.Soft; bool softShadows = shadowData.supportsSoftShadows && (mainLightHasSoftShadows || additionalLightHasSoftShadows); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
public override void Configure(CommandBuffer cmd, RenderTextureDescriptor cameraTextureDescriptor) { if (m_AdditionalLightsShadowmapTexture != null) { Debug.LogWarning($"Texture {m_AdditionalLightsShadowmapTexture.name} wasn't released"); FrameCleanup(cmd); } cmd.name += " (Additional lights)"; m_AdditionalLightsShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); ConfigureTarget(new RenderTargetIdentifier(m_AdditionalLightsShadowmapTexture)); ConfigureClear(ClearFlag.All, Color.black); }
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]; // NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name"). // Currently there's an issue which results in mismatched markers. CommandBuffer cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.MainLightShadow))) { var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { //settings.splitData = m_CascadeSlices[cascadeIndex].splitData; // NOTE: currently DrawShadows culls more casters if no ShadowSplitData.cullingPlanes are set (version cds 8652678b), so it is currently better to not pass the m_CascadeSlices[cascadeIndex].splitData object returned by CullingResults.ComputeDirectionalShadowMatricesAndCullingPrimitives (change introduced in 8bf71cf). Culling is only based on the ShadowSplitData.cullingSphere distances. 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); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.CastingPunctualLightShadow, false); 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, shadowData.mainLightShadowCascadesCount == 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); SetupMainLightShadowReceiverConstants(cmd, shadowLight, shadowData.supportsSoftShadows); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
protected override void AllocateShadows(FrameId frameId, VisibleLight[] lights, uint totalGranted, ref ShadowRequestVector grantedRequests, ref ShadowIndicesVector shadowIndices, ref ShadowDataVector shadowDatas, ref ShadowPayloadVector shadowmapPayload) { ShadowData sd = new ShadowData(); shadowDatas.Reserve(totalGranted); shadowIndices.Reserve(grantedRequests.Count()); for (uint i = 0, cnt = grantedRequests.Count(); i < cnt; ++i) { VisibleLight vl = lights[grantedRequests[i].index]; Light l = vl.light; AdditionalLightData ald = l.GetComponent <AdditionalLightData>(); // set light specific values that are not related to the shadowmap GPUShadowType shadowtype; ShadowUtils.MapLightType(ald.archetype, vl.lightType, out sd.lightType, out shadowtype); sd.bias = l.shadowBias; sd.quality = 0; shadowIndices.AddUnchecked((int)shadowDatas.Count()); int smidx = 0; while (smidx < k_MaxShadowmapPerType) { if (m_ShadowmapsPerType[(int)shadowtype, smidx].Reserve(frameId, ref sd, grantedRequests[i], (uint)ald.shadowResolution, (uint)ald.shadowResolution, ref shadowDatas, ref shadowmapPayload, lights)) { break; } smidx++; } if (smidx == k_MaxShadowmapPerType) { throw new ArgumentException("The requested shadows do not fit into any shadowmap."); } } // final step for shadowmaps that only gather data during the previous loop and do the actual allocation once they have all the data. foreach (var sm in m_Shadowmaps) { if (!sm.ReserveFinalize(frameId, ref shadowDatas, ref shadowmapPayload)) { throw new ArgumentException("Shadow allocation failed in the ReserveFinalize step."); } } }
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 ProfilingSample(cmd, m_ProfilerTag)) { 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); //* pwrd majiao: frag阶段计算shadowCoord // CoreUtils.SetKeyword(cmd, "_TRADITIONAL_SHADOW", shadowData.useTraditionalShadow); //* pwrd majiao // CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); SetupMainLightShadowReceiverConstants(cmd, shadowLight, softShadows); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
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]; // NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name"). // Currently there's an issue which results in mismatched markers. CommandBuffer cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, ProfilingSampler.Get(URPProfileId.MainLightShadow))) { var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); settings.useRenderingLayerMaskTest = UniversalRenderPipeline.asset.supportsLightLayers; for (int cascadeIndex = 0; cascadeIndex < m_ShadowCasterCascadesCount; ++cascadeIndex) { settings.splitData = m_CascadeSlices[cascadeIndex].splitData; Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, m_CascadeSlices[cascadeIndex].projectionMatrix, m_CascadeSlices[cascadeIndex].resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.CastingPunctualLightShadow, false); 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, shadowData.mainLightShadowCascadesCount == 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); SetupMainLightShadowReceiverConstants(cmd, shadowLight, shadowData.supportsSoftShadows); } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
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(k_RenderMainLightShadowmapTag); using (new ProfilingSample(cmd, k_RenderMainLightShadowmapTag)) { var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(m_ShadowmapWidth, m_ShadowmapHeight, k_ShadowmapBufferBits); SetRenderTarget(cmd, m_MainLightShadowmapTexture, RenderBufferLoadAction.DontCare, RenderBufferStoreAction.Store, ClearFlag.Depth, Color.black, TextureDimension.Tex2D); 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); } SetupMainLightShadowReceiverConstants(cmd, ref shadowData, shadowLight); } CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadows, true); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.MainLightShadowCascades, shadowData.mainLightShadowCascadesCount > 1); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, shadowLight.light.shadows == LightShadows.Soft && shadowData.supportsSoftShadows); context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
protected override void PrioritizeShadowCasters(Camera camera, VisibleLight[] lights, uint shadowRequestsCount, int[] shadowRequests) { // this function simply looks at the projected area on the screen, ignoring all light types and shapes m_TmpSortKeys.Reset(shadowRequestsCount); for (int i = 0; i < shadowRequestsCount; ++i) { int vlidx = shadowRequests[i]; VisibleLight vl = lights[vlidx]; Light l = vl.light; // use the screen rect as a measure of importance float area = vl.screenRect.width * vl.screenRect.height; long val = ShadowUtils.Asint(area); val <<= 32; val |= (long)(uint)vlidx; m_TmpSortKeys.AddUnchecked(val); } m_TmpSortKeys.Sort(); m_TmpSortKeys.ExtractTo(shadowRequests, 0, out shadowRequestsCount, delegate(long key) { return((int)(key & 0xffffffff)); }); }
void LateUpdate() { //calculate bounding box of the shadow caster Bounds b = new Bounds(); for (int i = 0; i < _shadowCasterList.Count; i++) { if (_shadowCasterList[i] != null) { b.Encapsulate(_shadowCasterList[i].bounds); } } b.extents += Vector3.one * boundsOffset; #if UNITY_EDITOR _boundsCollider.center = b.center; _boundsCollider.size = b.size; #endif //according to the mainCamera,updating position of lightCamera and projector ShadowUtils.SetLightCamera(b, _lightCamera); _projector.aspectRatio = _lightCamera.aspect; _projector.orthographicSize = _lightCamera.orthographicSize; _projector.nearClipPlane = _lightCamera.nearClipPlane; _projector.farClipPlane = _lightCamera.farClipPlane; }
void SetupMainLightShadowReceiverConstants(CommandBuffer cmd, VisibleLight shadowLight, bool supportsSoftShadows) { Light light = shadowLight.light; bool softShadows = shadowLight.light.shadows == LightShadows.Soft && supportsSoftShadows; 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 / renderTargetWidth; float invShadowAtlasHeight = 1.0f / renderTargetHeight; float invHalfShadowAtlasWidth = 0.5f * invShadowAtlasWidth; float invHalfShadowAtlasHeight = 0.5f * invShadowAtlasHeight; float softShadowsProp = softShadows ? 1.0f : 0.0f; ShadowUtils.GetScaleAndBiasForLinearDistanceFade(m_MaxShadowDistanceSq, m_CascadeBorder, out float shadowFadeScale, out float shadowFadeBias); cmd.SetGlobalTexture(m_MainLightShadowmap.id, m_MainLightShadowmapTexture); cmd.SetGlobalMatrixArray(MainLightShadowConstantBuffer._WorldToShadow, m_MainLightShadowMatrices); cmd.SetGlobalVector(MainLightShadowConstantBuffer._ShadowParams, new Vector4(light.shadowStrength, softShadowsProp, shadowFadeScale, shadowFadeBias)); 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)); } // Inside shader soft shadows are controlled through global keyword. // If any additional light has soft shadows it will force soft shadows on main light too. // As it is not trivial finding out which additional light has soft shadows, we will pass main light properties if soft shadows are supported. // This workaround will be removed once we will support soft shadows per light. if (supportsSoftShadows) { 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, renderTargetWidth, renderTargetHeight)); } }
public bool Setup(ref RenderingData renderingData) { Clear(); m_ShadowmapWidth = renderingData.shadowData.additionalLightsShadowmapWidth; m_ShadowmapHeight = renderingData.shadowData.additionalLightsShadowmapHeight; var visibleLights = renderingData.lightData.visibleLights; int additionalLightsCount = renderingData.lightData.additionalLightsCount; if (m_AdditionalLightSlices == null || m_AdditionalLightSlices.Length < additionalLightsCount) { m_AdditionalLightSlices = new ShadowSliceData[additionalLightsCount]; } if (m_AdditionalLightsShadowData == null || m_AdditionalLightsShadowData.Length < additionalLightsCount) { m_AdditionalLightsShadowData = new ShaderInput.ShadowData[additionalLightsCount]; } // By default visible lights do not have shadow light indices. for (int i = 0; i < visibleLights.Length; ++i) { m_ShadowCastingLightIndicesMap.Add(-1); } int validShadowCastingLights = 0; bool supportsSoftShadows = renderingData.shadowData.supportsSoftShadows; for (int i = 0; i < visibleLights.Length && m_AdditionalShadowCastingLightIndices.Count < additionalLightsCount; ++i) { VisibleLight shadowLight = visibleLights[i]; // Skip main directional light as it is not packed into the shadow atlas if (i == renderingData.lightData.mainLightIndex) { continue; } int shadowCastingLightIndex = m_AdditionalShadowCastingLightIndices.Count; bool isValidShadowSlice = false; if (renderingData.cullResults.GetShadowCasterBounds(i, out var bounds)) { // We need to iterate the lights even though additional lights are disabled because // cullResults.GetShadowCasterBounds() does the fence sync for the shadow culling jobs. if (!renderingData.shadowData.supportsAdditionalLightShadows) { continue; } if (IsValidShadowCastingLight(ref renderingData.lightData, i)) { bool success = ShadowUtils.ExtractSpotLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData, i, out var shadowTransform, out m_AdditionalLightSlices[shadowCastingLightIndex].viewMatrix, out m_AdditionalLightSlices[shadowCastingLightIndex].projectionMatrix); if (success) { m_AdditionalShadowCastingLightIndices.Add(i); var light = shadowLight.light; float shadowStrength = light.shadowStrength; float softShadows = (supportsSoftShadows && light.shadows == LightShadows.Soft) ? 1.0f : 0.0f; Vector4 shadowParams = new Vector4(shadowStrength, softShadows, 0.0f, 0.0f); if (m_UseStructuredBuffer) { m_AdditionalLightsShadowData[shadowCastingLightIndex].worldToShadowMatrix = shadowTransform; m_AdditionalLightsShadowData[shadowCastingLightIndex].shadowParams = shadowParams; } else { m_AdditionalLightsWorldToShadow[shadowCastingLightIndex] = shadowTransform; m_AdditionalLightsShadowParams[shadowCastingLightIndex] = shadowParams; } isValidShadowSlice = true; validShadowCastingLights++; } } } if (m_UseStructuredBuffer) { // When using StructuredBuffers all the valid shadow casting slices data // are stored in a the ShadowData buffer and then we setup a index map to // map from light indices to shadow buffer index. A index map of -1 means // the light is not a valid shadow casting light and there's no data for it // in the shadow buffer. int indexMap = (isValidShadowSlice) ? shadowCastingLightIndex : -1; m_AdditionalShadowCastingLightIndicesMap.Add(indexMap); } else if (!isValidShadowSlice) { // When NOT using structured buffers we have no performant way to sample the // index map as int[]. Unity shader compiler converts int[] to float4[] to force memory alignment. // This makes indexing int[] arrays very slow. So, in order to avoid indexing shadow lights we // setup slice data and reserve shadow map space even for invalid shadow slices. // The data is setup with zero shadow strength. This has the same visual effect of no shadow // attenuation contribution from this light. // This makes sampling shadow faster but introduces waste in shadow map atlas. // The waste increases with the amount of additional lights to shade. // Therefore Universal RP try to keep the limit at sane levels when using uniform buffers. Matrix4x4 identity = Matrix4x4.identity; m_AdditionalShadowCastingLightIndices.Add(i); m_AdditionalLightsWorldToShadow[shadowCastingLightIndex] = identity; m_AdditionalLightsShadowParams[shadowCastingLightIndex] = Vector4.zero; m_AdditionalLightSlices[shadowCastingLightIndex].viewMatrix = identity; m_AdditionalLightSlices[shadowCastingLightIndex].projectionMatrix = identity; } m_ShadowCastingLightIndicesMap[i] = isValidShadowSlice ? shadowCastingLightIndex : -1; } // Lights that need to be rendered in the shadow map atlas if (validShadowCastingLights == 0) { return(false); } int atlasWidth = renderingData.shadowData.additionalLightsShadowmapWidth; int atlasHeight = renderingData.shadowData.additionalLightsShadowmapHeight; int sliceResolution = ShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, validShadowCastingLights); // In the UI we only allow for square shadow map atlas. Here we check if we can fit // all shadow slices into half resolution of the atlas and adjust height to have tighter packing. int maximumSlices = (m_ShadowmapWidth / sliceResolution) * (m_ShadowmapHeight / sliceResolution); if (validShadowCastingLights <= (maximumSlices / 2)) { m_ShadowmapHeight /= 2; } int shadowSlicesPerRow = (atlasWidth / sliceResolution); float oneOverAtlasWidth = 1.0f / m_ShadowmapWidth; float oneOverAtlasHeight = 1.0f / m_ShadowmapHeight; int sliceIndex = 0; int shadowCastingLightsBufferCount = m_AdditionalShadowCastingLightIndices.Count; Matrix4x4 sliceTransform = Matrix4x4.identity; sliceTransform.m00 = sliceResolution * oneOverAtlasWidth; sliceTransform.m11 = sliceResolution * oneOverAtlasHeight; for (int i = 0; i < shadowCastingLightsBufferCount; ++i) { // we can skip the slice if strength is zero. Some slices with zero // strength exists when using uniform array path. if (!m_UseStructuredBuffer && Mathf.Approximately(m_AdditionalLightsShadowParams[i].x, 0.0f)) { continue; } m_AdditionalLightSlices[i].offsetX = (sliceIndex % shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].offsetY = (sliceIndex / shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].resolution = sliceResolution; sliceTransform.m03 = m_AdditionalLightSlices[i].offsetX * oneOverAtlasWidth; sliceTransform.m13 = m_AdditionalLightSlices[i].offsetY * oneOverAtlasHeight; // We bake scale and bias to each shadow map in the atlas in the matrix. // saves some instructions in shader. if (m_UseStructuredBuffer) { m_AdditionalLightsShadowData[i].worldToShadowMatrix = sliceTransform * m_AdditionalLightsShadowData[i].worldToShadowMatrix; } else { m_AdditionalLightsWorldToShadow[i] = sliceTransform * m_AdditionalLightsWorldToShadow[i]; } sliceIndex++; } return(true); }
void RenderAdditionalShadowmapAtlas(ref ScriptableRenderContext context, ref CullingResults cullResults, ref LightData lightData, ref ShadowData shadowData) { NativeArray <VisibleLight> visibleLights = lightData.visibleLights; bool additionalLightHasSoftShadows = false; // NOTE: Do NOT mix ProfilingScope with named CommandBuffers i.e. CommandBufferPool.Get("name"). // Currently there's an issue which results in mismatched markers. CommandBuffer cmd = CommandBufferPool.Get(); using (new ProfilingScope(cmd, m_ProfilingSampler)) { bool anyShadowSliceRenderer = false; int shadowSlicesCount = m_AdditionalShadowCastingLightIndices.Count; for (int i = 0; i < shadowSlicesCount; ++i) { // we do the shadow strength check here again here because when using // the uniform array path we might have zero strength shadow lights. // In that case we need the shadow data buffer but we can skip // rendering them to shadowmap. if (!m_UseStructuredBuffer && Mathf.Approximately(m_AdditionalLightsShadowParams[i].x, 0.0f)) { continue; } // Index of the VisibleLight int shadowLightIndex = m_AdditionalShadowCastingLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; ShadowSliceData shadowSliceData = m_AdditionalLightSlices[i]; var settings = new ShadowDrawingSettings(cullResults, shadowLightIndex); Vector4 shadowBias = ShadowUtils.GetShadowBias(ref shadowLight, shadowLightIndex, ref shadowData, shadowSliceData.projectionMatrix, shadowSliceData.resolution); ShadowUtils.SetupShadowCasterConstantBuffer(cmd, ref shadowLight, shadowBias); ShadowUtils.RenderShadowSlice(cmd, ref context, ref shadowSliceData, ref settings); additionalLightHasSoftShadows |= shadowLight.light.shadows == LightShadows.Soft; anyShadowSliceRenderer = true; } // We share soft shadow settings for main light and additional lights to save keywords. // So we check here if pipeline supports soft shadows and either main light or any additional light has soft shadows // to enable the keyword. // TODO: In PC and Consoles we can upload shadow data per light and branch on shader. That will be more likely way faster. bool mainLightHasSoftShadows = shadowData.supportsMainLightShadows && lightData.mainLightIndex != -1 && visibleLights[lightData.mainLightIndex].light.shadows == LightShadows.Soft; bool softShadows = shadowData.supportsSoftShadows && (mainLightHasSoftShadows || additionalLightHasSoftShadows); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.AdditionalLightShadows, anyShadowSliceRenderer); CoreUtils.SetKeyword(cmd, ShaderKeywordStrings.SoftShadows, softShadows); if (anyShadowSliceRenderer) { SetupAdditionalLightsShadowReceiverConstants(cmd, ref shadowData, softShadows); } } context.ExecuteCommandBuffer(cmd); CommandBufferPool.Release(cmd); }
public bool Setup(RenderTargetHandle destination, ref RenderingData renderingData, int maxVisibleAdditinalLights) { Clear(); this.destination = destination; if (m_AdditionalLightShadowMatrices.Length != maxVisibleAdditinalLights) { m_AdditionalLightShadowMatrices = new Matrix4x4[maxVisibleAdditinalLights]; m_AdditionalLightSlices = new ShadowSliceData[maxVisibleAdditinalLights]; m_AdditionalLightsShadowStrength = new float[maxVisibleAdditinalLights]; } m_AdditionalShadowCastingLightIndices.Clear(); Bounds bounds; var visibleLights = renderingData.lightData.visibleLights; int additionalLightsCount = renderingData.lightData.additionalLightsCount; for (int i = 0; i < visibleLights.Length && m_AdditionalShadowCastingLightIndices.Count < additionalLightsCount; ++i) { if (i == renderingData.lightData.mainLightIndex) { continue; } VisibleLight shadowLight = visibleLights[i]; Light light = shadowLight.light; if (shadowLight.lightType == LightType.Spot && light != null && light.shadows != LightShadows.None) { if (renderingData.cullResults.GetShadowCasterBounds(i, out bounds)) { m_AdditionalShadowCastingLightIndices.Add(i); } } } int shadowCastingLightsCount = m_AdditionalShadowCastingLightIndices.Count; if (shadowCastingLightsCount == 0) { return(false); } // 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 atlasWidth = renderingData.shadowData.additionalLightsShadowmapWidth; int atlasHeight = renderingData.shadowData.additionalLightsShadowmapHeight; int sliceResolution = ShadowUtils.GetMaxTileResolutionInAtlas(atlasWidth, atlasHeight, shadowCastingLightsCount); bool anyShadows = false; int shadowSlicesPerRow = (atlasWidth / sliceResolution); for (int i = 0; i < shadowCastingLightsCount; ++i) { int shadowLightIndex = m_AdditionalShadowCastingLightIndices[i]; VisibleLight shadowLight = visibleLights[shadowLightIndex]; // Currently Only Spot Lights are supported in additional lights Debug.Assert(shadowLight.lightType == LightType.Spot); Matrix4x4 shadowTransform; bool success = ShadowUtils.ExtractSpotLightMatrix(ref renderingData.cullResults, ref renderingData.shadowData, shadowLightIndex, out shadowTransform, out m_AdditionalLightSlices[i].viewMatrix, out m_AdditionalLightSlices[i].projectionMatrix); if (success) { // TODO: We need to pass bias and scale list to shader to be able to support multiple // shadow casting additional lights. m_AdditionalLightSlices[i].offsetX = (i % shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].offsetY = (i / shadowSlicesPerRow) * sliceResolution; m_AdditionalLightSlices[i].resolution = sliceResolution; m_AdditionalLightSlices[i].shadowTransform = shadowTransform; m_AdditionalLightsShadowStrength[i] = shadowLight.light.shadowStrength; anyShadows = true; } else { m_AdditionalShadowCastingLightIndices.RemoveAt(i--); } } return(anyShadows); }
void LateUpdate() { ShadowUtils.SetLightCamera(_mainCamera, _lightCamera); }
public bool Setup(ref RenderingData renderingData) { using var profScope = new ProfilingScope(null, m_ProfilingSetupSampler); 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); renderTargetWidth = renderingData.shadowData.mainLightShadowmapWidth; renderTargetHeight = (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, renderTargetWidth, renderTargetHeight, shadowResolution, light.shadowNearPlane, out m_CascadeSplitDistances[cascadeIndex], out m_CascadeSlices[cascadeIndex]); if (!success) { return(false); } } m_MainLightShadowmapTexture = ShadowUtils.GetTemporaryShadowTexture(renderTargetWidth, renderTargetHeight, k_ShadowmapBufferBits); m_MaxShadowDistanceSq = renderingData.cameraData.maxShadowDistance * renderingData.cameraData.maxShadowDistance; m_CascadeBorder = renderingData.shadowData.mainLightShadowCascadeBorder; return(true); }
override public bool Reserve(FrameId frameId, ref ShadowData shadowData, ShadowRequest sr, uint[] widths, uint[] heights, ref VectorArray <ShadowData> entries, ref VectorArray <ShadowPayload> payload, VisibleLight[] lights) { ShadowData sd = shadowData; ShadowData dummy = new ShadowData(); if (sr.shadowType != GPUShadowType.Point && sr.shadowType != GPUShadowType.Spot && sr.shadowType != GPUShadowType.Directional) { return(false); } if (sr.shadowType == GPUShadowType.Directional) { for (uint i = 0; i < k_MaxCascadesInShader; ++i) { m_TmpSplits[i].Set(0.0f, 0.0f, 0.0f, float.NegativeInfinity); } } Key key; key.id = sr.instanceId; key.faceIdx = 0; key.visibleIdx = (int)sr.index; key.shadowDataIdx = entries.Count(); uint originalEntryCount = entries.Count(); uint originalPayloadCount = payload.Count(); uint originalActiveEntries = m_ActiveEntriesCount; uint facecnt = sr.facecount; uint facemask = sr.facemask; uint bit = 1; int resIdx = 0; entries.Reserve(6); float nearPlaneOffset = QualitySettings.shadowNearPlaneOffset; while (facecnt > 0) { if ((bit & facemask) != 0) { uint width = widths[resIdx]; uint height = heights[resIdx]; uint ceIdx; if (!Alloc(frameId, key, width, height, out ceIdx, payload)) { entries.Purge(entries.Count() - originalEntryCount); payload.Purge(payload.Count() - originalPayloadCount); uint added = m_ActiveEntriesCount - originalActiveEntries; for (uint i = originalActiveEntries; i < m_ActiveEntriesCount; ++i) { m_EntryCache.Swap(i, m_EntryCache.Count() - i - 1); } m_EntryCache.Purge(added, Free); m_ActiveEntriesCount = originalActiveEntries; return(false); } // read CachedEntry ce = m_EntryCache[ceIdx]; // modify Matrix4x4 vp; if (sr.shadowType == GPUShadowType.Point) { vp = ShadowUtils.ExtractPointLightMatrix(lights[sr.index], key.faceIdx, 2.0f, out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData, m_CullResults, (int)sr.index); } else if (sr.shadowType == GPUShadowType.Spot) { vp = ShadowUtils.ExtractSpotLightMatrix(lights[sr.index], out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData); } else if (sr.shadowType == GPUShadowType.Directional) { vp = ShadowUtils.ExtractDirectionalLightMatrix(lights[sr.index], key.faceIdx, m_CascadeCount, m_CascadeRatios, nearPlaneOffset, width, height, out ce.current.view, out ce.current.proj, out ce.current.lightDir, out ce.current.splitData, m_CullResults, (int)sr.index); m_TmpSplits[key.faceIdx] = ce.current.splitData.cullingSphere; m_TmpSplits[key.faceIdx].w *= ce.current.splitData.cullingSphere.w; } else { vp = Matrix4x4.identity; // should never happen, though } // write :( m_EntryCache[ceIdx] = ce; sd.worldToShadow = vp.transpose; // apparently we need to transpose matrices that are sent to HLSL sd.scaleOffset = new Vector4(ce.current.viewport.width * m_WidthRcp, ce.current.viewport.height * m_HeightRcp, ce.current.viewport.x, ce.current.viewport.y); sd.texelSizeRcp = new Vector2(m_WidthRcp, m_HeightRcp); sd.PackShadowmapId(m_TexSlot, m_SampSlot, ce.current.slice); sd.shadowType = sr.shadowType; sd.payloadOffset = payload.Count(); entries.AddUnchecked(sd); resIdx++; facecnt--; key.shadowDataIdx++; } else { // we push a dummy face in, otherwise we'd need a mapping from face index to shadowData in the shader as well entries.AddUnchecked(dummy); } key.faceIdx++; bit <<= 1; } if (sr.shadowType == GPUShadowType.Directional) { ShadowPayload sp = new ShadowPayload(); payload.Reserve(k_MaxCascadesInShader); for (uint i = 0; i < k_MaxCascadesInShader; i++) { sp.Set(m_TmpSplits[i]); payload.AddUnchecked(sp); } } return(true); }