Пример #1
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();
            }
        }
Пример #2
0
 private void OnGUI()
 {
     terrainData   = (MTerrainData)EditorGUILayout.ObjectField("Terrain Data", terrainData, typeof(MTerrainData), false);
     chunkPosition = EditorGUILayout.Vector2IntField("Chunk Position", new Vector2Int(chunkPosition.x, chunkPosition.y));
     chunkSize     = EditorGUILayout.IntField("Chunk Size", chunkSize);
     chunkSize     = max(1, chunkSize);
     maskTexture   = EditorGUILayout.ObjectField("Mask Texture", maskTexture, typeof(Texture), false) as Texture;
     heightTexture = EditorGUILayout.ObjectField("Height Texture", heightTexture, typeof(Texture), false) as Texture;
     if (!terrainData)
     {
         return;
     }
     if (GUILayout.Button("Update Height Mask Texture"))
     {
         TerrainFactory factory = new TerrainFactory(terrainData.lodDistances.Length - terrainData.renderingLevelCount, terrainData.lodDistances.Length, terrainData.readWritePath);
         try
         {
             int resolution = (int)(0.1 + pow(2.0, terrainData.renderingLevelCount));
             for (int x = 0; x < chunkSize; ++x)
             {
                 for (int y = 0; y < chunkSize; ++y)
                 {
                     int2 currentPos = int2(x + chunkPosition.x, y + chunkPosition.y);
                     if (currentPos.x > resolution || currentPos.y > resolution)
                     {
                         continue;
                     }
                     factory.BlitMask(currentPos, terrainData.lodDistances.Length - 1, maskTexture, 1f / chunkSize, float2(x, y) / chunkSize);
                     factory.BlitHeight(currentPos, terrainData.lodDistances.Length - 1, heightTexture, 1f / chunkSize, float2(x, y) / chunkSize);
                 }
             }
         }
         finally
         {
             factory.Dispose();
         }
     }
     if (GUILayout.Button("Generate Mipmap"))
     {
         TerrainFactory factory = new TerrainFactory(terrainData.lodDistances.Length - terrainData.renderingLevelCount, terrainData.lodDistances.Length, terrainData.readWritePath);
         try
         {
             for (int i = terrainData.lodDistances.Length - 2; i >= terrainData.lodDistances.Length - terrainData.renderingLevelCount; --i)
             {
                 int resolution = (int)(0.1 + pow(2.0, i));
                 for (int x = 0; x < resolution; ++x)
                 {
                     for (int y = 0; y < resolution; ++y)
                     {
                         factory.GenerateMaskMip(int2(x, y), i);
                         factory.GenerateHeightMip(int2(x, y), i);
                     }
                 }
             }
         }
         finally
         {
             factory.Dispose();
         }
     }
 }