Exemplo n.º 1
0
            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
                };
            }
Exemplo n.º 2
0
        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);
        }