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: