private void RenderCommandLists(ImDrawDataPtr drawData) { // TODO Pass in the game window to get the screen width and height var m_Ortho = Monorail.Mathlib.Matrix4.CreateOrthographicOffCenter(0, 1280, 800, 0, -1, 1); m_GraphicsDevice.BindVertexArrayObject(m_VertexArrayObject.VaoId); var drawcount = 0; int vtxOffset = 0; int idxOffset = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; var texId = drawCmd.TextureId; OpenGL.GlBindings.Enable(OpenGL.Enable.GL_SCISSOR_TEST); OpenGL.GlBindings.glScissor((int)drawCmd.ClipRect.X, (int)drawCmd.ClipRect.Y, (uint)(drawCmd.ClipRect.Z - drawCmd.ClipRect.X), (uint)(drawCmd.ClipRect.W - drawCmd.ClipRect.Y)); // TODO If textureId not loaded? // m_GraphicsDevice.ScissorRect(); m_GraphicsDevice.BindShaderProgram(m_ShaderProgram.ShaderProgramId); m_GraphicsDevice.BindVertexArrayObject(m_VertexArrayObject.VaoId); m_GraphicsDevice.BindTexture(m_Texture.TextureId, OpenGL.TextureType.GL_TEXTURE_2D); m_ShaderProgram.SetUniform("projection_matrix", m_Ortho); m_ShaderProgram.SetUniform("FontTexture", 0); m_GraphicsDevice.DrawElements(PrimitiveType.TriangleList, (int)drawCmd.ElemCount, DrawElementsType.UnsignedInt, idxOffset); drawcount++; idxOffset += (int)drawCmd.ElemCount; } vtxOffset += cmdList.VtxBuffer.Size; } OpenGL.GlBindings.Disable(OpenGL.Enable.GL_SCISSOR_TEST); }
unsafe void updateBuffers(ImDrawDataPtr drawData) { if (drawData.TotalVtxCount == 0) { return; } // Expand buffers if we need more room if (drawData.TotalVtxCount > _vertexBufferSize) { _vertexBuffer?.Dispose(); _vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); _vertexBuffer = new VertexBuffer(Core.graphicsDevice, _vertexDeclaration, _vertexBufferSize, BufferUsage.None); _vertexData = new byte[_vertexBufferSize * _vertexDeclarationSize]; } if (drawData.TotalIdxCount > _indexBufferSize) { _indexBuffer?.Dispose(); _indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); _indexBuffer = new IndexBuffer(Core.graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); _indexData = new byte[_indexBufferSize * sizeof(ushort)]; } // Copy ImGui's vertices and indices to a set of managed byte arrays int vtxOffset = 0; int idxOffset = 0; for (var n = 0; n < drawData.CmdListsCount; n++) { var cmdList = drawData.CmdListsRange[n]; fixed(void *vtxDstPtr = &_vertexData[vtxOffset *_vertexDeclarationSize]) fixed(void *idxDstPtr = &_indexData[idxOffset * sizeof(ushort)]) { Buffer.MemoryCopy((void *)cmdList.VtxBuffer.Data, vtxDstPtr, _vertexData.Length, cmdList.VtxBuffer.Size * _vertexDeclarationSize); Buffer.MemoryCopy((void *)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); } vtxOffset += cmdList.VtxBuffer.Size; idxOffset += cmdList.IdxBuffer.Size; } // Copy the managed byte arrays to the gpu vertex- and index buffers _vertexBuffer.SetData(_vertexData, 0, drawData.TotalVtxCount * _vertexDeclarationSize); _indexBuffer.SetData(_indexData, 0, drawData.TotalIdxCount * sizeof(ushort)); }
void UpdateBuffers(ImDrawDataPtr drawData) { // copy de dators int vtxOffsetBytes = 0; int idxOffsetBytes = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; vertexBinding.Buffer.SetData(commandList, new DataPointer(cmdList.VtxBuffer.Data, cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>()), vtxOffsetBytes); indexBinding.Buffer.SetData(commandList, new DataPointer(cmdList.IdxBuffer.Data, cmdList.IdxBuffer.Size * sizeof(ushort)), idxOffsetBytes); vtxOffsetBytes += cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>(); idxOffsetBytes += cmdList.IdxBuffer.Size * sizeof(ushort); } }
private unsafe void RenderCommandLists(ImDrawDataPtr ptr) { GraphicsDevice.SetVertexBuffer(VertexBuffer); GraphicsDevice.Indices = IndexBuffer; int vtxOffset = 0; int idxOffset = 0; for (int i = 0; i < ptr.CmdListsCount; i++) { ImDrawListPtr cmdList = ptr.CmdListsRange[i]; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmdPtr cmd = cmdList.CmdBuffer[cmdi]; if (!Textures.ContainsKey(cmd.TextureId)) { throw new InvalidOperationException($"Could not find ImGUI texture with ID {cmd.TextureId}"); } GraphicsDevice.ScissorRectangle = new Rectangle( (int)cmd.ClipRect.X, (int)cmd.ClipRect.Y, (int)(cmd.ClipRect.Z - cmd.ClipRect.X), (int)(cmd.ClipRect.W - cmd.ClipRect.Y) ); Effect e = UpdateEffect(Textures[cmd.TextureId]); for (int passIndex = 0; passIndex < e.CurrentTechnique.Passes.Count; passIndex++) { EffectPass pass = e.CurrentTechnique.Passes[passIndex]; pass.Apply(); GraphicsDevice.DrawIndexedPrimitives( primitiveType: PrimitiveType.TriangleList, baseVertex: vtxOffset, minVertexIndex: 0, numVertices: cmdList.VtxBuffer.Size, startIndex: idxOffset, primitiveCount: (int)cmd.ElemCount / 3 ); } idxOffset += (int)cmd.ElemCount; } vtxOffset += cmdList.VtxBuffer.Size; } }
/// <summary> /// Ensures that the geometry buffers exist and have sufficient size. /// </summary> private void EnsureBuffers(ref ImDrawDataPtr drawDataPtr) { var dirty = false; var vtxCount = 0; var idxCount = 0; for (var i = 0; i < drawDataPtr.CmdListsCount; i++) { var cmd = drawDataPtr.CmdListsRange[i]; vtxCount = Math.Max(vtxCount, cmd.VtxBuffer.Size); idxCount = Math.Max(idxCount, cmd.IdxBuffer.Size); } if (vertexBuffer == null || vertexBuffer.VertexCount < vtxCount) { if (vertexBuffer != null) { vertexBuffer.Dispose(); } vertexBuffer = DynamicVertexBuffer.Create(ImGuiVertex.VertexDeclaration, vtxCount); dirty = true; } if (indexBuffer == null || indexBuffer.IndexCount < idxCount) { if (indexBuffer != null) { indexBuffer.Dispose(); } indexBuffer = DynamicIndexBuffer.Create(IndexBufferElementType.Int16, idxCount); dirty = true; } if (rasterizerState == null) { rasterizerState = RasterizerState.Create(); rasterizerState.ScissorTestEnable = true; } if (geometryStream == null || dirty) { this.geometryStream = GeometryStream.Create(); this.geometryStream.Attach(this.vertexBuffer); this.geometryStream.Attach(this.indexBuffer); } }
private unsafe void UpdateBuffers(ImDrawDataPtr drawData) { if (drawData.TotalVtxCount == 0) { return; } //// Expand buffers if we need more room //if (drawData.TotalVtxCount > _vertexBufferSize) //{ // _vertexBuffer?.Dispose(); // _vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); // _vertexBuffer = new VertexBuffer(_graphicsDevice, DrawVertDeclaration.Declaration, _vertexBufferSize, BufferUsage.None); // _vertexData = new byte[_vertexBufferSize * DrawVertDeclaration.Size]; //} //if (drawData.TotalIdxCount > _indexBufferSize) //{ // _indexBuffer?.Dispose(); // _indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); // _indexBuffer = new IndexBuffer(_graphicsDevice, IndexElementSize.SixteenBits, _indexBufferSize, BufferUsage.None); // _indexData = new byte[_indexBufferSize * sizeof(ushort)]; //} //// Copy ImGui's vertices and indices to a set of managed byte arrays //int vtxOffset = 0; //int idxOffset = 0; //for (int n = 0; n < drawData.CmdListsCount; n++) //{ // ImDrawListPtr cmdList = drawData.CmdListsRange[n]; // fixed (void* vtxDstPtr = &_vertexData[vtxOffset * DrawVertDeclaration.Size]) // fixed (void* idxDstPtr = &_indexData[idxOffset * sizeof(ushort)]) // { // Buffer.MemoryCopy((void*)cmdList.VtxBuffer.Data, vtxDstPtr, _vertexData.Length, cmdList.VtxBuffer.Size * DrawVertDeclaration.Size); // Buffer.MemoryCopy((void*)cmdList.IdxBuffer.Data, idxDstPtr, _indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); // } // vtxOffset += cmdList.VtxBuffer.Size; // idxOffset += cmdList.IdxBuffer.Size; //} //// Copy the managed byte arrays to the gpu vertex- and index buffers //_vertexBuffer.SetData(_vertexData, 0, drawData.TotalVtxCount * DrawVertDeclaration.Size); //_indexBuffer.SetData(_indexData, 0, drawData.TotalIdxCount * sizeof(ushort)); }
public static void Render(ImDrawDataPtr drawData, int w, int h) { var io = ImGui.GetIO(); GL.Enable(EnableCap.Blend); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); m_shader.Use(); GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, m_fontsTextureHandle); m_shader.SetVector2("viewport_min", new Vector2(0, 0)); m_shader.SetVector2("viewport_max", new Vector2(w, h)); GL.BindVertexArray(m_vertexArray); for (int i = 0; i < drawData.CmdListsCount; ++i) { var cmdList = drawData.CmdListsRange[i]; GL.BindBuffer(BufferTarget.ArrayBuffer, m_vertexBuffer); GL.BufferData(BufferTarget.ArrayBuffer, cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>(), cmdList.VtxBuffer.Data, BufferUsageHint.DynamicDraw); GL.BindBuffer(BufferTarget.ElementArrayBuffer, m_indexBuffer); GL.BufferData(BufferTarget.ElementArrayBuffer, cmdList.IdxBuffer.Size * sizeof(ushort), cmdList.IdxBuffer.Data, BufferUsageHint.DynamicDraw); for (int j = 0; j < cmdList.CmdBuffer.Size; ++j) { var cmd = cmdList.CmdBuffer[j]; int elemCount = (int)cmd.ElemCount; int offset = (int)cmd.IdxOffset; GL.DrawElements(PrimitiveType.Triangles, elemCount, DrawElementsType.UnsignedShort, offset * sizeof(ushort)); } //cmdList.VtxBuffer.Size //var d = drawList.VtxBuffer //drawList.VtxBuffer[0]. } }
private unsafe void RenderCommandLists(ImDrawDataPtr drawData) { _graphicsDevice.SetVertexBuffer(_vertexBuffer); _graphicsDevice.Indices = _indexBuffer; int vtxOffset = 0; int idxOffset = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; if (!_loadedTextures.ContainsKey(drawCmd.TextureId)) { throw new InvalidOperationException($"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings"); } _graphicsDevice.ScissorRectangle = new Rectangle( (int)drawCmd.ClipRect.X, (int)drawCmd.ClipRect.Y, (int)(drawCmd.ClipRect.Z - drawCmd.ClipRect.X), (int)(drawCmd.ClipRect.W - drawCmd.ClipRect.Y) ); var effect = UpdateEffect(_loadedTextures[drawCmd.TextureId]); foreach (var pass in effect.CurrentTechnique.Passes) { pass.Apply(); _graphicsDevice.DrawIndexedPrimitives( PrimitiveType.TriangleList, vtxOffset, idxOffset, (int)drawCmd.ElemCount / 3); } idxOffset += (int)drawCmd.ElemCount; } vtxOffset += cmdList.VtxBuffer.Size; } }
private void SetupRenderState(ImDrawDataPtr drawData, int fbWidth, int fbHeight, uint vertexArrayObject) { glEnable(GL_BLEND); glBlendEquation(GL_FUNC_ADD); glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA); glDisable(GL_CULL_FACE); glDisable(GL_DEPTH_TEST); glDisable(GL_STENCIL_TEST); glEnable(GL_SCISSOR_TEST); glDisable(GL_PRIMITIVE_RESTART); glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); glViewport(0, 0, fbWidth, fbHeight); var l = drawData.DisplayPos.X; var r = drawData.DisplayPos.X + drawData.DisplaySize.X; var t = drawData.DisplayPos.Y; var b = drawData.DisplayPos.Y + drawData.DisplaySize.Y; var orthoProjection = new[, ] { { 2.0f / (r - l), 0.0f, 0.0f, 0.0f }, { 0.0f, 2.0f / (t - b), 0.0f, 0.0f }, { 0.0f, 0.0f, -1.0f, 0.0f }, { (r + l) / (l - r), (t + b) / (b - t), 0.0f, 1.0f }, }; glUseProgram(_shaderHandle); glUniform1i(_attribLocationTex, 0); glUniformMatrix4fv(_attribLocationProjMtx, 1, false, orthoProjection[0, 0]); glBindSampler(0, 0); glBindVertexArray(vertexArrayObject); glBindBuffer(GL_ARRAY_BUFFER, _vboHandle); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _elementsHandle); glEnableVertexAttribArray(_attribLocationVtxPos); glEnableVertexAttribArray(_attribLocationVtxUv); glEnableVertexAttribArray(_attribLocationVtxColor); glVertexAttribPointer(_attribLocationVtxPos, 2, GL_FLOAT, false, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf <ImDrawVert>("pos")); glVertexAttribPointer(_attribLocationVtxUv, 2, GL_FLOAT, false, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf <ImDrawVert>("uv")); glVertexAttribPointer(_attribLocationVtxColor, 4, GL_UNSIGNED_BYTE, true, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf <ImDrawVert>("col")); }
private unsafe void UpdateBuffers(ImDrawDataPtr drawData) { if (drawData.TotalVtxCount == 0) { return; } if (drawData.TotalVtxCount > vertexBufferSize) { vertexBuffer?.Dispose(); vertexBufferSize = (int)(drawData.TotalVtxCount * 1.5f); vertexBuffer = new VertexBuffer(GraphicsDevice, DrawVertexDeclaration.Declaration, vertexBufferSize, BufferUsage.None); vertexData = new byte[vertexBufferSize * DrawVertexDeclaration.Size]; } if (drawData.TotalIdxCount > indexBufferSize) { indexBuffer?.Dispose(); indexBufferSize = (int)(drawData.TotalIdxCount * 1.5f); indexBuffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, indexBufferSize, BufferUsage.None); indexData = new byte[indexBufferSize * sizeof(ushort)]; } int vtxOffset = 0; int idxOffset = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; fixed(void *vtxDstPtr = &vertexData[vtxOffset *DrawVertexDeclaration.Size]) fixed(void *idxDstPtr = &indexData[idxOffset * sizeof(ushort)]) { Buffer.MemoryCopy((void *)cmdList.VtxBuffer.Data, vtxDstPtr, vertexData.Length, cmdList.VtxBuffer.Size * DrawVertexDeclaration.Size); Buffer.MemoryCopy((void *)cmdList.IdxBuffer.Data, idxDstPtr, indexData.Length, cmdList.IdxBuffer.Size * sizeof(ushort)); } vtxOffset += cmdList.VtxBuffer.Size; idxOffset += cmdList.IdxBuffer.Size; } vertexBuffer.SetData(vertexData, 0, drawData.TotalVtxCount * DrawVertexDeclaration.Size); indexBuffer.SetData(indexData, 0, drawData.TotalIdxCount * sizeof(ushort)); }
private unsafe void UpdateBuffers(ImDrawDataPtr drawData) { if (drawData.TotalVtxCount == 0) { return; } if (drawData.TotalVtxCount > _imGuiVertex.BufferSize) { _imGuiVertex.Buffer?.Dispose(); _imGuiVertex.BufferSize = (int)(drawData.TotalVtxCount * 1.5f); _imGuiVertex.Buffer = new VertexBuffer(GraphicsDevice, DrawVertexDeclaration.Declaration, _imGuiVertex.BufferSize, BufferUsage.None); _imGuiVertex.Data = new byte[_imGuiVertex.BufferSize * DrawVertexDeclaration.Size]; } if (drawData.TotalIdxCount > _imGuiIndex.BufferSize) { _imGuiIndex.Buffer?.Dispose(); _imGuiIndex.BufferSize = (int)(drawData.TotalIdxCount * 1.5f); _imGuiIndex.Buffer = new IndexBuffer(GraphicsDevice, IndexElementSize.SixteenBits, _imGuiIndex.BufferSize, BufferUsage.None); _imGuiIndex.Data = new byte[_imGuiIndex.BufferSize * sizeof(ushort)]; } var vertexOffset = 0; var indexOffset = 0; for (var i = 0; i < drawData.CmdListsCount; ++i) { var commands = drawData.CmdListsRange[i]; fixed(void *vtxDstPtr = &_imGuiVertex.Data[vertexOffset *DrawVertexDeclaration.Size]) { fixed(void *idxDstPtr = &_imGuiIndex.Data[indexOffset * sizeof(ushort)]) { Buffer.MemoryCopy((void *)commands.VtxBuffer.Data, vtxDstPtr, _imGuiVertex.Data.Length, commands.VtxBuffer.Size * DrawVertexDeclaration.Size); Buffer.MemoryCopy((void *)commands.IdxBuffer.Data, idxDstPtr, _imGuiIndex.Data.Length, commands.IdxBuffer.Size * sizeof(ushort)); } } vertexOffset += commands.VtxBuffer.Size; indexOffset += commands.IdxBuffer.Size; } _imGuiVertex.Buffer.SetData(_imGuiVertex.Data, 0, drawData.TotalVtxCount * DrawVertexDeclaration.Size); _imGuiIndex.Buffer.SetData(_imGuiIndex.Data, 0, drawData.TotalIdxCount * sizeof(ushort)); }
public void RenderDrawLists(CommandBuffer cmd, ImDrawDataPtr drawData) { Vector2 fbSize = drawData.DisplaySize * drawData.FramebufferScale; if (fbSize.x <= 0f || fbSize.y <= 0f || drawData.TotalVtxCount == 0) { return; // avoid rendering when minimized } s_updateBuffersPerfMarker.Begin(); UpdateBuffers(drawData); s_updateBuffersPerfMarker.End(); cmd.BeginSample("DearImGui.ExecuteDrawCommands"); s_createDrawComandsPerfMarker.Begin(); CreateDrawCommands(cmd, drawData, fbSize); s_createDrawComandsPerfMarker.End(); cmd.EndSample("DearImGui.ExecuteDrawCommands"); }
void CreateDrawCommands(CommandBuffer cmd, ImDrawDataPtr drawData, Vector2 fbSize) { var prevTextureId = System.IntPtr.Zero; var clipOffst = new Vector4(drawData.DisplayPos.x, drawData.DisplayPos.y, drawData.DisplayPos.x, drawData.DisplayPos.y); var clipScale = new Vector4(drawData.FramebufferScale.x, drawData.FramebufferScale.y, drawData.FramebufferScale.x, drawData.FramebufferScale.y); _material.SetBuffer(_verticesID, _vtxBuf); // bind vertex buffer cmd.SetViewport(new Rect(0f, 0f, fbSize.x, fbSize.y)); cmd.SetViewProjectionMatrices( Matrix4x4.Translate(new Vector3(0.5f / fbSize.x, 0.5f / fbSize.y, 0f)), // small adjustment to improve text Matrix4x4.Ortho(0f, fbSize.x, fbSize.y, 0f, 0f, 1f)); int vtxOf = 0; int argOf = 0; for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { ImDrawListPtr drawList = drawData.CmdListsRange[n]; for (int i = 0, iMax = drawList.CmdBuffer.Size; i < iMax; ++i, argOf += 5 * 4) { ImDrawCmdPtr drawCmd = drawList.CmdBuffer[i]; // TODO: user callback in drawCmd.UserCallback & drawCmd.UserCallbackData // project scissor rectangle into framebuffer space and skip if fully outside var clip = Vector4.Scale(drawCmd.ClipRect - clipOffst, clipScale); if (clip.x >= fbSize.x || clip.y >= fbSize.y || clip.z < 0f || clip.w < 0f) { continue; } if (prevTextureId != drawCmd.TextureId) { _properties.SetTexture(_texID, _texManager.GetTexture((int)(prevTextureId = drawCmd.TextureId))); } _properties.SetInt(_baseVertexID, vtxOf + (int)drawCmd.VtxOffset); // base vertex location not automatically added to SV_VertexID cmd.EnableScissorRect(new Rect(clip.x, fbSize.y - clip.w, clip.z - clip.x, clip.w - clip.y)); // invert y cmd.DrawProceduralIndirect(_idxBuf, Matrix4x4.identity, _material, -1, MeshTopology.Triangles, _argBuf, argOf, _properties); } vtxOf += drawList.VtxBuffer.Size; } cmd.DisableScissorRect(); }
private void RenderDrawData(ImDrawDataPtr drawData) { var width = (int)(drawData.DisplaySize.X * drawData.FramebufferScale.X); var height = (int)(drawData.DisplaySize.Y * drawData.FramebufferScale.Y); var renderState = SaveRenderState(); SetupRenderState(drawData, width, height, _vertexArray); var clipOff = drawData.DisplayPos; var clipScale = drawData.FramebufferScale; for (int n = 0; n < drawData.CmdListsCount; n++) { var cmdList = drawData.CmdListsRange[n]; GL.BufferData(BufferTarget.ArrayBuffer, cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>(), cmdList.VtxBuffer.Data, BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ElementArrayBuffer, cmdList.IdxBuffer.Size * sizeof(short), cmdList.IdxBuffer.Data, BufferUsageHint.StreamDraw); for (int cmd_i = 0; cmd_i < cmdList.CmdBuffer.Size; cmd_i++) { var pcmd = cmdList.CmdBuffer[cmd_i]; Vector4 clipRect = new Vector4 ( (pcmd.ClipRect.X - clipOff.X) * clipScale.X, (pcmd.ClipRect.Y - clipOff.Y) * clipScale.Y, (pcmd.ClipRect.Z - clipOff.X) * clipScale.X, (pcmd.ClipRect.W - clipOff.Y) * clipScale.Y ); if (clipRect.X < width && clipRect.Y < height && clipRect.Z >= 0.0f && clipRect.W >= 0.0f) { GL.Scissor((int)(clipRect.X), (int)(height - clipRect.W), (int)(clipRect.Z - clipRect.X), (int)(clipRect.W - clipRect.Y)); GL.BindTexture(TextureTarget.Texture2D, (int)pcmd.TextureId); GL.DrawElements(PrimitiveType.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (IntPtr)(pcmd.IdxOffset * sizeof(short))); } } } RestoreRenderState(renderState); }
private void RenderDrawData(ImDrawDataPtr ptr) { Viewport lastViewport = GraphicsDevice.Viewport; Rectangle lastScissor = GraphicsDevice.ScissorRectangle; GraphicsDevice.BlendFactor = Color.White; GraphicsDevice.BlendState = BlendState.NonPremultiplied; GraphicsDevice.RasterizerState = RasterizerState; GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; ptr.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); GraphicsDevice.Viewport = new Viewport(0, 0, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight); UpdateBuffers(ptr); RenderCommandLists(ptr); // Restore graphics state GraphicsDevice.Viewport = lastViewport; GraphicsDevice.ScissorRectangle = lastScissor; }
void CheckBuffers(ImDrawDataPtr drawData) { uint totalVBOSize = (uint)(drawData.TotalVtxCount * Unsafe.SizeOf <ImDrawVert>()); if (totalVBOSize > vertexBinding.Buffer.SizeInBytes) { var vertexBuffer = Xenko.Graphics.Buffer.Vertex.New(device, (int)(totalVBOSize * 1.5f)); vertexBinding = new VertexBufferBinding(vertexBuffer, imVertLayout, 0); } uint totalIBOSize = (uint)(drawData.TotalIdxCount * sizeof(ushort)); if (totalIBOSize > indexBinding.Buffer.SizeInBytes) { var is32Bits = false; var indexBuffer = Xenko.Graphics.Buffer.Index.New(device, (int)(totalIBOSize * 1.5f)); indexBinding = new IndexBufferBinding(indexBuffer, is32Bits, 0); } }
private void SetupRenderState(ImDrawDataPtr drawData) { // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, polygon fill 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, orthographic projection matrix // Our visible imgui space lies from draw_data->DisplayPos (top left) to draw_data->DisplayPos+data_data->DisplaySize (bottom right). DisplayPos is (0,0) for single viewport apps. Gl.Viewport(0, 0, (int)(drawData.DisplaySize.X * drawData.FramebufferScale.X), (int)(drawData.DisplaySize.Y * drawData.FramebufferScale.Y)); var L = drawData.DisplayPos.X; var R = drawData.DisplayPos.X + drawData.DisplaySize.X; var T = drawData.DisplayPos.Y; var B = drawData.DisplayPos.Y + drawData.DisplaySize.Y; var ortho_projection = new float[] { 2f / (R - L), 0, 0, 0, 0, 2f / (T - B), 0, 0, 0, 0, -1f, 0, (R + L) / (L - R), (T + B) / (B - T), 0, 1f }; Gl.UseProgram(_shaderHandle); Gl.Uniform1(_attribLocationTex, 0); Gl.UniformMatrix4(_attribLocationProjMtx, false, ortho_projection); Gl.BindVertexArray(_vertexArrayObject); // Bind vertex/index buffers and setup attributes for ImDrawVert Gl.BindBuffer(BufferTarget.ArrayBuffer, _vboHandle); Gl.BindBuffer(BufferTarget.ElementArrayBuffer, _elementsHandle); Gl.EnableVertexAttribArray((uint)_attribLocationVtxPos); Gl.EnableVertexAttribArray((uint)_attribLocationVtxUV); Gl.EnableVertexAttribArray((uint)_attribLocationVtxColor); Gl.VertexAttribPointer((uint)_attribLocationVtxPos, 2, VertexAttribType.Float, false, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf(typeof(ImDrawVert), "pos")); Gl.VertexAttribPointer((uint)_attribLocationVtxUV, 2, VertexAttribType.Float, false, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf(typeof(ImDrawVert), "uv")); Gl.VertexAttribPointer((uint)_attribLocationVtxColor, 4, VertexAttribType.UnsignedByte, true, Unsafe.SizeOf <ImDrawVert>(), Marshal.OffsetOf(typeof(ImDrawVert), "col")); }
private unsafe void RenderImDrawData(DrawEvent e) { CommandBuffer cmdBuffer = e.cmd; var io = ImGui.GetIO(); var graphics = Graphics.Instance; float width = io.DisplaySize.X; float height = io.DisplaySize.Y; ImDrawDataPtr draw_data = ImGui.GetDrawData(); if (draw_data.CmdListsCount == 0) { return; } if (pipeline == VkPipeline.Null) { pipeline = pass.CreateGraphicsPipeline(e.rendrPass, 0, VertexPos2dTexColor.Layout, VkPrimitiveTopology.TriangleList); } ref Buffer vb = ref vertexBuffer[graphics.WorkContext];
public unsafe void RenderDrawLists(CommandBuffer cmd, ImDrawDataPtr drawData) { NumericsV2f fbOSize = drawData.DisplaySize * drawData.FramebufferScale; if (fbOSize.X <= 0f || fbOSize.Y <= 0f || drawData.TotalVtxCount == 0) { return; // avoid rendering when minimized } Vector2 fbSize = *(Vector2 *)&fbOSize; s_updateMeshPerfMarker.Begin(); UpdateMesh(drawData, fbSize); s_updateMeshPerfMarker.End(); cmd.BeginSample("DearImGui.ExecuteDrawCommands"); s_createDrawComandsPerfMarker.Begin(); CreateDrawCommands(cmd, drawData, fbSize); s_createDrawComandsPerfMarker.End(); cmd.EndSample("DearImGui.ExecuteDrawCommands"); }
private void UpdateBuffers(ImDrawDataPtr data) { GL.BindVertexArray(vao); GL.BindBuffer(BufferTarget.ArrayBuffer, vertexBuffer); GL.BindBuffer(BufferTarget.ElementArrayBuffer, indexBuffer); int totalVBSize = (data.TotalVtxCount * Marshal.SizeOf <ImDrawVert>()); if (totalVBSize > sizeVertex) { sizeVertex = (int)(totalVBSize * 1.5f); GL.BufferData(BufferTarget.ArrayBuffer, sizeVertex, IntPtr.Zero, BufferUsageHint.DynamicDraw); } uint totalIBSize = (uint)(data.TotalIdxCount * sizeof(ushort)); if (totalIBSize > sizeIndex) { sizeIndex = (int)(totalIBSize * 1.5f); GL.BufferData(BufferTarget.ElementArrayBuffer, sizeIndex, IntPtr.Zero, BufferUsageHint.DynamicDraw); } int vertexOffsetInVertices = 0; int indexOffsetInElements = 0; for (int i = 0; i < data.CmdListsCount; i++) { ImDrawListPtr cmd_list = data.CmdListsRange[i]; GL.BufferSubData(BufferTarget.ArrayBuffer, (IntPtr)(vertexOffsetInVertices * Marshal.SizeOf <ImDrawVert>()), cmd_list.VtxBuffer.Size * Marshal.SizeOf <ImDrawVert>(), cmd_list.VtxBuffer.Data); GL.BufferSubData(BufferTarget.ElementArrayBuffer, (IntPtr)(indexOffsetInElements * sizeof(ushort)), cmd_list.IdxBuffer.Size * sizeof(ushort), cmd_list.IdxBuffer.Data); vertexOffsetInVertices += cmd_list.VtxBuffer.Size; indexOffsetInElements += cmd_list.IdxBuffer.Size; } }
private void RenderIMGui(Renderer renderer) { ImGui.Render(); ImDrawDataPtr drawData = ImGui.GetDrawData(); for (int i = 0; i < drawData.CmdListsCount; i++) { ImDrawListPtr cmdList = drawData.CmdListsRange[i]; IVertexBuffer vertexBuffer = CreateVertexBuffer(cmdList); int IndexOffset = 0; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmdPtr DrawCommand = cmdList.CmdBuffer[cmdi]; using (RenderingCommand cmd = renderer.RendererResourceFactory.CreateRenderCommand()) { cmd.WithVertexBuffer(vertexBuffer) .WithMaterial(Renderer.DefaultMaterialPtr.Get <Watertight.Rendering.Materials.Material>()) .WithCamera(UICamera); if (_ImGUITextureMap.ContainsKey(DrawCommand.TextureId)) { cmd.WithTexture(_ImGUITextureMap[DrawCommand.TextureId]); } cmd.WithStartIndex(IndexOffset) .WithPrimitveCount((int)DrawCommand.ElemCount / 3) .WithDebugName("IMGUI Renderer"); renderer.ExecuteRenderCommand(cmd); } IndexOffset += (int)DrawCommand.ElemCount; } } }
private void CreateDrawCommands(CommandBuffer cmd, ImDrawDataPtr drawData, Vector2 fbSize) { System.IntPtr prevTextureId = System.IntPtr.Zero; Vector4 clipOffst = new Vector4(drawData.DisplayPos.X, drawData.DisplayPos.Y, drawData.DisplayPos.X, drawData.DisplayPos.Y); Vector4 clipScale = new Vector4(drawData.FramebufferScale.X, drawData.FramebufferScale.Y, drawData.FramebufferScale.X, drawData.FramebufferScale.Y); cmd.SetViewport(new Rect(0f, 0f, fbSize.x, fbSize.y)); cmd.SetViewProjectionMatrices( Matrix4x4.Translate(new Vector3(0.5f / fbSize.x, 0.5f / fbSize.y, 0f)), // small adjustment to improve text Matrix4x4.Ortho(0f, fbSize.x, fbSize.y, 0f, 0f, 1f)); int subOf = 0; for (int n = 0, nMax = drawData.CmdListsCount; n < nMax; ++n) { ImDrawListPtr drawList = drawData.CmdListsRange[n]; for (int i = 0, iMax = drawList.CmdBuffer.Size; i < iMax; ++i, ++subOf) { ImDrawCmdPtr drawCmd = drawList.CmdBuffer[i]; // TODO: user callback in drawCmd.UserCallback & drawCmd.UserCallbackData // project scissor rectangle into framebuffer space and skip if fully outside Vector4 clip = Vector4.Scale(Helper.V4f(drawCmd.ClipRect) - clipOffst, clipScale); if (clip.x >= fbSize.x || clip.y >= fbSize.y || clip.z < 0f || clip.w < 0f) { continue; } if (prevTextureId != drawCmd.TextureId) { _properties.SetTexture(_texID, _texManager.GetTexture((int)(prevTextureId = drawCmd.TextureId))); } cmd.EnableScissorRect(new Rect(clip.x, fbSize.y - clip.w, clip.z - clip.x, clip.w - clip.y)); // invert y cmd.DrawMesh(_mesh, Matrix4x4.identity, _material, subOf, -1, _properties); } } cmd.DisableScissorRect(); }
private void RenderCommandLists(ImDrawDataPtr drawData) { this.GraphicsDevice.SetVertexBuffer(this.vertexBuffer); this.GraphicsDevice.Indices = this.indexBuffer; int vtxOffset = 0; int idxOffset = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++) { ImDrawCmdPtr drawCmd = cmdList.CmdBuffer[cmdi]; if (!this.LoadedTextures.ContainsKey(drawCmd.TextureId)) { throw new InvalidOperationException($"Could not find a texture with id '{drawCmd.TextureId}', please check your bindings"); } this.GraphicsDevice.ScissorRectangle = new Rectangle( (int)drawCmd.ClipRect.X, (int)drawCmd.ClipRect.Y, (int)(drawCmd.ClipRect.Z - drawCmd.ClipRect.X), (int)(drawCmd.ClipRect.W - drawCmd.ClipRect.Y) ); this.UpdateEffect(drawCmd.TextureId); this.Effect.Apply(); this.GraphicsDevice.DrawIndexedPrimitives(PrimitiveType.TriangleList, vtxOffset, idxOffset, (int)drawCmd.ElemCount / 3); idxOffset += (int)drawCmd.ElemCount; } vtxOffset += cmdList.VtxBuffer.Size; } }
void SetupRenderState(ImDrawDataPtr drawData, int fbWidth, int fbHeight) { glEnable(EnableCap.Blend); glBlendEquation(BlendEquationMode.FuncAdd); glBlendFunc(BlendingFactorSrc.SrcAlpha, BlendingFactorDest.OneMinusSrcAlpha); glDisable(EnableCap.CullFace); glDisable(EnableCap.DepthTest); glEnable(EnableCap.ScissorTest); glUseProgram(_shader.ProgramID); var left = drawData.DisplayPos.X; var right = drawData.DisplayPos.X + drawData.DisplaySize.X; var top = drawData.DisplayPos.Y; var bottom = drawData.DisplayPos.Y + drawData.DisplaySize.Y; _shader["Texture"].SetValue(0); _shader["ProjMtx"].SetValue(Matrix4x4.CreateOrthographicOffCenter(left, right, bottom, top, -1, 1)); glBindSampler(0, 0); glBindVertexArray(_vertexArrayObject); // Bind vertex/index buffers and setup attributes for ImDrawVert glBindBuffer(BufferTarget.ArrayBuffer, _vboHandle); glBindBuffer(BufferTarget.ElementArrayBuffer, _elementsHandle); EnableVertexAttribArray(_shader["Position"].Location); EnableVertexAttribArray(_shader["UV"].Location); EnableVertexAttribArray(_shader["Color"].Location); var drawVertSize = Marshal.SizeOf <ImDrawVert>(); VertexAttribPointer(_shader["Position"].Location, 2, VertexAttribPointerType.Float, false, drawVertSize, Marshal.OffsetOf <ImDrawVert>("pos")); VertexAttribPointer(_shader["UV"].Location, 2, VertexAttribPointerType.Float, false, drawVertSize, Marshal.OffsetOf <ImDrawVert>("uv")); VertexAttribPointer(_shader["Color"].Location, 4, VertexAttribPointerType.UnsignedByte, true, drawVertSize, Marshal.OffsetOf <ImDrawVert>("col")); }
public void RenderDrawData(RenderContext renderContext, ImDrawDataPtr drawData, int windowWidth, int windowHeight) { // If width or height is zero, game is minimized, so don't draw anything. if (windowWidth == 0 || windowHeight == 0) { return; } Rectangle lastViewport = renderContext.ViewportRectangle; Rectangle lastScissorRectangle = renderContext.ScissorRectangle; bool lastBlend = renderContext.Blend; bool lastDepthTest = renderContext.DepthTest; bool lastScissorTest = renderContext.ScissorTest; bool lastCullBackfaces = renderContext.CullBackfaces; // RenderContext.State state = renderContext.GetState(); renderContext.ViewportRectangle = new Rectangle(0, 0, windowWidth, windowHeight); renderContext.ScissorRectangle = new Rectangle(0, 0, windowWidth, windowHeight); renderContext.Blend = true; renderContext.DepthTest = false; renderContext.ScissorTest = true; renderContext.CullBackfaces = false; UpdateBuffers(renderContext, drawData); RenderCommandLists(renderContext, drawData); // renderContext.SetState(state); renderContext.ViewportRectangle = lastViewport; renderContext.ScissorRectangle = lastScissorRectangle; renderContext.Blend = lastBlend; renderContext.DepthTest = lastDepthTest; renderContext.ScissorTest = lastScissorTest; renderContext.CullBackfaces = lastCullBackfaces; }
/// <summary> /// Gets the geometry as set up by ImGui and sends it to the graphics device /// </summary> void RenderDrawData(ImDrawDataPtr drawData) { // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled, vertex/texcoord/color pointers var lastViewport = Core.GraphicsDevice.Viewport; var lastScissorBox = Core.GraphicsDevice.ScissorRectangle; Core.GraphicsDevice.BlendFactor = Color.White; Core.GraphicsDevice.BlendState = BlendState.NonPremultiplied; Core.GraphicsDevice.RasterizerState = _rasterizerState; Core.GraphicsDevice.DepthStencilState = DepthStencilState.DepthRead; // Handle cases of screen coordinates != from framebuffer coordinates (e.g. retina displays) drawData.ScaleClipRects(ImGui.GetIO().DisplayFramebufferScale); // Setup projection Core.GraphicsDevice.Viewport = new Viewport(0, 0, Core.GraphicsDevice.PresentationParameters.BackBufferWidth, Core.GraphicsDevice.PresentationParameters.BackBufferHeight); UpdateBuffers(drawData); RenderCommandLists(drawData); // Restore modified state Core.GraphicsDevice.Viewport = lastViewport; Core.GraphicsDevice.ScissorRectangle = lastScissorBox; }
private void RenderImDrawData(ImDrawDataPtr drawData, GraphicsDevice gd, CommandList cl) { uint vertexOffsetInVertices = 0; uint indexOffsetInElements = 0; if (drawData.CmdListsCount == 0) { return; } uint totalVbSize = (uint)(drawData.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)(drawData.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 < drawData.CmdListsCount; i++) { ImDrawListPtr cmdList = drawData.CmdListsRange[i]; cl.UpdateBuffer( _vertexBuffer, vertexOffsetInVertices * (uint)Unsafe.SizeOf <ImDrawVert>(), cmdList.VtxBuffer.Data, (uint)(cmdList.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>())); cl.UpdateBuffer( _indexBuffer, indexOffsetInElements * sizeof(ushort), cmdList.IdxBuffer.Data, (uint)(cmdList.IdxBuffer.Size * sizeof(ushort))); vertexOffsetInVertices += (uint)cmdList.VtxBuffer.Size; indexOffsetInElements += (uint)cmdList.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); drawData.ScaleClipRects(io.DisplayFramebufferScale); // Render command lists int vtxOffset = 0; int idxOffset = 0; for (int n = 0; n < drawData.CmdListsCount; n++) { ImDrawListPtr cmdList = drawData.CmdListsRange[n]; for (int cmdI = 0; cmdI < cmdList.CmdBuffer.Size; cmdI++) { ImDrawCmdPtr pcmd = cmdList.CmdBuffer[cmdI]; 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)idxOffset, vtxOffset, 0); } idxOffset += (int)pcmd.ElemCount; } vtxOffset += cmdList.VtxBuffer.Size; } }
private void RenderImDrawData(ImDrawDataPtr draw_data) { if (draw_data.CmdListsCount == 0) { return; } for (int i = 0; i < draw_data.CmdListsCount; i++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[i]; int vertexSize = cmd_list.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>(); if (vertexSize > _vertexBufferSize) { int newSize = (int)Math.Max(_vertexBufferSize * 1.5f, vertexSize); GL.NamedBufferData(_vertexBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw); _vertexBufferSize = newSize; Console.WriteLine($"Resized dear imgui vertex buffer to new size {_vertexBufferSize}"); } int indexSize = cmd_list.IdxBuffer.Size * sizeof(ushort); if (indexSize > _indexBufferSize) { int newSize = (int)Math.Max(_indexBufferSize * 1.5f, indexSize); GL.NamedBufferData(_indexBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw); _indexBufferSize = newSize; Console.WriteLine($"Resized dear imgui index buffer to new size {_indexBufferSize}"); } } // Setup orthographic projection matrix into our constant buffer ImGuiIOPtr io = ImGui.GetIO(); Matrix4 mvp = Matrix4.CreateOrthographicOffCenter( 0.0f, io.DisplaySize.X, io.DisplaySize.Y, 0.0f, -1.0f, 1.0f); _shaderLoader.UseShader(); GL.UniformMatrix4(_shaderLoader.GetUniformLocation("projection_matrix"), false, ref mvp); GL.Uniform1(_shaderLoader.GetUniformLocation("in_fontTexture"), 0); Util.CheckGLError("Projection"); GL.BindVertexArray(_vertexArray); Util.CheckGLError("VAO"); draw_data.ScaleClipRects(io.DisplayFramebufferScale); GL.Enable(EnableCap.Blend); GL.Enable(EnableCap.ScissorTest); GL.BlendEquation(BlendEquationMode.FuncAdd); GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha); GL.Disable(EnableCap.CullFace); GL.Disable(EnableCap.DepthTest); // Render command lists for (int n = 0; n < draw_data.CmdListsCount; n++) { ImDrawListPtr cmd_list = draw_data.CmdListsRange[n]; GL.NamedBufferSubData(_vertexBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Unsafe.SizeOf <ImDrawVert>(), cmd_list.VtxBuffer.Data); Util.CheckGLError($"Data Vert {n}"); GL.NamedBufferSubData(_indexBuffer, IntPtr.Zero, cmd_list.IdxBuffer.Size * sizeof(ushort), cmd_list.IdxBuffer.Data); Util.CheckGLError($"Data Idx {n}"); int vtx_offset = 0; int idx_offset = 0; 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 { GL.ActiveTexture(TextureUnit.Texture0); GL.BindTexture(TextureTarget.Texture2D, (int)pcmd.TextureId); Util.CheckGLError("Texture"); // We do _windowHeight - (int)clip.W instead of (int)clip.Y because gl has flipped Y when it comes to these coordinates var clip = pcmd.ClipRect; GL.Scissor((int)clip.X, _windowHeight - (int)clip.W, (int)(clip.Z - clip.X), (int)(clip.W - clip.Y)); Util.CheckGLError("Scissor"); if ((io.BackendFlags & ImGuiBackendFlags.RendererHasVtxOffset) != 0) { GL.DrawElementsBaseVertex(PrimitiveType.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (IntPtr)(idx_offset * sizeof(ushort)), vtx_offset); } else { GL.DrawElements(BeginMode.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (int)pcmd.IdxOffset * sizeof(ushort)); } Util.CheckGLError("Draw"); } idx_offset += (int)pcmd.ElemCount; } vtx_offset += cmd_list.VtxBuffer.Size; } GL.Disable(EnableCap.Blend); GL.Disable(EnableCap.ScissorTest); }
void LateUpdate() { last_start = stopwatch.Elapsed.TotalSeconds; if (drawDebugWindow) { DrawDebugWindow(); } ImGui.EndFrame(); if (queue_font_rebuild) { RebuildFonts(); queue_font_rebuild = false; } // custom cursors if (enableCustomCursors) { ImGuiMouseCursor cursor = ImGui.GetMouseCursor(); Texture2D cursorTex = null; Vector2 hotspot = cursorHotspot; switch (cursor) { case ImGuiMouseCursor.Arrow: cursorTex = customCursorArrow; break; case ImGuiMouseCursor.TextInput: cursorTex = customCursorTextInput; break; case ImGuiMouseCursor.ResizeEW: cursorTex = customCursorResizeEW; break; case ImGuiMouseCursor.ResizeNESW: cursorTex = customCursorResizeNESW; hotspot.x += 5; hotspot.y += 5; break; case ImGuiMouseCursor.ResizeNS: cursorTex = customCursorResizeNS; break; case ImGuiMouseCursor.ResizeNWSE: cursorTex = customCursorResizeNWSE; hotspot.x += 5; hotspot.y += 5; break; default: break; } // Don't set cursor if it has not actually changed if (currentCursorTex != cursorTex) { if (cursorTex != null) { Cursor.SetCursor(cursorTex, hotspot, CursorMode.Auto); } else { Cursor.SetCursor(null, cursorHotspot, CursorMode.Auto); } currentCursorTex = cursorTex; } } ImGui.Render(); // render ImGui ImDrawDataPtr data = ImGui.GetDrawData(); if (commandBuffer != null) { // Clear buffer regardless of whether we have something to render or not commandBuffer.Clear(); } // Don't update meshes and Command Buffers if there is nothing to render if (data.CmdListsCount > 0) { // resize meshes array int numDrawCommands = 0; for (int i = 0; i < data.CmdListsCount; i++) { ImDrawListPtr cmdList = data.getDrawListPtr(i); var cmdBuffer = cmdList.CmdBuffer; numDrawCommands += cmdBuffer.Size; } if (meshes == null) { meshes = new List <ImGuiMesh>(); } if (meshes.Count != numDrawCommands) { // add new meshes to list if needed for (int i = meshes.Count; i < numDrawCommands; i++) { ImGuiMesh mesh = new ImGuiMesh(); meshes.Add(mesh); } // delete extra meshes if needed for (int i = meshes.Count - 1; i >= numDrawCommands; i--) { Destroy(meshes[i].mesh); meshes.RemoveAt(i); } } if (commandBuffer == null) { commandBuffer = new CommandBuffer(); commandBuffer.name = "ImGui Renderer"; commandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); guiCamera.AddCommandBuffer(CameraEvent.AfterEverything, commandBuffer); } commandBuffer.SetRenderTarget(BuiltinRenderTextureType.CameraTarget); // orthogonal projection of GUI mesh to camera space Matrix4x4 matrix = Matrix4x4.Ortho(0, Screen.width, 0, Screen.height, 0, 0.1f); // negate world to camera transform and projection which Unity applies itself matrix = guiCamera.cameraToWorldMatrix * guiCamera.projectionMatrix.inverse * matrix; // update Command Buffers int count = 0; for (int i = 0; i < data.CmdListsCount; i++) { ImDrawListPtr cmdList = data.getDrawListPtr(i); var cmdBuffer = cmdList.CmdBuffer; uint startElement = 0; for (int j = 0; j < cmdBuffer.Size; j++) { ImDrawCmd cmd = cmdBuffer[j]; Rect rect = new Rect { min = new Vector2(cmd.ClipRect.x, Screen.height - cmd.ClipRect.y), max = new Vector2(cmd.ClipRect.z, Screen.height - cmd.ClipRect.w) }; commandBuffer.EnableScissorRect(rect); meshes[count].UpdateMesh(cmd, cmdList.IdxBuffer, cmdList.VtxBuffer, (int)startElement); if (cmd.TextureId == fontTexturePtr) { mpb.SetTexture(main_tex_id, fontTexture); commandBuffer.DrawMesh(meshes[count].mesh, matrix, material, 0, 0, mpb); } else if (textures.ContainsKey(cmd.TextureId)) { mpb.SetTexture(main_tex_id, textures[cmd.TextureId]); commandBuffer.DrawMesh(meshes[count].mesh, matrix, material, 0, 0, mpb); } else { Debug.LogWarning("Image texture missing!"); } startElement += cmd.ElemCount; count++; } } } else if (commandBuffer != null) { // Remove Command Buffer if there is nothing to render guiCamera.RemoveCommandBuffer(CameraEvent.AfterEverything, commandBuffer); commandBuffer = null; } textures.Clear(); last_end = stopwatch.Elapsed.TotalSeconds; }
unsafe void RenderImDrawData(ImDrawDataPtr draw_data, RenderState rstate) { var io = ImGui.GetIO(); //Set cursor var cur = ImGuiNative.igGetMouseCursor(); switch (cur) { case ImGuiMouseCursor.Arrow: game.CursorKind = CursorKind.Arrow; break; case ImGuiMouseCursor.ResizeAll: game.CursorKind = CursorKind.Move; break; case ImGuiMouseCursor.TextInput: game.CursorKind = CursorKind.TextInput; break; case ImGuiMouseCursor.ResizeNS: game.CursorKind = CursorKind.ResizeNS; break; case ImGuiMouseCursor.ResizeNESW: game.CursorKind = CursorKind.ResizeNESW; break; case ImGuiMouseCursor.ResizeNWSE: game.CursorKind = CursorKind.ResizeNWSE; break; } //Render draw_data.ScaleClipRects(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.CmdListsRange[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 = (ImDrawVert *)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 = cmd_list.CmdBuffer[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; } } }