public void ProcessLighting(Camera camera) { if (DaydreamLight.s_resortLights) { DaydreamLight.s_resortLights = false; DaydreamLight.ResortLights(); } bool changed = true; if (DaydreamLight.s_masterLightArray != null && DaydreamLight.s_masterLightArray.Length > 0) { // update lights DaydreamLight.StartFrame(camera); DaydreamLight lightData = null; for (int i = 0, k = DaydreamLight.s_masterLightArray.Length; i < k; ++i) { if (i >= DaydreamLight.s_masterLightArray.Length) { break; } lightData = DaydreamLight.s_masterLightArray[i]; #if UNITY_EDITOR lightData.InEditorUpdate(); #endif lightData.CheckForChange(); lightData.UpdateFrame(); lightData.UpdateViewSpace(); } changed = DaydreamLight.AnyLightChanged() || m_lightCount != DaydreamLight.GetLightCount(); m_lightCount = DaydreamLight.GetLightCount(); } if (DaydreamMeshRenderer.m_objectList != null) { DaydreamMeshRenderer.StartFrame(); // process objects for (int i = 0, k = DaydreamMeshRenderer.m_objectList.Count; i < k; ++i) { DaydreamMeshRenderer dmr = DaydreamMeshRenderer.m_objectList[i]; if (!dmr.m_didInit) { dmr.DMRInit(); } #if UNITY_EDITOR dmr.InEditorUpdate(); #endif dmr.UpdateStaticState(); dmr.ApplyLighting(changed); } } }
// called during culling right before render public void ApplyLighting(bool lightChange) { #if UNITY_EDITOR bool enableUpdateWindow = Application.isPlaying; #else const bool enableUpdateWindow = true; #endif bool canUpdateLights = true; if (enableUpdateWindow) { ++m_freqKey; int updatesLeft = (s_count - ++s_countUpdated); if (s_updateWindow <= 0 || (updatesLeft >= s_updateWindow && (m_freqKey % s_updateFreq) != 0)) { canUpdateLights = false; } else { m_freqKey = 0; // decrements the size of the update window --s_updateWindow; } } m_daydreamLightArray = DaydreamLight.s_masterLightArray; // setup light uniforms bool rebuildLights = false; if (canUpdateLights) { rebuildLights = (m_key != m_upateKey || lightChange); if (rebuildLights || s_startup) { int usedSlots = 0; // rebuild the light array DaydreamLight.GetSortedLights(m_upateKey, gameObject.layer, m_static, transform.position, m_bounds, ref m_lightList, ref usedSlots); } } m_key = m_upateKey; bool noLights = true; // update data for (int i = 0; i < m_activeLightCount; ++i) { int lightIdx = m_lightList[i]; if (lightIdx != -1 && (!m_static || m_daydreamLightArray[lightIdx].m_curMode == LightModes.REALTIME)) { noLights = false; DaydreamLight dl = m_daydreamLightArray[lightIdx]; LightType type = dl.m_type; if (type == LightType.Directional) { dl.GetViewSpaceDir(ref m_positions[i]); } else { dl.GetViewSpacePos(ref m_positions[i]); } // view-space spot light directions, or (0,0,1,0) for non-spot if (type == LightType.Spot) { dl.GetViewSpaceDir(ref m_spotDir[i]); } else { m_spotDir[i].x = 0f; m_spotDir[i].y = 0f; m_spotDir[i].z = 1f; m_spotDir[i].w = 0f; } dl.GetColor(ref m_colors[i]); // from UnityShaderVariables.cginc // x = cos(spotAngle/2) or -1 for non-spot // y = 1/cos(spotAngle/4) or 1 for non-spot // z = quadratic attenuation // w = range*range if (type == LightType.Spot) { m_atten[i].x = dl.GetAttenX(); m_atten[i].y = dl.GetAttenY(); } else { m_atten[i].x = -1f; m_atten[i].y = 1f; } m_atten[i].z = dl.GetAttenZ(); m_atten[i].w = dl.GetAttenW(); } else { // reset state m_colors[i].x = 0f; m_colors[i].y = 0f; m_colors[i].z = 0f; m_colors[i].w = 0f; } } // re-instate the property block, we do this to not interfere needlessly with batching if (!noLights && m_propsBlock == null) { m_propsBlock = new MaterialPropertyBlock(); } if (m_propsBlock != null && m_activeLightCount > 0) { m_propsBlock.SetVectorArray(s_lightAttenId, m_atten); m_propsBlock.SetVectorArray(s_lightColorId, m_colors); m_propsBlock.SetVectorArray(s_lightPositionId, m_positions); m_propsBlock.SetVectorArray(s_spotDirectionId, m_spotDir); } m_renderer.SetPropertyBlock(m_propsBlock); // we clear the property block when there are not lights in order to not interfere with batching if (noLights) { m_propsBlock = null; } }
public static void GetSortedLights(int updateKey, int layer, bool isStatic, Vector3 objPosition, Bounds bounds, ref int[] outLightList, ref int usedSlots) { ClearList(ref outLightList); float dist2 = 0f; DaydreamLight dl = null; usedSlots = 0; // number of directional lights int dirCount = 0; // insert sort lights - Note: directional lights are always sorted to the top of the master list // this allows for some assumptions for (int i = 0, k = s_masterLightArray.Length; i < k; ++i) { // i'th light data dl = s_masterLightArray[i]; int ithLight = i; if ((dl.m_cullingMask & (1 << layer)) == 0 || (isStatic && dl.m_curMode != LightModes.REALTIME)) { continue; } if (dl.m_type != LightType.Directional) { // from cam to light objPosition = bounds.center; // only update if needed float range2 = dl.m_lastRange * dl.m_lastRange; float x = (dl.m_worlPos.x - objPosition.x) * (dl.m_worlPos.x - objPosition.x); float y = (dl.m_worlPos.y - objPosition.y) * (dl.m_worlPos.y - objPosition.y); float z = (dl.m_worlPos.z - objPosition.z) * (dl.m_worlPos.z - objPosition.z); dl.m_dist = (x + y + z) - range2; dist2 = dl.m_dist; for (int j = dirCount; j < outLightList.Length; ++j) { if (outLightList[j] == -1) { // insert the i'th light outLightList[j] = ithLight; usedSlots++; break; } // if the i'th light is closer than the j'th light else if (dist2 < s_masterLightArray[outLightList[j]].m_dist) { // butterfly swap ithLight ^= outLightList[j]; outLightList[j] ^= ithLight; ithLight ^= outLightList[j]; // update distance to the i'th light dist2 = s_masterLightArray[ithLight].m_dist; } } } else { dirCount = i; outLightList[i] = ithLight; usedSlots++; } } }
public void ProcessLighting(Camera camera) { if (DaydreamLight.s_resortLights) { DaydreamLight.s_resortLights = false; DaydreamLight.ResortLights(); } #if UNITY_EDITOR for (int i = 0, k = s_inEditorUpdateList.Count; i < k; ++i) { s_inEditorUpdateList[i].InEditorUpdate(); } #endif bool changed = true; if (DaydreamLight.s_masterLightArray != null && DaydreamLight.s_masterLightArray.Length > 0) { // update lights DaydreamLight.StartFrame(camera); DaydreamLight lightData = null; for (int i = 0, k = DaydreamLight.s_masterLightArray.Length; i < k; ++i) { if (i >= DaydreamLight.s_masterLightArray.Length) { break; } lightData = DaydreamLight.s_masterLightArray[i]; // these should update once per frame regardless of camera count if (m_frameStarted) { #if UNITY_EDITOR lightData.InEditorUpdate(); #endif lightData.CheckForChange(); lightData.UpdateFrame(); } // this updates each frame for each camera lightData.UpdateViewSpace(); } // first time through this should get set back to false so other cameras // don't update light values that only need to be udpate once per frame m_frameStarted = false; changed = DaydreamLight.AnyLightChanged() || m_lightCount != DaydreamLight.GetLightCount(); m_lightCount = DaydreamLight.GetLightCount(); } if (s_objectList != null) { DaydreamMeshRenderer.StartFrame(); // process objects for (int i = 0, k = s_objectList.Count; i < k; ++i) { DaydreamMeshRenderer dmr = s_objectList[i]; if (!dmr.m_didInit) { dmr.DMRInit(); } #if UNITY_EDITOR if (!dmr.InEditorUpdate()) { continue; } #endif dmr.UpdateStaticState(); dmr.ApplyLighting(changed); } } }
static void DrawGizmos(DaydreamLight source, GizmoType gizmoType) { if (source == null || !source.enabled) { return; } Vector4 pos = source.transform.position; pos.w = 1f; m_annotationUtilType = typeof(Editor).Assembly.GetTypes().Where(t => t.Name == "AnnotationUtility").FirstOrDefault(); if (m_annotationUtilType == null) { Debug.LogWarning("The internal type 'AnnotationUtility' could not be found. Maybe something changed inside Unity"); return; } m_iconSizeProp = m_annotationUtilType.GetProperty("iconSize", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic); if (m_iconSizeProp == null) { Debug.LogWarning("The internal class 'AnnotationUtility' doesn't have a property called 'iconSize'"); } Vector3 toCam = Camera.current.transform.position - source.transform.position; float z = Vector3.Dot(Camera.current.transform.forward, toCam); // create rotation towards the camera Matrix4x4 rot = Matrix4x4.LookAt(pos, source.transform.position + Camera.current.transform.forward * z, Camera.current.transform.up); Matrix4x4 world = new Matrix4x4(); float scale = m_iconSizeProp == null ? 1f : (float)m_iconSizeProp.GetValue(null, null); Vector3 screen = new Vector3(Screen.width, Screen.height); Vector3 tr = Camera.current.ScreenToViewportPoint(screen) * 0.5f; Vector3 bl = Camera.current.ScreenToViewportPoint(-screen) * 0.5f; Rect r = new Rect(bl.x, bl.y, tr.x - bl.x, tr.y - bl.y); float multiplier = 1; if (Camera.current.orthographic) { multiplier = (r.height * 0.5f) / (Camera.current.orthographicSize); } else { multiplier = (r.height * 0.5f) / Mathf.Tan(Mathf.Deg2Rad * (Camera.current.fieldOfView * 0.5f)); } scale *= multiplier * 20f; world.m00 = scale; world.m11 = scale; world.m22 = scale; world *= rot; world.SetColumn(3, pos); Material m = IconMaterial; m.SetMatrix("_world", world); m.color = source.m_light.color; m.mainTexture = Styles.daydreamLight; Gizmos.DrawGUITexture(new Rect(-1f, -1f, 2f, 2f), Styles.daydreamLight, m); }