mirror of
https://github.com/Outer-Wilds-New-Horizons/new-horizons.git
synced 2025-12-11 20:15:44 +01:00
Better proc gen (#1045)
## Minor features - Add visual options for proc gen (i.e., asteroids). Can add a triplanar texture or use a preset material for quantum, ice, or rocks. Fixes #1014
This commit is contained in:
commit
730f6f804f
BIN
NewHorizons/Assets/textures/Ice.png
Normal file
BIN
NewHorizons/Assets/textures/Ice.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.8 MiB |
BIN
NewHorizons/Assets/textures/Quantum.png
Normal file
BIN
NewHorizons/Assets/textures/Quantum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.9 MiB |
BIN
NewHorizons/Assets/textures/Rocks.png
Normal file
BIN
NewHorizons/Assets/textures/Rocks.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 564 KiB |
@ -39,7 +39,8 @@ namespace NewHorizons.Builder.Body
|
||||
{
|
||||
surfaceGravity = belt.gravity,
|
||||
surfaceSize = size,
|
||||
gravityFallOff = GravityFallOff.InverseSquared
|
||||
gravityFallOff = GravityFallOff.InverseSquared,
|
||||
hasFluidDetector = false
|
||||
};
|
||||
|
||||
config.Orbit = new OrbitModule()
|
||||
@ -95,6 +96,7 @@ namespace NewHorizons.Builder.Body
|
||||
color = new MColor(126, 94, 73)
|
||||
};
|
||||
}
|
||||
config.AmbientLights = new[] { new AmbientLightModule() { outerRadius = size * 1.2f, intensity = 0.1f } };
|
||||
|
||||
var asteroid = new NewHorizonsBody(config, mod);
|
||||
PlanetCreationHandler.GenerateBody(asteroid);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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<Shader>("Assets/Shaders/SphereTextureWrapperTriplanar.shader");
|
||||
if (_planetShader == null) _planetShader = AssetBundleUtilities.NHAssetBundle.LoadAsset<Shader>("Assets/Shaders/SphereTextureWrapperTriplanar.shader");
|
||||
|
||||
var stretch = module.stretch != null ? (Vector3)module.stretch : Vector3.one;
|
||||
|
||||
@ -115,7 +115,7 @@ namespace NewHorizons.Builder.Body
|
||||
LODCubeSphere.AddComponent<MeshFilter>().mesh = CubeSphere.Build(resolution, heightMap, module.minHeight, module.maxHeight, stretch);
|
||||
|
||||
var cubeSphereMR = LODCubeSphere.AddComponent<MeshRenderer>();
|
||||
var material = new Material(PlanetShader);
|
||||
var material = new Material(_planetShader);
|
||||
cubeSphereMR.material = material;
|
||||
material.name = textureMap.name;
|
||||
|
||||
|
||||
@ -1,21 +1,50 @@
|
||||
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<ProcGenModule, Material> _materialCache = new();
|
||||
|
||||
public static void ClearCache()
|
||||
{
|
||||
if (quantumMaterial == null) quantumMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Rock_QM_EyeRock_mat");
|
||||
if (iceMaterial == null) iceMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Rock_BH_IceSpike_mat");
|
||||
foreach (var material in _materialCache.Values)
|
||||
{
|
||||
Object.Destroy(material);
|
||||
}
|
||||
_materialCache.Clear();
|
||||
}
|
||||
|
||||
private static Material MakeMaterial()
|
||||
{
|
||||
var material = new Material(_planetShader);
|
||||
|
||||
GameObject icosphere = new GameObject("Icosphere");
|
||||
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<Shader>("Assets/Shaders/SphereTextureWrapperTriplanar.shader");
|
||||
if (_material == null) _material = MakeMaterial();
|
||||
|
||||
var icosphere = new GameObject("Icosphere");
|
||||
icosphere.SetActive(false);
|
||||
icosphere.transform.parent = sector?.transform ?? planetGO.transform;
|
||||
icosphere.transform.rotation = Quaternion.Euler(90, 0, 0);
|
||||
@ -26,8 +55,61 @@ namespace NewHorizons.Builder.Body
|
||||
icosphere.AddComponent<MeshFilter>().mesh = mesh;
|
||||
|
||||
var cubeSphereMR = icosphere.AddComponent<MeshRenderer>();
|
||||
cubeSphereMR.material = new Material(Shader.Find("Standard"));
|
||||
cubeSphereMR.material.color = module.color != null ? module.color.ToColor() : Color.white;
|
||||
|
||||
if (!_materialCache.TryGetValue(module, out var material))
|
||||
{
|
||||
material = new Material(_material);
|
||||
material.name = planetGO.name;
|
||||
if (module.material == ProcGenModule.Material.Default)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(module.texture))
|
||||
{
|
||||
material.SetTexture($"_BaseTileAlbedo", ImageUtilities.GetTexture(mod, module.texture, wrap: true));
|
||||
}
|
||||
else
|
||||
{
|
||||
material.mainTexture = ImageUtilities.MakeSolidColorTexture(1, 1, module.color?.ToColor() ?? Color.white);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(module.smoothnessMap))
|
||||
{
|
||||
material.SetTexture($"_BaseTileSmoothnessMap", ImageUtilities.GetTexture(mod, module.smoothnessMap, wrap: true));
|
||||
}
|
||||
if (!string.IsNullOrEmpty(module.normalMap))
|
||||
{
|
||||
material.SetFloat($"_BaseTileBumpStrength", module.normalStrength);
|
||||
material.SetTexture($"_BaseTileBumpMap", ImageUtilities.GetTexture(mod, module.normalMap, wrap: true));
|
||||
}
|
||||
}
|
||||
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.SetFloat("_Smoothness", module.smoothness);
|
||||
material.SetFloat("_Metallic", module.metallic);
|
||||
|
||||
_materialCache[module] = material;
|
||||
}
|
||||
|
||||
cubeSphereMR.sharedMaterial = material;
|
||||
|
||||
var cubeSphereMC = icosphere.AddComponent<MeshCollider>();
|
||||
cubeSphereMC.sharedMesh = mesh;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
68
NewHorizons/External/Modules/ProcGenModule.cs
vendored
68
NewHorizons/External/Modules/ProcGenModule.cs
vendored
@ -1,14 +1,78 @@
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.Runtime.Serialization;
|
||||
using NewHorizons.External.SerializableData;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace NewHorizons.External.Modules
|
||||
{
|
||||
[JsonObject]
|
||||
public class ProcGenModule
|
||||
{
|
||||
/// <summary>
|
||||
/// Scale height of the proc gen.
|
||||
/// </summary>
|
||||
[Range(0, double.MaxValue)] public float scale;
|
||||
|
||||
/// <summary>
|
||||
/// Ground color, only applied if no texture or material is chosen.
|
||||
/// </summary>
|
||||
public MColor color;
|
||||
|
||||
[Range(0, double.MaxValue)] public float scale;
|
||||
/// <summary>
|
||||
/// Can pick a preset material with a texture from the base game. Does not work with color or any textures.
|
||||
/// </summary>
|
||||
public Material material;
|
||||
|
||||
/// <summary>
|
||||
/// Can use a custom texture. Does not work with material or color.
|
||||
/// </summary>
|
||||
public string texture;
|
||||
|
||||
/// <summary>
|
||||
/// Relative filepath to the texture used for the terrain's smoothness and metallic, which are controlled by the texture's alpha and red channels respectively. Optional.
|
||||
/// Typically black with variable transparency, when metallic isn't wanted.
|
||||
/// </summary>
|
||||
public string smoothnessMap;
|
||||
|
||||
/// <summary>
|
||||
/// How "glossy" the surface is, where 0 is diffuse, and 1 is like a mirror.
|
||||
/// Multiplies with the alpha of the smoothness map if using one.
|
||||
/// </summary>
|
||||
[Range(0f, 1f)]
|
||||
[DefaultValue(0f)]
|
||||
public float smoothness = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// How metallic the surface is, from 0 to 1.
|
||||
/// Multiplies with the red of the smoothness map if using one.
|
||||
/// </summary>
|
||||
[Range(0f, 1f)]
|
||||
[DefaultValue(0f)]
|
||||
public float metallic = 0f;
|
||||
|
||||
/// <summary>
|
||||
/// Relative filepath to the texture used for the normal (aka bump) map. Optional.
|
||||
/// </summary>
|
||||
public string normalMap;
|
||||
|
||||
/// <summary>
|
||||
/// Strength of the normal map. Usually 0-1, but can go above, or negative to invert the map.
|
||||
/// </summary>
|
||||
[DefaultValue(1f)]
|
||||
public float normalStrength = 1f;
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public enum Material
|
||||
{
|
||||
[EnumMember(Value = @"default")] Default = 0,
|
||||
|
||||
[EnumMember(Value = @"ice")] Ice = 1,
|
||||
|
||||
[EnumMember(Value = @"quantum")] Quantum = 2,
|
||||
|
||||
[EnumMember(Value = @"rock")] Rock = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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)
|
||||
|
||||
@ -309,6 +309,7 @@ namespace NewHorizons
|
||||
ImageUtilities.ClearCache();
|
||||
AudioUtilities.ClearCache();
|
||||
AssetBundleUtilities.ClearCache();
|
||||
ProcGenBuilder.ClearCache();
|
||||
}
|
||||
|
||||
IsSystemReady = false;
|
||||
|
||||
@ -353,16 +353,72 @@
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"color": {
|
||||
"$ref": "#/definitions/MColor"
|
||||
},
|
||||
"scale": {
|
||||
"type": "number",
|
||||
"description": "Scale height of the proc gen.",
|
||||
"format": "float",
|
||||
"minimum": 0.0
|
||||
},
|
||||
"color": {
|
||||
"description": "Ground color, only applied if no texture or material is chosen.",
|
||||
"$ref": "#/definitions/MColor"
|
||||
},
|
||||
"material": {
|
||||
"description": "Can pick a preset material with a texture from the base game. Does not work with color or any textures.",
|
||||
"$ref": "#/definitions/Material"
|
||||
},
|
||||
"texture": {
|
||||
"type": "string",
|
||||
"description": "Can use a custom texture. Does not work with material or color."
|
||||
},
|
||||
"smoothnessMap": {
|
||||
"type": "string",
|
||||
"description": "Relative filepath to the texture used for the terrain's smoothness and metallic, which are controlled by the texture's alpha and red channels respectively. Optional.\nTypically black with variable transparency, when metallic isn't wanted."
|
||||
},
|
||||
"smoothness": {
|
||||
"type": "number",
|
||||
"description": "How \"glossy\" the surface is, where 0 is diffuse, and 1 is like a mirror.\nMultiplies with the alpha of the smoothness map if using one.",
|
||||
"format": "float",
|
||||
"default": 0.0,
|
||||
"maximum": 1.0,
|
||||
"minimum": 0.0
|
||||
},
|
||||
"metallic": {
|
||||
"type": "number",
|
||||
"description": "How metallic the surface is, from 0 to 1.\nMultiplies with the red of the smoothness map if using one.",
|
||||
"format": "float",
|
||||
"default": 0.0,
|
||||
"maximum": 1.0,
|
||||
"minimum": 0.0
|
||||
},
|
||||
"normalMap": {
|
||||
"type": "string",
|
||||
"description": "Relative filepath to the texture used for the normal (aka bump) map. Optional."
|
||||
},
|
||||
"normalStrength": {
|
||||
"type": "number",
|
||||
"description": "Strength of the normal map. Usually 0-1, but can go above, or negative to invert the map.",
|
||||
"format": "float",
|
||||
"default": 1.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"Material": {
|
||||
"type": "string",
|
||||
"description": "",
|
||||
"x-enumNames": [
|
||||
"Default",
|
||||
"Ice",
|
||||
"Quantum",
|
||||
"Rock"
|
||||
],
|
||||
"enum": [
|
||||
"default",
|
||||
"ice",
|
||||
"quantum",
|
||||
"rock"
|
||||
]
|
||||
},
|
||||
"AtmosphereModule": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user