SunLight
From Unify Community Wiki
SunLight
TODO: - A dynamic sky. - test the sun colors - improve code
Version change : i added a algorithm that changes the color of the sunlight. but i have the feeling this is not totaly correct.
Code
using UnityEngine; using System; using System.Collections; /////////////////////////////////////// /// Sunlight script. /// /// Version 0.2 by Martijn Dekker /// /// martijn.pixelstudio@gmail.com /// /////////////////////////////////////// public class sunlight: MonoBehaviour { public float DayOfTheYear = 250; public float latitude = 0f; public float longitude = 0f; public float domeRadius = 0f; public float updateTime = 5.0f; public float timeWarp = 180.0f; public float timeOfTheDay = 12.0f; private float stdMeridian = -45.0f; private Vector3 sunDirection = new Vector3(); private Vector3 sunPosition = new Vector3(); private float latitudeInRadian, solarDeclination, sunnyTime, phiSun, thetaSun; void Update () { setLatitude(); setDay(); maingui MG = (maingui)GameObject.Find("mainManager").GetComponent(typeof(maingui)); timeOfTheDay = MG.hourValue; DayOfTheYear = MG.dayOftheyear; setTimeOfDay(); solarDeclination = calculateSolarDiclination(DayOfTheYear); sunnyTime = calculateSunnyTime(latitude, solarDeclination); setSunPosition(timeOfTheDay); updateSunLightColor(timeOfTheDay); } void setSunPosition(float time) { float solarTime, solarAltitude, opp, adj, solarAzimuth, cosSolarDeclination, sinSolarDeclination, cosLatitude, sinLatitude; sinLatitude = Mathf.Sin(latitudeInRadian); cosLatitude = Mathf.Cos(latitudeInRadian); sinSolarDeclination = Mathf.Sin(solarDeclination); cosSolarDeclination = Mathf.Cos(solarDeclination); solarTime = time + (0.170f * Mathf.Sin(4f * Mathf.PI * (DayOfTheYear - 80f) / 373f) - 0.129f * Mathf.Sin(2 * Mathf.PI * (DayOfTheYear - 8f) / 355f)) + (stdMeridian - longitude) / 15; solarAltitude = Mathf.Asin(sinLatitude * sinSolarDeclination - cosLatitude * cosSolarDeclination * Mathf.Cos(Mathf.PI * solarTime / sunnyTime)); opp = -cosSolarDeclination * Mathf.Sin(Mathf.PI * solarTime / sunnyTime); adj = (cosLatitude * sinSolarDeclination + sinLatitude * cosSolarDeclination * Mathf.Cos(Mathf.PI * solarTime / sunnyTime)); solarAzimuth = Mathf.Atan2(opp, adj); if (solarAltitude > 0.0f) { if ((opp < 0.0f && solarAzimuth < 0.0f) || (opp > 0.0f && solarAzimuth > 0.0f)) { solarAzimuth = (0.5f * Mathf.PI ) + solarAzimuth; } else { solarAzimuth = (0.5f * Mathf.PI) - solarAzimuth; } phiSun = (Mathf.PI * 2.0f) - solarAzimuth; this.thetaSun = (0.5f * Mathf.PI ) - solarAltitude; sunDirection.x = domeRadius; sunDirection.y = phiSun; sunDirection.z = solarAltitude; Vector3 sunDirection2 = new Vector3(); sunDirection2 = calcDirection(); sunPosition = sphericalToCartesian(sunDirection); transform.localPosition = sunPosition; //position transform.LookAt(sunDirection2); // rotation } } Vector3 calcDirection() { Vector3 dir = new Vector3(); dir.x = Mathf.Cos(0.5f * Mathf.PI - thetaSun) * Mathf.Cos(phiSun); dir.y = Mathf.Sin(0.5f * Mathf.PI - thetaSun); dir.z = Mathf.Cos(0.5f * Mathf.PI - thetaSun) * Mathf.Sin(phiSun); return dir.normalized; } Vector3 sphericalToCartesian(Vector3 sunDir) { Vector3 res = new Vector3(); res.y = sunDirection.x * Mathf.Sin(sunDir.z); float tmp = sunDirection.x * Mathf.Cos(sunDir.z); res.x = tmp * Mathf.Cos(sunDir.y); res.z = tmp * Mathf.Sin(sunDir.y); return res; } void setLatitude() { latitude = Mathf.Clamp(latitude, -90.0f, 90.0f); latitudeInRadian = Mathf.Deg2Rad * latitude; } void setDay() { this.DayOfTheYear = Mathf.Clamp(DayOfTheYear, 0.0f, 365f); } void setTimeOfDay() { this.timeOfTheDay = Mathf.Clamp(timeOfTheDay, 8f, 23f); } float calculateSolarDiclination(float jDay) { return (0.4093f * Mathf.Sin(2 * Mathf.PI * (284f + jDay) / 365f)); } float calculateSunnyTime(float lat, float solarDeclin) { float st = (2.0f * Mathf.Acos(-Mathf.Tan(lat) * Mathf.Tan(solarDeclin))); return (st*Mathf.Rad2Deg)/15; } private void updateSunLightColor(float currentTime) { float[] dColor = new float[4]; dColor[0] = 0.9843f; dColor[1] = 0.5098f; dColor[2] = 0; dColor[3] = 1; // Create an array defines the new sunlight color. float[] newColor = new float[4]; // If the current time is between 6:00 and 12:00, change the color towards white. if (currentTime >= 6 && currentTime < 12) { for (int i = 0; i < newColor.Length; i++) { newColor[i] = dColor[i] + ((1 - dColor[i]) / 6) * (currentTime - 6); } } // Else if the current time is between 12:00 and 18:00, change the color towards dColor. else if (currentTime >= 12 && currentTime < 18) { for (int i = 0; i < newColor.Length; i++) { newColor[i] = 1 - ((1 - dColor[i]) / 6) * (currentTime - 12); } } // Else if the current time is between 18:00 and 24:00, change the color towards black. else if (currentTime >= 18 && currentTime < 24) { for (int i = 0; i < newColor.Length; i++) { newColor[i] = dColor[i] - (dColor[i] / 6) * (currentTime - 18); } } // Else if the current time is between 0:00 and 6:00, change the color towards dColor. else if (currentTime >= 0 && currentTime < 6) { for (int i = 0; i < newColor.Length; i++) { newColor[i] = (dColor[i] / 6) * (currentTime - 0); } } // RenderSettings.fogColor = new Color(newColor[0], newColor[1], newColor[2], newColor[3]); light.color = new Color(newColor[0], newColor[1], newColor[2], newColor[3]); } }