Skip to content

Commit

Permalink
Move the imgui rendering to the opengl renderer
Browse files Browse the repository at this point in the history
  • Loading branch information
behindcurtain3 committed Jan 10, 2025
1 parent 335aa64 commit 6ba330f
Show file tree
Hide file tree
Showing 4 changed files with 122 additions and 125 deletions.
124 changes: 0 additions & 124 deletions Pulsar4X/Pulsar4X.Client/IMGUISDL/ImGuiSDL2CSHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System;
using ImGuiNET;
using System.IO;
using System.Runtime.CompilerServices;
using Pulsar4X.DataStructures;
using Vector2 = System.Numerics.Vector2;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -97,129 +96,6 @@ public static void NewFrame(Vector2 size, Vector2 scale, Vector2 mousePosition,
ImGui.NewFrame();
}

public static void Render(Vector2 size)
{
ImGui.Render();
//if (ImGui.GetIO().RenderDrawListsFn == IntPtr.Zero)
RenderDrawData(ImGui.GetDrawData(), (int) Math.Round(size.X), (int) Math.Round(size.Y));
}

public static void RenderDrawData(ImDrawDataPtr 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.
GL.GetIntegerv(GL.Enum.GL_TEXTURE_BINDING_2D, out int lastTexture);
GL.GetIntegerv4(GL.Enum.GL_VIEWPORT, out Int4 lastViewport);
GL.GetIntegerv4(GL.Enum.GL_SCISSOR_BOX, out Int4 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)
ImGuiIOPtr io = ImGui.GetIO();

//ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); imgui.net doesn't apear to have this

// 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++)
{
ImDrawListPtr cmdList = drawData.CmdListsRange[n];
//ImDrawList cmdList = drawData[n];
ImPtrVector<ImDrawVertPtr> vtxBuffer = cmdList.VtxBuffer;
ImVector<ushort> idxBuffer = cmdList.IdxBuffer;
int posOffset = 0;
int uvOffset = 8;
int colOffset = 16;
//GL.VertexPointer(
GL.VertexPointer(2, GL.Enum.GL_FLOAT, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + posOffset));
GL.TexCoordPointer(2, GL.Enum.GL_FLOAT, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + uvOffset));
GL.ColorPointer(4, GL.Enum.GL_UNSIGNED_BYTE, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + colOffset));

long idxBufferOffset = 0;
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++)
{
ImDrawCmdPtr pcmd = cmdList.CmdBuffer[cmdi];

if (pcmd.UserCallback != IntPtr.Zero)
{
throw new NotImplementedException();
//pcmd.InvokeUserCallback(ref cmdList, ref pcmd);
}
else if (FontTextureID == pcmd.TextureId)
{
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));

}
else
{
float w, h;
var txid = pcmd.TextureId;
var sdlid = SDL.SDL_GL_BindTexture(pcmd.TextureId, out w, out h);

string errstr = SDL.SDL_GetError();
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 static bool HandleEvent(SDL.SDL_Event e, ref float mouseWheel, bool[] mousePressed)
{
ImGuiIOPtr io = ImGui.GetIO();
Expand Down
3 changes: 2 additions & 1 deletion Pulsar4X/Pulsar4X.Client/IMGUISDL/ImGuiSDL2CSWindow.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,8 @@ public virtual void ImGuiRender()

ImGuiLayout();

ImGuiSDL2CSHelper.Render(Size);
ImGui.Render();
Renderer.RenderImGui(ImGui.GetDrawData(), (int) Size.X, (int) Size.Y);
}

public virtual void ImGuiLayout()
Expand Down
2 changes: 2 additions & 0 deletions Pulsar4X/Pulsar4X.Client/Rendering/IRenderer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System;
using ImGuiNET;

namespace Pulsar4X.Client.Rendering;

Expand All @@ -18,4 +19,5 @@ public interface IRenderer : IDisposable
void Clear(float r, float g, float b, float a);

int CreateDefaultFontTexture(int width, int height, IntPtr pixels);
void RenderImGui(ImDrawDataPtr drawData, int displayWidth, int displayHeight);
}
118 changes: 118 additions & 0 deletions Pulsar4X/Pulsar4X.Client/Rendering/OpenGLRenderer.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System;
using System.Runtime.CompilerServices;
using ImGuiNET;
using ImGuiSDL2CS;
using SDL2;

Expand Down Expand Up @@ -67,6 +69,122 @@ public int CreateDefaultFontTexture(int width, int height, IntPtr pixels)
return fontTextureID;
}

public void RenderImGui(ImDrawDataPtr drawData, int displayWidth, int displayHeight)
{
// 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.
GL.GetIntegerv(GL.Enum.GL_TEXTURE_BINDING_2D, out int lastTexture);
GL.GetIntegerv4(GL.Enum.GL_VIEWPORT, out Int4 lastViewport);
GL.GetIntegerv4(GL.Enum.GL_SCISSOR_BOX, out Int4 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)
ImGuiIOPtr io = ImGui.GetIO();

//ImGui.ScaleClipRects(drawData, io.DisplayFramebufferScale); imgui.net doesn't apear to have this

// Setup orthographic projection matrix
GL.Viewport(0, 0, displayWidth, displayHeight);
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++)
{
ImDrawListPtr cmdList = drawData.CmdListsRange[n];
//ImDrawList cmdList = drawData[n];
ImPtrVector<ImDrawVertPtr> vtxBuffer = cmdList.VtxBuffer;
ImVector<ushort> idxBuffer = cmdList.IdxBuffer;
int posOffset = 0;
int uvOffset = 8;
int colOffset = 16;
//GL.VertexPointer(
GL.VertexPointer(2, GL.Enum.GL_FLOAT, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + posOffset));
GL.TexCoordPointer(2, GL.Enum.GL_FLOAT, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + uvOffset));
GL.ColorPointer(4, GL.Enum.GL_UNSIGNED_BYTE, Unsafe.SizeOf<ImDrawVert>(), new IntPtr((long) vtxBuffer.Data + colOffset));

long idxBufferOffset = 0;
for (int cmdi = 0; cmdi < cmdList.CmdBuffer.Size; cmdi++)
{
ImDrawCmdPtr pcmd = cmdList.CmdBuffer[cmdi];

if (pcmd.UserCallback != IntPtr.Zero)
{
throw new NotImplementedException();
//pcmd.InvokeUserCallback(ref cmdList, ref pcmd);
}
else if (io.Fonts.TexID == pcmd.TextureId)
{
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));

}
else
{
float w, h;
var txid = pcmd.TextureId;
var sdlid = SDL.SDL_GL_BindTexture(pcmd.TextureId, out w, out h);

string errstr = SDL.SDL_GetError();
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 Dispose()
{
if(_glContext != IntPtr.Zero)
Expand Down

0 comments on commit 6ba330f

Please sign in to comment.