public static void RenderDrawData(ImDrawData drawData, int displayW, int displayH) { // We are using the OpenGL fixed pipeline to make the example code simpler to read! // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. int lastTexture; GL.GetIntegerv(GL.Enum.GL_TEXTURE_BINDING_2D, out lastTexture); Int4 lastViewport; GL.GetIntegerv4(GL.Enum.GL_VIEWPORT, out lastViewport); Int4 lastScissorBox; GL.GetIntegerv4(GL.Enum.GL_SCISSOR_BOX, out lastScissorBox); GL.PushAttrib(GL.Enum.GL_ENABLE_BIT | GL.Enum.GL_COLOR_BUFFER_BIT | GL.Enum.GL_TRANSFORM_BIT); GL.Enable(GL.Enum.GL_BLEND); GL.BlendFunc(GL.Enum.GL_SRC_ALPHA, GL.Enum.GL_ONE_MINUS_SRC_ALPHA); GL.Disable(GL.Enum.GL_CULL_FACE); GL.Disable(GL.Enum.GL_DEPTH_TEST); GL.Enable(GL.Enum.GL_SCISSOR_TEST); GL.EnableClientState(GL.Enum.GL_VERTEX_ARRAY); GL.EnableClientState(GL.Enum.GL_TEXTURE_COORD_ARRAY); GL.EnableClientState(GL.Enum.GL_COLOR_ARRAY); GL.Enable(GL.Enum.GL_TEXTURE_2D); GL.UseProgram(0); // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) ImGuiIO io = ImGui.GetIO(); ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); // Setup orthographic projection matrix GL.Viewport(0, 0, displayW, displayH); GL.MatrixMode(GL.Enum.GL_PROJECTION); GL.PushMatrix(); GL.LoadIdentity(); GL.Ortho( 0.0f, io.DisplaySize.X / io.DisplayFramebufferScale.X, io.DisplaySize.Y / io.DisplayFramebufferScale.Y, 0.0f, -1.0f, 1.0f ); GL.MatrixMode(GL.Enum.GL_MODELVIEW); GL.PushMatrix(); GL.LoadIdentity(); // Render command lists for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawList cmdList = drawData[n]; ImVector <ImDrawVert> vtxBuffer = cmdList.VtxBuffer; ImVector <ushort> idxBuffer = cmdList.IdxBuffer; GL.VertexPointer(2, GL.Enum.GL_FLOAT, ImDrawVert.Size, new IntPtr((long)vtxBuffer.Data + ImDrawVert.PosOffset)); GL.TexCoordPointer(2, GL.Enum.GL_FLOAT, ImDrawVert.Size, new IntPtr((long)vtxBuffer.Data + ImDrawVert.UVOffset)); GL.ColorPointer(4, GL.Enum.GL_UNSIGNED_BYTE, ImDrawVert.Size, new IntPtr((long)vtxBuffer.Data + ImDrawVert.ColOffset)); long idxBufferOffset = 0; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmd pcmd = cmdList.CmdBuffer[cmdi]; if (pcmd.UserCallback != IntPtr.Zero) { pcmd.InvokeUserCallback(ref cmdList, ref pcmd); } else { GL.BindTexture(GL.Enum.GL_TEXTURE_2D, (int)pcmd.TextureId); GL.Scissor( (int)pcmd.ClipRect.X, (int)(io.DisplaySize.Y - pcmd.ClipRect.W), (int)(pcmd.ClipRect.Z - pcmd.ClipRect.X), (int)(pcmd.ClipRect.W - pcmd.ClipRect.Y) ); GL.DrawElements(GL.Enum.GL_TRIANGLES, (int)pcmd.ElemCount, GL.Enum.GL_UNSIGNED_SHORT, new IntPtr((long)idxBuffer.Data + idxBufferOffset)); } idxBufferOffset += pcmd.ElemCount * 2 /*sizeof(ushort)*/; } } // Restore modified state GL.DisableClientState(GL.Enum.GL_COLOR_ARRAY); GL.DisableClientState(GL.Enum.GL_TEXTURE_COORD_ARRAY); GL.DisableClientState(GL.Enum.GL_VERTEX_ARRAY); GL.BindTexture(GL.Enum.GL_TEXTURE_2D, lastTexture); GL.MatrixMode(GL.Enum.GL_MODELVIEW); GL.PopMatrix(); GL.MatrixMode(GL.Enum.GL_PROJECTION); GL.PopMatrix(); GL.PopAttrib(); GL.Viewport(lastViewport.X, lastViewport.Y, lastViewport.Z, lastViewport.W); GL.Scissor(lastScissorBox.X, lastScissorBox.Y, lastScissorBox.Z, lastScissorBox.W); }
public void RenderDrawData(ImDrawData drawData) { GraphicsDevice device = Game.GraphicsDevice; // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers. Viewport lastViewport = device.Viewport; Rectangle lastScissorBox = device.ScissorRectangle; device.BlendFactor = Color.White; device.BlendState = BlendState.NonPremultiplied; device.RasterizerState = RasterizerState; device.DepthStencilState = DepthStencilState.DepthRead; // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) ImGuiIO io = ImGui.GetIO(); ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); // Setup projection device.Viewport = new Viewport(0, 0, device.PresentationParameters.BackBufferWidth, device.PresentationParameters.BackBufferHeight); if (Effect == null) { Effect = new BasicEffect(device); } Effect effect = Effect; SetupEffect(this, effect); // Render command lists for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawList cmdList = drawData[n]; ImVector <ImDrawVertXNA> vtxBuffer; unsafe { vtxBuffer = new ImVector <ImDrawVertXNA>(cmdList.VtxBuffer.Native); } ImDrawVertXNA[] vtxArray = new ImDrawVertXNA[vtxBuffer.Size]; for (int i = 0; i < vtxBuffer.Size; i++) { vtxArray[i] = vtxBuffer[i]; } ImVector <short> idxBuffer; unsafe { idxBuffer = new ImVector <short>(cmdList.IdxBuffer.Native); } /* * short[] idxArray = new short[idxBuffer.Size]; * for (int i = 0; i < idxBuffer.Size; i++) * idxArray[i] = idxBuffer[i]; */ uint offset = 0; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmd pcmd = cmdList.CmdBuffer[cmdi]; if (pcmd.UserCallback != IntPtr.Zero) { pcmd.InvokeUserCallback(ref cmdList, ref pcmd); } else { // Instead of uploading the complete idxBuffer again and again, just upload what's required. short[] idxArray = new short[pcmd.ElemCount]; for (int i = 0; i < pcmd.ElemCount; i++) { idxArray[i] = idxBuffer[(int)offset + i]; } SetEffectTexture(this, effect, GetTexture((int)pcmd.TextureId)); device.ScissorRectangle = new Rectangle( (int)pcmd.ClipRect.X, (int)pcmd.ClipRect.Y, (int)(pcmd.ClipRect.Z - pcmd.ClipRect.X), (int)(pcmd.ClipRect.W - pcmd.ClipRect.Y) ); foreach (EffectPass pass in effect.CurrentTechnique.Passes) { pass.Apply(); device.DrawUserIndexedPrimitives( PrimitiveType.TriangleList, vtxArray, 0, vtxBuffer.Size, idxArray, 0, (int)pcmd.ElemCount / 3, ImDrawVertXNA._VertexDeclaration ); } } offset += pcmd.ElemCount; } } // Restore modified state device.Viewport = lastViewport; device.ScissorRectangle = lastScissorBox; }