Exemplo n.º 1
0
        private LightComponentCollectionGroup GetLightGroup(RenderViewLightData renderViewData, LightComponent light)
        {
            LightComponentCollectionGroup lightGroup;

            var directLight = light.Type as IDirectLight;
            var lightGroups = renderViewData.ActiveLightGroups;

            var type = light.Type.GetType();
            if (!lightGroups.TryGetValue(type, out lightGroup))
            {
                lightGroup = new LightComponentCollectionGroup(type);
                lightGroups.Add(type, lightGroup);
            }
            return lightGroup;
        }
Exemplo n.º 2
0
        /// <summary>
        /// Collects the visible lights by intersecting them with the frustum.
        /// </summary>
        private void CollectVisibleLights()
        {
            foreach (var renderView in RenderSystem.Views)
            {
                if (renderView.GetType() != typeof(RenderView))
                    continue;

                lightProcessor = renderView.SceneInstance.GetProcessor<LightProcessor>();

                // No light processors means no light in the scene, so we can early exit
                if (lightProcessor == null)
                    continue;

                RenderViewLightData renderViewLightData;
                if (!renderViewDatas.TryGetValue(renderView, out renderViewLightData))
                {
                    renderViewLightData = new RenderViewLightData();
                    renderViewDatas.Add(renderView, renderViewLightData);
                }
                else
                {
                    // 1) Clear the cache of current lights (without destroying collections but keeping previously allocated ones)
                    ClearCache(renderViewLightData.ActiveLightGroups);
                }

                renderViewLightData.VisibleLights.Clear();
                renderViewLightData.VisibleLightsWithShadows.Clear();

                // TODO GRAPHICS REFACTOR
                var sceneCullingMask = renderView.CullingMask;

                // 2) Cull lights with the frustum
                var frustum = renderView.Frustum;
                foreach (var light in lightProcessor.Lights)
                {
                    // If light is not part of the culling mask group, we can skip it
                    var entityLightMask = (EntityGroupMask)(1 << (int)light.Entity.Group);
                    if ((entityLightMask & sceneCullingMask) == 0 && (light.CullingMask & sceneCullingMask) == 0)
                    {
                        continue;
                    }

                    // If light is not in the frustum, we can skip it
                    var directLight = light.Type as IDirectLight;
                    if (directLight != null && directLight.HasBoundingBox && !frustum.Contains(ref light.BoundingBoxExt))
                    {
                        continue;
                    }

                    // Find the group for this light
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.PrepareLight(light);

                    // This is a visible light
                    renderViewLightData.VisibleLights.Add(light);

                    // Add light to a special list if it has shadows
                    if (directLight != null && directLight.Shadow.Enabled && ShadowMapRenderer != null)
                    {
                        // A visible light with shadows
                        renderViewLightData.VisibleLightsWithShadows.Add(light);
                    }
                }

                // 3) Allocate collection based on their culling mask
                AllocateCollectionsPerGroupOfCullingMask(renderViewLightData.ActiveLightGroups);

                // 4) Collect lights to the correct light collection group
                foreach (var light in renderViewLightData.VisibleLights)
                {
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.AddLight(light);
                }
            }
        }
Exemplo n.º 3
0
        private static void PrepareLightGroups(RenderDrawContext context, FastList<RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, ShadowMapRenderer shadowMapRenderer, EntityGroup group)
        {
            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightRenderer = activeRenderer.LightRenderer;
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                {
                    Context = context,
                    ViewIndex = renderViewData.ViewIndex,
                    View = renderView,
                    Views = renderViews,
                    LightCollection = lightCollection,
                    LightType = activeRenderer.LightGroup.LightType,
                    LightStart = 0,
                    LightEnd = lightCollection.Count,
                    ShadowMapRenderer = shadowMapRenderer,
                    ShadowMapTexturesPerLight = renderViewData.LightComponentsWithShadows,
                };

                lightRenderer.ProcessLights(processLightsParameters);
            }
        }
Exemplo n.º 4
0
        private void PrepareLightGroups(RenderDrawContext context, FastList <RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, IShadowMapRenderer shadowMapRenderer, RenderGroup group)
        {
            var viewIndex = renderViews.IndexOf(renderView);

            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                // Light collections aren't cleared (see ClearCache). Can be null after switching to empty scenes.
                if (lightCollection is null)
                {
                    continue;
                }

                // Indices of lights in lightCollection that need processing
                lightIndicesToProcess.Clear();
                for (int i = 0; i < lightCollection.Count; i++)
                {
                    lightIndicesToProcess.Add(i);
                }

                // Loop over all the renderers in order
                int rendererIndex = 0;
                foreach (var renderer in activeRenderer.Renderers)
                {
                    var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                    {
                        Context                   = context,
                        ViewIndex                 = viewIndex,
                        View                      = renderView,
                        Views                     = renderViews,
                        Renderers                 = activeRenderer.Renderers,
                        RendererIndex             = rendererIndex++,
                        LightCollection           = lightCollection,
                        LightIndices              = lightIndicesToProcess,
                        LightType                 = activeRenderer.LightGroup.LightType,
                        ShadowMapRenderer         = shadowMapRenderer,
                        ShadowMapTexturesPerLight = renderViewData.RenderLightsWithShadows,
                    };
                    renderer.ProcessLights(processLightsParameters);
                }
            }
        }
Exemplo n.º 5
0
        /// <summary>
        /// Collects the visible lights by intersecting them with the frustum.
        /// </summary>
        private void CollectVisibleLights()
        {
            foreach (var renderView in RenderSystem.Views)
            {
                if (renderView.GetType() != typeof(RenderView))
                {
                    continue;
                }

                var lightRenderView = renderView.LightingView ?? renderView;

                // Check if already processed
                if (!processedRenderViews.Add(lightRenderView))
                {
                    continue;
                }

                RenderViewLightData renderViewLightData;
                if (!renderViewDatas.TryGetValue(lightRenderView, out renderViewLightData))
                {
                    renderViewLightData = new RenderViewLightData();
                    renderViewDatas.Add(lightRenderView, renderViewLightData);
                }
                else
                {
                    // 1) Clear the cache of current lights (without destroying collections but keeping previously allocated ones)
                    ClearCache(renderViewLightData.ActiveLightGroups);
                }

                renderViewLightData.VisibleLights.Clear();
                renderViewLightData.VisibleLightsWithShadows.Clear();

                var lights = Context.VisibilityGroup.Tags.Get(CurrentLights);

                // No light processors means no light in the scene, so we can early exit
                if (lights == null)
                {
                    continue;
                }

                // TODO GRAPHICS REFACTOR
                var sceneCullingMask = lightRenderView.CullingMask;

                // 2) Cull lights with the frustum
                var frustum = lightRenderView.Frustum;
                foreach (var light in lights)
                {
                    // TODO: New mechanism for light selection (probably in ForwardLighting configuration)
                    //       Light should probably have their own LightGroup (separate from RenderGroup)
                    // If light is not part of the culling mask group, we can skip it
                    //var entityLightMask = (RenderGroupMask)(1 << (int)light.Entity.Group);
                    //if ((entityLightMask & sceneCullingMask) == 0 && (light.CullingMask & sceneCullingMask) == 0)
                    //{
                    //    continue;
                    //}

                    // If light is not in the frustum, we can skip it
                    var directLight = light.Type as IDirectLight;
                    if (directLight != null && directLight.HasBoundingBox && !frustum.Contains(ref light.BoundingBoxExt))
                    {
                        continue;
                    }

                    // Find the group for this light
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.PrepareLight(light);

                    // This is a visible light
                    renderViewLightData.VisibleLights.Add(light);

                    // Add light to a special list if it has shadows
                    if (directLight != null && directLight.Shadow.Enabled && ShadowMapRenderer != null)
                    {
                        // A visible light with shadows
                        renderViewLightData.VisibleLightsWithShadows.Add(light);
                    }
                }

                // 3) Allocate collection based on their culling mask
                AllocateCollectionsPerGroupOfCullingMask(renderViewLightData.ActiveLightGroups);

                // 4) Collect lights to the correct light collection group
                foreach (var light in renderViewLightData.VisibleLights)
                {
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.AddLight(light);
                }
            }

            processedRenderViews.Clear();
        }
Exemplo n.º 6
0
        private LightParametersPermutationEntry PrepareRenderMeshForRendering(RenderViewLightData renderViewData, RenderMesh renderMesh, RenderEffect renderEffect, int effectSlot)
        {
            var shaderKeyIdBuilder     = new ObjectIdSimpleBuilder();
            var parametersKeyIdBuilder = new ObjectIdSimpleBuilder();

            var renderModel    = renderMesh.RenderModel;
            var modelComponent = renderModel.ModelComponent;
            var group          = modelComponent.Entity.Group;
            var boundingBox    = modelComponent.BoundingBox;

            directLightsPerMesh.Clear();
            directLightShaderGroupEntryKeys.Clear();

            environmentLightsPerMesh.Clear();
            environmentLightShaderGroupEntryKeys.Clear();

            // Create different parameter collections depending on shadows
            // TODO GRAPHICS REFACTOR can we use the same parameter collection for shadowed/non-shadowed?
            var isShadowReceiver = renderMesh.IsShadowReceiver && modelComponent.IsShadowReceiver;

            parametersKeyIdBuilder.Write(isShadowReceiver ? 1U : 0U);
            shaderKeyIdBuilder.Write(isShadowReceiver ? 1U : 0U);
            shaderKeyIdBuilder.Write((uint)effectSlot);

            // This loop is looking for visible lights per render model and calculate a ShaderId and ParametersId
            // TODO: Part of this loop could be processed outisde of the PrepareRenderMeshForRendering
            // For example: Environment lights or directional lights are always active, so we could pregenerate part of the
            // id and groups outside this loop. Also considering that each light renderer has a maximum of lights
            // we could pre
            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                var lightRenderer   = activeRenderer.LightRenderer;
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                var lightCount                = lightCollection == null ? 0 : lightCollection.Count;
                int lightMaxCount             = Math.Min(lightCount, lightRenderer.LightMaxCount);
                var lightRendererId           = lightRenderer.LightRendererId;
                var allocCountForNewLightType = lightRenderer.AllocateLightMaxCount ? (byte)lightRenderer.LightMaxCount : (byte)1;

                var currentShaderKey = new LightForwardShaderEntryKey();

                // Path for environment lights
                if (lightRenderer.IsEnvironmentLight)
                {
                    // The loop is simpler for environment lights (single group per light, no shadow maps, no bounding box...etc)
                    for (int i = 0; i < lightMaxCount; i++)
                    {
                        var light = lightCollection[i];
                        currentShaderKey = new LightForwardShaderEntryKey(lightRendererId, 0, allocCountForNewLightType);
                        unsafe
                        {
                            shaderKeyIdBuilder.Write(*(uint *)&currentShaderKey);
                        }
                        parametersKeyIdBuilder.Write(light.Id);

                        environmentLightsPerMesh.Add(new LightEntry(environmentLightShaderGroupEntryKeys.Count, light, null));
                        environmentLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, null));
                    }
                }
                else
                {
                    ILightShadowMapRenderer currentShadowRenderer = null;

                    for (int i = 0; i < lightMaxCount; i++)
                    {
                        var light       = lightCollection[i];
                        var directLight = (IDirectLight)light.Type;
                        // If the light does not intersects the model, we can skip it
                        if (directLight.HasBoundingBox && !light.BoundingBox.Intersects(ref boundingBox))
                        {
                            continue;
                        }

                        LightShadowMapTexture   shadowTexture     = null;
                        LightShadowType         shadowType        = 0;
                        ILightShadowMapRenderer newShadowRenderer = null;

                        if (ShadowMapRenderer != null && renderViewData.LightComponentsWithShadows.TryGetValue(light, out shadowTexture))
                        {
                            shadowType        = shadowTexture.ShadowType;
                            newShadowRenderer = (ILightShadowMapRenderer)shadowTexture.Renderer;
                        }

                        if (i == 0)
                        {
                            currentShaderKey      = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType);
                            currentShadowRenderer = newShadowRenderer;
                        }
                        else
                        {
                            if (currentShaderKey.LightRendererId == lightRendererId && currentShaderKey.ShadowType == shadowType)
                            {
                                if (!lightRenderer.AllocateLightMaxCount)
                                {
                                    currentShaderKey.LightCount++;
                                }
                            }
                            else
                            {
                                unsafe
                                {
                                    shaderKeyIdBuilder.Write(*(uint *)&currentShaderKey);
                                }

                                directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, isShadowReceiver ? currentShadowRenderer : null));
                                currentShaderKey      = new LightForwardShaderEntryKey(lightRendererId, shadowType, allocCountForNewLightType);
                                currentShadowRenderer = newShadowRenderer;
                            }
                        }

                        parametersKeyIdBuilder.Write(light.Id);
                        directLightsPerMesh.Add(new LightEntry(directLightShaderGroupEntryKeys.Count, light, shadowTexture));
                    }

                    if (directLightsPerMesh.Count > 0)
                    {
                        unsafe
                        {
                            shaderKeyIdBuilder.Write(*(uint *)&currentShaderKey);
                        }
                        directLightShaderGroupEntryKeys.Add(new LightForwardShaderFullEntryKey(currentShaderKey, lightRenderer, isShadowReceiver ? currentShadowRenderer : null));
                    }
                }
            }

            // Find or create an existing shaders/parameters permutation

            // Build the keys for Shaders and Parameters permutations
            ObjectId shaderKeyId;
            ObjectId parametersKeyId;

            shaderKeyIdBuilder.ComputeHash(out shaderKeyId);
            parametersKeyIdBuilder.ComputeHash(out parametersKeyId);

            // Calculate the shader parameters just once
            // If we don't have already this permutation, use it
            LightShaderPermutationEntry newLightShaderPermutationEntry;

            if (!shaderEntries.TryGetValue(shaderKeyId, out newLightShaderPermutationEntry))
            {
                newLightShaderPermutationEntry = CreateShaderPermutationEntry(renderEffect);
                shaderEntries.Add(shaderKeyId, newLightShaderPermutationEntry);
            }

            // Calculate the shader parameters just once per light combination and for this rendering pass
            LightParametersPermutationEntry newShaderEntryParameters;

            if (!lightParameterEntries.TryGetValue(parametersKeyId, out newShaderEntryParameters))
            {
                newShaderEntryParameters = CreateParametersPermutationEntry(newLightShaderPermutationEntry);
                lightParameterEntries.Add(parametersKeyId, newShaderEntryParameters);
            }

            newShaderEntryParameters.ApplyEffectPermutations(renderEffect);

            return(newShaderEntryParameters);
        }
Exemplo n.º 7
0
        /// <summary>
        /// Collects the visible lights by intersecting them with the frustum.
        /// </summary>
        private void CollectVisibleLights()
        {
            foreach (var renderView in RenderSystem.Views)
            {
                if (renderView.GetType() != typeof(RenderView))
                {
                    continue;
                }

                if (renderView.Camera == null)
                {
                    continue;
                }

                lightProcessor = renderView.SceneInstance.GetProcessor <LightProcessor>();

                // No light processors means no light in the scene, so we can early exit
                if (lightProcessor == null)
                {
                    continue;
                }

                RenderViewLightData renderViewLightData;
                if (!renderViewDatas.TryGetValue(renderView, out renderViewLightData))
                {
                    renderViewLightData = new RenderViewLightData();
                    renderViewDatas.Add(renderView, renderViewLightData);
                }
                else
                {
                    // 1) Clear the cache of current lights (without destroying collections but keeping previously allocated ones)
                    ClearCache(renderViewLightData.ActiveLightGroups);
                    ClearCache(renderViewLightData.ActiveLightGroupsWithShadows);
                }

                renderViewLightData.VisibleLights.Clear();
                renderViewLightData.VisibleLightsWithShadows.Clear();

                // TODO GRAPHICS REFACTOR
                var sceneCullingMask = renderView.SceneCameraRenderer.CullingMask;

                // 2) Cull lights with the frustum
                var frustum = renderView.Camera.Frustum;
                foreach (var light in lightProcessor.Lights)
                {
                    // If light is not part of the culling mask group, we can skip it
                    var entityLightMask = (EntityGroupMask)(1 << (int)light.Entity.Group);
                    if ((entityLightMask & sceneCullingMask) == 0 && (light.CullingMask & sceneCullingMask) == 0)
                    {
                        continue;
                    }

                    // If light is not in the frustum, we can skip it
                    var directLight = light.Type as IDirectLight;
                    if (directLight != null && directLight.HasBoundingBox && !frustum.Contains(ref light.BoundingBoxExt))
                    {
                        continue;
                    }

                    // Find the group for this light
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.PrepareLight(light);

                    // This is a visible light
                    renderViewLightData.VisibleLights.Add(light);

                    // Add light to a special list if it has shadows
                    if (directLight != null && directLight.Shadow.Enabled && ShadowMapRenderer != null)
                    {
                        // A visible light with shadows
                        renderViewLightData.VisibleLightsWithShadows.Add(light);
                    }
                }

                // 3) Allocate collection based on their culling mask
                AllocateCollectionsPerGroupOfCullingMask(renderViewLightData.ActiveLightGroups);
                AllocateCollectionsPerGroupOfCullingMask(renderViewLightData.ActiveLightGroupsWithShadows);

                // 4) Collect lights to the correct light collection group
                foreach (var light in renderViewLightData.VisibleLights)
                {
                    var lightGroup = GetLightGroup(renderViewLightData, light);
                    lightGroup.AddLight(light);
                }
            }
        }
Exemplo n.º 8
0
        private static void PrepareLightGroups(RenderDrawContext context, FastList <RenderView> renderViews, RenderView renderView, RenderViewLightData renderViewData, ShadowMapRenderer shadowMapRenderer, EntityGroup group)
        {
            foreach (var activeRenderer in renderViewData.ActiveRenderers)
            {
                // Find lights
                var lightRenderer   = activeRenderer.LightRenderer;
                var lightCollection = activeRenderer.LightGroup.FindLightCollectionByGroup(group);

                var processLightsParameters = new LightGroupRendererBase.ProcessLightsParameters
                {
                    Context                   = context,
                    ViewIndex                 = renderViewData.ViewIndex,
                    View                      = renderView,
                    Views                     = renderViews,
                    LightCollection           = lightCollection,
                    LightType                 = activeRenderer.LightGroup.LightType,
                    LightStart                = 0,
                    LightEnd                  = lightCollection.Count,
                    ShadowMapRenderer         = shadowMapRenderer,
                    ShadowMapTexturesPerLight = renderViewData.LightComponentsWithShadows,
                };

                lightRenderer.ProcessLights(processLightsParameters);
            }
        }