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 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); }