Exemple #1
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);
                }
            }
        }
Exemple #2
0
        protected override void DrawCore(RenderContext context)
        {
            modelProcessor = SceneInstance.GetCurrent(context).GetProcessor <ModelProcessor>();
            lightProcessor = SceneInstance.GetCurrent(context).GetProcessor <LightProcessor>();

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

            // Not in the context of a SceneCameraRenderer? just exit
            sceneCameraRenderer = context.Tags.Get(SceneCameraRenderer.Current);
            sceneCamera         = context.Tags.Get(CameraComponentRenderer.Current);
            if (sceneCameraRenderer == null || sceneCamera == null)
            {
                return;
            }
            sceneCullingMask = sceneCameraRenderer.CullingMask;

            // Setup the callback on the ModelRenderer and shadow map LightGroupRenderer
            if (!isModelComponentRendererSetup)
            {
                // TODO: Check if we could discover declared renderers in a better way than just hacking the tags of a component
                var modelRenderer = ModelComponentRenderer.GetAttached(sceneCameraRenderer);
                if (modelRenderer == null)
                {
                    return;
                }

                modelRenderer.Callbacks.PreRenderModel += PrepareRenderModelForRendering;
                modelRenderer.Callbacks.PreRenderMesh  += PreRenderMesh;

                // TODO: Make this pluggable
                // TODO: Shadows should work on mobile platforms
                if (context.GraphicsDevice.Features.Profile >= GraphicsProfile.Level_10_0 &&
                    (Platform.Type == PlatformType.Windows || Platform.Type == PlatformType.WindowsStore || Platform.Type == PlatformType.Windows10))
                {
                    shadowMapRenderer = new ShadowMapRenderer(modelRenderer.EffectName);
                    shadowMapRenderer.Renderers.Add(typeof(LightDirectional), new LightDirectionalShadowMapRenderer());
                    shadowMapRenderer.Renderers.Add(typeof(LightSpot), new LightSpotShadowMapRenderer());
                }

                isModelComponentRendererSetup = true;
            }

            // Collect all visible lights
            CollectVisibleLights();

            // Draw shadow maps
            if (shadowMapRenderer != null)
            {
                shadowMapRenderer.Draw(context, visibleLightsWithShadows);
            }

            // Prepare active renderers in an ordered list (by type and shadow on/off)
            CollectActiveLightRenderers(context);

            currentModelLightShadersPermutationEntry = null;
            currentModelShadersParameters            = null;
            currentShadowReceiver = true;

            // Clear the cache of parameter entries
            lightParameterEntries.Clear();
            parameterCollectionEntryPool.Clear();

            // Clear association between model and lights
            modelToLights.Clear();

            // Clear all data generated by shader entries
            foreach (var shaderEntry in shaderEntries)
            {
                shaderEntry.Value.ResetGroupDatas();
            }
        }