private void UpdateSun(Camera camera, WeatherMakerCelestialObject sun, float l) { if (camera != null && camera.orthographic) { sun.Transform.rotation = Quaternion.AngleAxis(180.0f + ((TimeOfDay / SecondsPerDay) * 360.0f), Vector3.right); float dot = Mathf.Clamp(Vector3.Dot(sun.Transform.forward, Vector3.forward) + 0.5f, 0.0f, 1.0f); sun.Light.intensity = sun.LightBaseIntensity * dot; } else { // convert local time of day to UTC time of day - quick and dirty calculation double offsetSeconds = TimeZoneOffsetSeconds; TimeSpan t = TimeSpan.FromSeconds(TimeOfDay - offsetSeconds); SunData.DateTime = new DateTime(Year, Month, Day, 0, 0, 0, DateTimeKind.Utc) + t; SunData.Latitude = Latitude; SunData.Longitude = Longitude; SunData.AxisTilt = AxisTilt; // calculate and set sun position in sky CalculateSunPosition(SunData, sun.RotateYDegrees); SetCelestialObjectPosition(sun, SunData.UnitVectorDown); // calculate sun intensity and shadow strengths float sunIntensityLookup = SunIntensityGradient.Evaluate(l).grayscale; sunIntensityLookup *= sunIntensityLookup; float sunShadowLookup = SunShadowStrengthGradient.Evaluate(l).grayscale; sun.Light.color *= SunTintColorGradient.Evaluate(l); sun.Light.intensity = sun.LightBaseIntensity * sunIntensityLookup; sun.Light.shadowStrength = sun.LightBaseShadowStrength * sunShadowLookup; } }
private void UpdateMoons(Camera camera, WeatherMakerCelestialObject sun, IList <WeatherMakerCelestialObject> moons) { float dot, yPower; while (MoonDatas.Count > moons.Count) { MoonDatas.RemoveAt(MoonDatas.Count - 1); } while (MoonDatas.Count < moons.Count) { MoonDatas.Add(new MoonInfo()); } for (int i = 0; i < moons.Count; i++) { WeatherMakerCelestialObject moon = moons[i]; CalculateMoonPosition(SunData, MoonDatas[i], moon.RotateYDegrees); SetCelestialObjectPosition(moon, MoonDatas[i].UnitVectorDown); // intensity raises squared compare to moon fullness - this means less full is squared amount of less light // moon light intensity reduces as sun light intensity approaches 1 // reduce moon light as it drops below horizon dot = Mathf.Clamp(Vector3.Dot(MoonDatas[i].UnitVectorDown, Vector3.down) + 0.2f, 0.0f, 1.0f); dot = Mathf.Pow(dot, 0.25f); yPower = Mathf.Clamp((MoonDatas[i].UnitVectorUp.y + 0.1f) * 3.0f, 0.0f, 1.0f); moon.Light.intensity = moon.LightBaseIntensity * yPower * (1.0f - Mathf.Min(1.0f, sun.Light.intensity)) * (float)MoonDatas[i].PercentFull * (float)MoonDatas[i].PercentFull * dot * moon.LightMultiplier; } }
private void SetCelestialObjectPosition(WeatherMakerCelestialObject obj, Vector3 transformForward) { switch (obj.OrbitType) { case WeatherMakerOrbitType.Custom: IWeatherMakerCelestialObjectCustomOrbit orbitInterface = obj.OrbitTypeCustomScript as IWeatherMakerCelestialObjectCustomOrbit; if (orbitInterface == null) { Debug.LogErrorFormat("Unable to use custom orbit for celestial object {0}, field OrbitTypeCustomScript" + " must be set to a MonoBehavior script implementing IWeatherMakerCelestialObjectCustomOrbit", obj.Transform.gameObject.name); } else { transformForward = orbitInterface.CalculatePosition(obj); } break; default: // drop sun faster as it dips below horizon, in summer the sky horizon is visible even at 3am! if (transformForward.y > 0.1f) { transformForward.y = Mathf.Pow(transformForward.y, 0.8f); } break; } obj.Transform.forward = transformForward; }
private void UpdateDayMultipliers(Camera camera, WeatherMakerCelestialObject sun, float l) { Color lookup = DayDawnDuskNightGradient.Evaluate(l); DayMultiplier = lookup.g; DawnDuskMultiplier = lookup.r; NightMultiplier = lookup.b; TimeOfDayCategory = (WeatherMakerTimeOfDayCategory)0; if (DayMultiplier > 0.0f) { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Day; } if (DawnDuskMultiplier > 0.0f) { if (TimeOfDay > (SecondsPerDay * 0.5)) { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Dusk; } else { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Dawn; } } if (NightMultiplier > 0.0f) { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Night; } if (camera != null && camera.orthographic) { float z = sun.Transform.forward.z; if (z >= -0.1f && z <= 0.1f) { if (TimeOfDay > (SecondsPerDay * 0.5f)) { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Sunset; } else { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Sunrise; } } } else { float y = sun.Transform.forward.y; if (y >= -0.05f && y <= 0.2f) { if (TimeOfDay > (SecondsPerDay * 0.5f)) { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Sunset; } else { TimeOfDayCategory |= WeatherMakerTimeOfDayCategory.Sunrise; } } } }
private void UpdateLightIntensitiesAndShadows(WeatherMakerCelestialObject sun, ICollection <WeatherMakerCelestialObject> moons, Dictionary <string, float> directionalLightIntensityModifiers, Dictionary <string, float> directionalLightShadowModifier) { ProcessCelestialObject(sun, directionalLightIntensityModifiers, directionalLightShadowModifier); foreach (WeatherMakerCelestialObject obj in moons) { ProcessCelestialObject(obj, directionalLightIntensityModifiers, directionalLightShadowModifier); } }
private void SetGlobalShaders() { // Sun Shader.SetGlobalVector("_WeatherMakerSunDirectionUp", -Sun.Transform.forward); Shader.SetGlobalVector("_WeatherMakerSunDirectionDown", Sun.Transform.forward); Shader.SetGlobalVector("_WeatherMakerSunPositionNormalized", Sun.Transform.position.normalized); Shader.SetGlobalVector("_WeatherMakerSunPositionWorldSpace", Sun.Transform.position); Vector4 sunColor = new Vector4(Sun.Light.color.r, Sun.Light.color.g, Sun.Light.color.b, Sun.Light.intensity); Shader.SetGlobalVector("_WeatherMakerSunColor", sunColor); sunColor = new Vector4(Sun.TintColor.r, Sun.TintColor.g, Sun.TintColor.b, Sun.TintColor.a * Sun.TintIntensity * Sun.Light.intensity); Shader.SetGlobalVector("_WeatherMakerSunTintColor", sunColor); float sunHorizonScaleMultiplier = Mathf.Clamp(Mathf.Abs(Sun.Transform.forward.y) * 3.0f, 0.5f, 1.0f); sunHorizonScaleMultiplier = Mathf.Min(1.0f, Sun.Scale / sunHorizonScaleMultiplier); Shader.SetGlobalVector("_WeatherMakerSunLightPower", new Vector4(Sun.LightPower, Sun.LightMultiplier, Sun.Light.shadowStrength, 0.0f)); Shader.SetGlobalVector("_WeatherMakerSunVar1", new Vector4(sunHorizonScaleMultiplier, 0.0f, 0.0f, 0.0f)); if (Sun.Renderer != null) { if (Sun.RenderHintFast) { Sun.Renderer.sharedMaterial.EnableKeyword("RENDER_HINT_FAST"); } else { Sun.Renderer.sharedMaterial.DisableKeyword("RENDER_HINT_FAST"); } } // Moons Shader.SetGlobalInt("_WeatherMakerMoonCount", Moons.Length); for (int i = 0; i < Moons.Length; i++) { WeatherMakerCelestialObject moon = Moons[i]; moon.Renderer.sharedMaterial.SetFloat("_MoonIndex", i); moonDirectionUpShaderBuffer[i] = -moon.Transform.forward; moonDirectionDownShaderBuffer[i] = moon.Transform.forward; moonLightColorShaderBuffer[i] = (moon.LightIsOn ? new Vector4(moon.Light.color.r, moon.Light.color.g, moon.Light.color.b, moon.Light.intensity) : Vector4.zero); moonLightPowerShaderBuffer[i] = new Vector4(moon.LightPower, moon.LightMultiplier, moon.Light.shadowStrength, 0.0f); moonTintColorShaderBuffer[i] = new Vector4(moon.TintColor.r, moon.TintColor.g, moon.TintColor.b, moon.TintColor.a * moon.TintIntensity); moonVar1ShaderBuffer[i] = new Vector4(moon.Scale, 0.0f, 0.0f, 0.0f); } Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonDirectionUp, moonDirectionUpShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonDirectionDown, moonDirectionDownShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonLightColor, moonLightColorShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonLightPower, moonLightPowerShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonTintColor, moonTintColorShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonVar1, moonVar1ShaderBuffer); }
private void UpdateMoons() { float dot, yPower; while (MoonDatas.Count > WeatherScript.Moons.Length) { MoonDatas.RemoveAt(MoonDatas.Count - 1); } while (MoonDatas.Count < WeatherScript.Moons.Length) { MoonDatas.Add(new MoonInfo()); } for (int i = 0; i < WeatherScript.Moons.Length; i++) { WeatherMakerCelestialObject moon = WeatherScript.Moons[i]; CalculateMoonPosition(SunData, MoonDatas[i], moon.RotateYDegrees); Vector3 moonPos = MoonDatas[i].UnitVectorDown; moon.Transform.forward = moonPos; // intensity raises squared compare to moon fullness - this means less full is squared amount of less light // moon light intensity reduces as sun light intensity approaches 1 // reduce moon light as it drops below horizon dot = Mathf.Clamp(Vector3.Dot(moonPos, Vector3.down) + 0.1f, 0.0f, 1.0f); dot = Mathf.Pow(dot, 0.25f); yPower = Mathf.Pow(Mathf.Max(0.0f, MoonDatas[i].UnitVectorUp.y), 0.5f); moon.Light.intensity = yPower * (1.0f - Mathf.Min(1.0f, WeatherScript.Sun.Light.intensity)) * (float)MoonDatas[i].PercentFull * (float)MoonDatas[i].PercentFull * dot * moon.LightMultiplier; foreach (float multiplier in DirectionalLightIntensityMultipliers.Values) { moon.Light.intensity *= multiplier; } // set moon light shadow strength moon.Light.shadowStrength = 1.0f; foreach (float multiplier in DirectionalLightShadowIntensityMultipliers.Values) { moon.Light.shadowStrength *= multiplier; } // reduce shadow strength as moon gets near the horizon float moonYShadowReducer = Mathf.Pow(Mathf.Clamp(0.7f - moonPos.y, 0.0f, 1.0f), 0.5f); moon.Light.shadowStrength *= moonYShadowReducer; moon.Light.shadows = LightShadows.None; } }
private void ProcessCelestialObject(WeatherMakerCelestialObject obj, Dictionary <string, float> directionalLightIntensityModifiers, Dictionary <string, float> directionalLightShadowModifier) { if (obj.Light != null) { foreach (KeyValuePair <string, float> multiplier in directionalLightIntensityModifiers) { obj.Light.intensity *= multiplier.Value; } obj.Light.color = obj.LightColor; if (obj.Light.shadows != LightShadows.None) { foreach (KeyValuePair <string, float> multiplier in directionalLightShadowModifier) { obj.Light.shadowStrength *= multiplier.Value; } } } }
private void SetCelestialObjectPosition(WeatherMakerCelestialObject obj, Vector3 transformForward) { switch (obj.OrbitType) { case WeatherMakerOrbitType.Custom: IWeatherMakerCelestialObjectCustomOrbit orbitInterface = obj.OrbitTypeCustomScript as IWeatherMakerCelestialObjectCustomOrbit; if (orbitInterface == null) { Debug.LogErrorFormat("Unable to use custom orbit for celestial object {0}, field OrbitTypeCustomScript" + " must be set to a MonoBehavior script implementing IWeatherMakerCelestialObjectCustomOrbit", obj.Transform.gameObject.name); } else { transformForward = orbitInterface.CalculatePosition(obj); } break; } obj.Transform.forward = transformForward; }
/// <summary> /// Update /// </summary> /// <param name="camera">Camera</param> /// <param name="sun">Sun</param> /// <param name="moons">Moons</param> /// <param name="directionalLightIntensityModifiers">Directional light intensity modifiers</param> /// <param name="directionalLightShadowModifier">Directional light shadow modifiers</param> /// <param name="updateTimeOfDay">Whether to update the time of day</param> public void UpdateFromProfile ( Camera camera, WeatherMakerCelestialObject sun, IList <WeatherMakerCelestialObject> moons, Dictionary <string, float> directionalLightIntensityModifiers, Dictionary <string, float> directionalLightShadowModifier, bool updateTimeOfDay) { float l = WeatherMakerScript.GetSunGradientLookup(camera, sun.Transform); UpdateAmbientColors(camera, sun.Transform, l); accumulatedTime += Time.deltaTime; if (accumulatedTime > UpdateInterval) { UpdateTimeOfDay(updateTimeOfDay); UpdateSun(camera, sun, l); UpdateDayMultipliers(camera, sun, l); UpdateMoons(camera, sun, moons); accumulatedTime = 0.0f; } UpdateLightIntensitiesAndShadows(sun, moons, directionalLightIntensityModifiers, directionalLightShadowModifier); }
private void SetGlobalShaders() { if (Sun != null) { // Sun Vector3 sunForward = Sun.Transform.forward; Vector3 sunForward2D = Quaternion.AngleAxis(-90.0f, Vector3.right) * Sun.Transform.forward; Shader.SetGlobalVector("_WeatherMakerSunDirectionUp", -sunForward); Shader.SetGlobalVector("_WeatherMakerSunDirectionUp2D", -sunForward2D); Shader.SetGlobalVector("_WeatherMakerSunDirectionDown", Sun.Transform.forward); Shader.SetGlobalVector("_WeatherMakerSunDirectionDown2D", sunForward2D); Shader.SetGlobalVector("_WeatherMakerSunPositionNormalized", Sun.Transform.position.normalized); Shader.SetGlobalVector("_WeatherMakerSunPositionWorldSpace", Sun.Transform.position); Vector4 sunColor = new Vector4(Sun.Light.color.r, Sun.Light.color.g, Sun.Light.color.b, Sun.Light.intensity); Shader.SetGlobalVector("_WeatherMakerSunColor", sunColor); sunColor = new Vector4(Sun.TintColor.r, Sun.TintColor.g, Sun.TintColor.b, Sun.TintColor.a * Sun.TintIntensity * Sun.Light.intensity); Shader.SetGlobalVector("_WeatherMakerSunTintColor", sunColor); float sunHorizonScaleMultiplier = Mathf.Clamp(Mathf.Abs(Sun.Transform.forward.y) * 3.0f, 0.5f, 1.0f); sunHorizonScaleMultiplier = Mathf.Min(1.0f, Sun.Scale / sunHorizonScaleMultiplier); Shader.SetGlobalVector("_WeatherMakerSunLightPower", new Vector4(Sun.LightPower, Sun.LightMultiplier, Sun.Light.shadowStrength, 1.0f - Sun.Light.shadowStrength)); Shader.SetGlobalVector("_WeatherMakerSunVar1", new Vector4(sunHorizonScaleMultiplier, Mathf.Pow(Sun.Light.intensity, 0.5f), Mathf.Pow(Sun.Light.intensity, 0.75f), Sun.Light.intensity * Sun.Light.intensity)); if (Sun.Renderer != null) { if (Sun.RenderHintFast) { Sun.Renderer.sharedMaterial.EnableKeyword("RENDER_HINT_FAST"); } else { Sun.Renderer.sharedMaterial.DisableKeyword("RENDER_HINT_FAST"); } } } // Moons Shader.SetGlobalInt("_WeatherMakerMoonCount", Moons.Length); for (int i = 0; i < Moons.Length; i++) { WeatherMakerCelestialObject moon = Moons[i]; moon.Renderer.sharedMaterial.SetFloat("_MoonIndex", i); moonDirectionUpShaderBuffer[i] = -moon.Transform.forward; moonDirectionDownShaderBuffer[i] = moon.Transform.forward; moonLightColorShaderBuffer[i] = (moon.LightIsOn ? new Vector4(moon.Light.color.r, moon.Light.color.g, moon.Light.color.b, moon.Light.intensity) : Vector4.zero); moonLightPowerShaderBuffer[i] = new Vector4(moon.LightPower, moon.LightMultiplier, moon.Light.shadowStrength, 1.0f - moon.Light.shadowStrength); moonTintColorShaderBuffer[i] = new Vector4(moon.TintColor.r, moon.TintColor.g, moon.TintColor.b, moon.TintColor.a * moon.TintIntensity); moonVar1ShaderBuffer[i] = new Vector4(moon.Scale, 0.0f, 0.0f, 0.0f); } Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonDirectionUp, moonDirectionUpShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonDirectionDown, moonDirectionDownShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonLightColor, moonLightColorShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonLightPower, moonLightPowerShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonTintColor, moonTintColorShaderBuffer); Shader.SetGlobalVectorArray(WeatherMakerShaderIds.ArrayWeatherMakerMoonVar1, moonVar1ShaderBuffer); float t = Time.timeSinceLevelLoad; Shader.SetGlobalVector("_WeatherMakerTime", new Vector4(t * 0.05f, t, (float)System.Math.Truncate(t * 0.05f), (float)System.Math.Truncate(t))); Shader.SetGlobalVector("_WeatherMakerTimeSin", new Vector4(Mathf.Sin(t * 0.05f), Mathf.Sin(t), Mathf.Sin(t * 2.0f), Mathf.Sin(t * 3.0f))); }