public override void Update()
        {
            // Wait until visibility group is available
            if (VisibilityGroup == null)
            {
                VisibilityGroup = SceneSystem.SceneInstance.VisibilityGroups.FirstOrDefault();
            }

            if (VisibilityGroup == null)
            {
                return;
            }

            // Check whether counts have changed
            if (lastCountX != CountX || lastCountY != CountY)
            {
                RebuildRenderObjects();
            }

            // Update render objects
            UpdateRenderObjects();

            lastCountX = CountX;
            lastCountY = CountY;
        }
        public VisibilityGroup GetOrCreateVisibilityGroup(RenderSystem renderSystem)
        {
            // Find if it exists
            VisibilityGroup visibilityGroup = null;

            foreach (var currentVisibilityGroup in VisibilityGroups)
            {
                if (currentVisibilityGroup.RenderSystem == renderSystem)
                {
                    visibilityGroup = currentVisibilityGroup;
                    break;
                }
            }

            // If first time, let's create and register it
            if (visibilityGroup == null)
            {
                VisibilityGroups.Add(visibilityGroup = new VisibilityGroup(renderSystem));
            }

            return(visibilityGroup);
        }
        /// <inheritdoc/>
        protected override void DrawCore(RenderDrawContext context)
        {
            if (Game != null)
            {
                // Get or create VisibilityGroup for this RenderSystem + SceneInstance
                var             sceneInstance   = SceneInstance.GetCurrent(context.RenderContext);
                VisibilityGroup visibilityGroup = null;
                if (sceneInstance != null)
                {
                    // Find if VisibilityGroup
                    foreach (var currentVisibilityGroup in sceneInstance.VisibilityGroups)
                    {
                        if (currentVisibilityGroup.RenderSystem == RenderSystem)
                        {
                            visibilityGroup = currentVisibilityGroup;
                            break;
                        }
                    }

                    // If first time, let's create and register it
                    if (visibilityGroup == null)
                    {
                        sceneInstance.VisibilityGroups.Add(visibilityGroup = new VisibilityGroup(RenderSystem));
                        initializedSceneInstances.Add(sceneInstance);
                    }

                    // Reset & cleanup
                    visibilityGroup.Reset();
                }

                using (context.RenderContext.PushTagAndRestore(SceneInstance.CurrentVisibilityGroup, visibilityGroup))
                    using (context.RenderContext.PushTagAndRestore(SceneInstance.CurrentRenderSystem, RenderSystem))
                        using (context.RenderContext.PushTagAndRestore(SceneCameraSlotCollection.Current, Cameras))
                        {
                            // Set render system
                            context.RenderContext.RenderSystem    = RenderSystem;
                            context.RenderContext.VisibilityGroup = visibilityGroup;

                            // Set start states for viewports and output (it will be used during the Collect phase)
                            var renderOutputs = new RenderOutputDescription();
                            renderOutputs.CaptureState(context.CommandList);
                            context.RenderContext.RenderOutput = renderOutputs;

                            var viewports = new ViewportState();
                            viewports.CaptureState(context.CommandList);
                            context.RenderContext.ViewportState = viewports;

                            try
                            {
                                // Collect in the game graphics compositor: Setup features/stages, enumerate views and populates VisibilityGroup
                                Game.Collect(context.RenderContext);

                                // Collect in render features
                                RenderSystem.Collect(context.RenderContext);

                                // Collect visibile objects from each view (that were not properly collected previously)
                                if (visibilityGroup != null)
                                {
                                    foreach (var view in RenderSystem.Views)
                                    {
                                        visibilityGroup.TryCollect(view);
                                    }
                                }

                                // Extract
                                RenderSystem.Extract(context.RenderContext);

                                // Prepare
                                RenderSystem.Prepare(context);

                                // Draw using the game graphics compositor
                                Game.Draw(context);

                                // Flush
                                RenderSystem.Flush(context);
                            }
                            finally
                            {
                                // Reset render context data
                                RenderSystem.Reset();
                            }
                        }
            }
        }
Exemple #4
0
        private bool DrawBoundingVolumes(RenderDrawContext context, IReadOnlyList <RenderLightShaftBoundingVolume> boundingVolumes, Matrix viewProjection)
        {
            var commandList = context.CommandList;

            bool effectUpdated = minmaxVolumeEffectShader.UpdateEffect(GraphicsDevice);

            if (minmaxVolumeEffectShader.Effect == null)
            {
                return(false);
            }

            var  needEffectUpdate = effectUpdated || previousMinmaxEffectBytecode != minmaxVolumeEffectShader.Effect.Bytecode;
            bool visibleMeshes    = false;

            for (int pass = 0; pass < 2; ++pass)
            {
                var minmaxPipelineState = minmaxPipelineStates[pass];

                bool pipelineDirty = false;
                if (needEffectUpdate)
                {
                    // The EffectInstance might have been updated from outside
                    previousMinmaxEffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.RootSignature  = minmaxVolumeEffectShader.RootSignature;
                    minmaxPipelineState.State.EffectBytecode = minmaxVolumeEffectShader.Effect.Bytecode;

                    minmaxPipelineState.State.Output.RenderTargetCount   = 1;
                    minmaxPipelineState.State.Output.RenderTargetFormat0 = commandList.RenderTarget.Format;
                    pipelineDirty = true;
                }

                MeshDraw currentDraw = null;
                var      frustum     = new BoundingFrustum(ref viewProjection);
                foreach (var volume in boundingVolumes)
                {
                    if (volume.Model == null)
                    {
                        continue;
                    }

                    // Update parameters for the minmax shader
                    Matrix worldViewProjection = Matrix.Multiply(volume.World, viewProjection);
                    minmaxVolumeEffectShader.Parameters.Set(VolumeMinMaxShaderKeys.WorldViewProjection, worldViewProjection);

                    foreach (var mesh in volume.Model.Meshes)
                    {
                        // Frustum culling
                        BoundingBox meshBoundingBox;
                        Matrix      world = volume.World;
                        BoundingBox.Transform(ref mesh.BoundingBox, ref world, out meshBoundingBox);
                        var boundingBoxExt = new BoundingBoxExt(meshBoundingBox);
                        if (boundingBoxExt.Extent != Vector3.Zero &&
                            !VisibilityGroup.FrustumContainsBox(ref frustum, ref boundingBoxExt, true))
                        {
                            continue;
                        }

                        visibleMeshes = true;

                        var draw = mesh.Draw;

                        if (currentDraw != draw)
                        {
                            if (minmaxPipelineState.State.PrimitiveType != draw.PrimitiveType)
                            {
                                minmaxPipelineState.State.PrimitiveType = draw.PrimitiveType;
                                pipelineDirty = true;
                            }

                            var inputElements = draw.VertexBuffers.CreateInputElements();
                            if (inputElements.ComputeHash() != minmaxPipelineState.State.InputElements.ComputeHash())
                            {
                                minmaxPipelineState.State.InputElements = inputElements;
                                pipelineDirty = true;
                            }

                            // Update mesh
                            for (int i = 0; i < draw.VertexBuffers.Length; i++)
                            {
                                var vertexBuffer = draw.VertexBuffers[i];
                                commandList.SetVertexBuffer(i, vertexBuffer.Buffer, vertexBuffer.Offset, vertexBuffer.Stride);
                            }
                            if (draw.IndexBuffer != null)
                            {
                                commandList.SetIndexBuffer(draw.IndexBuffer.Buffer, draw.IndexBuffer.Offset, draw.IndexBuffer.Is32Bit);
                            }
                            currentDraw = draw;
                        }

                        if (pipelineDirty)
                        {
                            minmaxPipelineState.Update();
                            pipelineDirty = false;
                        }

                        context.CommandList.SetPipelineState(minmaxPipelineState.CurrentState);

                        minmaxVolumeEffectShader.Apply(context.GraphicsContext);

                        // Draw
                        if (currentDraw.IndexBuffer == null)
                        {
                            commandList.Draw(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                        else
                        {
                            commandList.DrawIndexed(currentDraw.DrawCount, currentDraw.StartLocation);
                        }
                    }
                }
            }

            return(visibleMeshes);
        }
        private EntityProcessor CreateRenderProcessor(RegisteredRenderProcessors registeredRenderProcessor, VisibilityGroup visibilityGroup)
        {
            // Create
            var processor = (EntityProcessor)Activator.CreateInstance(registeredRenderProcessor.Type);

            // Set visibility group
            ((IEntityComponentRenderProcessor)processor).VisibilityGroup = visibilityGroup;

            // Add processor
            Processors.Add(processor);
            registeredRenderProcessor.Instances.Add(new KeyValuePair <VisibilityGroup, EntityProcessor>(visibilityGroup, processor));

            return(processor);
        }