using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEngine.Rendering; namespace Pinwheel.Jupiter { [ExecuteInEditMode] public class JDayNightCycle : MonoBehaviour { [SerializeField] private JDayNightCycleProfile profile; public JDayNightCycleProfile Profile { get { return profile; } set { profile = value; } } [SerializeField] private JSky sky; public JSky Sky { get { return sky; } set { sky = value; } } [SerializeField] private bool useSunPivot; public bool UseSunPivot { get { return useSunPivot; } set { useSunPivot = value; } } [SerializeField] private Transform sunOrbitPivot; public Transform SunOrbitPivot { get { return sunOrbitPivot; } set { sunOrbitPivot = value; } } [SerializeField] private bool useMoonPivot; public bool UseMoonPivot { get { return useMoonPivot; } set { useMoonPivot = value; } } [SerializeField] private Transform moonOrbitPivot; public Transform MoonOrbitPivot { get { return moonOrbitPivot; } set { moonOrbitPivot = value; } } [SerializeField] private float startTime; public float StartTime { get { return startTime; } set { startTime = Mathf.Clamp(value, 0f, 24f); } } [SerializeField] private float timeIncrement; public float TimeIncrement { get { return timeIncrement; } set { timeIncrement = Mathf.Max(0, value); } } [SerializeField] private bool autoTimeIncrement; public bool AutoTimeIncrement { get { return autoTimeIncrement; } set { autoTimeIncrement = value; } } private float time; public float Time { get { return time % 24f; } set { time = value % 24f; } } [SerializeField] private bool shouldUpdateEnvironmentReflection; public bool ShouldUpdateEnvironmentReflection { get { return shouldUpdateEnvironmentReflection; } set { shouldUpdateEnvironmentReflection = value; } } [SerializeField] private int environmentReflectionResolution; public int EnvironmentReflectionResolution { get { return environmentReflectionResolution; } set { int oldValue = environmentReflectionResolution; int newValue = Mathf.Clamp(value, 16, 2048); environmentReflectionResolution = newValue; if (oldValue != newValue) { if (environmentReflection != null) { JUtilities.DestroyObject(environmentReflection); } if (environmentProbe != null) { JUtilities.DestroyGameobject(environmentProbe.gameObject); } } } } [SerializeField] private ReflectionProbeTimeSlicingMode environmentReflectionTimeSlicingMode; public ReflectionProbeTimeSlicingMode EnvironmentReflectionTimeSlicingMode { get { return environmentReflectionTimeSlicingMode; } set { environmentReflectionTimeSlicingMode = value; } } [SerializeField] private ReflectionProbe environmentProbe; private ReflectionProbe EnvironmentProbe { get { if (environmentProbe == null) { GameObject probeGO = new GameObject("~EnvironmentReflectionRenderer"); probeGO.transform.parent = transform; probeGO.transform.position = new Vector3(0, -1000, 0); probeGO.transform.rotation = Quaternion.identity; probeGO.transform.localScale = Vector3.one; environmentProbe = probeGO.AddComponent(); environmentProbe.resolution = EnvironmentReflectionResolution; environmentProbe.size = new Vector3(1, 1, 1); environmentProbe.cullingMask = 0; } environmentProbe.clearFlags = ReflectionProbeClearFlags.Skybox; environmentProbe.mode = ReflectionProbeMode.Realtime; environmentProbe.refreshMode = ReflectionProbeRefreshMode.ViaScripting; environmentProbe.timeSlicingMode = EnvironmentReflectionTimeSlicingMode; environmentProbe.hdr = false; return environmentProbe; } } private Cubemap environmentReflection; private Cubemap EnvironmentReflection { get { if (environmentReflection == null) { environmentReflection = new Cubemap(EnvironmentProbe.resolution, TextureFormat.RGBA32, true); } return environmentReflection; } } private int probeRenderId = -1; private float DeltaTime { get { if (Application.isPlaying) return UnityEngine.Time.deltaTime; else return 1.0f / 60f; } } private void Reset() { Sky = GetComponent(); StartTime = 0; TimeIncrement = 1; AutoTimeIncrement = true; Time = 0; } private void OnEnable() { time = StartTime; Camera.onPreCull += OnCameraPreCull; RenderPipelineManager.beginFrameRendering += OnBeginFrameRenderingSRP; } private void OnDisable() { Camera.onPreCull -= OnCameraPreCull; RenderPipelineManager.beginFrameRendering -= OnBeginFrameRenderingSRP; CleanUp(); } private void OnCameraPreCull(Camera cam) { if (!Application.isPlaying) Update(); } private void OnBeginFrameRenderingSRP(ScriptableRenderContext context, Camera[] cameras) { if (!Application.isPlaying) Update(); } private void CleanUp() { if (environmentProbe != null) { JUtilities.DestroyGameobject(environmentProbe.gameObject); } if (environmentReflection != null) { JUtilities.DestroyObject(environmentReflection); } if (Sky != null) { Sky.DNC = null; } } private void Update() { AnimateSky(); if (ShouldUpdateEnvironmentReflection) { UpdateEnvironmentReflection(); } else { RenderSettings.defaultReflectionMode = DefaultReflectionMode.Skybox; } } private void AnimateSky() { if (Profile == null) return; if (Sky == null) return; if (Sky.Profile == null) return; Sky.DNC = this; if (AutoTimeIncrement) { Time += TimeIncrement * DeltaTime; } float evalTime = Mathf.InverseLerp(0f, 24f, Time); Profile.Animate(Sky, evalTime); if (Sky.Profile.EnableSun && Sky.SunLightSource != null) { float angle = evalTime * 360f; Matrix4x4 localRotationMatrix = Matrix4x4.Rotate(Quaternion.Euler(angle, 0, 0)); Vector3 localDirection = localRotationMatrix.MultiplyVector(Vector3.up); Transform pivot = (UseSunPivot && SunOrbitPivot != null) ? SunOrbitPivot : transform; Matrix4x4 localToWorld = pivot.localToWorldMatrix; Vector3 worldDirection = localToWorld.MultiplyVector(localDirection); Sky.SunLightSource.transform.forward = worldDirection; Sky.SunLightSource.color = Sky.Profile.Material.GetColor(JMat.SUN_LIGHT_COLOR); Sky.SunLightSource.intensity = Sky.Profile.Material.GetFloat(JMat.SUN_LIGHT_INTENSITY); } if (Sky.Profile.EnableMoon && Sky.MoonLightSource != null) { float angle = evalTime * 360f; Matrix4x4 localRotationMatrix = Matrix4x4.Rotate(Quaternion.Euler(angle, 0, 0)); Vector3 localDirection = localRotationMatrix.MultiplyVector(Vector3.down); Transform pivot = (UseMoonPivot && MoonOrbitPivot != null) ? MoonOrbitPivot : transform; Matrix4x4 localToWorld = pivot.localToWorldMatrix; Vector3 worldDirection = localToWorld.MultiplyVector(localDirection); Sky.MoonLightSource.transform.forward = worldDirection; Sky.MoonLightSource.color = Sky.Profile.Material.GetColor(JMat.MOON_LIGHT_COLOR); Sky.MoonLightSource.intensity = Sky.Profile.Material.GetFloat(JMat.MOON_LIGHT_INTENSITY); } } private void UpdateEnvironmentReflection() { if ((SystemInfo.copyTextureSupport & CopyTextureSupport.RTToTexture) != 0) { if (EnvironmentProbe.texture == null) { probeRenderId = EnvironmentProbe.RenderProbe(); } else if (EnvironmentProbe.texture != null || EnvironmentProbe.IsFinishedRendering(probeRenderId)) { Graphics.CopyTexture(EnvironmentProbe.texture, EnvironmentReflection as Texture); RenderSettings.customReflection = EnvironmentReflection; RenderSettings.defaultReflectionMode = DefaultReflectionMode.Custom; probeRenderId = EnvironmentProbe.RenderProbe(); } } } } }