Improved Level Generator
New asteroid models Asteroid belts have a custom width curve = tighter belts Zone Generator uses color theory now Zone gravity well is much deeper, filled with ambient glow Gravity waves flow over time Fog follows gravity waves Gas Giant shader fixed, offsets distort albedo properly Fog sample distances follow exponential curve Fog noise offsets sampling position instead of subtracting density = more natural looking noise Fog brightness fades out at max view distance
This commit is contained in:
parent
1f90d3639a
commit
34e20c5488
679 changed files with 42717 additions and 209 deletions
|
|
@ -76,5 +76,6 @@ public class ActionGameManager : MonoBehaviour
|
|||
Context.Time = Time.time;
|
||||
}
|
||||
Zone.Update(_time, Time.deltaTime);
|
||||
SectorRenderer.Time = _time;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ public class GameSettings : ScriptableObject
|
|||
public float DefaultZoneMass;
|
||||
public float DefaultViewDistance;
|
||||
public float DefaultMinimapDistance;
|
||||
public int AsteroidMeshCount = 5;
|
||||
public PlanetSettings PlanetSettings;
|
||||
public ZoneGenerationSettings ZoneSettings;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ using UniRx;
|
|||
using UnityEngine;
|
||||
using static Unity.Mathematics.math;
|
||||
using Unity.Mathematics;
|
||||
using Random = UnityEngine.Random;
|
||||
|
||||
public class SectorRenderer : MonoBehaviour
|
||||
{
|
||||
|
|
@ -14,14 +15,17 @@ public class SectorRenderer : MonoBehaviour
|
|||
public GameSettings Settings;
|
||||
public Transform SectorRoot;
|
||||
public Transform SectorBrushes;
|
||||
public CinemachineVirtualCamera SceneCamera;
|
||||
public MeshRenderer SectorBoundaryBrush;
|
||||
public CinemachineVirtualCamera[] SceneCameras;
|
||||
public Camera[] FogCameras;
|
||||
public Camera[] MinimapCameras;
|
||||
public Material FogMaterial;
|
||||
public float FogFarFadeFraction = .125f;
|
||||
public float FarPlaneDistanceMultiplier = 2;
|
||||
public Mesh[] AsteroidMeshes;
|
||||
public Material AsteroidMaterial;
|
||||
public InstancedMesh[] AsteroidMeshes;
|
||||
|
||||
// public Mesh[] AsteroidMeshes;
|
||||
// public Material AsteroidMaterial;
|
||||
|
||||
[Header("Prefabs")]
|
||||
public GameObject Belt;
|
||||
|
|
@ -34,8 +38,11 @@ public class SectorRenderer : MonoBehaviour
|
|||
public Texture2D PlanetIcon;
|
||||
|
||||
private Dictionary<Guid, PlanetObject> _planets = new Dictionary<Guid, PlanetObject>();
|
||||
private Dictionary<Guid, InstancedMesh[]> _beltMeshes = new Dictionary<Guid, InstancedMesh[]>();
|
||||
private Zone _zone;
|
||||
private float _viewDistance;
|
||||
|
||||
public float Time { get; set; }
|
||||
|
||||
public float ViewDistance
|
||||
{
|
||||
|
|
@ -44,7 +51,8 @@ public class SectorRenderer : MonoBehaviour
|
|||
_viewDistance = value;
|
||||
foreach (var camera in FogCameras)
|
||||
camera.orthographicSize = value;
|
||||
SceneCamera.m_Lens.FarClipPlane = value * FarPlaneDistanceMultiplier;
|
||||
foreach(var camera in SceneCameras)
|
||||
camera.m_Lens.FarClipPlane = value * FarPlaneDistanceMultiplier;
|
||||
FogMaterial.SetFloat("_DepthCeiling", value - FogFarFadeFraction * value);
|
||||
FogMaterial.SetFloat("_DepthBlend", FogFarFadeFraction * value);
|
||||
}
|
||||
|
|
@ -69,9 +77,6 @@ public class SectorRenderer : MonoBehaviour
|
|||
{
|
||||
_zone = zone;
|
||||
SectorBrushes.localScale = zone.Data.Radius * 2 * Vector3.one;
|
||||
_zone.ZoneDepth = 125;
|
||||
_zone.ZoneDepthExponent = .25f;
|
||||
_zone.ZoneDepthRadius = zone.Data.Radius * 2;
|
||||
ClearZone();
|
||||
foreach(var p in zone.Planets.Values)
|
||||
LoadPlanet(p);
|
||||
|
|
@ -86,6 +91,7 @@ public class SectorRenderer : MonoBehaviour
|
|||
DestroyImmediate(planet.gameObject);
|
||||
}
|
||||
_planets.Clear();
|
||||
_beltMeshes.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -93,7 +99,10 @@ public class SectorRenderer : MonoBehaviour
|
|||
{
|
||||
if (planetData is AsteroidBeltData beltData)
|
||||
{
|
||||
|
||||
var meshes = AsteroidMeshes.ToList();
|
||||
while(meshes.Count > Settings.AsteroidMeshCount)
|
||||
meshes.RemoveAt(Random.Range(0,meshes.Count));
|
||||
_beltMeshes[planetData.ID] = meshes.ToArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -113,7 +122,7 @@ public class SectorRenderer : MonoBehaviour
|
|||
|
||||
var gas = (GasGiantObject) planet;
|
||||
var gasGiant = _zone.PlanetInstances[planetData.ID] as GasGiant;
|
||||
gasGiantData.Colors.Subscribe(c => gas.Body.material.SetTexture("_ColorRamp", c.ToGradient().ToTexture()));
|
||||
gasGiantData.Colors.Subscribe(c => gas.Body.material.SetTexture("_ColorRamp", c.ToGradient(!(planetData is SunData)).ToTexture()));
|
||||
gasGiantData.AlbedoRotationSpeed.Subscribe(f => gas.SunMaterial.AlbedoRotationSpeed = f);
|
||||
gasGiantData.FirstOffsetRotationSpeed.Subscribe(f => gas.SunMaterial.FirstOffsetRotationSpeed = f);
|
||||
gasGiantData.SecondOffsetRotationSpeed.Subscribe(f => gas.SunMaterial.SecondOffsetRotationSpeed = f);
|
||||
|
|
@ -139,41 +148,52 @@ public class SectorRenderer : MonoBehaviour
|
|||
}
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
foreach(var belt in _zone.AsteroidBelts.Values)
|
||||
{
|
||||
for (int i = 0; i < AsteroidMeshes.Length; i++)
|
||||
{
|
||||
var matrices = belt.Transforms
|
||||
.Skip((int) (((float)i / AsteroidMeshes.Length) * belt.Transforms.Length))
|
||||
.Take((int) (1f / AsteroidMeshes.Length * belt.Transforms.Length))
|
||||
.Select(v => Matrix4x4.TRS(
|
||||
new Vector3(v.x, _zone.GetHeight(v.xy), v.y),
|
||||
Quaternion.Euler(cos(v.z + (float) i / AsteroidMeshes.Length) * 100, sin(v.z + (float) i / AsteroidMeshes.Length) * 100, 0),
|
||||
Vector3.one * (v.w)))
|
||||
.ToArray();
|
||||
Graphics.DrawMeshInstanced(AsteroidMeshes[i], 0, AsteroidMaterial, matrices);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LateUpdate()
|
||||
{
|
||||
foreach(var belt in _zone.AsteroidBelts)
|
||||
{
|
||||
var meshes = _beltMeshes[belt.Key];
|
||||
for (int i = 0; i < meshes.Length; i++)
|
||||
{
|
||||
var matrices = belt.Value.Transforms
|
||||
.Skip((int) (((float)i / meshes.Length) * belt.Value.Transforms.Length))
|
||||
.Take((int) (1f / meshes.Length * belt.Value.Transforms.Length))
|
||||
.Select((v, x) => Matrix4x4.TRS(
|
||||
new Vector3(v.x, _zone.GetHeight(v.xy), v.y),
|
||||
Quaternion.Euler(cos(v.z + (float) i / meshes.Length) * 100, sin(v.z + (float) i / meshes.Length) * 100, (float)x/belt.Value.Transforms.Length * 360),
|
||||
Vector3.one * v.w))
|
||||
.ToArray();
|
||||
Graphics.DrawMeshInstanced(meshes[i].Mesh, 0, meshes[i].Material, matrices);
|
||||
}
|
||||
}
|
||||
|
||||
foreach (var planet in _planets)
|
||||
{
|
||||
var planetInstance = _zone.PlanetInstances[planet.Key];
|
||||
var p = _zone.GetOrbitPosition(planetInstance.BodyData.Orbit);
|
||||
planet.Value.transform.position = new Vector3(p.x, _zone.GetHeight(p) + planetInstance.BodyRadius.Value * 2, p.y);
|
||||
if(planet.Value is GasGiantObject gasGiantObject && !(planet.Value is SunObject))
|
||||
if(planet.Value is GasGiantObject gasGiantObject)
|
||||
{
|
||||
var toParent = normalize(_zone.GetOrbitPosition(_zone.Orbits[planetInstance.BodyData.Orbit].Data.Parent) - p);
|
||||
gasGiantObject.SunMaterial.LightingDirection = new Vector3(toParent.x, 0, toParent.y);
|
||||
gasGiantObject.GravityWaves.material.SetFloat("_Phase", Time * Settings.PlanetSettings.WaveSpeed.Evaluate(planetInstance.BodyData.Mass.Value));
|
||||
if(!(planet.Value is SunObject))
|
||||
{
|
||||
var toParent = normalize(_zone.GetOrbitPosition(_zone.Orbits[planetInstance.BodyData.Orbit].Data.Parent) - p);
|
||||
gasGiantObject.SunMaterial.LightingDirection = new Vector3(toParent.x, 0, toParent.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var fogPos = FogCameraParent.position;
|
||||
SectorBoundaryBrush.material.SetFloat("_Power", Settings.PlanetSettings.ZoneDepthExponent);
|
||||
SectorBoundaryBrush.material.SetFloat("_Depth", Settings.PlanetSettings.ZoneDepth + Settings.PlanetSettings.ZoneBoundaryFog);
|
||||
FogMaterial.SetFloat("_GridOffset", Settings.PlanetSettings.ZoneBoundaryFog);
|
||||
FogMaterial.SetVector("_GridTransform", new Vector4(fogPos.x,fogPos.z,_viewDistance*2));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
[Serializable]
|
||||
public class InstancedMesh
|
||||
{
|
||||
public Mesh Mesh;
|
||||
public Material Material;
|
||||
}
|
||||
|
|
|
|||
55
Assets/Scripts/ServerShared/ColorMath.cs
Normal file
55
Assets/Scripts/ServerShared/ColorMath.cs
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using Unity.Mathematics;
|
||||
using static Unity.Mathematics.math;
|
||||
|
||||
// Thanks to Ian Taylor at https://www.chilliant.com/rgb2hsv.html
|
||||
public static class ColorMath
|
||||
{
|
||||
public static float3 HueToRgb(in float h)
|
||||
{
|
||||
float r = abs(h * 6 - 3) - 1;
|
||||
float g = 2 - abs(h * 6 - 2);
|
||||
float b = 2 - abs(h * 6 - 4);
|
||||
return saturate(float3(r,g,b));
|
||||
}
|
||||
|
||||
public static float3 HsvToRgb(in float3 hsv)
|
||||
{
|
||||
float3 rgb = HueToRgb(hsv.x);
|
||||
return ((rgb - 1) * hsv.y + 1) * hsv.z;
|
||||
}
|
||||
|
||||
public static float3 HslToRgb(in float3 hsl)
|
||||
{
|
||||
float3 rgb = HueToRgb(hsl.x);
|
||||
float c = (1 - abs(2 * hsl.z - 1)) * hsl.y;
|
||||
return (rgb - 0.5f) * c + hsl.z;
|
||||
}
|
||||
|
||||
const float Epsilon = 1e-10f;
|
||||
public static float3 RgbToHcv(in float3 rgb)
|
||||
{
|
||||
// Based on work by Sam Hocevar and Emil Persson
|
||||
float4 p = (rgb.y < rgb.z) ? float4(rgb.zy, -1.0f, 2.0f/3.0f) : float4(rgb.zy, 0.0f, -1.0f/3.0f);
|
||||
float4 q = (rgb.x < p.x) ? float4(p.xyw, rgb.x) : float4(rgb.x, p.yzx);
|
||||
float c = q.x - min(q.w, q.y);
|
||||
float h = abs((q.w - q.y) / (6 * c + Epsilon) + q.z);
|
||||
return float3(h, c, q.x);
|
||||
}
|
||||
|
||||
public static float3 RgbToHsv(in float3 rgb)
|
||||
{
|
||||
float3 hcv = RgbToHcv(rgb);
|
||||
float s = hcv.y / (hcv.z + Epsilon);
|
||||
return float3(hcv.x, s, hcv.z);
|
||||
}
|
||||
|
||||
public static float3 RgbToHsl(in float3 rgb)
|
||||
{
|
||||
float3 hcv = RgbToHcv(rgb);
|
||||
float l = hcv.z - hcv.y * 0.5f;
|
||||
float s = hcv.y / (1 - abs(l * 2 - 1) + Epsilon);
|
||||
return float3(hcv.x, s, l);
|
||||
}
|
||||
}
|
||||
11
Assets/Scripts/ServerShared/ColorMath.cs.meta
Normal file
11
Assets/Scripts/ServerShared/ColorMath.cs.meta
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
fileFormatVersion: 2
|
||||
guid: 7e37873d142bdaf429c4be95a1d087f2
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
|
|
@ -9,6 +9,9 @@ using static Unity.Mathematics.math;
|
|||
[Serializable, MessagePackObject(keyAsPropertyName:true), JsonObject]
|
||||
public class PlanetSettings
|
||||
{
|
||||
public float ZoneDepthExponent;
|
||||
public float ZoneDepth;
|
||||
public float ZoneBoundaryFog;
|
||||
public ExponentialCurve GravityDepth;
|
||||
public ExponentialCurve GravityRadius;
|
||||
public ExponentialCurve WaveDepth;
|
||||
|
|
@ -59,9 +62,21 @@ public class ZoneGenerationSettings
|
|||
public float BeltProbability = .05f;
|
||||
public float BeltMassCeiling = 500f;
|
||||
|
||||
public ExponentialCurve AsteroidBeltWidth;
|
||||
public ExponentialCurve AsteroidCount;
|
||||
public ExponentialLerp AsteroidRotationSpeed;
|
||||
|
||||
public float ResourceDensityMinimum = .1f;
|
||||
public float ResourceDensityMaximum = 1.5f;
|
||||
|
||||
public float SunColorSaturation = .75f;
|
||||
public float SunSecondaryColorDistance = .25f;
|
||||
public float SunLightSaturation = .5f;
|
||||
public float SunFogTintSaturation = .5f;
|
||||
|
||||
public ExponentialLerp GasGiantBandCount;
|
||||
public float GasGiantBandColorSeparation = .25f;
|
||||
public float GasGiantBandAltColorChance = .25f;
|
||||
public ExponentialLerp GasGiantBandSaturation;
|
||||
public ExponentialLerp GasGiantBandBrightness;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,9 +10,6 @@ using Random = Unity.Mathematics.Random;
|
|||
|
||||
public class Zone
|
||||
{
|
||||
public float ZoneDepth;
|
||||
public float ZoneDepthExponent;
|
||||
public float ZoneDepthRadius;
|
||||
//public HashSet<Guid> Planets = new HashSet<Guid>();
|
||||
public Dictionary<Guid, Entity> Entities = new Dictionary<Guid, Entity>();
|
||||
//public Dictionary<Guid, OrbitData> Orbits = new Dictionary<Guid, OrbitData>();
|
||||
|
|
@ -266,7 +263,7 @@ public class Zone
|
|||
}
|
||||
public float GetHeight(float2 position)
|
||||
{
|
||||
float result = -PowerPulse(length(position)/ZoneDepthRadius, ZoneDepthExponent) * ZoneDepth;
|
||||
float result = -PowerPulse(length(position)/(Data.Radius*2), _settings.ZoneDepthExponent) * _settings.ZoneDepth;
|
||||
foreach (var body in PlanetInstances.Values)
|
||||
{
|
||||
var p = (position - GetOrbitPosition(body.BodyData.Orbit));
|
||||
|
|
|
|||
|
|
@ -142,7 +142,7 @@ public class ZoneGenerator
|
|||
Enumerable.Range(0, (int) (settings.AsteroidCount.Evaluate(beltData.Mass.Value * orbitMap[planet].Distance.Value)))
|
||||
.Select(_ => new Asteroid
|
||||
{
|
||||
Distance = random.NextFloat(orbitMap[planet].Distance.Value * .5f, orbitMap[planet].Distance.Value * 1.5f),
|
||||
Distance = random.NextFloat(orbitMap[planet].Distance.Value, orbitMap[planet].Distance.Value + settings.AsteroidBeltWidth.Evaluate(orbitMap[planet].Distance.Value)),
|
||||
Phase = random.NextFloat(),
|
||||
Size = random.NextFloat(),
|
||||
RotationSpeed = settings.AsteroidRotationSpeed.Evaluate(random.NextFloat())
|
||||
|
|
@ -152,18 +152,46 @@ public class ZoneGenerator
|
|||
}
|
||||
else if (planetData is GasGiantData gas)
|
||||
{
|
||||
var times = Enumerable.Range(0, 5).Select(i => (float) i / 4).ToArray();
|
||||
gas.Colors.Value = times.Select(time => float4(random.NextFloat3(),time)).ToArray();
|
||||
gas.AlbedoRotationSpeed.Value = -3;
|
||||
gas.FirstOffsetRotationSpeed.Value = 5;
|
||||
gas.FirstOffsetDomainRotationSpeed.Value = 0;
|
||||
gas.SecondOffsetRotationSpeed.Value = 10;
|
||||
gas.SecondOffsetDomainRotationSpeed.Value = -25;
|
||||
if (planetData is SunData sun)
|
||||
if (gas is SunData sun)
|
||||
{
|
||||
sun.FogTintColor.Value = sun.LightColor.Value = random.NextFloat3();
|
||||
float primary = random.NextFloat();
|
||||
float secondary = frac(primary + 1 + settings.SunSecondaryColorDistance * (random.NextFloat() > .5 ? 1 : -1));
|
||||
gas.Colors.Value = new []
|
||||
{
|
||||
float4(ColorMath.HsvToRgb(float3(primary, settings.SunColorSaturation, .5f)), 0),
|
||||
float4(ColorMath.HsvToRgb(float3(secondary, settings.SunColorSaturation, 1)), 1)
|
||||
};
|
||||
sun.FogTintColor.Value = ColorMath.HsvToRgb(float3(primary, settings.SunFogTintSaturation, 1));
|
||||
sun.LightColor.Value = ColorMath.HsvToRgb(float3(primary, settings.SunLightSaturation, 1));
|
||||
gas.FirstOffsetDomainRotationSpeed.Value = 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Define primary color and two adjacent colors
|
||||
float primary = random.NextFloat();
|
||||
float right = frac(primary + settings.GasGiantBandColorSeparation);
|
||||
float left = frac(primary + 1 - settings.GasGiantBandColorSeparation);
|
||||
|
||||
// Create n time keys from 0 to 1
|
||||
var bandCount = (int) (settings.GasGiantBandCount.Evaluate(random.NextFloat()) + .5f);
|
||||
var times = Enumerable.Range(0, bandCount)
|
||||
.Select(i => (float) i / (bandCount-1));
|
||||
|
||||
// Each band has a chance of being either the primary or one of the adjacent hues
|
||||
// Saturation and Value are random with curves applied
|
||||
gas.Colors.Value = times
|
||||
.Select(time => float4(ColorMath.HsvToRgb(float3(
|
||||
random.NextFloat() > settings.GasGiantBandAltColorChance ? primary : (random.NextFloat() > .5f ? right : left),
|
||||
settings.GasGiantBandSaturation.Evaluate(random.NextFloat()),
|
||||
settings.GasGiantBandSaturation.Evaluate(random.NextFloat()))),time))
|
||||
.ToArray();
|
||||
|
||||
gas.FirstOffsetDomainRotationSpeed.Value = 0;
|
||||
}
|
||||
gas.AlbedoRotationSpeed.Value = -3;
|
||||
gas.FirstOffsetRotationSpeed.Value = 5;
|
||||
gas.SecondOffsetRotationSpeed.Value = 10;
|
||||
gas.SecondOffsetDomainRotationSpeed.Value = -25;
|
||||
}
|
||||
return planetData;
|
||||
}).ToList();
|
||||
|
|
|
|||
|
|
@ -96,9 +96,10 @@ public static class UnityExtensions
|
|||
return tex;
|
||||
}
|
||||
|
||||
public static Gradient ToGradient(this float4[] keys)
|
||||
public static Gradient ToGradient(this float4[] keys, bool sharp = false)
|
||||
{
|
||||
var grad = new Gradient();
|
||||
grad.mode = sharp ? GradientMode.Fixed : GradientMode.Blend;
|
||||
grad.alphaKeys = new[] {new GradientAlphaKey(1, 0), new GradientAlphaKey(1, 1)};
|
||||
grad.colorKeys = keys.Select(k => new GradientColorKey(k.xyz, k.w)).ToArray();
|
||||
return grad;
|
||||
|
|
|
|||
Loading…
Reference in a new issue