public void InitShadowManager(RenderPipelineResources renderPipelineResources, DepthBits directionalShadowDepthBits, HDShadowInitParameters.HDShadowAtlasInitParams punctualLightAtlasInfo, HDShadowInitParameters.HDShadowAtlasInitParams areaLightAtlasInfo, int maxShadowRequests, Shader clearShader) { Material clearMaterial = CoreUtils.CreateEngineMaterial(clearShader); // Prevent the list from resizing their internal container when we add shadow requests m_ShadowDatas.Capacity = maxShadowRequests; m_ShadowResolutionRequests = new HDShadowResolutionRequest[maxShadowRequests]; m_ShadowRequests = new HDShadowRequest[maxShadowRequests]; m_CachedDirectionalShadowData = new HDDirectionalShadowData[1]; // we only support directional light shadow for (int i = 0; i < maxShadowRequests; i++) { m_ShadowResolutionRequests[i] = new HDShadowResolutionRequest(); } // The cascade atlas will be allocated only if there is a directional light m_Atlas = new HDShadowAtlas(renderPipelineResources, punctualLightAtlasInfo.shadowAtlasResolution, punctualLightAtlasInfo.shadowAtlasResolution, HDShaderIDs._ShadowmapAtlas, HDShaderIDs._ShadowAtlasSize, clearMaterial, maxShadowRequests, depthBufferBits: punctualLightAtlasInfo.shadowAtlasDepthBits, name: "Shadow Map Atlas"); // Cascade atlas render texture will only be allocated if there is a shadow casting directional light HDShadowAtlas.BlurAlgorithm cascadeBlur = GetDirectionalShadowAlgorithm() == DirectionalShadowAlgorithm.IMS ? HDShadowAtlas.BlurAlgorithm.IM : HDShadowAtlas.BlurAlgorithm.None; m_CascadeAtlas = new HDShadowAtlas(renderPipelineResources, 1, 1, HDShaderIDs._ShadowmapCascadeAtlas, HDShaderIDs._CascadeShadowAtlasSize, clearMaterial, maxShadowRequests, cascadeBlur, depthBufferBits: directionalShadowDepthBits, name: "Cascade Shadow Map Atlas"); m_AreaLightShadowAtlas = new HDShadowAtlas(renderPipelineResources, areaLightAtlasInfo.shadowAtlasResolution, areaLightAtlasInfo.shadowAtlasResolution, HDShaderIDs._AreaLightShadowmapAtlas, HDShaderIDs._AreaShadowAtlasSize, clearMaterial, maxShadowRequests, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: areaLightAtlasInfo.shadowAtlasDepthBits, name: "Area Light Shadow Map Atlas", momentAtlasShaderID: HDShaderIDs._AreaShadowmapMomentAtlas); m_ShadowDataBuffer = new ComputeBuffer(maxShadowRequests, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDShadowData))); m_DirectionalShadowDataBuffer = new ComputeBuffer(1, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDDirectionalShadowData))); m_MaxShadowRequests = maxShadowRequests; }
internal void UpdateResolutionRequest(ref HDShadowResolutionRequest request, int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { punctualShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.AreaLightAtlas) { areaShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } }
// Used to update the resolution request processed by the light loop internal void UpdateResolutionRequest(ref HDShadowResolutionRequest request, int shadowIdx) { CachedShadowRecord record; bool valueFound = m_PlacedShadows.TryGetValue(shadowIdx, out record); if (!valueFound) { Debug.LogWarning("Trying to render a cached shadow map that doesn't have a slot in the atlas yet."); } request.cachedAtlasViewport = new Rect(record.offsetInAtlas.x, record.offsetInAtlas.y, record.viewportSize, record.viewportSize); request.resolution = new Vector2(record.viewportSize, record.viewportSize); }
public void InitShadowManager(RenderPipelineResources renderPipelineResources, HDShadowInitParameters initParams, RenderGraph renderGraph, Shader clearShader) { // Even when shadows are disabled (maxShadowRequests == 0) we need to allocate compute buffers to avoid having // resource not bound errors when dispatching a compute shader. m_ShadowDataBuffer = new ComputeBuffer(Mathf.Max(initParams.maxShadowRequests, 1), System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDShadowData))); m_DirectionalShadowDataBuffer = new ComputeBuffer(1, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDDirectionalShadowData))); m_MaxShadowRequests = initParams.maxShadowRequests; m_ShadowRequestCount = 0; if (initParams.maxShadowRequests == 0) { return; } m_ClearShadowMaterial = CoreUtils.CreateEngineMaterial(clearShader); m_BlitShadowMaterial = CoreUtils.CreateEngineMaterial(renderPipelineResources.shaders.shadowBlitPS); // Prevent the list from resizing their internal container when we add shadow requests m_ShadowDatas.Capacity = Math.Max(initParams.maxShadowRequests, m_ShadowDatas.Capacity); m_ShadowResolutionRequests = new HDShadowResolutionRequest[initParams.maxShadowRequests]; m_ShadowRequests = new HDShadowRequest[initParams.maxShadowRequests]; m_CachedDirectionalShadowData = new HDDirectionalShadowData[1]; // we only support directional light shadow for (int i = 0; i < initParams.maxShadowRequests; i++) { m_ShadowResolutionRequests[i] = new HDShadowResolutionRequest(); } // The cascade atlas will be allocated only if there is a directional light m_Atlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, initParams.punctualLightShadowAtlas.shadowAtlasResolution, initParams.punctualLightShadowAtlas.shadowAtlasResolution, HDShaderIDs._ShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, depthBufferBits: initParams.punctualLightShadowAtlas.shadowAtlasDepthBits, name: "Shadow Map Atlas"); // Cascade atlas render texture will only be allocated if there is a shadow casting directional light HDShadowAtlas.BlurAlgorithm cascadeBlur = GetDirectionalShadowAlgorithm() == DirectionalShadowAlgorithm.IMS ? HDShadowAtlas.BlurAlgorithm.IM : HDShadowAtlas.BlurAlgorithm.None; m_CascadeAtlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, 1, 1, HDShaderIDs._ShadowmapCascadeAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, cascadeBlur, depthBufferBits: initParams.directionalShadowsDepthBits, name: "Cascade Shadow Map Atlas"); if (ShaderConfig.s_AreaLights == 1) { m_AreaLightShadowAtlas = new HDDynamicShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: false, initParams.areaLightShadowAtlas.shadowAtlasResolution, initParams.areaLightShadowAtlas.shadowAtlasResolution, HDShaderIDs._ShadowmapAreaAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: initParams.areaLightShadowAtlas.shadowAtlasDepthBits, name: "Area Light Shadow Map Atlas"); } cachedShadowManager.InitPunctualShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: true, initParams.cachedPunctualLightShadowAtlas, initParams.cachedPunctualLightShadowAtlas, HDShaderIDs._CachedShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams: initParams, depthBufferBits: initParams.punctualLightShadowAtlas.shadowAtlasDepthBits, name: "Cached Shadow Map Atlas"); if (ShaderConfig.s_AreaLights == 1) { cachedShadowManager.InitAreaLightShadowAtlas(renderPipelineResources, renderGraph, useSharedTexture: true, initParams.cachedAreaLightShadowAtlas, initParams.cachedAreaLightShadowAtlas, HDShaderIDs._CachedAreaLightShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams: initParams, HDShadowAtlas.BlurAlgorithm.EVSM, depthBufferBits: initParams.areaLightShadowAtlas.shadowAtlasDepthBits, name: "Cached Area Light Shadow Map Atlas"); } }
internal void UpdateResolutionRequest(ref HDShadowResolutionRequest request, int shadowIdx, ShadowMapType shadowMapType) { if (shadowMapType == ShadowMapType.PunctualAtlas) { punctualShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.AreaLightAtlas) { areaShadowAtlas.UpdateResolutionRequest(ref request, shadowIdx); } else if (shadowMapType == ShadowMapType.CascadedDirectional) { request.cachedAtlasViewport = request.dynamicAtlasViewport; } }
public HDShadowAtlas(RenderPipelineResources renderPipelineResources, int width, int height, int atlasShaderID, Material clearMaterial, int maxShadowRequests, BlurAlgorithm blurAlgorithm = BlurAlgorithm.None, FilterMode filterMode = FilterMode.Bilinear, DepthBits depthBufferBits = DepthBits.Depth16, RenderTextureFormat format = RenderTextureFormat.Shadowmap, string name = "") { this.width = width; this.height = height; m_FilterMode = filterMode; m_DepthBufferBits = depthBufferBits; m_Format = format; m_Name = name; m_AtlasShaderID = atlasShaderID; m_ClearMaterial = clearMaterial; m_BlurAlgorithm = blurAlgorithm; m_RenderPipelineResources = renderPipelineResources; m_SortedRequestsCache = new HDShadowResolutionRequest[Mathf.CeilToInt(maxShadowRequests * 1.5f)]; m_CachedResolutionRequests = new HDShadowResolutionRequest[maxShadowRequests]; for (int i = 0; i < maxShadowRequests; ++i) { m_CachedResolutionRequests[i] = new HDShadowResolutionRequest(); } AllocateRenderTexture(); }
internal void ReserveResolution(HDShadowResolutionRequest shadowRequest) { m_ShadowResolutionRequests.Add(shadowRequest); }
internal int RegisterCachedLight(HDShadowResolutionRequest request) { // Since we are starting caching light resolution requests, it means that data cached from now on will be valid. frameOfCacheValidity++; // If it is already registered, we do nothing. int shadowIndex = -1; for (int i = 0; i < m_ListOfCachedShadowRequests.Count; ++i) { if (!m_ListOfCachedShadowRequests[i].emptyRequest && m_ListOfCachedShadowRequests[i].lightID == request.lightID && m_ListOfCachedShadowRequests[i].indexInLight == request.indexInLight) { shadowIndex = i; break; } } if (shadowIndex == -1) { // First we search if we have a hole we can fill with it. float resolutionOfNewLight = request.atlasViewport.width; request.lastFrameActive = frameCounter; int holeWithRightSize = -1; for (int i = 0; i < m_ListOfCachedShadowRequests.Count; ++i) { var currReq = m_ListOfCachedShadowRequests[i]; if (currReq.emptyRequest && // Is empty request.atlasViewport.width <= currReq.atlasViewport.width && // fits the request (currReq.atlasViewport.width - request.atlasViewport.width) <= currReq.atlasViewport.width * 0.1f) // but is not much smaller. { holeWithRightSize = i; break; } } if (holeWithRightSize >= 0) { m_ListOfCachedShadowRequests[holeWithRightSize] = request.ShallowCopy(); return(holeWithRightSize); } else { // We need to resort the list, so we use the occasion to reset the pool. This feels suboptimal, but it is the easiest way to comply with the pooling system. // TODO: Make this cleaner and more efficient. m_CachedResolutionRequestsCounter = 0; for (int i = 0; i < m_ListOfCachedShadowRequests.Count; ++i) { int currEntryInPool = m_CachedResolutionRequestsCounter; m_CachedResolutionRequests[currEntryInPool] = m_ListOfCachedShadowRequests[i].ShallowCopy(); m_ListOfCachedShadowRequests[i] = m_CachedResolutionRequests[currEntryInPool]; m_CachedResolutionRequestsCounter++; } // Now we add the new element m_CachedResolutionRequests[m_CachedResolutionRequestsCounter] = request.ShallowCopy(); m_ListOfCachedShadowRequests.Add(m_CachedResolutionRequests[m_CachedResolutionRequestsCounter]); m_CachedResolutionRequestsCounter++; InsertionSort(m_ListOfCachedShadowRequests.ToArray(), 0, m_ListOfCachedShadowRequests.Count); frameOfCacheValidity = 0; // Invalidate cached data for (int i = 0; i < m_ListOfCachedShadowRequests.Count; ++i) { if (m_ListOfCachedShadowRequests[i].lightID == request.lightID && m_ListOfCachedShadowRequests[i].indexInLight == request.indexInLight) { return(i); } } } } else if (m_ListOfCachedShadowRequests[shadowIndex].emptyRequest) { // We still hold the spot, so fill it up again. m_ListOfCachedShadowRequests[shadowIndex].emptyRequest = false; } m_ListOfCachedShadowRequests[shadowIndex].lastFrameActive = frameCounter; return(shadowIndex); }
public void InitShadowManager(RenderPipelineResources renderPipelineResources, HDShadowInitParameters initParams, Shader clearShader) { // Even when shadows are disabled (maxShadowRequests == 0) we need to allocate compute buffers to avoid having // resource not bound errors when dispatching a compute shader. m_ShadowDataBuffer = new ComputeBuffer(Mathf.Max(initParams.maxShadowRequests, 1), System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDShadowData))); m_DirectionalShadowDataBuffer = new ComputeBuffer(1, System.Runtime.InteropServices.Marshal.SizeOf(typeof(HDDirectionalShadowData))); m_MaxShadowRequests = initParams.maxShadowRequests; m_ShadowRequestCount = 0; if (initParams.maxShadowRequests == 0) { return; } m_ClearShadowMaterial = CoreUtils.CreateEngineMaterial(clearShader); m_BlitShadowMaterial = CoreUtils.CreateEngineMaterial(renderPipelineResources.shaders.shadowBlitPS); // Prevent the list from resizing their internal container when we add shadow requests m_ShadowDatas.Capacity = Math.Max(initParams.maxShadowRequests, m_ShadowDatas.Capacity); m_ShadowResolutionRequests = new HDShadowResolutionRequest[initParams.maxShadowRequests]; m_ShadowRequests = new HDShadowRequest[initParams.maxShadowRequests]; m_CachedDirectionalShadowData = new HDDirectionalShadowData[1]; // we only support directional light shadow m_GlobalShaderVariables = new ConstantBuffer <ShaderVariablesGlobal>(); for (int i = 0; i < initParams.maxShadowRequests; i++) { m_ShadowResolutionRequests[i] = new HDShadowResolutionRequest(); } HDShadowAtlas.HDShadowAtlasInitParameters punctualAtlasInitParams = new HDShadowAtlas.HDShadowAtlasInitParameters(renderPipelineResources, initParams.punctualLightShadowAtlas.shadowAtlasResolution, initParams.punctualLightShadowAtlas.shadowAtlasResolution, HDShaderIDs._ShadowmapAtlas, m_ClearShadowMaterial, initParams.maxShadowRequests, initParams, m_GlobalShaderVariables); punctualAtlasInitParams.name = "Shadow Map Atlas"; // The cascade atlas will be allocated only if there is a directional light m_Atlas = new HDDynamicShadowAtlas(punctualAtlasInitParams); // Cascade atlas render texture will only be allocated if there is a shadow casting directional light HDShadowAtlas.BlurAlgorithm cascadeBlur = GetDirectionalShadowAlgorithm() == DirectionalShadowAlgorithm.IMS ? HDShadowAtlas.BlurAlgorithm.IM : HDShadowAtlas.BlurAlgorithm.None; HDShadowAtlas.HDShadowAtlasInitParameters dirAtlasInitParams = punctualAtlasInitParams; dirAtlasInitParams.width = 1; dirAtlasInitParams.height = 1; dirAtlasInitParams.atlasShaderID = HDShaderIDs._ShadowmapCascadeAtlas; dirAtlasInitParams.blurAlgorithm = cascadeBlur; dirAtlasInitParams.depthBufferBits = initParams.directionalShadowsDepthBits; dirAtlasInitParams.name = "Cascade Shadow Map Atlas"; m_CascadeAtlas = new HDDynamicShadowAtlas(dirAtlasInitParams); HDShadowAtlas.HDShadowAtlasInitParameters areaAtlasInitParams = punctualAtlasInitParams; if (ShaderConfig.s_AreaLights == 1) { areaAtlasInitParams.width = initParams.areaLightShadowAtlas.shadowAtlasResolution; areaAtlasInitParams.height = initParams.areaLightShadowAtlas.shadowAtlasResolution; areaAtlasInitParams.atlasShaderID = HDShaderIDs._ShadowmapAreaAtlas; areaAtlasInitParams.blurAlgorithm = HDShadowAtlas.BlurAlgorithm.EVSM; areaAtlasInitParams.depthBufferBits = initParams.areaLightShadowAtlas.shadowAtlasDepthBits; areaAtlasInitParams.name = "Area Light Shadow Map Atlas"; m_AreaLightShadowAtlas = new HDDynamicShadowAtlas(areaAtlasInitParams); } HDShadowAtlas.HDShadowAtlasInitParameters cachedPunctualAtlasInitParams = punctualAtlasInitParams; cachedPunctualAtlasInitParams.width = initParams.cachedPunctualLightShadowAtlas; cachedPunctualAtlasInitParams.height = initParams.cachedPunctualLightShadowAtlas; cachedPunctualAtlasInitParams.atlasShaderID = HDShaderIDs._CachedShadowmapAtlas; cachedPunctualAtlasInitParams.name = "Cached Shadow Map Atlas"; cachedShadowManager.InitPunctualShadowAtlas(cachedPunctualAtlasInitParams); if (ShaderConfig.s_AreaLights == 1) { HDShadowAtlas.HDShadowAtlasInitParameters cachedAreaAtlasInitParams = areaAtlasInitParams; cachedAreaAtlasInitParams.width = initParams.cachedAreaLightShadowAtlas; cachedAreaAtlasInitParams.height = initParams.cachedAreaLightShadowAtlas; cachedAreaAtlasInitParams.atlasShaderID = HDShaderIDs._CachedAreaLightShadowmapAtlas; cachedAreaAtlasInitParams.name = "Cached Area Light Shadow Map Atlas"; cachedShadowManager.InitAreaLightShadowAtlas(cachedAreaAtlasInitParams); } }