public void Execute(RenderContext context) { _renderList.Clear(); context.Scene.Scene3D?.World.Terrain.BuildRenderList(_renderList); context.Scene.Scene2D.WndWindowManager.BuildRenderList(_renderList); foreach (var system in context.Game.GameSystems) { system.BuildRenderList(_renderList); } var commandBuffer = context.GraphicsDevice.CommandQueue.GetCommandBuffer(); var renderPassDescriptor = new RenderPassDescriptor(); var clearColor = context.Camera.BackgroundColor.ToColorRgbaF(); renderPassDescriptor.SetRenderTargetDescriptor( context.RenderTarget, LoadAction.Clear, clearColor); var depthStencilBuffer = _depthStencilBufferCache.Get( context.SwapChain.BackBufferWidth, context.SwapChain.BackBufferHeight); renderPassDescriptor.SetDepthStencilDescriptor(depthStencilBuffer); var commandEncoder = commandBuffer.GetCommandEncoder(renderPassDescriptor); commandEncoder.SetViewport(context.Camera.Viewport); UpdateGlobalConstantBuffers(commandEncoder, context); void doRenderPass(RenderBucket bucket) { Culler.Cull(bucket.RenderItems, bucket.CulledItems, context); if (bucket.CulledItems.Count == 0) { return; } bucket.CulledItems.Sort(); RenderItem?lastRenderItem = null; foreach (var renderItem in bucket.CulledItems) { if (lastRenderItem == null || lastRenderItem.Value.Effect != renderItem.Effect) { var effect = renderItem.Effect; effect.Begin(commandEncoder); SetDefaultConstantBuffers(effect); } if (lastRenderItem == null || lastRenderItem.Value.VertexBuffer0 != renderItem.VertexBuffer0) { commandEncoder.SetVertexBuffer(0, renderItem.VertexBuffer0); } if (lastRenderItem == null || lastRenderItem.Value.VertexBuffer1 != renderItem.VertexBuffer1) { commandEncoder.SetVertexBuffer(1, renderItem.VertexBuffer1); } var renderItemConstantsVSParameter = renderItem.Effect.GetParameter("RenderItemConstantsVS", throwIfMissing: false); if (renderItemConstantsVSParameter != null) { _renderItemConstantsBufferVS.Value.World = renderItem.World; _renderItemConstantsBufferVS.Update(); renderItemConstantsVSParameter.SetData(_renderItemConstantsBufferVS.Buffer); } renderItem.Material.Apply(); renderItem.Effect.Apply(commandEncoder); switch (renderItem.DrawCommand) { case DrawCommand.Draw: commandEncoder.Draw( PrimitiveType.TriangleList, renderItem.VertexStart, renderItem.VertexCount); break; case DrawCommand.DrawIndexed: commandEncoder.DrawIndexed( PrimitiveType.TriangleList, renderItem.IndexCount, renderItem.IndexBuffer, renderItem.StartIndex); break; default: throw new System.Exception(); } lastRenderItem = renderItem; } } doRenderPass(_renderList.Opaque); doRenderPass(_renderList.Transparent); doRenderPass(_renderList.Gui); commandEncoder.Close(); commandBuffer.CommitAndPresent(context.SwapChain); }
public void Execute(RenderContext context) { var renderList = context.Graphics.RenderList; // Culling foreach (var renderItem in renderList.RenderItems) { renderItem.Visible = true; if (renderItem.Renderable.IsAlwaysVisible) { continue; } if (!renderItem.Renderable.Entity.VisibleInHierarchy) { renderItem.Visible = false; continue; } if (!context.Camera.BoundingFrustum.Intersects(renderItem.Renderable.BoundingBox)) { renderItem.Visible = false; continue; } } foreach (var instanceData in renderList.InstanceData.Values) { foreach (var instancedRenderable in instanceData.InstancedRenderables) { instancedRenderable.Visible = true; if (instancedRenderable.Renderable.IsAlwaysVisible) { continue; } if (!instancedRenderable.Renderable.Entity.VisibleInHierarchy) { instancedRenderable.Visible = false; continue; } if (!context.Camera.BoundingFrustum.Intersects(instancedRenderable.Renderable.BoundingBox)) { instancedRenderable.Visible = false; continue; } } instanceData.Update(context.GraphicsDevice); } var commandBuffer = context.GraphicsDevice.CommandQueue.GetCommandBuffer(); var renderPassDescriptor = new RenderPassDescriptor(); var clearColor = context.Camera.BackgroundColor.ToColorRgba(); renderPassDescriptor.SetRenderTargetDescriptor( context.RenderTarget, LoadAction.Clear, clearColor); var depthStencilBuffer = _depthStencilBufferCache.Get( context.SwapChain.BackBufferWidth, context.SwapChain.BackBufferHeight); renderPassDescriptor.SetDepthStencilDescriptor(depthStencilBuffer); var commandEncoder = commandBuffer.GetCommandEncoder(renderPassDescriptor); // TODO: Object lights. var lights = context.Scene.Settings.CurrentLightingConfiguration.TerrainLights; commandEncoder.SetViewport(context.Camera.Viewport); void doDrawPass(List <RenderListEffectGroup> effectGroups) { foreach (var effectGroup in effectGroups) { var effect = effectGroup.Effect; effect.Begin(commandEncoder); if (effect is IEffectMatrices m) { m.SetView(context.Camera.View); m.SetProjection(context.Camera.Projection); } if (effect is IEffectLights l) { l.SetLights(ref lights); } if (effect is IEffectTime t) { t.SetTimeInSeconds(context.GameTime.TotalGameTime.Seconds); } foreach (var pipelineStateGroup in effectGroup.PipelineStateGroups) { var pipelineStateHandle = pipelineStateGroup.PipelineStateHandle; effect.SetPipelineState(pipelineStateHandle); foreach (var renderItem in pipelineStateGroup.RenderItems) { if (!renderItem.Visible) { continue; } if (effect is IEffectMatrices m2) { m2.SetWorld(renderItem.Renderable.Entity.Transform.LocalToWorldMatrix); } renderItem.RenderCallback( commandEncoder, effectGroup.Effect, pipelineStateGroup.PipelineStateHandle, null); } foreach (var instancedRenderItem in pipelineStateGroup.InstancedRenderItems) { if (instancedRenderItem.InstanceData.NumInstances == 0) { continue; } instancedRenderItem.RenderCallback( commandEncoder, effectGroup.Effect, pipelineStateGroup.PipelineStateHandle, instancedRenderItem.InstanceData); } } } } // TODO: Culling, based on: // - Renderable.BoundingBox // - Renderable.VisibleInHierarchy // - Renderable.IsAlwaysVisible doDrawPass(renderList.Opaque); doDrawPass(renderList.Transparent); commandEncoder.Close(); commandBuffer.CommitAndPresent(context.SwapChain); }