diff --git a/NewHorizons/Assets/textures/Ice.png b/NewHorizons/Assets/textures/Ice.png new file mode 100644 index 00000000..c4d945db Binary files /dev/null and b/NewHorizons/Assets/textures/Ice.png differ diff --git a/NewHorizons/Assets/textures/Quantum.png b/NewHorizons/Assets/textures/Quantum.png new file mode 100644 index 00000000..606b7870 Binary files /dev/null and b/NewHorizons/Assets/textures/Quantum.png differ diff --git a/NewHorizons/Assets/textures/Rocks.png b/NewHorizons/Assets/textures/Rocks.png new file mode 100644 index 00000000..1a2ccf91 Binary files /dev/null and b/NewHorizons/Assets/textures/Rocks.png differ diff --git a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs index 53d56301..263fb0ce 100644 --- a/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs +++ b/NewHorizons/Builder/Body/AsteroidBeltBuilder.cs @@ -87,10 +87,6 @@ namespace NewHorizons.Builder.Body { config.ProcGen = belt.procGen; config.ProcGen.scale = size; - if (belt.procGen.color == null) - { - config.ProcGen.color = new MColor(126, 94, 73); - } } else { @@ -100,7 +96,7 @@ namespace NewHorizons.Builder.Body color = new MColor(126, 94, 73) }; } - config.AmbientLights = new[] { new AmbientLightModule() { outerRadius = size * 1.2f, intensity = 0.6f } }; + config.AmbientLights = new[] { new AmbientLightModule() { outerRadius = size * 1.2f, intensity = 0.1f } }; var asteroid = new NewHorizonsBody(config, mod); PlanetCreationHandler.GenerateBody(asteroid); diff --git a/NewHorizons/Builder/Body/Geometry/Icosphere.cs b/NewHorizons/Builder/Body/Geometry/Icosphere.cs index 71233c18..a5da82e6 100644 --- a/NewHorizons/Builder/Body/Geometry/Icosphere.cs +++ b/NewHorizons/Builder/Body/Geometry/Icosphere.cs @@ -100,6 +100,11 @@ namespace NewHorizons.Builder.Body.Geometry mesh.normals = normals; mesh.uv = uvs; + mesh.RecalculateBounds(); + // Unity recalculate normals does not support smooth normals + //mesh.RecalculateNormals(); + mesh.RecalculateTangents(); + return mesh; } diff --git a/NewHorizons/Builder/Body/HeightMapBuilder.cs b/NewHorizons/Builder/Body/HeightMapBuilder.cs index 48e15193..f816ca80 100644 --- a/NewHorizons/Builder/Body/HeightMapBuilder.cs +++ b/NewHorizons/Builder/Body/HeightMapBuilder.cs @@ -11,7 +11,7 @@ namespace NewHorizons.Builder.Body { public static class HeightMapBuilder { - public static Shader PlanetShader; + private static Shader _planetShader; // I hate nested functions okay private static IModBehaviour _currentMod; @@ -62,7 +62,7 @@ namespace NewHorizons.Builder.Body cubeSphere.SetActive(false); cubeSphere.transform.SetParent(sector?.transform ?? planetGO.transform, false); - if (PlanetShader == null) PlanetShader = AssetBundleUtilities.NHAssetBundle.LoadAsset("Assets/Shaders/SphereTextureWrapperTriplanar.shader"); + if (_planetShader == null) _planetShader = AssetBundleUtilities.NHAssetBundle.LoadAsset("Assets/Shaders/SphereTextureWrapperTriplanar.shader"); var stretch = module.stretch != null ? (Vector3)module.stretch : Vector3.one; @@ -115,7 +115,7 @@ namespace NewHorizons.Builder.Body LODCubeSphere.AddComponent().mesh = CubeSphere.Build(resolution, heightMap, module.minHeight, module.maxHeight, stretch); var cubeSphereMR = LODCubeSphere.AddComponent(); - var material = new Material(PlanetShader); + var material = new Material(_planetShader); cubeSphereMR.material = material; material.name = textureMap.name; diff --git a/NewHorizons/Builder/Body/ProcGenBuilder.cs b/NewHorizons/Builder/Body/ProcGenBuilder.cs index f97b21aa..754252dc 100644 --- a/NewHorizons/Builder/Body/ProcGenBuilder.cs +++ b/NewHorizons/Builder/Body/ProcGenBuilder.cs @@ -2,18 +2,47 @@ using NewHorizons.Builder.Body.Geometry; using NewHorizons.External.Modules; using NewHorizons.Utility; using NewHorizons.Utility.Files; +using OWML.Common; +using System.Collections.Generic; using UnityEngine; + namespace NewHorizons.Builder.Body { public static class ProcGenBuilder { - private static Material quantumMaterial; - private static Material iceMaterial; + private static Material _material; + private static Shader _planetShader; - public static GameObject Make(GameObject planetGO, Sector sector, ProcGenModule module) + private static Dictionary _materialCache = new(); + + public static void ClearCache() { - if (quantumMaterial == null) quantumMaterial = SearchUtilities.FindResourceOfTypeAndName("Rock_QM_EyeRock_mat"); - if (iceMaterial == null) iceMaterial = SearchUtilities.FindResourceOfTypeAndName("Rock_BH_IceSpike_mat"); + foreach (var material in _materialCache.Values) + { + Object.Destroy(material); + } + _materialCache.Clear(); + } + + private static Material MakeMaterial() + { + var material = new Material(_planetShader); + + var keyword = "BASE_TILE"; + var prefix = "_BaseTile"; + + material.SetFloat(prefix, 1); + material.EnableKeyword(keyword); + + material.SetTexture("_BlendMap", ImageUtilities.MakeSolidColorTexture(1, 1, Color.white)); + + return material; + } + + public static GameObject Make(IModBehaviour mod, GameObject planetGO, Sector sector, ProcGenModule module) + { + if (_planetShader == null) _planetShader = AssetBundleUtilities.NHAssetBundle.LoadAsset("Assets/Shaders/SphereTextureWrapperTriplanar.shader"); + if (_material == null) _material = MakeMaterial(); var icosphere = new GameObject("Icosphere"); icosphere.SetActive(false); @@ -27,28 +56,51 @@ namespace NewHorizons.Builder.Body var cubeSphereMR = icosphere.AddComponent(); - Material material; - var colour = module.color?.ToColor() ?? Color.white; - switch (module.material) + if (!_materialCache.TryGetValue(module, out var material)) { - case ProcGenModule.Material.Ice: - material = iceMaterial; - break; - case ProcGenModule.Material.Quantum: - material = quantumMaterial; - break; - default: - // Todo: copy stuff from heightmap builder such as triplanar - material = new Material(HeightMapBuilder.PlanetShader); - material.name = planetGO.name; + material = new Material(_material); + material.name = planetGO.name; + if (module.material == ProcGenModule.Material.Default) + { + if (!string.IsNullOrEmpty(module.texturePath)) + { + material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(mod, module.texturePath, wrap: true)); + } + else + { + material.mainTexture = ImageUtilities.MakeSolidColorTexture(1, 1, module.color?.ToColor() ?? Color.white); + } + } + else + { + switch (module.material) + { + case ProcGenModule.Material.Ice: + material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Ice.png", wrap: true)); + break; + case ProcGenModule.Material.Quantum: + material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Quantum.png", wrap: true)); + break; + case ProcGenModule.Material.Rock: + material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(Main.Instance, "Assets/textures/Rocks.png", wrap: true)); + break; + default: + break; + } + material.SetFloat($"_BaseTileScale", 5 / module.scale); + if (module.color != null) + { + material.color = module.color.ToColor(); + } + } - material.mainTexture = ImageUtilities.TintImage(ImageUtilities.ClearTexture(1, 1), colour); - material.SetFloat("_Smoothness", 0.1f); - material.SetFloat("_Metallic", 0.1f); - break; + material.SetFloat("_Smoothness", 0.1f); + material.SetFloat("_Metallic", 0.1f); + + _materialCache[module] = material; } - material.color = colour; - cubeSphereMR.material = material; + + cubeSphereMR.sharedMaterial = material; var cubeSphereMC = icosphere.AddComponent(); cubeSphereMC.sharedMesh = mesh; diff --git a/NewHorizons/Builder/Body/ProxyBuilder.cs b/NewHorizons/Builder/Body/ProxyBuilder.cs index f1567659..3520008d 100644 --- a/NewHorizons/Builder/Body/ProxyBuilder.cs +++ b/NewHorizons/Builder/Body/ProxyBuilder.cs @@ -162,7 +162,7 @@ namespace NewHorizons.Builder.Body GameObject procGen = null; if (body.Config.ProcGen != null) { - procGen = ProcGenBuilder.Make(proxy, null, body.Config.ProcGen); + procGen = ProcGenBuilder.Make(body.Mod, proxy, null, body.Config.ProcGen); if (realSize < body.Config.ProcGen.scale) realSize = body.Config.ProcGen.scale; } diff --git a/NewHorizons/External/Modules/ProcGenModule.cs b/NewHorizons/External/Modules/ProcGenModule.cs index ed675d02..f96e632a 100644 --- a/NewHorizons/External/Modules/ProcGenModule.cs +++ b/NewHorizons/External/Modules/ProcGenModule.cs @@ -9,12 +9,26 @@ namespace NewHorizons.External.Modules [JsonObject] public class ProcGenModule { - public MColor color; - + /// + /// Scale height of the proc gen. + /// [Range(0, double.MaxValue)] public float scale; + /// + /// Ground color, only applied if no texture or material is chosen. + /// + public MColor color; + + /// + /// Can pick a preset material with a texture from the base game. Does not work with color. + /// public Material material; + /// + /// Can use a custom texture. Does not work with material or color. + /// + public string texturePath; + [JsonConverter(typeof(StringEnumConverter))] public enum Material { @@ -22,7 +36,9 @@ namespace NewHorizons.External.Modules [EnumMember(Value = @"ice")] Ice = 1, - [EnumMember(Value = @"quantum")] Quantum = 2 + [EnumMember(Value = @"quantum")] Quantum = 2, + + [EnumMember(Value = @"rock")] Rock = 3 } } } \ No newline at end of file diff --git a/NewHorizons/Handlers/PlanetCreationHandler.cs b/NewHorizons/Handlers/PlanetCreationHandler.cs index 6898382f..aaeec71e 100644 --- a/NewHorizons/Handlers/PlanetCreationHandler.cs +++ b/NewHorizons/Handlers/PlanetCreationHandler.cs @@ -581,7 +581,7 @@ namespace NewHorizons.Handlers GameObject procGen = null; if (body.Config.ProcGen != null) { - procGen = ProcGenBuilder.Make(go, sector, body.Config.ProcGen); + procGen = ProcGenBuilder.Make(body.Mod, go, sector, body.Config.ProcGen); } if (body.Config.Star != null) diff --git a/NewHorizons/Main.cs b/NewHorizons/Main.cs index 468793aa..8db96867 100644 --- a/NewHorizons/Main.cs +++ b/NewHorizons/Main.cs @@ -308,6 +308,7 @@ namespace NewHorizons ImageUtilities.ClearCache(); AudioUtilities.ClearCache(); AssetBundleUtilities.ClearCache(); + ProcGenBuilder.ClearCache(); } IsSystemReady = false;