override public bool ReserveFinalize(FrameId frameId, ref VectorArray <ShadowData> entries, ref VectorArray <ShadowPayload> payload) { if (Layout()) { // patch up the shadow data contents with the result of the layouting step for (uint i = 0; i < m_ActiveEntriesCount; ++i) { CachedEntry ce = m_EntryCache[i]; ShadowData sd = entries[ce.key.shadowDataIdx]; // update the shadow data with the actual result of the layouting step sd.scaleOffset = new Vector4(ce.current.viewport.width * m_WidthRcp, ce.current.viewport.height * m_HeightRcp, ce.current.viewport.x * m_WidthRcp, ce.current.viewport.y * m_HeightRcp); sd.PackShadowmapId(m_TexSlot, m_SampSlot, ce.current.slice); // write back the correct results entries[ce.key.shadowDataIdx] = sd; } m_EntryCache.Purge(m_EntryCache.Count() - m_ActiveEntriesCount, (CachedEntry entry) => { Free(entry); }); return(true); } m_ActiveEntriesCount = 0; m_EntryCache.Reset((CachedEntry entry) => { Free(entry); }); return(false); }
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); }