void SetLod(List <int> quadKeys, int lodBias)
        {
            List <Vector2> quadLODList = new List <Vector2>();

            for (int i = 0; i < quadKeys.Count; i++)
            {
                int quadKey = quadKeys[i];
                int mip     = MortonUtility.getMip(quadKey) + lodBias;
                quadLODList.Add(new Vector2(mip, mip));
                quadLODList.Add(new Vector2(mip, mip));
                quadLODList.Add(new Vector2(mip, mip));
                quadLODList.Add(new Vector2(mip, mip));
            }

            mQuads.SetUVs(1, quadLODList);
        }
        public void GeneratePage()
        {
            if (TilesToGenerate.Count == 0)
            {
                return;
            }
            //print("generating page" + Time.frameCount + "  " + TilesToGenerate.Count);

            List <int> TilesForMesh = new List <int>();

            // 优先处理mipmap等级高的tile
            TilesToGenerate.Sort((x, y) => { return(MortonUtility.getMip(x).CompareTo(MortonUtility.getMip(y))); });

            //一次最多贴5个
            for (int i = 0; TilesToGenerate.Count > 0; i++)
            {
                int quadKey = TilesToGenerate[TilesToGenerate.Count - 1];
                TilesToGenerate.RemoveAt(TilesToGenerate.Count - 1);
                TilesForMesh.Add(quadKey);
            }

            SetUpMesh(TilesForMesh);

            RenderBuffer[] colorBuffers = new RenderBuffer[1];

            for (int textureType = 0; textureType < physicalTexture.NumTextureType; textureType++)
            {
                colorBuffers[0] = physicalTexture.PhysicalTextures[textureType].colorBuffer;
                RenderBuffer depthBuffer = physicalTexture.PhysicalTextures[textureType].depthBuffer;
                for (int i = 0; i < 10; i++)
                {
                    SetLod(TilesForMesh, i);
                    RenderTargetSetup rtsMip = new RenderTargetSetup(colorBuffers, depthBuffer, i, CubemapFace.Unknown);
                    Graphics.SetRenderTarget(rtsMip);
                    CommandBuffer tempCB = new CommandBuffer();
                    tempCB.DrawMesh(mQuads, Matrix4x4.identity, TileGeneratorMat, 0, textureType);
                    //tempCB.DrawMesh(mQuads, Matrix4x4.identity, TileGeneratorMat);

                    Graphics.ExecuteCommandBuffer(tempCB);
                }
            }



            OnTileGenerationComplete?.Invoke(TilesForMesh);
        }
        private void SetUpMesh(List <int> quadKeys)
        {
            List <Vector3> quadVertexList   = new List <Vector3>();
            List <int>     quadTriangleList = new List <int>();
            List <Vector2> quadUVList       = new List <Vector2>();
            List <Vector2> quadLODList      = new List <Vector2>();


            int tableSize = pageTable.TableSize;
            //有可能出现的最高mip
            int maxMip = (int)Math.Log(tableSize, 2);

            mQuads = new Mesh();

            for (int i = 0; i < quadKeys.Count; i++)
            {
                int        quadKey = quadKeys[i];
                int        mip     = MortonUtility.getMip(quadKey);
                Vector2Int pageXY  = MortonUtility.getPageXY(quadKey);
                //最高mip到当前mip的偏移
                int   mipBias           = maxMip - mip;
                float rectBaseLength    = 1.0f / (float)tableSize;
                float currMipRectLength = 1.0f / (float)Math.Pow(2.0, mipBias);
                float paddingLength     = currMipRectLength * ((float)physicalTexture.PaddingSize / (float)physicalTexture.TileSize);


                Vector2 uv0 = new Vector2((float)pageXY.x * rectBaseLength - paddingLength, (float)pageXY.y * rectBaseLength - paddingLength);
                Vector2 uv1 = new Vector2((float)pageXY.x * rectBaseLength + currMipRectLength + paddingLength, (float)pageXY.y * rectBaseLength - paddingLength);
                Vector2 uv2 = new Vector2((float)pageXY.x * rectBaseLength + currMipRectLength + paddingLength, (float)pageXY.y * rectBaseLength + currMipRectLength + paddingLength);
                Vector2 uv3 = new Vector2((float)pageXY.x * rectBaseLength - paddingLength, (float)pageXY.y * rectBaseLength + currMipRectLength + paddingLength);

                quadUVList.Add(uv0);
                quadUVList.Add(uv1);
                quadUVList.Add(uv2);
                quadUVList.Add(uv3);


                float Width  = (float)physicalTexture.PhysicalTextureSize.x;
                float Height = (float)physicalTexture.PhysicalTextureSize.y;

                Vector2Int tile = m_TilePool.RequestTile(mip, Time.frameCount);
                //SetActive(tile);
                //TODO 加tiling offset

                Vector3 vertex0;
                Vector3 vertex1;
                Vector3 vertex2;
                Vector3 vertex3;

                if (SystemInfo.graphicsDeviceType.ToString().Contains("Direct3D"))
                {
                    vertex0 = new Vector3(tile.x * 2 / Width - 1, (Height - tile.y) * 2 / Height - 1, 0.1f);
                    vertex1 = new Vector3((tile.x + 1) * 2 / Width - 1, (Height - tile.y) * 2 / Height - 1, 0.1f);
                    vertex2 = new Vector3((tile.x + 1) * 2 / Width - 1, (Height - tile.y - 1) * 2 / Height - 1, 0.1f);
                    vertex3 = new Vector3(tile.x * 2 / Width - 1, (Height - tile.y - 1) * 2 / Height - 1, 0.1f);
                }
                else
                {
                    vertex0 = new Vector3(tile.x * 2 / Width - 1, tile.y * 2 / Height - 1, 0.1f);
                    vertex1 = new Vector3((tile.x + 1) * 2 / Width - 1, tile.y * 2 / Height - 1, 0.1f);
                    vertex2 = new Vector3((tile.x + 1) * 2 / Width - 1, (tile.y + 1) * 2 / Height - 1, 0.1f);
                    vertex3 = new Vector3(tile.x * 2 / Width - 1, (tile.y + 1) * 2 / Height - 1, 0.1f);
                }



                quadVertexList.Add(vertex0);
                quadVertexList.Add(vertex1);
                quadVertexList.Add(vertex2);
                quadVertexList.Add(vertex3);

                quadTriangleList.Add(4 * i);
                quadTriangleList.Add(4 * i + 1);
                quadTriangleList.Add(4 * i + 2);

                quadTriangleList.Add(4 * i + 2);
                quadTriangleList.Add(4 * i + 3);
                quadTriangleList.Add(4 * i);

                //Mapping Processsssss
                // morton version

                /*pageTable.AddressMapping[quadKey].TileIndex = tile;
                 *
                 * int oldQuad;
                 * if(physicalTexture.TileToQuadMapping.TryGetValue(tile,out oldQuad))
                 * {
                 *  pageTable.AddressMapping.Remove(oldQuad);
                 * }*/

                //Pointer version


                int oldQuad;
                if (physicalTexture.TileToQuadMapping.TryGetValue(tile, out oldQuad))
                {
                    pageTable.m_Pages[oldQuad].Payload.tileStatus = TileStatus.Uninitialized;
                    pageTable.m_Pages.Remove(oldQuad);
                }
                physicalTexture.TileToQuadMapping[tile] = quadKey;

                pageTable.m_Pages[quadKey].Payload.TileIndex = tile;
            }

            mQuads.SetVertices(quadVertexList);
            mQuads.SetUVs(0, quadUVList);
            mQuads.SetTriangles(quadTriangleList, 0);
        }