Beispiel #1
0
            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);
            }