Proxy atmosphere, fog, and lightning

This commit is contained in:
Noah Pilarski 2022-08-15 06:20:00 -04:00
parent adc962f14e
commit cc4194ccad
10 changed files with 269 additions and 57 deletions

View File

@ -18,7 +18,7 @@ namespace NewHorizons.Builder.Atmosphere
Skys.Clear();
}
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmosphereModule, float surfaceSize)
public static GameObject Make(GameObject planetGO, Sector sector, AtmosphereModule atmosphereModule, float surfaceSize, bool proxy = false)
{
GameObject atmoGO = new GameObject("Atmosphere");
atmoGO.SetActive(false);
@ -26,36 +26,73 @@ namespace NewHorizons.Builder.Atmosphere
if (atmosphereModule.useAtmosphereShader)
{
GameObject atmo = GameObject.Instantiate(SearchUtilities.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere"), atmoGO.transform, true);
atmo.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
atmo.transform.localScale = Vector3.one * atmosphereModule.size * 1.2f;
var renderers = atmo.GetComponentsInChildren<MeshRenderer>();
var material = renderers[0].material; // makes a new material
foreach (var renderer in renderers)
if (proxy)
{
renderer.sharedMaterial = material;
}
material.SetFloat(InnerRadius, atmosphereModule.clouds != null ? atmosphereModule.size : surfaceSize);
material.SetFloat(OuterRadius, atmosphereModule.size * 1.2f);
if (atmosphereModule.atmosphereTint != null) material.SetColor(SkyColor, atmosphereModule.atmosphereTint.ToColor());
var distantProxy = (SearchUtilities.Find("TimberHearth_DistantProxy", false) ?? SearchUtilities.Find("TimberHearth_DistantProxy(Clone)", false))?.FindChild("Atmosphere_TH/Atmosphere_LOD3");
if (distantProxy != null)
{
GameObject atmo = GameObject.Instantiate(distantProxy, atmoGO.transform, true);
atmo.name = "Atmosphere_LOD3";
atmo.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
atmo.transform.localScale = Vector3.one * atmosphereModule.size * 1.2f * 2f;
atmo.SetActive(true);
var renderer = atmo.GetComponent<MeshRenderer>();
var material = renderer.material; // makes a new material
renderer.sharedMaterial = material;
material.SetFloat(InnerRadius, atmosphereModule.clouds != null ? atmosphereModule.size : surfaceSize);
material.SetFloat(OuterRadius, atmosphereModule.size * 1.2f);
if (atmosphereModule.atmosphereTint != null) material.SetColor(SkyColor, atmosphereModule.atmosphereTint.ToColor());
if (atmosphereModule.atmosphereSunIntensity == 0)
{
// do it based on distance
Skys.Add((planetGO, material));
atmo.SetActive(true);
if (atmosphereModule.atmosphereSunIntensity == 0)
{
// do it based on distance
Skys.Add((planetGO, material));
}
else
{
// use the override instead
material.SetFloat(SunIntensity, atmosphereModule.atmosphereSunIntensity);
}
}
}
else
{
// use the override instead
material.SetFloat(SunIntensity, atmosphereModule.atmosphereSunIntensity);
GameObject atmo = GameObject.Instantiate(SearchUtilities.Find("TimberHearth_Body/Atmosphere_TH/AtmoSphere"), atmoGO.transform, true);
atmo.name = "AtmoSphere";
atmo.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
atmo.transform.localScale = Vector3.one * atmosphereModule.size * 1.2f;
var renderers = atmo.GetComponentsInChildren<MeshRenderer>();
var material = renderers[0].material; // makes a new material
foreach (var renderer in renderers)
{
renderer.sharedMaterial = material;
}
material.SetFloat(InnerRadius, atmosphereModule.clouds != null ? atmosphereModule.size : surfaceSize);
material.SetFloat(OuterRadius, atmosphereModule.size * 1.2f);
if (atmosphereModule.atmosphereTint != null) material.SetColor(SkyColor, atmosphereModule.atmosphereTint.ToColor());
atmo.SetActive(true);
if (atmosphereModule.atmosphereSunIntensity == 0)
{
// do it based on distance
Skys.Add((planetGO, material));
}
else
{
// use the override instead
material.SetFloat(SunIntensity, atmosphereModule.atmosphereSunIntensity);
}
}
}
atmoGO.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
atmoGO.SetActive(true);
return atmoGO;
}
}
}

View File

@ -109,26 +109,7 @@ namespace NewHorizons.Builder.Atmosphere
// Lightning
if (atmo.clouds.hasLightning)
{
var lightning = _lightningPrefab.InstantiateInactive();
lightning.transform.parent = cloudsMainGO.transform;
lightning.transform.localPosition = Vector3.zero;
var lightningGenerator = lightning.GetComponent<CloudLightningGenerator>();
lightningGenerator._altitude = (atmo.clouds.outerCloudRadius + atmo.clouds.innerCloudRadius) / 2f;
lightningGenerator._audioSector = sector;
if (atmo.clouds.lightningGradient != null)
{
var gradient = new GradientColorKey[atmo.clouds.lightningGradient.Length];
for(int i = 0; i < atmo.clouds.lightningGradient.Length; i++)
{
var pair = atmo.clouds.lightningGradient[i];
gradient[i] = new GradientColorKey(pair.tint.ToColor(), pair.time);
}
lightningGenerator._lightColor.colorKeys = gradient;
}
lightning.SetActive(true);
MakeLightning(cloudsMainGO, sector, atmo);
}
cloudsMainGO.transform.position = planetGO.transform.TransformPoint(Vector3.zero);
@ -140,6 +121,37 @@ namespace NewHorizons.Builder.Atmosphere
cloudsMainGO.SetActive(true);
}
public static CloudLightningGenerator MakeLightning(GameObject rootObject, Sector sector, AtmosphereModule atmo, bool noAudio = false)
{
var lightning = _lightningPrefab.InstantiateInactive();
lightning.name = "LightningGenerator";
lightning.transform.parent = rootObject.transform;
lightning.transform.localPosition = Vector3.zero;
var lightningGenerator = lightning.GetComponent<CloudLightningGenerator>();
lightningGenerator._altitude = (atmo.clouds.outerCloudRadius + atmo.clouds.innerCloudRadius) / 2f;
if (noAudio)
{
lightningGenerator._audioPrefab = null;
lightningGenerator._audioSourcePool = null;
}
lightningGenerator._audioSector = sector;
if (atmo.clouds.lightningGradient != null)
{
var gradient = new GradientColorKey[atmo.clouds.lightningGradient.Length];
for (int i = 0; i < atmo.clouds.lightningGradient.Length; i++)
{
var pair = atmo.clouds.lightningGradient[i];
gradient[i] = new GradientColorKey(pair.tint.ToColor(), pair.time);
}
lightningGenerator._lightColor.colorKeys = gradient;
}
lightning.SetActive(true);
return lightningGenerator;
}
public static GameObject MakeTopClouds(GameObject rootObject, AtmosphereModule atmo, IModBehaviour mod)
{
Color cloudTint = atmo.clouds.tint?.ToColor() ?? UnityEngine.Color.white;

View File

@ -14,7 +14,7 @@ namespace NewHorizons.Builder.Atmosphere
private static readonly int DensityExponent = Shader.PropertyToID("_DensityExp");
private static readonly int ColorRampTexture = Shader.PropertyToID("_ColorRampTex");
public static void Make(GameObject planetGO, Sector sector, AtmosphereModule atmo)
public static PlanetaryFogController Make(GameObject planetGO, Sector sector, AtmosphereModule atmo)
{
if (_ramp == null) _ramp = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/FogColorRamp.png");
@ -58,6 +58,41 @@ namespace NewHorizons.Builder.Atmosphere
fogGO.transform.position = planetGO.transform.position;
fogGO.SetActive(true);
return PFC;
}
public static Renderer MakeProxy(GameObject proxyGO, AtmosphereModule atmo)
{
if (_ramp == null) _ramp = ImageUtilities.GetTexture(Main.Instance, "Assets/textures/FogColorRamp.png");
GameObject fogGO = new GameObject("FogSphere");
fogGO.SetActive(false);
fogGO.transform.parent = proxyGO.transform;
fogGO.transform.localScale = Vector3.one * atmo.fogSize;
var fog = (SearchUtilities.Find("TimberHearth_DistantProxy", false) ?? SearchUtilities.Find("TimberHearth_DistantProxy(Clone)", false))?.FindChild("Atmosphere_TH/FogSphere");
MeshFilter MF = fogGO.AddComponent<MeshFilter>();
MF.mesh = fog.GetComponent<MeshFilter>().mesh;
MeshRenderer MR = fogGO.AddComponent<MeshRenderer>();
MR.materials = fog.GetComponent<MeshRenderer>().materials;
MR.allowOcclusionWhenDynamic = true;
var colorRampTexture = atmo.fogTint == null ? _ramp : ImageUtilities.TintImage(_ramp, atmo.fogTint.ToColor());
if (atmo.fogTint != null)
{
MR.material.SetColor(Tint, atmo.fogTint.ToColor());
}
MR.material.SetFloat(Radius, atmo.fogSize);
MR.material.SetFloat(Density, atmo.fogDensity);
MR.material.SetFloat(DensityExponent, 1);
MR.material.SetTexture(ColorRampTexture, colorRampTexture);
fogGO.transform.position = proxyGO.transform.position;
fogGO.SetActive(true);
return MR;
}
}
}

View File

@ -4,7 +4,7 @@ namespace NewHorizons.Builder.Body
{
public static class GeometryBuilder
{
public static void Make(GameObject planetGO, Sector sector, float groundScale)
public static GameObject Make(GameObject planetGO, Sector sector, float groundScale)
{
GameObject groundGO = GameObject.CreatePrimitive(PrimitiveType.Sphere);
groundGO.transform.name = "GroundSphere";
@ -15,6 +15,8 @@ namespace NewHorizons.Builder.Body
groundGO.GetComponent<MeshFilter>().mesh = SearchUtilities.Find("CloudsTopLayer_GD").GetComponent<MeshFilter>().mesh;
groundGO.GetComponent<SphereCollider>().radius = 1f;
groundGO.SetActive(true);
return groundGO;
}
}
}

View File

@ -14,7 +14,7 @@ namespace NewHorizons.Builder.Body
{
public static Shader PlanetShader;
public static void Make(GameObject planetGO, Sector sector, HeightMapModule module, IModBehaviour mod, int resolution, bool useLOD = false)
public static GameObject Make(GameObject planetGO, Sector sector, HeightMapModule module, IModBehaviour mod, int resolution, bool useLOD = false)
{
var deleteHeightmapFlag = false;
@ -60,7 +60,7 @@ namespace NewHorizons.Builder.Body
catch (Exception e)
{
Logger.LogError($"Couldn't load HeightMap textures:\n{e}");
return;
return null;
}
GameObject cubeSphere = new GameObject("CubeSphere");
@ -111,6 +111,8 @@ namespace NewHorizons.Builder.Body
// Now that we've made the mesh we can delete the heightmap texture
if (deleteHeightmapFlag) ImageUtilities.DeleteTexture(mod, module.heightMap, heightMap);
return cubeSphere;
}
public static MeshRenderer MakeLODTerrain(GameObject root, Texture2D heightMap, Texture2D textureMap, float minHeight, float maxHeight, int resolution, Vector3 stretch)

View File

@ -9,7 +9,7 @@ namespace NewHorizons.Builder.Body
private static Material quantumMaterial;
private static Material iceMaterial;
public static void Make(GameObject planetGO, Sector sector, ProcGenModule module)
public static GameObject Make(GameObject planetGO, Sector sector, ProcGenModule module)
{
if (quantumMaterial == null) quantumMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Rock_QM_EyeRock_mat");
if (iceMaterial == null) iceMaterial = SearchUtilities.FindResourceOfTypeAndName<Material>("Rock_BH_IceSpike_mat");
@ -40,6 +40,7 @@ namespace NewHorizons.Builder.Body
if (superGroup != null) icosphere.AddComponent<ProxyShadowCaster>()._superGroup = superGroup;
icosphere.SetActive(true);
return icosphere;
}
}
}

View File

@ -34,43 +34,73 @@ namespace NewHorizons.Builder.Body
var proxyName = $"{body.Config.name}_Proxy";
var newProxy = new GameObject(proxyName);
newProxy.SetActive(false);
try
{
var proxyController = newProxy.AddComponent<NHProxy>();
proxyController.astroName = body.Config.name;
// We want to take the largest size I think
var realSize = body.Config.Base.surfaceSize;
GameObject heightMap = null;
if (body.Config.HeightMap != null)
{
HeightMapBuilder.Make(newProxy, null, body.Config.HeightMap, body.Mod, 20);
heightMap = HeightMapBuilder.Make(newProxy, null, body.Config.HeightMap, body.Mod, 20);
if (realSize < body.Config.HeightMap.maxHeight) realSize = body.Config.HeightMap.maxHeight;
}
if (body.Config.Base.groundSize != 0)
{
GeometryBuilder.Make(newProxy, null, body.Config.Base.groundSize);
if (realSize < body.Config.Base.groundSize) realSize = body.Config.Base.groundSize;
}
if (body.Config.Atmosphere?.clouds != null)
if (body.Config.Atmosphere != null)
{
CloudsBuilder.MakeTopClouds(newProxy, body.Config.Atmosphere, body.Mod);
if (realSize < body.Config.Atmosphere.size) realSize = body.Config.Atmosphere.size;
proxyController._atmosphere = AtmosphereBuilder.Make(newProxy, null, body.Config.Atmosphere, body.Config.Base.surfaceSize, true).GetComponentInChildren<MeshRenderer>();
proxyController._mieCurveMaxVal = 0.1f;
proxyController._mieCurve = AnimationCurve.EaseInOut(0.0011f, 1, 1, 0);
if (body.Config.Atmosphere.fogSize != 0)
{
proxyController._fog = FogBuilder.MakeProxy(newProxy, body.Config.Atmosphere);
proxyController._fogCurveMaxVal = body.Config.Atmosphere.fogDensity;
proxyController._fogCurve = AnimationCurve.Linear(0, 1, 1, 0);
}
if (body.Config.Atmosphere.clouds != null)
{
proxyController._mainBody = CloudsBuilder.MakeTopClouds(newProxy, body.Config.Atmosphere, body.Mod).GetComponent<MeshRenderer>();
if (body.Config.Atmosphere.clouds.hasLightning)
{
proxyController._lightningGenerator = CloudsBuilder.MakeLightning(newProxy, null, body.Config.Atmosphere, true);
}
if (realSize < body.Config.Atmosphere.size) realSize = body.Config.Atmosphere.size;
}
}
if (body.Config.Ring != null)
{
RingBuilder.MakeRingGraphics(newProxy, null, body.Config.Ring, body.Mod);
if (realSize < body.Config.Ring.outerRadius) realSize = body.Config.Ring.outerRadius;
}
if (body.Config.Star != null)
{
var starGO = StarBuilder.MakeStarProxy(planetGO, newProxy, body.Config.Star, body.Mod);
if (realSize < body.Config.Star.size) realSize = body.Config.Star.size;
}
GameObject procGen = null;
if (body.Config.ProcGen != null)
{
ProcGenBuilder.Make(newProxy, null, body.Config.ProcGen);
procGen = ProcGenBuilder.Make(newProxy, null, body.Config.ProcGen);
if (realSize < body.Config.ProcGen.scale) realSize = body.Config.ProcGen.scale;
}
if (body.Config.Lava != null)
{
var sphere = AddColouredSphere(newProxy, body.Config.Lava.size, body.Config.Lava.curve, Color.black);
@ -80,18 +110,21 @@ namespace NewHorizons.Builder.Body
if (body.Config.Lava.tint != null) material.SetColor(EmissionColor, body.Config.Lava.tint.ToColor());
sphere.GetComponent<MeshRenderer>().material = material;
}
if (body.Config.Water != null)
{
var colour = body.Config.Water.tint?.ToColor() ?? Color.blue;
AddColouredSphere(newProxy, body.Config.Water.size, body.Config.Water.curve, colour);
if (realSize < body.Config.Water.size) realSize = body.Config.Water.size;
}
if (body.Config.Sand != null)
{
var colour = body.Config.Sand.tint?.ToColor() ?? Color.yellow;
AddColouredSphere(newProxy, body.Config.Sand.size, body.Config.Sand.curve, colour);
if (realSize < body.Config.Sand.size) realSize = body.Config.Sand.size;
}
// Could improve this to actually use the proper renders and materials
if (body.Config.Props?.singularities != null)
{
@ -109,10 +142,12 @@ namespace NewHorizons.Builder.Body
if (realSize < singularity.size) realSize = singularity.size;
}
}
if (body.Config.Base.hasCometTail)
{
CometTailBuilder.Make(newProxy, null, body.Config);
}
if (body.Config.Props?.proxyDetails != null)
{
foreach (var detailInfo in body.Config.Props.proxyDetails)
@ -138,8 +173,6 @@ namespace NewHorizons.Builder.Body
tessellatedRenderer.enabled = true;
}
var proxyController = newProxy.AddComponent<NHProxy>();
proxyController.astroName = body.Config.name;
proxyController._realObjectDiameter = realSize;
}
catch (Exception ex)
@ -147,6 +180,8 @@ namespace NewHorizons.Builder.Body
Logger.LogError($"Exception thrown when generating proxy for [{body.Config.name}]:\n{ex}");
GameObject.Destroy(newProxy);
}
newProxy.SetActive(true);
}
private static GameObject AddColouredSphere(GameObject rootObj, float size, VariableSizeModule.TimeValuePair[] curve, Color color)

View File

@ -4,7 +4,7 @@ namespace NewHorizons.Builder.General
{
public static class AmbientLightBuilder
{
public static void Make(GameObject planetGO, Sector sector, float scale, float intensity)
public static Light Make(GameObject planetGO, Sector sector, float scale, float intensity)
{
GameObject lightGO = GameObject.Instantiate(SearchUtilities.Find("BrittleHollow_Body/AmbientLight_BH_Surface"), sector?.transform ?? planetGO.transform);
lightGO.transform.position = planetGO.transform.position;
@ -21,6 +21,8 @@ namespace NewHorizons.Builder.General
light.color = new Color(0.0f, 0.0f, 0.8f, 0.0225f);
light.range = scale;
light.intensity = intensity;
return light;
}
}
}

View File

@ -1,4 +1,4 @@
using NewHorizons.Components.SizeControllers;
using NewHorizons.Components.SizeControllers;
using NewHorizons.Utility;
using System.Collections.Generic;
using UnityEngine;
@ -13,6 +13,8 @@ namespace NewHorizons.Components
private TessellatedRenderer[] _starTessellatedRenderers;
private ParticleSystemRenderer[] _starParticleRenderers;
private SolarFlareEmitter _solarFlareEmitter;
public CloudLightningGenerator _lightningGenerator;
public MeshRenderer _mainBody;
public override void Awake()
{
@ -30,6 +32,8 @@ namespace NewHorizons.Components
_solarFlareEmitter = _star.GetComponentInChildren<SolarFlareEmitter>();
}
if (_lightningGenerator == null) _lightningGenerator = GetComponentInChildren<CloudLightningGenerator>();
// Start off
_outOfRange = false;
ToggleRendering(false);
@ -39,9 +43,9 @@ namespace NewHorizons.Components
{
AstroObject astroObject = AstroObjectLocator.GetAstroObject(astroName);
_realObjectTransform = astroObject.transform;
_hasAtmosphere = _atmosphere != null;
if (_hasAtmosphere)
if (_atmosphere != null)
{
_hasAtmosphere = true;
_atmosphereMaterial = new Material(_atmosphere.sharedMaterial);
_baseAtmoMatShellInnerRadius = _atmosphereMaterial.GetFloat(propID_AtmoInnerRadius);
_baseAtmoMatShellOuterRadius = _atmosphereMaterial.GetFloat(propID_AtmoOuterRadius);
@ -73,6 +77,16 @@ namespace NewHorizons.Components
_solarFlareEmitter.gameObject.SetActive(on);
}
if (_mainBody != null)
{
_mainBody.enabled = on;
}
if (_lightningGenerator != null)
{
_lightningGenerator.enabled = on;
}
foreach (var renderer in _starRenderers)
{
renderer.enabled = on;

View File

@ -1,4 +1,9 @@
using HarmonyLib;
using HarmonyLib;
using NewHorizons.Utility;
using System;
using System.Runtime.CompilerServices;
using UnityEngine;
namespace NewHorizons.Patches
{
[HarmonyPatch]
@ -46,5 +51,72 @@ namespace NewHorizons.Patches
GlobalMessenger.RemoveListener("EnterMapView", __instance.OnEnterMapView);
GlobalMessenger.RemoveListener("ExitMapView", __instance.OnExitMapView);
}
[HarmonyReversePatch]
[HarmonyPatch(typeof(ProxyPlanet), nameof(ProxyPlanet.Initialize))]
[MethodImpl(MethodImplOptions.NoInlining)]
public static void ProxyPlanet_Initialize(ProxyPlanet instance) { }
[HarmonyPrefix]
[HarmonyPatch(typeof(ProxyBrittleHollow), nameof(ProxyBrittleHollow.Initialize))]
public static bool ProxyBrittleHollow_Initialize(ProxyBrittleHollow __instance)
{
try
{
ProxyPlanet_Initialize(__instance);
__instance._moon.SetOriginalBodies(Locator.GetAstroObject(AstroObject.Name.VolcanicMoon).transform, Locator.GetAstroObject(AstroObject.Name.BrittleHollow).transform);
if (!__instance._fragmentsResolved) __instance.ResolveFragments();
__instance._blackHoleMaterial = new Material(__instance._blackHoleRenderer.sharedMaterial);
__instance._blackHoleRenderer.sharedMaterial = __instance._blackHoleMaterial;
}
catch (NullReferenceException ex)
{
__instance.PrintInitializeFailMessage(ex);
UnityEngine.Object.Destroy(__instance._moon.gameObject);
UnityEngine.Object.Destroy(__instance.gameObject);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ProxyTimberHearth), nameof(ProxyTimberHearth.Initialize))]
public static bool ProxyTimberHearth_Initialize(ProxyTimberHearth __instance)
{
try
{
ProxyPlanet_Initialize(__instance);
__instance._moon.SetOriginalBodies(Locator.GetAstroObject(AstroObject.Name.TimberMoon).transform, Locator.GetAstroObject(AstroObject.Name.TimberHearth).transform);
}
catch (NullReferenceException ex)
{
__instance.PrintInitializeFailMessage(ex);
UnityEngine.Object.Destroy(__instance._moon.gameObject);
UnityEngine.Object.Destroy(__instance.gameObject);
}
return false;
}
[HarmonyPrefix]
[HarmonyPatch(typeof(ProxyAshTwin), nameof(ProxyAshTwin.Initialize))]
public static bool ProxyAshTwin_Initialize(ProxyAshTwin __instance)
{
try
{
ProxyPlanet_Initialize(__instance);
__instance._realSandTransform = Locator.GetAstroObject(AstroObject.Name.TowerTwin).GetSandLevelController().transform;
SandFunnelController sandFunnelController = SearchUtilities.Find("SandFunnel_Body", false)?.GetComponent<SandFunnelController>();
if (sandFunnelController != null)
{
__instance._realSandColumnRoot = sandFunnelController.scaleRoot;
__instance._realSandColumnRenderObject = sandFunnelController.sandGeoObjects[0];
}
}
catch (NullReferenceException ex)
{
__instance.PrintInitializeFailMessage(ex);
UnityEngine.Object.Destroy(__instance.gameObject);
}
return false;
}
}
}