private void RenderImDrawData(DrawData *data) { for (int n = 0; n < data->CmdListsCount; n++) { NativeDrawList *cmdList = data->CmdLists[n]; byte * vb = (byte *)cmdList->VtxBuffer.Data; ushort * ib = (ushort *)cmdList->IdxBuffer.Data; UpdateVB(cmdList->VtxBuffer.Size, vb); for (int cmd_i = 0; cmd_i < cmdList->CmdBuffer.Size; cmd_i++) { DrawCmd *pcmd = &(((DrawCmd *)cmdList->CmdBuffer.Data)[cmd_i]); if (pcmd->UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } else { var texid = pcmd->TextureId.ToInt32(); UpdateIB((int)pcmd->ElemCount, ib); _indexBuffer.Draw(_vertexBuffer, 0, (int)pcmd->ElemCount); } ib += pcmd->ElemCount; } } }
public unsafe void Draw() { ImGui.Render(); DrawData *data = ImGui.GetDrawData(); ImGuiRenderDraw(data); }
public unsafe void EndFrame() { ImGui.Render(); DrawData *data = ImGui.GetDrawData(); RenderImDrawData(data); }
public void Render(RenderState rstate) { ImGui.Render(); unsafe { DrawData *data = ImGui.GetDrawData(); RenderImDrawData(data, rstate); } }
private void RenderFrame() { IO io = ImGui.GetIO(); io.DisplaySize = new System.Numerics.Vector2(_device.ScreenWidth, _device.ScreenHeight); io.DisplayFramebufferScale = new System.Numerics.Vector2(1); io.DeltaTime = (1f / 60f); UpdateImGuiInput(io); ImGui.NewFrame(); SubmitImGuiStuff(); ImGui.Render(); DrawData *data = ImGui.GetDrawData(); RenderImDrawData(data); }
public unsafe static void RenderDrawData(DrawData *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.GetInteger(GetPName.TextureBinding2D, out lastTexture); Int4 lastViewport = new Int4(); TypedReference tr = __makeref(lastViewport); IntPtr ptr = **(IntPtr **)(&tr); GL.GetInteger(GetPName.Viewport, (int *)ptr); Int4 lastScissorBox = new Int4(); tr = __makeref(lastScissorBox); ptr = **(IntPtr **)(&tr); GL.GetInteger(GetPName.ScissorBox, (int *)ptr); GL.PushAttrib(AttribMask.EnableBit | AttribMask.ColorBufferBit | AttribMask.TransformBit); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); GL.Disable(EnableCap.CullFace); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.ScissorTest); GL.EnableClientState(ArrayCap.VertexArray); GL.EnableClientState(ArrayCap.TextureCoordArray); GL.EnableClientState(ArrayCap.ColorArray); GL.Enable(EnableCap.Texture2D); GL.UseProgram(0); // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) IO io = ImGui.GetIO(); ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); // Setup orthographic projection matrix GL.Viewport(0, 0, displayW, displayH); GL.MatrixMode(MatrixMode.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(MatrixMode.Modelview); GL.PushMatrix(); GL.LoadIdentity(); // Render command lists for (int n = 0; n < drawData->CmdListsCount; n++) { DrawList cmddList = new DrawList(drawData->CmdLists[n]); NativeDrawList *cmdList = drawData->CmdLists[n]; ImVector vtxBuffer = cmdList->VtxBuffer; ImVector idxBuffer = cmdList->IdxBuffer; GL.VertexPointer(2, VertexPointerType.Float, sizeof(DrawVert), new IntPtr((long)vtxBuffer.Data + DrawVert.PosOffset)); GL.TexCoordPointer(2, TexCoordPointerType.Float, sizeof(DrawVert), new IntPtr((long)vtxBuffer.Data + DrawVert.UVOffset)); GL.ColorPointer(4, ColorPointerType.UnsignedByte, sizeof(DrawVert), new IntPtr((long)vtxBuffer.Data + DrawVert.ColOffset)); long idxBufferOffset = 0; for (int cmdi = 0; cmdi < cmdList->CmdBuffer.Size; cmdi++) { DrawCmd *pcmd = &(((DrawCmd *)cmdList->CmdBuffer.Data)[cmdi]); /* if (pcmd->UserCallback!= IntPtr.Zero) { * pcmd->(ref cmdList, ref pcmd); * } else {*/ GL.BindTexture(TextureTarget.Texture2D, (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(PrimitiveType.Triangles, (int)pcmd->ElemCount, DrawElementsType.UnsignedByte, new IntPtr((long)idxBuffer.Data + idxBufferOffset)); idxBufferOffset += pcmd->ElemCount * 2 /*sizeof(ushort)*/; } } // Restore modified state GL.DisableClientState(ArrayCap.ColorArray); GL.DisableClientState(ArrayCap.TextureCoordArray); GL.DisableClientState(ArrayCap.VertexArray); GL.BindTexture(TextureTarget.Texture2D, lastTexture); GL.MatrixMode(MatrixMode.Modelview); GL.PopMatrix(); GL.MatrixMode(MatrixMode.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); }
private unsafe void ImGuiRenderDraw(DrawData *drawData) { if (drawData == null) { return; } var io = ImGui.GetIO(); if (io.DisplaySize.X <= 0.0f || io.DisplaySize.Y <= 0.0f) { return; } var st = new StateBlock(device, StateBlockType.All); var vp = new Viewport(); vp.X = vp.Y = 0; vp.Width = (int)io.DisplaySize.X; vp.Height = (int)io.DisplaySize.Y; vp.MinDepth = 0.0f; vp.MaxDepth = 1.0f; device.Viewport = vp; device.PixelShader = null; device.VertexShader = null; device.SetRenderState(RenderState.CullMode, Cull.None); device.SetRenderState(RenderState.Lighting, false); device.SetRenderState(RenderState.ZEnable, false); device.SetRenderState(RenderState.AlphaBlendEnable, true); device.SetRenderState(RenderState.AlphaTestEnable, false); device.SetRenderState(RenderState.BlendOperation, BlendOperation.Add); device.SetRenderState(RenderState.SourceBlend, Blend.SourceAlpha); device.SetRenderState(RenderState.DestinationBlend, Blend.BothInverseSourceAlpha); device.SetRenderState(RenderState.ScissorTestEnable, true); device.SetTextureStageState(0, TextureStage.ColorOperation, TextureOperation.Modulate); device.SetTextureStageState(0, TextureStage.ColorArg1, TextureArgument.Texture); device.SetTextureStageState(0, TextureStage.ColorArg2, TextureArgument.Diffuse); device.SetTextureStageState(0, TextureStage.AlphaOperation, TextureOperation.Modulate); device.SetTextureStageState(0, TextureStage.AlphaArg1, TextureArgument.Texture); device.SetTextureStageState(0, TextureStage.AlphaArg2, TextureArgument.Diffuse); device.SetSamplerState(0, SamplerState.MinFilter, TextureFilter.Linear); device.SetSamplerState(0, SamplerState.MagFilter, TextureFilter.Linear); // Setup orthographic projection matrix { const float L = 0.5f; var R = io.DisplaySize.X + 0.5f; const float T = 0.5f; var B = io.DisplaySize.Y + 0.5f; RawMatrix mat_identity = new Matrix(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f); RawMatrix mat_projection = new Matrix( 2.0f / (R - L), 0.0f, 0.0f, 0.0f, 0.0f, 2.0f / (T - B), 0.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f, (L + R) / (L - R), (T + B) / (B - T), 0.5f, 1.0f); device.SetTransform(TransformState.World, ref mat_identity); device.SetTransform(TransformState.View, ref mat_identity); device.SetTransform(TransformState.Projection, ref mat_projection); } using (device.VertexDeclaration = new VertexDeclaration(device, GuiVertex.VertexElements)) { for (var n = 0; n < drawData->CmdListsCount; n++) { var cmdList = drawData->CmdLists[n]; var vtx_buffer = (DrawVert *)cmdList->VtxBuffer.Data; var idx_buffer = (ushort *)cmdList->IdxBuffer.Data; var myCustomVertices = new GuiVertex[cmdList->VtxBuffer.Size]; for (var i = 0; i < myCustomVertices.Length; i++) { var cl = (vtx_buffer[i].col & 0xFF00FF00) | ((vtx_buffer[i].col & 0xFF0000) >> 16) | ((vtx_buffer[i].col & 0xFF) << 16); myCustomVertices[i] = new GuiVertex(vtx_buffer[i].pos.X, vtx_buffer[i].pos.Y, vtx_buffer[i].uv.X, vtx_buffer[i].uv.Y, cl); } for (var i = 0; i < cmdList->CmdBuffer.Size; i++) { var pcmd = &((DrawCmd *)cmdList->CmdBuffer.Data)[i]; if (pcmd->UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } //Trace.WriteLine(pcmd->TextureId.ToString()); device.SetTexture(0, new Texture(pcmd->TextureId)); device.ScissorRect = new RectangleF((int)pcmd->ClipRect.X, (int)pcmd->ClipRect.Y, (int)(pcmd->ClipRect.Z - pcmd->ClipRect.X), (int)(pcmd->ClipRect.W - pcmd->ClipRect.Y)); var indices = new ushort[pcmd->ElemCount]; for (var j = 0; j < indices.Length; j++) { indices[j] = idx_buffer[j]; } device.DrawIndexedUserPrimitives(PrimitiveType.TriangleList, 0, myCustomVertices.Length, (int)(pcmd->ElemCount / 3), indices, Format.Index16, myCustomVertices); idx_buffer += pcmd->ElemCount; } } } st.Apply(); st.Dispose(); }
public static unsafe void render(BasicEffect effect) { IO io = ImGui.GetIO(); ImGui.Render(); DrawData *draw_data = ImGui.GetDrawData(); var graphicsDevice = _game.GraphicsDevice; graphicsDevice.DepthStencilState = DepthStencilState.None; graphicsDevice.RasterizerState = new RasterizerState() { ScissorTestEnable = true, CullMode = CullMode.None }; graphicsDevice.SamplerStates[0] = SamplerState.PointClamp; graphicsDevice.BlendState = BlendState.AlphaBlend; // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale); //var effect = Assets.defaultEffect; //effect.Texture = Assets.dummyTexture; effect.World = Matrix.Identity; effect.View = Matrix.Identity;// camera.viewMatrix3D; effect.Projection = Matrix.CreateOrthographicOffCenter( 0.0f, io.DisplaySize.X / io.DisplayFramebufferScale.X, io.DisplaySize.Y / io.DisplayFramebufferScale.Y, 0.0f, -1.0f, 1.0f ); // Render command lists for (int n = 0; n < draw_data->CmdListsCount; n++) { NativeDrawList *cmd_list = draw_data->CmdLists[n]; DrawVert * vtx_buffer = (DrawVert *)cmd_list->VtxBuffer.Data; ushort * idx_buffer = (ushort *)cmd_list->IdxBuffer.Data; var vertexElements = cmd_list->VtxBuffer.Size; var indexElements = cmd_list->IdxBuffer.Size; var idxPos = 0; if (vertices.Length < vertexElements) { vertices = new ImGuiVertex[vertexElements / 2 * 3]; _vertexBuffer.Dispose(); _vertexBuffer = new VertexBuffer(graphicsDevice, ImGuiVertex.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly); } for (int i = 0; i < vertexElements; i++) { DrawVert vert = *vtx_buffer++; vertices[i].x = vert.pos.X; vertices[i].y = vert.pos.Y; vertices[i].tx = vert.uv.X; vertices[i].ty = vert.uv.Y; vertices[i].color = vert.col; } _vertexBuffer.SetData(vertices, 0, vertexElements); if (indices.Length < indexElements) { indices = new short[indexElements / 2 * 3]; _indexBuffer.Dispose(); _indexBuffer = new IndexBuffer(graphicsDevice, IndexElementSize.SixteenBits, indices.Length, BufferUsage.WriteOnly); } for (int i = 0; i < indexElements; i++) { indices[i] = (short)idx_buffer[i]; } _indexBuffer.SetData(indices, 0, indexElements); graphicsDevice.Indices = _indexBuffer; graphicsDevice.SetVertexBuffer(_vertexBuffer); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { DrawCmd *pcmd = &(((DrawCmd *)cmd_list->CmdBuffer.Data)[cmd_i]); if (pcmd->UserCallback != IntPtr.Zero) { throw new NotImplementedException(); } else { graphicsDevice.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)); if (pcmd->TextureId.ToInt32() == fontTexture.GetHashCode()) { effect.Texture = fontTexture; } else { throw new NotImplementedException(); } var primivites = (int)pcmd->ElemCount / 3; foreach (var pass in effect.CurrentTechnique.Passes) { pass.Apply(); graphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, idxPos, primivites); //graphicsDevice.DrawUserIndexedPrimitives(PrimitiveType.TriangleList, vertices, 0, vertexElements, indices, 0, indexElements / 3); } } idxPos += (int)pcmd->ElemCount; } } }
unsafe void RenderImDrawData(DrawData *draw_data, RenderState rstate) { var io = ImGui.GetIO(); //Set cursor var cur = ImGuiNative.igGetMouseCursor(); switch (cur) { case MouseCursorKind.Arrow: game.CursorKind = CursorKind.Arrow; break; case MouseCursorKind.Move: game.CursorKind = CursorKind.Move; break; case MouseCursorKind.TextInput: game.CursorKind = CursorKind.TextInput; break; case MouseCursorKind.ResizeNS: game.CursorKind = CursorKind.ResizeNS; break; case MouseCursorKind.ResizeNESW: game.CursorKind = CursorKind.ResizeNESW; break; case MouseCursorKind.ResizeNWSE: game.CursorKind = CursorKind.ResizeNWSE; break; } //Render ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale); var mat = Matrix4.CreateOrthographicOffCenter(0, game.Width, game.Height, 0, 0, 1); Shader lastShader = textShader; textShader.SetMatrix(textShader.GetLocation("modelviewproj"), ref mat); textShader.SetInteger(textShader.GetLocation("tex"), 0); colorShader.SetMatrix(textShader.GetLocation("modelviewproj"), ref mat); colorShader.SetInteger(textShader.GetLocation("tex"), 0); textShader.UseProgram(); rstate.Cull = false; rstate.BlendMode = BlendMode.Normal; rstate.DepthEnabled = false; for (int n = 0; n < draw_data->CmdListsCount; n++) { var cmd_list = draw_data->CmdLists[n]; byte * vtx_buffer = (byte *)cmd_list->VtxBuffer.Data; ushort *idx_buffer = (ushort *)cmd_list->IdxBuffer.Data; var vtxCount = cmd_list->VtxBuffer.Size; var idxCount = cmd_list->IdxBuffer.Size; if (vboSize < vtxCount || iboSize < idxCount) { if (vbo != null) { vbo.Dispose(); } if (ibo != null) { ibo.Dispose(); } vboSize = Math.Max(vboSize, vtxCount); iboSize = Math.Max(iboSize, idxCount); vbo = new VertexBuffer(typeof(Vertex2D), vboSize, true); ibo = new ElementBuffer(iboSize, true); vbo.SetElementBuffer(ibo); vbuffer = new Vertex2D[vboSize]; ibuffer = new ushort[iboSize]; } for (int i = 0; i < cmd_list->IdxBuffer.Size; i++) { ibuffer[i] = idx_buffer[i]; } for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) { var ptr = (DrawVert *)vtx_buffer; var unint = ptr[i].col; var a = unint >> 24 & 0xFF; var b = unint >> 16 & 0xFF; var g = unint >> 8 & 0xFF; var r = unint & 0xFF; vbuffer[i] = new Vertex2D(ptr[i].pos, ptr[i].uv, new Color4(r / 255f, g / 255f, b / 255f, a / 255f)); } vbo.SetData(vbuffer, cmd_list->VtxBuffer.Size); ibo.SetData(ibuffer, cmd_list->IdxBuffer.Size); int startIndex = 0; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { var pcmd = &(((DrawCmd *)cmd_list->CmdBuffer.Data)[cmd_i]); //TODO: Do something with pcmd->UserCallback ?? var tid = pcmd->TextureId.ToInt32(); Texture2D tex; if (tid == FONT_TEXTURE_ID) { if (lastShader != textShader) { textShader.UseProgram(); lastShader = textShader; } fontTexture.BindTo(0); } else if (textures.TryGetValue(tid, out tex)) { if (lastShader != colorShader) { colorShader.UseProgram(); lastShader = colorShader; } tex.BindTo(0); } else { dot.BindTo(0); } GL.Enable(GL.GL_SCISSOR_TEST); 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)); vbo.Draw(PrimitiveTypes.TriangleList, 0, startIndex, (int)pcmd->ElemCount / 3); GL.Disable(GL.GL_SCISSOR_TEST); startIndex += (int)pcmd->ElemCount; } } }
private unsafe void RenderImDrawData(DrawData *draw_data) { var context = this.Device.ImmediateContext; throw new NotImplementedException(); }
unsafe void RenderImDrawData(DrawData *draw_data, RenderState rstate) { var io = ImGui.GetIO(); ImGui.ScaleClipRects(draw_data, io.DisplayFramebufferScale); var mat = Matrix4.CreateOrthographicOffCenter(0, game.Width, game.Height, 0, 0, 1); shader.SetMatrix(shader.GetLocation("modelviewproj"), ref mat); shader.SetInteger(shader.GetLocation("tex"), 0); shader.UseProgram(); rstate.Cull = false; rstate.BlendMode = BlendMode.Normal; rstate.DepthEnabled = false; for (int n = 0; n < draw_data->CmdListsCount; n++) { var cmd_list = draw_data->CmdLists[n]; byte * vtx_buffer = (byte *)cmd_list->VtxBuffer.Data; ushort *idx_buffer = (ushort *)cmd_list->IdxBuffer.Data; var vtxCount = cmd_list->VtxBuffer.Size; var idxCount = cmd_list->IdxBuffer.Size; if (vboSize < vtxCount || iboSize < idxCount) { if (vbo != null) { vbo.Dispose(); } if (ibo != null) { ibo.Dispose(); } vboSize = Math.Max(vboSize, vtxCount); iboSize = Math.Max(iboSize, idxCount); vbo = new VertexBuffer(typeof(Vertex2D), vboSize, true); ibo = new ElementBuffer(iboSize, true); vbo.SetElementBuffer(ibo); vbuffer = new Vertex2D[vboSize]; ibuffer = new ushort[iboSize]; } for (int i = 0; i < cmd_list->IdxBuffer.Size; i++) { ibuffer[i] = idx_buffer[i]; } for (int i = 0; i < cmd_list->VtxBuffer.Size; i++) { var ptr = (DrawVert *)vtx_buffer; var unint = ptr[i].col; var a = unint >> 24 & 0xFF; var b = unint >> 16 & 0xFF; var g = unint >> 8 & 0xFF; var r = unint & 0xFF; vbuffer[i] = new Vertex2D(ptr[i].pos, ptr[i].uv, new Color4(r / 255f, g / 255f, b / 255f, a / 255f)); } vbo.SetData(vbuffer, cmd_list->VtxBuffer.Size); ibo.SetData(ibuffer, cmd_list->IdxBuffer.Size); int startIndex = 0; for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { var pcmd = &(((DrawCmd *)cmd_list->CmdBuffer.Data)[cmd_i]); //TODO: Do something with pcmd->UserCallback ?? (pcmd->TextureId.ToInt32() == FONT_TEXTURE_ID ? fontTexture : dot).BindTo(0); GL.Enable(GL.GL_SCISSOR_TEST); 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)); vbo.Draw(PrimitiveTypes.TriangleList, 0, startIndex, (int)pcmd->ElemCount / 3); GL.Disable(GL.GL_SCISSOR_TEST); startIndex += (int)pcmd->ElemCount; } } }
private static unsafe void renderDrawData(DrawData *drawData) { // scale coordinates for retina displays IO io = ImGui.GetIO(); int fbWidth = (int)(io.DisplaySize.X * io.DisplayFramebufferScale.X); int fbHeight = (int)(io.DisplaySize.Y * io.DisplayFramebufferScale.Y); if (fbWidth < 0 || fbHeight < 0) { return; } ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); // backup GL state GL.GetInteger(GetPName.ActiveTexture, out int lastActiveTexture); GL.ActiveTexture(TextureUnit.Texture0); GL.GetInteger(GetPName.CurrentProgram, out int lastProgram); GL.GetInteger(GetPName.TextureBinding2D, out int lastTexture); GL.GetInteger(GetPName.SamplerBinding, out int lastSampler); GL.GetInteger(GetPName.ArrayBufferBinding, out int lastArrayBuffer); GL.GetInteger(GetPName.VertexArrayBinding, out int lastVertexArray); int[] lastPolygonMode = new int[2]; GL.GetInteger(GetPName.PolygonMode, lastPolygonMode); int[] lastViewport = new int[4]; GL.GetInteger(GetPName.Viewport, lastViewport); int[] lastScissorBox = new int[4]; GL.GetInteger(GetPName.ScissorBox, lastScissorBox); GL.GetInteger(GetPName.BlendSrcRgb, out int lastBlendSrcRgb); GL.GetInteger(GetPName.BlendDstRgb, out int lastBlendDstRgb); GL.GetInteger(GetPName.BlendSrcAlpha, out int lastBlendSrcAlpha); GL.GetInteger(GetPName.BlendDstAlpha, out int lastBlendDstAlpha); GL.GetInteger(GetPName.BlendEquationRgb, out int lastBlendEquationRgb); GL.GetInteger(GetPName.BlendEquationAlpha, out int lastBlendEquationAlpha); bool lastEnableBlend = GL.IsEnabled(EnableCap.Blend); bool lastEnableCullFace = GL.IsEnabled(EnableCap.CullFace); bool lastEnableDepthTest = GL.IsEnabled(EnableCap.DepthTest); bool lastEnableScissorTest = GL.IsEnabled(EnableCap.ScissorTest); // setup GL state GL.Enable(EnableCap.Blend); GL.BlendEquation(BlendEquationMode.FuncAdd); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.Disable(EnableCap.CullFace); GL.Disable(EnableCap.DepthTest); GL.Enable(EnableCap.ScissorTest); GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill); // setup viewport with orthographic projecton matrix GL.Viewport(0, 0, fbWidth, fbHeight); float l = 0; float r = io.DisplaySize.X; float t = 0; float b = io.DisplaySize.Y; Matrix4 orthoProjection = new Matrix4( 2.0f / (r - l), 0, 0, 0, 0, 2.0f / (t - b), 0, 0, 0, 0, -1.0f, 0, (r + l) / (l - r), (t + b) / (b - t), 0, 1.0f ); GL.UseProgram(_programHandle); GL.Uniform1(_attribLocationTex, 0); GL.UniformMatrix4(_attribLocationProjMtx, false, ref orthoProjection); GL.BindSampler(0, 0); // recreate the VAO every time int vaoHandle = GL.GenVertexArray(); GL.BindVertexArray(vaoHandle); GL.BindBuffer(BufferTarget.ArrayBuffer, _vboHandle); GL.EnableVertexAttribArray(_attribLocationPosition); GL.EnableVertexAttribArray(_attribLocationUV); GL.EnableVertexAttribArray(_attribLocationColor); GL.VertexAttribPointer(_attribLocationPosition, 2, VertexAttribPointerType.Float, false, ImGuiVert.Size, ImGuiVert.PosOffset); GL.VertexAttribPointer(_attribLocationUV, 2, VertexAttribPointerType.Float, false, ImGuiVert.Size, ImGuiVert.UVOffset); GL.VertexAttribPointer(_attribLocationColor, 4, VertexAttribPointerType.UnsignedByte, false, ImGuiVert.Size, ImGuiVert.ColOffset); // draw Vector2 pos = new Vector2(l, t); for (int n = 0; n < drawData->CmdListsCount; n++) { var cmdList = drawData->CmdLists[n]; int indexBufferOffset = 0; GL.BindBuffer(BufferTarget.ArrayBuffer, _vboHandle); GL.BufferData(BufferTarget.ArrayBuffer, cmdList->VtxBuffer.Size * ImGuiVert.Size, new IntPtr(cmdList->VtxBuffer.Data), BufferUsageHint.StreamDraw); GL.BindBuffer(BufferTarget.ElementArrayBuffer, _elementsHandle); GL.BufferData(BufferTarget.ElementArrayBuffer, cmdList->IdxBuffer.Size * sizeof(ushort), new IntPtr(cmdList->IdxBuffer.Data), BufferUsageHint.StreamDraw); DrawCmd *cmds = (DrawCmd *)cmdList->CmdBuffer.Data; for (int cmdIndex = 0; cmdIndex < cmdList->CmdBuffer.Size; cmdIndex++) { DrawCmd *drawCmd = &cmds[cmdIndex]; Vector4 clipRect = new Vector4( drawCmd->ClipRect.X - pos.X, drawCmd->ClipRect.Y - pos.Y, drawCmd->ClipRect.Z - pos.X, drawCmd->ClipRect.W - pos.Y ); GL.Scissor((int)clipRect.X, (int)(fbHeight - clipRect.W), (int)(clipRect.Z - clipRect.X), (int)(clipRect.W - clipRect.Y)); GL.BindTexture(TextureTarget.Texture2D, drawCmd->TextureId.ToInt32()); GL.DrawElements(BeginMode.Triangles, (int)drawCmd->ElemCount, DrawElementsType.UnsignedShort, indexBufferOffset); indexBufferOffset += (int)drawCmd->ElemCount * 2; } } GL.DeleteVertexArray(vaoHandle); // restore modified GL state GL.UseProgram(lastProgram); GL.BindTexture(TextureTarget.Texture2D, lastTexture); GL.BindSampler(0, lastSampler); GL.ActiveTexture((TextureUnit)lastActiveTexture); GL.BindVertexArray(lastVertexArray); GL.BindBuffer(BufferTarget.ArrayBuffer, lastArrayBuffer); GL.BlendEquationSeparate((BlendEquationMode)lastBlendEquationRgb, (BlendEquationMode)lastBlendEquationAlpha); GL.BlendFuncSeparate((BlendingFactorSrc)lastBlendSrcRgb, (BlendingFactorDest)lastBlendDstRgb, (BlendingFactorSrc)lastBlendSrcAlpha, (BlendingFactorDest)lastBlendDstAlpha); if (lastEnableBlend) { GL.Enable(EnableCap.Blend); } else { GL.Disable(EnableCap.Blend); } if (lastEnableCullFace) { GL.Enable(EnableCap.CullFace); } else { GL.Disable(EnableCap.CullFace); } if (lastEnableDepthTest) { GL.Enable(EnableCap.DepthTest); } else { GL.Disable(EnableCap.DepthTest); } if (lastEnableScissorTest) { GL.Enable(EnableCap.ScissorTest); } else { GL.Disable(EnableCap.ScissorTest); } GL.PolygonMode(MaterialFace.FrontAndBack, (PolygonMode)lastPolygonMode[0]); GL.Viewport(lastViewport[0], lastViewport[1], lastViewport[2], lastViewport[3]); GL.Scissor(lastScissorBox[0], lastScissorBox[1], lastScissorBox[2], lastScissorBox[3]); }