public void Execute(Entity entity, int index, [ReadOnly] ref Translation translation) { if (FrustumPlanes.Intersect(CullingPlanes, translation.Value, 20) == FrustumPlanes.IntersectResult.Out) { return; } var d = math.lengthsq(CameraPos - translation.Value); int j = ClosestLights.Length - 1; if (d >= ClosestLights[j].DistanceSq) { return; } while (j > 0 && d < ClosestLights[j - 1].DistanceSq) { ClosestLights[j] = ClosestLights[j - 1]; j -= 1; } ClosestLights[j] = new EntityDist { DistanceSq = d, ProxyEntity = entity }; }
protected override JobHandle OnUpdate(JobHandle handle) { if (Camera.main == null || !AdditiveScene.isLoaded) { return(handle); } #region Setup new lights ProfileUpdateA.Begin(); using (var chunks = m_NewSharedLights.CreateArchetypeChunkArray(Allocator.TempJob)) { if (chunks.Length > 0) { var lightProxyArchetype = EntityManager.CreateArchetype ( ComponentType.ReadWrite <LightPoolIndex>(), ComponentType.ReadWrite <Translation>(), ComponentType.ReadWrite <Rotation>() ); var lightProxies = new NativeArray <Entity>(m_NewSharedLights.CalculateLength(), Allocator.Temp); EntityManager.CreateEntity(lightProxyArchetype, lightProxies); int entityIndex = 0; var archetypeSharedLightType = GetArchetypeChunkSharedComponentType <SharedLight>(); var archetypeLightEntityType = GetArchetypeChunkEntityType(); var archetypeLocalToWorldType = GetArchetypeChunkComponentType <LocalToWorld>(true); foreach (var chunk in chunks) { var sharedLight = chunk.GetSharedComponentData(archetypeSharedLightType, EntityManager); var lightEntity = chunk.GetNativeArray(archetypeLightEntityType); var poolIndex = EnsurePool(sharedLight.Value); var localToWorldArray = chunk.GetNativeArray(archetypeLocalToWorldType); for (int i = 0; i < chunk.Count; ++i) { var position = localToWorldArray[i].Position; var rotation = new quaternion(localToWorldArray[i].Value); var proxy = lightProxies[entityIndex]; EntityManager.SetComponentData(proxy, new LightPoolIndex { SourceEntity = lightEntity[i], PrefabIndex = poolIndex, InstanceIndex = -1 }); EntityManager.SetComponentData(proxy, new Translation { Value = position }); EntityManager.SetComponentData(proxy, new Rotation() { Value = rotation }); entityIndex += 1; } } EntityManager.AddComponent(m_NewSharedLights, ComponentType.ReadOnly <LightPoolCreatedTag>()); } } ProfileUpdateA.End(); #endregion #region Find closest lights ProfileUpdateB.Begin(); { GeometryUtility.CalculateFrustumPlanes(Camera.main, ManagedCullingPlanes); CullingPlanes[0] = new float4(ManagedCullingPlanes[0].normal.x, ManagedCullingPlanes[0].normal.y, ManagedCullingPlanes[0].normal.z, ManagedCullingPlanes[0].distance); CullingPlanes[1] = new float4(ManagedCullingPlanes[1].normal.x, ManagedCullingPlanes[1].normal.y, ManagedCullingPlanes[1].normal.z, ManagedCullingPlanes[1].distance); CullingPlanes[2] = new float4(ManagedCullingPlanes[2].normal.x, ManagedCullingPlanes[2].normal.y, ManagedCullingPlanes[2].normal.z, ManagedCullingPlanes[2].distance); CullingPlanes[3] = new float4(ManagedCullingPlanes[3].normal.x, ManagedCullingPlanes[3].normal.y, ManagedCullingPlanes[3].normal.z, ManagedCullingPlanes[3].distance); CullingPlanes[4] = new float4(ManagedCullingPlanes[4].normal.x, ManagedCullingPlanes[4].normal.y, ManagedCullingPlanes[4].normal.z, ManagedCullingPlanes[4].distance); CullingPlanes[5] = new float4(ManagedCullingPlanes[5].normal.x, ManagedCullingPlanes[5].normal.y, ManagedCullingPlanes[5].normal.z, ManagedCullingPlanes[5].distance); } for (int i = 0; i < ClosestLights.Length; ++i) { ClosestLights[i] = new EntityDist { DistanceSq = float.MaxValue }; } new FindClosestLightsJob { ClosestLights = ClosestLights, CameraPos = Camera.main.transform.position, CullingPlanes = CullingPlanes }.ScheduleGroupSingle(m_ActiveLightProxies).Complete(); ProfileUpdateB.End(); #endregion #region Assign instances ProfileUpdateC.Begin(); for (int i = 0; i < AssignedLights.Length; ++i) { AssignedLights[i].Active = false; } var lightPoolIndexFromEntity = GetComponentDataFromEntity <LightPoolIndex>(); { var translationFromEntity = GetComponentDataFromEntity <Translation>(true); var rotationFromEntity = GetComponentDataFromEntity <Rotation>(true); var searchForAvailableAt = 0; for (int i = 0; i < ClosestLights.Length; ++i) { if (!EntityManager.Exists(ClosestLights[i].ProxyEntity)) { break; } var indices = lightPoolIndexFromEntity[ClosestLights[i].ProxyEntity]; if (!EntityManager.Exists(indices.SourceEntity)) { continue; } if (indices.InstanceIndex >= 0) { AssignedLights[indices.InstanceIndex].Active = true; continue; } while (true) { if (searchForAvailableAt == AssignedLights.Length) { break; } if (AssignedLights[searchForAvailableAt].Instance == null) { var entity = ClosestLights[i].ProxyEntity; var idx = searchForAvailableAt; indices.InstanceIndex = idx; lightPoolIndexFromEntity[entity] = indices; var instance = LightPool.AvailableStacks[indices.PrefabIndex].Pop(); AssignedLights[idx].Instance = instance; AssignedLights[idx].Active = true; AssignedLights[idx].ProxyEntity = entity; var translation = translationFromEntity[entity].Value; var rotation = rotationFromEntity[entity].Value; instance.SetActive(true); instance.transform.position = translation; instance.transform.rotation = rotation; AssignedLights[searchForAvailableAt].Components = instance.GetComponentsInChildren <Light>(); break; } searchForAvailableAt += 1; } } } ProfileUpdateC.End(); #endregion #region Update light intensity ProfileUpdateD.Begin(); var commandBuffer = m_CommandBufferSystem.CreateCommandBuffer(); float dimDeltaAbs = FadeDurationInSeconds > 0f ? Time.deltaTime / FadeDurationInSeconds : 1f; for (int i = 0; i < AssignedLights.Length; ++i) { if (AssignedLights[i].Instance == null) { continue; } var dimDelta = math.select(-dimDeltaAbs, +dimDeltaAbs, AssignedLights[i].Active); var newDim = math.saturate(AssignedLights[i].Dimmer + dimDelta); if (AssignedLights[i].Dimmer != newDim) { foreach (var light in AssignedLights[i].Components) { HDAdditionalLightData ald = light.GetComponent <HDAdditionalLightData>(); ald.lightDimmer = AssignedLights[i].Dimmer; } AssignedLights[i].Dimmer = newDim; } if (AssignedLights[i].Dimmer == 0f) { var indices = lightPoolIndexFromEntity[AssignedLights[i].ProxyEntity]; indices.InstanceIndex = -1; lightPoolIndexFromEntity[AssignedLights[i].ProxyEntity] = indices; if (!EntityManager.Exists(indices.SourceEntity)) { commandBuffer.DestroyEntity(AssignedLights[i].ProxyEntity); } LightPool.AvailableStacks[indices.PrefabIndex].Push(AssignedLights[i].Instance); AssignedLights[i].Instance.SetActive(false); AssignedLights[i].Instance = null; AssignedLights[i].ProxyEntity = Entity.Null; } } ProfileUpdateD.End(); #endregion return(handle); }