diff --git a/Runtime/Shaders/LayerSwitch8.shadersubgraph b/Runtime/Shaders/LayerSwitch8.shadersubgraph
index b8348c56fb2cde94bdc14917a9138ba01fe2cb7e..69586c0a2a4042a4e3074a21bd930846ff0e9fbf 100644
--- a/Runtime/Shaders/LayerSwitch8.shadersubgraph
+++ b/Runtime/Shaders/LayerSwitch8.shadersubgraph
@@ -4429,7 +4429,7 @@
     "overrideHLSLDeclaration": false,
     "hlslDeclarationOverride": 0,
     "m_Hidden": false,
-    "m_Value": 0.0,
+    "m_Value": 1.0,
     "m_FloatType": 0,
     "m_RangeValues": {
         "x": 0.0,
diff --git a/Runtime/Shaders/TerrainMaterial8.mat b/Runtime/Shaders/TerrainMaterial8.mat
index ec96083c18c28d07f7478f4bae8fcd68cc103be9..ff3d711735e11d201e83efd17eabdd96db84d29e 100644
--- a/Runtime/Shaders/TerrainMaterial8.mat
+++ b/Runtime/Shaders/TerrainMaterial8.mat
@@ -28,6 +28,7 @@ Material:
     type: 3}
   m_ValidKeywords:
   - _DISABLE_SSR_TRANSPARENT
+  - _TESSELLATION_PHONG
   m_InvalidKeywords: []
   m_LightmapFlags: 4
   m_EnableInstancingVariants: 0
@@ -175,14 +176,15 @@ Material:
     - _StencilWriteMaskMV: 40
     - _SupportDecals: 1
     - _SurfaceType: 0
-    - _TesselationFactor: 40
+    - _TesselationFactor: 15
     - _TessellationBackFaceCullEpsilon: -0.25
     - _TessellationFactorMaxDistance: 300
-    - _TessellationFactorMinDistance: 0
+    - _TessellationFactorMinDistance: 0.1
     - _TessellationFactorTriangleSize: 1
-    - _TessellationMaxDisplacement: 10
-    - _TessellationMode: 0
-    - _TessellationShapeFactor: 0.75
+    - _TessellationMaxDisplacement: 0
+    - _TessellationMode: 1
+    - _TessellationShapeFactor: 1
+    - _Tiling: 0.1
     - _TransparentBackfaceEnable: 0
     - _TransparentCullMode: 2
     - _TransparentDepthPostpassEnable: 0
diff --git a/Runtime/Shaders/TerrainShader8.shadergraph b/Runtime/Shaders/TerrainShader8.shadergraph
index bb4f5bcd2186d0e21e29d10bef5129c0bf52f0a8..25a9f3f08870557055c06a4ca6eb887974e652ad 100644
--- a/Runtime/Shaders/TerrainShader8.shadergraph
+++ b/Runtime/Shaders/TerrainShader8.shadergraph
@@ -32,6 +32,9 @@
         },
         {
             "m_Id": "9ac26edbdd214d8ca171d1e8baed7143"
+        },
+        {
+            "m_Id": "1e2db97241524487b44af6a4a86bd8cb"
         }
     ],
     "m_Keywords": [],
@@ -122,6 +125,9 @@
         },
         {
             "m_Id": "b5e6eada9cbb47d4aaed63b185bdc6e0"
+        },
+        {
+            "m_Id": "5738a0bbeb3840b8828e431f540341a7"
         }
     ],
     "m_GroupDatas": [],
@@ -197,6 +203,20 @@
                 "m_SlotId": 1
             }
         },
+        {
+            "m_OutputSlot": {
+                "m_Node": {
+                    "m_Id": "5738a0bbeb3840b8828e431f540341a7"
+                },
+                "m_SlotId": 0
+            },
+            "m_InputSlot": {
+                "m_Node": {
+                    "m_Id": "4052c0fd07c144c1bde8ca59237d2ea4"
+                },
+                "m_SlotId": 2135710056
+            }
+        },
         {
             "m_OutputSlot": {
                 "m_Node": {
@@ -612,6 +632,33 @@
     "m_Labels": []
 }
 
+{
+    "m_SGVersion": 1,
+    "m_Type": "UnityEditor.ShaderGraph.Internal.Vector1ShaderProperty",
+    "m_ObjectId": "1e2db97241524487b44af6a4a86bd8cb",
+    "m_Guid": {
+        "m_GuidSerialized": "0b31ad1a-224f-485f-ab84-860defd42ace"
+    },
+    "m_Name": "Tiling",
+    "m_DefaultRefNameVersion": 1,
+    "m_RefNameGeneratedByDisplayName": "Tiling",
+    "m_DefaultReferenceName": "_Tiling",
+    "m_OverrideReferenceName": "",
+    "m_GeneratePropertyBlock": true,
+    "m_UseCustomSlotLabel": false,
+    "m_CustomSlotLabel": "",
+    "m_Precision": 0,
+    "overrideHLSLDeclaration": false,
+    "hlslDeclarationOverride": 0,
+    "m_Hidden": false,
+    "m_Value": 0.10000000149011612,
+    "m_FloatType": 0,
+    "m_RangeValues": {
+        "x": 0.0,
+        "y": 1.0
+    }
+}
+
 {
     "m_SGVersion": 0,
     "m_Type": "UnityEditor.Rendering.HighDefinition.ShaderGraph.HDLitData",
@@ -815,9 +862,9 @@
         "m_Position": {
             "serializedVersion": "2",
             "x": -2534.0,
-            "y": -22.0,
+            "y": -20.000009536743165,
             "width": 219.0,
-            "height": 518.0
+            "height": 542.0
         }
     },
     "m_Slots": [
@@ -1103,6 +1150,41 @@
     "m_SerializedDescriptor": "SurfaceDescription.NormalTS"
 }
 
+{
+    "m_SGVersion": 0,
+    "m_Type": "UnityEditor.ShaderGraph.PropertyNode",
+    "m_ObjectId": "5738a0bbeb3840b8828e431f540341a7",
+    "m_Group": {
+        "m_Id": ""
+    },
+    "m_Name": "Property",
+    "m_DrawState": {
+        "m_Expanded": true,
+        "m_Position": {
+            "serializedVersion": "2",
+            "x": -2774.78271484375,
+            "y": 309.5652160644531,
+            "width": 0.0,
+            "height": 0.0
+        }
+    },
+    "m_Slots": [
+        {
+            "m_Id": "c0928c09cb6d41a78992e98a68b6a364"
+        }
+    ],
+    "synonyms": [],
+    "m_Precision": 0,
+    "m_PreviewExpanded": true,
+    "m_PreviewMode": 0,
+    "m_CustomColors": {
+        "m_SerializableColors": []
+    },
+    "m_Property": {
+        "m_Id": "1e2db97241524487b44af6a4a86bd8cb"
+    }
+}
+
 {
     "m_SGVersion": 0,
     "m_Type": "UnityEditor.ShaderGraph.PropertyNode",
@@ -1585,6 +1667,9 @@
         },
         {
             "m_Id": "ab95c558ffe149cf82054e08167814ef"
+        },
+        {
+            "m_Id": "1e2db97241524487b44af6a4a86bd8cb"
         }
     ]
 }
@@ -2094,6 +2179,21 @@
     "m_BareResource": false
 }
 
+{
+    "m_SGVersion": 0,
+    "m_Type": "UnityEditor.ShaderGraph.Vector1MaterialSlot",
+    "m_ObjectId": "c0928c09cb6d41a78992e98a68b6a364",
+    "m_Id": 0,
+    "m_DisplayName": "Tiling",
+    "m_SlotType": 1,
+    "m_Hidden": false,
+    "m_ShaderOutputName": "Out",
+    "m_StageCapability": 3,
+    "m_Value": 0.0,
+    "m_DefaultValue": 0.0,
+    "m_Labels": []
+}
+
 {
     "m_SGVersion": 0,
     "m_Type": "UnityEditor.ShaderGraph.Texture2DMaterialSlot",
diff --git a/Runtime/TerrainBuilder.cs b/Runtime/TerrainBuilder.cs
index 2bb58480fe01308d74fd3a1658610f2f8d321b89..5ba1b50adb3589dbbc79e96db66d492a0db5ba43 100644
--- a/Runtime/TerrainBuilder.cs
+++ b/Runtime/TerrainBuilder.cs
@@ -1,8 +1,10 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
+using System.IO;
 using System.Linq;
 using System.Threading.Tasks;
+using Unity.Collections;
 using UnityEditor;
 using UnityEngine;
 using UnityEngine.Networking;
@@ -15,7 +17,6 @@ namespace Wander
         internal int deltaTileX; // Relative tile index with respect to origin up left corner. So, 0, -1, etc.
         internal int deltaTileY;
         internal UnityWebRequest www;
-        internal Texture2D texture;
     }
 
     [Serializable]
@@ -28,7 +29,18 @@ namespace Wander
     [ExecuteAlways()]
     public class TerrainBuilder : MonoBehaviour
     {
+        [ReadOnly] public Vector2 rdOrigin;
+        [ReadOnly] public Vector2Int tileOrigin;
+        [ReadOnly] public Vector3 adjustedSize;
+        [ReadOnly] public double tileSize;
+        [ReadOnly] public int tilePixelSize;
+        [ReadOnly] public int nTilesWide;
+        [ReadOnly] public int nTilesHigh;
+        [ReadOnly] public TerrainData terrainData;
+        [ReadOnly] public Terrain terrain;
+
         public Vector2 originWGS84   = new Vector2(51.985365f, 5.664941f); // Copy directly from Google maps. This is Forum on Campus WUR.
+        public Vector2Int terrainOffset = new Vector2Int(0, 0);
         public int controlResolution = 8192;
         public float height          = 300;
         public int zoom              = 11;
@@ -36,21 +48,14 @@ namespace Wander
         public bool runOnStart       = false;
         public Material terrainMat   = null;
 
-        [ReadOnly]
-        public Texture2D controlTexture;
+        
         public List<TerrainLayer2> layers;
 
-        private Vector2Int tileOrigin;
-        private Vector3 adjustedSize;
-        private double tileSize;
-        private int tilePixelSize;
-        private int nTilesWide;
-        private int nTilesHigh;
-        private TerrainData terrainData;
-        private Terrain terrain;
+
         private List<MapTile> requests;
         private byte[] controlData;
         private Dictionary<uint, byte> pixelToLayerIndex;
+        private List<Task> writeControlTextureDataTasks;
 
         private bool isRunning;
 
@@ -66,31 +71,29 @@ namespace Wander
             }
         }
 
-        internal void Cancel()
+        internal void CancelOrClean()
         {
+            isRunning = false;
+            if (writeControlTextureDataTasks != null)
+            {
+                writeControlTextureDataTasks.ForEach( async l => await l );
+            }
+            writeControlTextureDataTasks = null;
             requests = null;
             controlData = null;
-            controlTexture = null;
-            isRunning = false;
         }
 
         internal void Build()
         {
-            Cancel();
-         //   try
-            {
-                controlData = new byte[controlResolution*controlResolution];
-                CalcPreliminaries();
-                CreatePixelToLayerIndex();
-                DownloadTiles();
-                CreateTerrainData();
-                LinkLayersToMaterial();
-                isRunning = true;
-            }
-            //finally
-            //{
-            //    Cancel();
-            //}
+            CancelOrClean();
+            controlData = new byte[controlResolution*controlResolution];
+            writeControlTextureDataTasks = new List<Task>();
+            CalcPreliminaries();
+            CreatePixelToLayerIndex();
+            DownloadTiles();
+            CreateTerrainData();
+            LinkLayersToMaterial();
+            isRunning = true;
         }
 
         void Update()
@@ -98,7 +101,12 @@ namespace Wander
             if (isRunning)
             {
                 CheckDownloadRequests();
-                FlashControlTexture();
+                if (requests !=null && requests.Count==0)
+                {
+                    var controlTex = CreateControlTexture();
+                    SaveToDisk( controlTex );
+                    CancelOrClean();
+                }
             }
         }
 
@@ -110,13 +118,18 @@ namespace Wander
                 return;
             }
 
-            RDUtils.GPS2RD( originWGS84.x, originWGS84.y, out double rdX, out double rdY );
-            tileOrigin    = RDUtils.RD2Tile( new Vector2( (float)rdX, (float)rdY ), zoom );
+            // Size
             tileSize      = RDUtils.CalcTileSizeRD( zoom );
             tilePixelSize = RDUtils.RDDefaultTileRes;
             nTilesWide    = controlResolution / tilePixelSize;
             nTilesHigh    = controlResolution / tilePixelSize;
             adjustedSize  = new Vector3( (float)(nTilesWide*tileSize), height, (float)(nTilesHigh*tileSize) );
+
+            // Location
+            RDUtils.GPS2RD( originWGS84.x, originWGS84.y, out double rdX, out double rdY );
+            tileOrigin    = RDUtils.RD2Tile( new Vector2( (float)rdX+adjustedSize.x*terrainOffset.x, (float)rdY+adjustedSize.z*terrainOffset.y ), zoom );
+            rdOrigin      = RDUtils.Tile2RD( tileOrigin, zoom );
+
         }
 
         void CreatePixelToLayerIndex()
@@ -173,10 +186,11 @@ namespace Wander
             terrain  = go.AddComponent<Terrain>();
 
             terrain.terrainData       = terrainData;
-            terrain.materialTemplate  = terrainMat;
+            terrain.materialTemplate  = new Material( terrainMat );
             terrainData.terrainLayers = layers.Select( l => l.layer ).ToArray();
 
             go.AddComponent<TerrainCollider>().terrainData = terrainData;
+            go.transform.position = new Vector3( terrainOffset.x*adjustedSize.x, 0, terrainOffset.y*adjustedSize.z );
         }
 
         internal void SyncLayersToMaterial()
@@ -219,26 +233,24 @@ namespace Wander
             terrain.materialTemplate.SetTexture( "ControlTexture", controlTex );
         }
 
-        void WriteTileToControlTexture( MapTile tile )
+        void WriteTileToControlTexture( MapTile tile, int width, int height, NativeArray<Color32> pixelData ) 
         {
-            var pixelData = tile.texture.GetPixelData<Color32>( 0 );
-            var height = tile.texture.height;
-            var width  = tile.texture.width;
-            byte layerIndex   = 255;
+            byte layerIndex   = 0;
             uint cachedMask   = 0;
             int x2 = tile.deltaTileX * tilePixelSize;
             int y2 = tile.deltaTileY * tilePixelSize;
+            // !! No need to lock controlData because every tile writes to its own designated area !!
             for (int y = 0;y < height;y++)
             {
                 for (int x = 0;x < width;x++)
                 {
                     Color32 col  = pixelData[y*width+x];
-                    uint colMask = ((uint)col.a<<16) | ((uint)col.b<<8) | (col.g); // Color is reversed in memory. So RGBA = ABGR.
-                    if ( cachedMask!=colMask || layerIndex==255 )
+                    uint colMask = ((uint)col.g<<16) | ((uint)col.b<<8) | (col.a); // Color is stored as ARGB, so for this Color32 struct becomes g,b,a ... because we want RGB.
+                    if (cachedMask!=colMask || layerIndex==255)
                     {
-                        if (!pixelToLayerIndex.TryGetValue( colMask, out layerIndex ))
+                        if (pixelToLayerIndex.TryGetValue( colMask, out byte queriedLayeredIndex ))
                         {
-                            layerIndex=255;
+                            layerIndex = queriedLayeredIndex;
                         }
                         cachedMask = colMask;
                     }
@@ -262,7 +274,7 @@ namespace Wander
                 for (int y = 0;y < nTilesHigh;y++)
                 {
                     int tileX  = x + tileOrigin.x;
-                    int tileY  = y + tileOrigin.y;
+                    int tileY  = -y + tileOrigin.y;
                     string url = GetMapUrl(tileX, tileY, zoom);
                     UnityWebRequest www = UnityWebRequestTexture.GetTexture(url);
                     www.SendWebRequest();
@@ -305,9 +317,12 @@ namespace Wander
                     }
                     else
                     {
-                        tile.texture = ((DownloadHandlerTexture)www.downloadHandler).texture;
-                        WriteTileToControlTexture( tile );
-                        FlashControlTexture();
+                        var texture     = ((DownloadHandlerTexture)www.downloadHandler).texture;
+                        var height      = texture.height;
+                        var width       = texture.width;
+                        var pixelData   = texture.GetPixelData<Color32>( 0 ); // Must be called on Main thread.
+                        var writeControlTextureTask = Task.Run( () => WriteTileToControlTexture( tile, width, height, pixelData ) );
+                        writeControlTextureDataTasks.Add( writeControlTextureTask );
                         requests.RemoveAt( i );
                         i--;
                     }
@@ -315,16 +330,29 @@ namespace Wander
             }
         }
 
-        void FlashControlTexture()
+        Texture2D CreateControlTexture()
         {
-            if (controlTexture == null)
-            {
-                controlTexture = new Texture2D( controlResolution, controlResolution, TextureFormat.R8, false );
-                terrain.materialTemplate.SetTexture( "ControlTexture", controlTexture );
-            }
+            var controlTexture = new Texture2D( controlResolution, controlResolution, TextureFormat.R8, false );
+            terrain.materialTemplate.SetTexture( "ControlTexture", controlTexture );
             controlTexture.SetPixelData( controlData, 0, 0 );
             controlTexture.Apply( false, false );
-        }            
+            return controlTexture;
+        }
+
+
+#if UNITY_EDITOR
+        void SaveToDisk( Texture2D controlTexture )
+        {
+            var generatedContent = $"BGT_terrain_{originWGS84.x}_{originWGS84.y}";
+            if (!Directory.Exists( Path.Combine( Application.dataPath, generatedContent ) ))
+            {
+                Directory.CreateDirectory( Path.Combine( Application.dataPath, generatedContent ) ); 
+            }
+            AssetDatabase.CreateAsset( terrainData, Path.Combine( "Assets", generatedContent, $"bgt_terrain_{terrainOffset.x}_{terrainOffset.y}.asset" ) );
+            AssetDatabase.CreateAsset( controlTexture, Path.Combine( "Assets", generatedContent, $"control_texture_{terrainOffset.x}_{terrainOffset.y}.asset" ) );
+        }
+#endif
+
     }
 
 #if UNITY_EDITOR
@@ -354,7 +382,7 @@ namespace Wander
                 }
                 if (GUILayout.Button( "Cancel" ))
                 {
-                    builder.Cancel();
+                    builder.CancelOrClean();
                 }
             }
             GUILayout.EndHorizontal();
diff --git a/TerrainBuilder.prefab b/TerrainBuilder.prefab
index bb0e4d627ff4c97b41633fc8cad3e0827cf4d8b2..0ff9d00e284fde4240678112d2c96f39e01c0315 100644
--- a/TerrainBuilder.prefab
+++ b/TerrainBuilder.prefab
@@ -44,14 +44,24 @@ MonoBehaviour:
   m_Script: {fileID: 11500000, guid: cd43ca4104daaec4a9d3a76a67972b44, type: 3}
   m_Name: 
   m_EditorClassIdentifier: 
-  originWGS84: {x: 51.985367, y: 5.664941}
-  controlResolution: 1024
+  rdOrigin: {x: 174084.8, y: 444116.8}
+  tileOrigin: {x: 34188, y: 34172}
+  controlTexture: {fileID: 0}
+  adjustedSize: {x: 430.08, y: 300, z: 430.08}
+  tileSize: 13.44
+  tilePixelSize: 256
+  nTilesWide: 32
+  nTilesHigh: 32
+  terrainData: {fileID: 0}
+  terrain: {fileID: 0}
+  originWGS84: {x: 51.985203, y: 5.665215}
+  terrainOffset: {x: 0, y: 0}
+  controlResolution: 16384
   height: 300
   zoom: 16
   numDLRetries: 5
   runOnStart: 0
   terrainMat: {fileID: 2100000, guid: 8179da2b0897196479bec0f26c2c46e7, type: 2}
-  controlTexture: {fileID: 0}
   layers:
   - layer: {fileID: 8574412962073106934, guid: f963e57374ac1ff44b017a60c3f8ad82, type: 2}
     colors: