public TerrainFactory(int initialLevel, int mipLevel, string path)
 {
     initLevel       = initialLevel;
     generatorShader = Resources.Load <ComputeShader>("TerrainGenerator");
     readBuffer      = new byte[CHUNK_SIZE];
     streamer        = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.ReadWrite, readBuffer.Length);
     positionOffset  = VirtualTextureLoader.GetStreamingPositionOffset(initialLevel, mipLevel - initialLevel);
 }
        public void UpdateMaterialIndex()
        {
            int           count   = 0;
            RenderTexture cacheRT = new RenderTexture(MTerrain.MASK_RESOLUTION, MTerrain.MASK_RESOLUTION, 0, GraphicsFormat.R32_SFloat, 0);

            cacheRT.dimension         = TextureDimension.Tex2DArray;
            cacheRT.volumeDepth       = 1;
            cacheRT.enableRandomWrite = true;
            cacheRT.Create();
            int largestChunkCount       = (int)(pow(2.0, targetData.GetLodOffset()) + 0.1);
            VirtualTextureLoader loader = new VirtualTextureLoader(
                targetData.maskmapPath,
                terrainEditShader,
                largestChunkCount,
                MTerrain.MASK_RESOLUTION, false, null);
            Dictionary <int2, List <Pair <SplatSettings, int> > > commandDict = new Dictionary <int2, List <Pair <SplatSettings, int> > >(256);

            for (int i = 0; i < allMaterials.Count; ++i)
            {
                for (int j = 0; j < allMaterials[i].blendWeights.Count; ++j)
                {
                    var mat = allMaterials[i].blendWeights[j];
                    foreach (var a in mat.splatSettings)
                    {
                        Texture splat = a.splatMap;
                        if (splat)
                        {
                            int2 border = largestChunkCount - a.splatStartPos;
                            border = min(border, splat.width / MTerrain.MASK_RESOLUTION);
                            for (int x = 0; x < border.x; ++x)
                            {
                                for (int y = 0; y < border.y; ++y)
                                {
                                    if (!commandDict.ContainsKey(int2(x, y) + a.splatStartPos))
                                    {
                                        commandDict.Add(int2(x, y) + a.splatStartPos, new List <Pair <SplatSettings, int> >());
                                    }
                                    commandDict[int2(x, y) + a.splatStartPos].Add(new Pair <SplatSettings, int>(a, count));
                                }
                            }
                        }
                    }
                    count++;
                }
            }
            foreach (var i in commandDict)
            {
                foreach (var j in i.Value)
                {
                    int2 offsetValue = i.Key - j.key.splatStartPos;
                    SaveToMask(cacheRT, j.key.splatMap, j.key.chan, offsetValue, j.value / (count - 1f));
                }
                loader.WriteToDisk(cacheRT, 0, i.Key);
            }
            loader.Dispose();
            DestroyImmediate(cacheRT);
        }
Example #3
0
        private void OnGUI()
        {
            if (!terrainEdit)
            {
                terrainEdit = Resources.Load <ComputeShader>("TerrainEdit");
            }
            terrainData = (MTerrainData)EditorGUILayout.ObjectField("Terrain Data", terrainData, typeof(MTerrainData), false);
            if (!terrainData)
            {
                return;
            }
            chunkPosition    = EditorGUILayout.Vector2IntField("Chunk Position", new Vector2Int(chunkPosition.x, chunkPosition.y));
            heightTexture    = EditorGUILayout.ObjectField("Height Texture", heightTexture, typeof(Texture), false) as Texture;
            targetChunkCount = EditorGUILayout.IntField("Chunk Count", targetChunkCount);
            targetChunkCount = max(0, targetChunkCount);

            int largestChunkCount = (int)(pow(2.0, terrainData.GetLodOffset()) + 0.1);

            if (GUILayout.Button("Update Height Texture"))
            {
                VirtualTextureLoader loader = new VirtualTextureLoader(
                    terrainData.heightmapPath,
                    terrainEdit,
                    largestChunkCount,
                    MTerrain.MASK_RESOLUTION, true, null);
                RenderTexture cacheRt = new RenderTexture(new RenderTextureDescriptor
                {
                    width             = MTerrain.MASK_RESOLUTION,
                    height            = MTerrain.MASK_RESOLUTION,
                    volumeDepth       = 1,
                    dimension         = UnityEngine.Rendering.TextureDimension.Tex2DArray,
                    msaaSamples       = 1,
                    graphicsFormat    = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat,
                    enableRandomWrite = true
                });
                cacheRt.Create();
                int           mipLevel       = 0;
                int           meshResolution = terrainData.GetMeshResolution();
                int           saveMipLevel   = 0;
                ComputeBuffer cb             = new ComputeBuffer(meshResolution * meshResolution, sizeof(float2));

                float2[]      resultArr = new float2[meshResolution * meshResolution];
                RenderTexture mipRT     = new RenderTexture(MTerrain.MASK_RESOLUTION, MTerrain.MASK_RESOLUTION, 0, UnityEngine.Experimental.Rendering.GraphicsFormat.R32G32_SFloat, mipLevel);
                mipRT.enableRandomWrite = true;
                mipRT.useMipMap         = true;
                mipRT.autoGenerateMips  = false;
                mipRT.Create();
                System.IO.FileStream fsm = new System.IO.FileStream(terrainData.boundPath, System.IO.FileMode.OpenOrCreate, System.IO.FileAccess.ReadWrite);
                for (int i = MTerrain.MASK_RESOLUTION; i > 0; i /= 2)
                {
                    mipLevel++;
                    if (i <= meshResolution)
                    {
                        saveMipLevel++;
                    }
                }
                MTerrainBoundingTree btree = new MTerrainBoundingTree(saveMipLevel);
                for (int x = 0; x < targetChunkCount; ++x)
                {
                    for (int y = 0; y < targetChunkCount; ++y)
                    {
                        int2 pos = int2(x, y) + int2(chunkPosition.x, chunkPosition.y);
                        if (pos.x >= largestChunkCount || pos.y >= largestChunkCount)
                        {
                            continue;
                        }
                        terrainEdit.SetTexture(6, ShaderIDs._SourceTex, heightTexture);
                        terrainEdit.SetTexture(6, ShaderIDs._DestTex, cacheRt);
                        terrainEdit.SetInt(ShaderIDs._Count, MTerrain.MASK_RESOLUTION);
                        terrainEdit.SetInt(ShaderIDs._OffsetIndex, 0);
                        terrainEdit.SetVector("_ScaleOffset", float4(float2(1.0 / targetChunkCount), float2(x, y) / targetChunkCount));
                        const int disp = MTerrain.MASK_RESOLUTION / 16;
                        terrainEdit.Dispatch(6, disp, disp, 1);
                        loader.WriteToDisk(cacheRt, 0, pos);
                        for (int i = 0, res = MTerrain.MASK_RESOLUTION; i < mipLevel; ++i, res /= 2)
                        {
                            int pass;
                            if (i == 0)
                            {
                                pass = 7;
                                terrainEdit.SetTexture(pass, "_SourceArray", cacheRt);
                                terrainEdit.SetTexture(pass, "_Mip1", mipRT);
                            }
                            else
                            {
                                if (res <= meshResolution)
                                {
                                    pass = 9;
                                    terrainEdit.SetBuffer(pass, "_DataBuffer", cb);
                                }
                                else
                                {
                                    pass = 8;
                                }
                                terrainEdit.SetTexture(pass, "_Mip0", mipRT, i - 1);
                                terrainEdit.SetTexture(pass, "_Mip1", mipRT, i);
                            }
                            terrainEdit.SetInt(ShaderIDs._Count, res);
                            int mipdisp = Mathf.CeilToInt(res / 16f);
                            terrainEdit.Dispatch(pass, mipdisp, mipdisp, 1);
                            if (pass == 9)
                            {
                                cb.GetData(resultArr, 0, 0, res * res);
                                int targetMipLevel = mipLevel - 1 - i;
                                for (int xx = 0; xx < res * res; ++xx)
                                {
                                    btree[xx, targetMipLevel] = resultArr[xx];
                                }
                            }
                        }
                        btree.WriteToDisk(fsm, x + y * largestChunkCount);
                    }
                }

                btree.Dispose();
                cacheRt.Release();
                cb.Dispose();
                mipRT.Release();
                loader.Dispose();
                fsm.Dispose();
                Debug.Log("Finish!");
            }
            maskTexture = EditorGUILayout.ObjectField("Mask Texture", maskTexture, typeof(Texture), false) as Texture;
            void SaveToMask(RenderTexture cacheRt)
            {
                VirtualTextureLoader loader = new VirtualTextureLoader(
                    terrainData.maskmapPath,
                    terrainEdit,
                    largestChunkCount,
                    MTerrain.MASK_RESOLUTION, false, null);

                for (int x = 0; x < targetChunkCount; ++x)
                {
                    for (int y = 0; y < targetChunkCount; ++y)
                    {
                        int2 pos = int2(x, y) + int2(chunkPosition.x, chunkPosition.y);
                        if (pos.x >= largestChunkCount || pos.y >= largestChunkCount)
                        {
                            continue;
                        }
                        terrainEdit.SetTexture(6, ShaderIDs._SourceTex, maskTexture);
                        terrainEdit.SetTexture(6, ShaderIDs._DestTex, cacheRt);
                        terrainEdit.SetInt(ShaderIDs._Count, MTerrain.MASK_RESOLUTION);
                        terrainEdit.SetInt(ShaderIDs._OffsetIndex, 0);
                        terrainEdit.SetVector("_ScaleOffset", float4(float2(1.0 / targetChunkCount), float2(x, y) / targetChunkCount));
                        const int disp = MTerrain.MASK_RESOLUTION / 16;
                        terrainEdit.Dispatch(6, disp, disp, 1);
                        loader.WriteToDisk(cacheRt, 0, pos);
                    }
                }
                loader.Dispose();
            }

            if (GUILayout.Button("Update Mask Texture"))
            {
                RenderTexture cacheRt = new RenderTexture(new RenderTextureDescriptor
                {
                    width             = MTerrain.MASK_RESOLUTION,
                    height            = MTerrain.MASK_RESOLUTION,
                    volumeDepth       = 1,
                    dimension         = UnityEngine.Rendering.TextureDimension.Tex2DArray,
                    msaaSamples       = 1,
                    graphicsFormat    = UnityEngine.Experimental.Rendering.GraphicsFormat.R32_SFloat,
                    enableRandomWrite = true
                });
                cacheRt.Create();
                SaveToMask(cacheRt);
                cacheRt.Release();
            }
        }
Example #4
0
        protected override void OnEnableFunc()
        {
            if (current && current != this)
            {
                enabled = false;
                Debug.LogError("Only One Terrain allowed!");
                return;
            }
            if (!terrainData)
            {
                enabled = false;
                Debug.LogError("No Data!");
                return;
            }
            msb           = new MStringBuilder(32);
            textureShader = Resources.Load <ComputeShader>("ProceduralTexture");
            shader        = Resources.Load <ComputeShader>("TerrainCompute");
            current       = this;
            int indexMapSize = 1;

            for (int i = 1; i < terrainData.lodDistances.Length; ++i)
            {
                indexMapSize *= 2;
            }
            dispatchDrawBuffer = new ComputeBuffer(5, sizeof(int), ComputeBufferType.IndirectArguments);
            const int INIT_LENGTH = 500;

            culledResultsBuffer = new ComputeBuffer(INIT_LENGTH, sizeof(int));
            loadedBuffer        = new ComputeBuffer(INIT_LENGTH, sizeof(TerrainChunkBuffer));
            loadedBufferList    = new NativeList <TerrainChunkBuffer>(INIT_LENGTH, Allocator.Persistent);
            lodOffset           = terrainData.lodDistances.Length - terrainData.renderingLevelCount;
            loader       = new VirtualTextureLoader(lodOffset, terrainData.renderingLevelCount, terrainData.readWritePath, this);
            loadDataList = new NativeQueue <TerrainLoadData>(100, Allocator.Persistent);
            NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory);

            dispatchDraw[0] = 96;
            dispatchDrawBuffer.SetData(dispatchDraw);
            VirtualTextureFormat *formats = stackalloc VirtualTextureFormat[]
            {
                new VirtualTextureFormat((VirtualTextureSize)HEIGHT_RESOLUTION, RenderTextureFormat.R16, "_VirtualHeightmap"),
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.ARGB32, "_VirtualMainTex"),
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.RGHalf, "_VirtualBumpMap"),
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, RenderTextureFormat.RG16, "_VirtualSMMap")
            };

            vt           = new VirtualTexture(terrainData.virtualTexCapacity, min(2048, (int)(pow(2.0, terrainData.lodDistances.Length) + 0.1)), formats, 4, "_TerrainVTIndexTex");
            allLodLevles = new NativeList_Float(terrainData.lodDistances.Length, Allocator.Persistent);
            for (int i = 0; i < terrainData.lodDistances.Length; ++i)
            {
                allLodLevles.Add(min(terrainData.lodDistances[max(0, i - 1)], terrainData.lodDistances[i]));
            }
            allLodLevles[terrainData.lodDistances.Length] = 0;

            albedoTex = new RenderTexture(new RenderTextureDescriptor
            {
                colorFormat       = RenderTextureFormat.ARGB32,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1
            });
            albedoTex.Create();
            normalTex = new RenderTexture(new RenderTextureDescriptor
            {
                colorFormat       = RenderTextureFormat.RGHalf,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1
            });
            normalTex.Create();
            smTex = new RenderTexture(new RenderTextureDescriptor
            {
                colorFormat       = RenderTextureFormat.RG16,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1
            });
            smTex.Create();
            smTex.wrapMode     = TextureWrapMode.Repeat;
            normalTex.wrapMode = TextureWrapMode.Repeat;
            albedoTex.wrapMode = TextureWrapMode.Repeat;
            mask = new RenderTexture(new RenderTextureDescriptor
            {
                colorFormat       = RenderTextureFormat.R8,
                dimension         = TextureDimension.Tex2D,
                width             = MASK_RESOLUTION,
                height            = MASK_RESOLUTION,
                volumeDepth       = 1,
                enableRandomWrite = true,
                msaaSamples       = 1
            });
            mask.Create();
            textureBuffer = new ComputeBuffer(max(MASK_RESOLUTION * MASK_RESOLUTION / 4, HEIGHT_RESOLUTION * HEIGHT_RESOLUTION / 2), 4);
            tree          = new TerrainQuadTree(-1, TerrainQuadTree.LocalPos.LeftDown, 0, terrainData.largestChunkSize);
            StartCoroutine(AsyncLoader());
        }

        void UpdateBuffer()
        {
            if (!loadedBufferList.isCreated)
            {
                return;
            }
            if (loadedBufferList.Length > loadedBuffer.count)
            {
                loadedBuffer.Dispose();
                culledResultsBuffer.Dispose();
                loadedBuffer        = new ComputeBuffer(loadedBufferList.Capacity, sizeof(TerrainChunkBuffer));
                culledResultsBuffer = new ComputeBuffer(loadedBufferList.Capacity, sizeof(int));
            }
            loadedBuffer.SetDataPtr(loadedBufferList.unsafePtr, loadedBufferList.Length);
        }
Example #5
0
        protected override void OnEnableFunc()
        {
            if (current && current != this)
            {
                enabled = false;
                Debug.LogError("Only One Terrain allowed!");
                return;
            }
            if (!terrainData)
            {
                enabled = false;
                Debug.LogError("No Data!");
                return;
            }
            if (!cam || !decalCamera)
            {
                enabled = false;
                Debug.LogError("No Decal Camera!");
                return;
            }
            initializing      = true;
            lodOffset         = terrainData.GetLodOffset();
            largestChunkCount = (int)(0.1 + pow(2.0, lodOffset));
            msb = new MStringBuilder(32);
            oneVTPixelWorldLength = terrainData.VTTexelLength();
            textureShader         = Resources.Load <ComputeShader>("ProceduralTexture");
            shader  = Resources.Load <ComputeShader>("TerrainCompute");
            current = this;
            int indexMapSize = 1;

            for (int i = 1; i < terrainData.lodDistances.Length; ++i)
            {
                indexMapSize *= 2;
            }
            vtContainer  = new NativeArray <int>(4, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            maskLoadList = new NativeQueue <MaskLoadCommand>(10, Allocator.Persistent);
            ComputeShader editShader = Resources.Load <ComputeShader>("TerrainEdit");

            loadingThread = new MTerrainLoadingThread(10);
            maskLoader    = new VirtualTextureLoader(terrainData.maskmapPath, editShader, largestChunkCount, MASK_RESOLUTION, false, loadingThread);
            heightLoader  = new VirtualTextureLoader(terrainData.heightmapPath, editShader, largestChunkCount, MASK_RESOLUTION, true, loadingThread);

            loadDataList       = new NativeQueue <TerrainLoadData>(100, Allocator.Persistent);
            initializeLoadList = new NativeQueue <TerrainLoadData>(100, Allocator.Persistent);
            NativeArray <uint> dispatchDraw = new NativeArray <uint>(5, Allocator.Temp, NativeArrayOptions.ClearMemory);

            dispatchDraw[0] = 6;
            VirtualTextureFormat *formats = stackalloc VirtualTextureFormat[]
            {
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, GraphicsFormat.R8G8B8A8_UNorm, "_VirtualMainTex", 2),
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, GraphicsFormat.R16G16_SNorm, "_VirtualBumpMap", 2),
                new VirtualTextureFormat((VirtualTextureSize)COLOR_RESOLUTION, GraphicsFormat.R8G8_UNorm, "_VirtualSMMap", 2),
                new VirtualTextureFormat((VirtualTextureSize)HEIGHT_RESOLUTION, HEIGHT_FORMAT, "_VirtualDisplacement", 0)
            };

            mipIDs          = new NativeArray <int>(2, Allocator.Persistent, NativeArrayOptions.UninitializedMemory);
            mipIDs[0]       = Shader.PropertyToID("_Mip0");
            mipIDs[1]       = Shader.PropertyToID("_Mip1");
            chunkCount      = (int)(pow(2.0, terrainData.lodDistances.Length - 1) + 0.1);
            vt              = new VirtualTexture(terrainData.virtualTexCapacity, min(2048, chunkCount), formats, 4, "_TerrainVTIndexTex");
            textureCapacity = terrainData.virtualTexCapacity;
            VirtualTextureFormat *maskFormats = stackalloc VirtualTextureFormat[]
            {
                new VirtualTextureFormat((VirtualTextureSize)MASK_RESOLUTION, GraphicsFormat.R8_UNorm, "_VirtualMaskmap"),
                new VirtualTextureFormat((VirtualTextureSize)MASK_RESOLUTION, GraphicsFormat.R16_UNorm, "_VirtualHeightmap"),
            };

            maskVT = new VirtualTexture(terrainData.heightmapTexCapacity, largestChunkCount, maskFormats, 2, "_MaskIndexMap");
            maskVT.GetTexture(0).filterMode = FilterMode.Point;
            maskVT.GetTexture(1).filterMode = FilterMode.Point;
            vt.GetTexture(0).filterMode     = FilterMode.Trilinear;
            vt.GetTexture(1).filterMode     = FilterMode.Trilinear;
            vt.GetTexture(2).filterMode     = FilterMode.Trilinear;
            vt.GetTexture(3).filterMode     = FilterMode.Bilinear;
            allLodLevles = new NativeList_Float(terrainData.lodDistances.Length, Allocator.Persistent);
            for (int i = 0; i < terrainData.lodDistances.Length; ++i)
            {
                allLodLevles.Add((float)min(terrainData.lodDistances[max(0, i - 1)], terrainData.lodDistances[i]));
            }
            allLodLevles[terrainData.lodDistances.Length] = 0;
            meshResolution = terrainData.GetMeshResolution();
            cullingFlags   = new RenderTexture(new RenderTextureDescriptor
            {
                graphicsFormat    = GraphicsFormat.R8_UNorm,
                dimension         = TextureDimension.Tex2D,
                width             = meshResolution,
                height            = meshResolution,
                volumeDepth       = 1,
                enableRandomWrite = true,
                msaaSamples       = 1,
                useMipMap         = false
            });
            cullingFlags.filterMode = FilterMode.Point;
            cullingFlags.Create();
            albedoTex = new RenderTexture(new RenderTextureDescriptor
            {
                graphicsFormat    = GraphicsFormat.R8G8B8A8_UNorm,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1,
                autoGenerateMips  = false,
                useMipMap         = true,
                mipCount          = 6,
            });
            albedoTex.Create();
            normalTex = new RenderTexture(new RenderTextureDescriptor
            {
                graphicsFormat    = GraphicsFormat.R16G16_SNorm,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                autoGenerateMips  = false,
                useMipMap         = true,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1,
                mipCount          = 6,
            });
            normalTex.Create();
            smTex = new RenderTexture(new RenderTextureDescriptor
            {
                graphicsFormat    = GraphicsFormat.R16G16_UNorm,
                dimension         = TextureDimension.Tex2DArray,
                width             = COLOR_RESOLUTION,
                height            = COLOR_RESOLUTION,
                volumeDepth       = Mathf.Max(1, terrainData.textures.Length),
                enableRandomWrite = true,
                msaaSamples       = 1,
                useMipMap         = true,
                autoGenerateMips  = false,
                mipCount          = 6,
                depthBufferBits   = 0,
                useDynamicScale   = false
            });
            smTex.Create();

            /*   heightTex = new RenderTexture(new RenderTextureDescriptor
             * {
             *     graphicsFormat = GraphicsFormat.R8_UNorm,
             *     dimension = TextureDimension.Tex2DArray,
             *     width = COLOR_RESOLUTION,
             *     height = COLOR_RESOLUTION,
             *     volumeDepth = Mathf.Max(1, terrainData.textures.Length),
             *     enableRandomWrite = true,
             *     msaaSamples = 1,
             *     useMipMap = true,
             *     autoGenerateMips = false,
             *     mipCount = 6,
             *     depthBufferBits = 0,
             *     useDynamicScale = false
             * });*/
            heightloadingCacheRT = new RenderTexture(new RenderTextureDescriptor
            {
                width             = COLOR_RESOLUTION + 2,
                height            = COLOR_RESOLUTION + 2,
                volumeDepth       = 1,
                enableRandomWrite = true,
                dimension         = TextureDimension.Tex2D,
                graphicsFormat    = GraphicsFormat.R16_UNorm,
                msaaSamples       = 1,
                useMipMap         = false,
                autoGenerateMips  = false,
                mipCount          = 0,
                depthBufferBits   = 0,
                useDynamicScale   = false,
            });
            randomTileRT = new RenderTexture(256, 256, 0, GraphicsFormat.R16G16B16A16_SNorm, 0);
            randomTileRT.enableRandomWrite = true;
            randomTileRT.wrapMode          = TextureWrapMode.Repeat;
            randomTileRT.filterMode        = FilterMode.Point;
            randomTileRT.Create();

            heightloadingCacheRT.Create();
            //    heightTex.Create();
            smTex.wrapMode     = TextureWrapMode.Repeat;
            normalTex.wrapMode = TextureWrapMode.Repeat;
            albedoTex.wrapMode = TextureWrapMode.Repeat;
            //   heightTex.wrapMode = TextureWrapMode.Repeat;
            boundBoxLoadList   = new NativeQueue <MaskLoadCommand>(10, Allocator.Persistent);
            boundingLoadStream = new FileStream(terrainData.boundPath, FileMode.OpenOrCreate, FileAccess.ReadWrite);
            boundingDict       = new NativeDictionary <int2, MTerrainBoundingTree, Int2Equal>(20, Allocator.Persistent, new Int2Equal());
            InitializeMeshData();
            allDrawCommand = new NativeList <TerrainDrawCommand>(20, Allocator.Persistent);
            materialBuffer = new ComputeBuffer(max(1, terrainData.allMaterials.Length), sizeof(MTerrainData.HeightBlendMaterial));
            materialBuffer.SetData(terrainData.allMaterials);
            decalLayerOffset = max(0, terrainData.lodDistances.Length - terrainData.allDecalLayers.Length);
            tree             = new TerrainQuadTree(-1, TerrainQuadTree.LocalPos.LeftDown, 0, 0, terrainData.largestChunkSize, double3(1, 0, 0), 0);

            StartCoroutine(AsyncLoader());
        }