/// <summary> /// Gets the geometry as set up by ImGui and sends it to the graphics device /// </summary> private void RenderDrawData(ImDrawDataPtr drawData) { // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers var lastViewport = _graphicsDevice.Viewport; var lastScissorBox = _graphicsDevice.ScissorRectangle; _graphicsDevice.BlendFactor = Color.White; _graphicsDevice.BlendState = BlendState.NonPremultiplied; _graphicsDevice.RasterizerState = _rasterizerState; _graphicsDevice.DepthStencilState = DepthStencilState.DepthRead; // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); // Setup projection _graphicsDevice.Viewport = new Viewport(0, 0, _graphicsDevice.PresentationParameters.BackBufferWidth, _graphicsDevice.PresentationParameters.BackBufferHeight); UpdateBuffers(drawData); RenderCommandLists(drawData); // Restore modified state _graphicsDevice.Viewport = lastViewport; _graphicsDevice.ScissorRectangle = lastScissorBox; }
private void RenderImDrawData(ImDrawDataPtr draw_data, GraphicsDevice gd, CommandList cl) { uint vertexOffsetInVertices = 0; uint indexOffsetInElements = 0; if (draw_data.CmdListsCount == 0) { return; } uint totalVBSize = (uint)(draw_data.TotalVtxCount * Unsafe.SizeOf <ImDrawVert>()); if (totalVBSize > _vertexBuffer.SizeInBytes) { gd.DisposeWhenIdle(_vertexBuffer); _vertexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalVBSize * 1.5f), BufferUsage.VertexBuffer | BufferUsage.Dynamic)); } uint totalIBSize = (uint)(draw_data.TotalIdxCount * sizeof(ushort)); if (totalIBSize > _indexBuffer.SizeInBytes) { gd.DisposeWhenIdle(_indexBuffer); _indexBuffer = gd.ResourceFactory.CreateBuffer(new BufferDescription((uint)(totalIBSize * 1.5f), BufferUsage.IndexBuffer | BufferUsage.Dynamic)); } for (int i = 0; i < draw_data.CmdListsCount; i++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[i]; cl.UpdateBuffer( _vertexBuffer, vertexOffsetInVertices * (uint)Unsafe.SizeOf <ImDrawVert>(), cmd_list.VtxBuffer.Data, (uint)(cmd_list.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>())); cl.UpdateBuffer( _indexBuffer, indexOffsetInElements * sizeof(ushort), cmd_list.IdxBuffer.Data, (uint)(cmd_list.IdxBuffer.Size * sizeof(ushort))); vertexOffsetInVertices += (uint)cmd_list.VtxBuffer.Size; indexOffsetInElements += (uint)cmd_list.IdxBuffer.Size; } // Setup orthographic projection matrix into our constant buffer ImGuiIOPtr io = ImGui.GetIO(); Matrix4x4 mvp = Matrix4x4.CreateOrthographicOffCenter( 0f, io.DisplaySize.X, io.DisplaySize.Y, 0.0f, -1.0f, 1.0f); _gd.UpdateBuffer(_projMatrixBuffer, 0, ref mvp); cl.SetVertexBuffer(0, _vertexBuffer); cl.SetIndexBuffer(_indexBuffer, IndexFormat.UInt16); cl.SetPipeline(_pipeline); cl.SetGraphicsResourceSet(0, _mainResourceSet); draw_data.ScaleClipRects(io.DisplayFramebufferScale); // Render command lists int vtx_offset = 0; int idx_offset = 0; for (int n = 0; n < draw_data.CmdListsCount; n++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[n]; for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++) { ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i]; if (pcmd.UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } else { if (pcmd.TextureId != IntPtr.Zero) { if (pcmd.TextureId == _fontAtlasID) { cl.SetGraphicsResourceSet(1, _fontTextureResourceSet); } else { cl.SetGraphicsResourceSet(1, GetImageResourceSet(pcmd.TextureId)); } } cl.SetScissorRect( 0, (uint)pcmd.ClipRect.X, (uint)pcmd.ClipRect.Y, (uint)(pcmd.ClipRect.Z - pcmd.ClipRect.X), (uint)(pcmd.ClipRect.W - pcmd.ClipRect.Y)); cl.DrawIndexed(pcmd.ElemCount, 1, (uint)idx_offset, vtx_offset, 0); } idx_offset += (int)pcmd.ElemCount; } vtx_offset += cmd_list.VtxBuffer.Size; } }