theUpsider

ImGuiController

Jul 13th, 2025
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 26.54 KB | Gaming | 0 0
  1. using ImGuiNET;
  2. using System.Runtime.CompilerServices;
  3. using OpenTK.Graphics.OpenGL;
  4. using OpenTK.Mathematics;
  5. using OpenTK.Windowing.Desktop;
  6. using OpenTK.Windowing.GraphicsLibraryFramework;
  7. using System.Diagnostics;
  8. using ErrorCode = OpenTK.Graphics.OpenGL4.ErrorCode;
  9.  
  10. namespace Dear_ImGui_Sample
  11. {
  12.     public class ImGuiController : IDisposable
  13.     {
  14.         private bool _frameBegun;
  15.         private IntPtr context;
  16.  
  17.         private int _vertexArray;
  18.         private int _vertexBuffer;
  19.         private int _vertexBufferSize;
  20.         private int _indexBuffer;
  21.         private int _indexBufferSize;
  22.  
  23.         //private Texture _fontTexture;
  24.  
  25.         private int _fontTexture;
  26.  
  27.         private int _shader;
  28.         private int _shaderFontTextureLocation;
  29.         private int _shaderProjectionMatrixLocation;
  30.  
  31.         private int _windowWidth;
  32.         private int _windowHeight;
  33.  
  34.         private System.Numerics.Vector2 _scaleFactor = System.Numerics.Vector2.One;
  35.  
  36.         private static bool KHRDebugAvailable = false;
  37.  
  38.         private int GLVersion;
  39.         private bool CompatibilityProfile;
  40.  
  41.         private bool _disposed;
  42.  
  43.         public IntPtr Context => context;
  44.  
  45.         /// <summary>
  46.         /// Constructs a new ImGuiController.
  47.         /// </summary>
  48.         public ImGuiController(int width, int height)
  49.         {
  50.             _windowWidth = width;
  51.             _windowHeight = height;
  52.  
  53.             int major = GL.GetInteger(GetPName.MajorVersion);
  54.             int minor = GL.GetInteger(GetPName.MinorVersion);
  55.  
  56.             GLVersion = major * 100 + minor * 10;
  57.  
  58.             KHRDebugAvailable = (major == 4 && minor >= 3) || IsExtensionSupported("KHR_debug");
  59.  
  60.             CompatibilityProfile = (GL.GetInteger((GetPName)All.ContextProfileMask) & (int)All.ContextCompatibilityProfileBit) != 0;
  61.  
  62.             context = ImGui.CreateContext();
  63.             ImGui.SetCurrentContext(context);
  64.             var io = ImGui.GetIO();
  65.             io.Fonts.AddFontDefault();
  66.  
  67.             io.BackendFlags |= ImGuiBackendFlags.RendererHasVtxOffset;
  68.             // Enable Docking
  69.             io.ConfigFlags |= ImGuiConfigFlags.DockingEnable;
  70.  
  71.             CreateDeviceResources();
  72.  
  73.             SetPerFrameImGuiData(1f / 60f);
  74.  
  75.             ImGui.NewFrame();
  76.             _frameBegun = true;
  77.         }
  78.  
  79.         // Add finalizer
  80.         ~ImGuiController()
  81.         {
  82.             Dispose(false);
  83.         }
  84.  
  85.         // Modify existing Dispose method to call new protected Dispose method
  86.         public void Dispose()
  87.         {
  88.             Dispose(true);
  89.             GC.SuppressFinalize(this);
  90.         }
  91.  
  92.         // Add protected virtual Dispose method
  93.         protected virtual void Dispose(bool disposing)
  94.         {
  95.             if (_disposed)
  96.                 return;
  97.  
  98.             if (disposing)
  99.             {
  100.                 // Dispose managed resources
  101.                 GL.DeleteVertexArray(_vertexArray);
  102.                 GL.DeleteBuffer(_vertexBuffer);
  103.                 GL.DeleteBuffer(_indexBuffer);
  104.                 GL.DeleteTexture(_fontTexture);
  105.                 GL.DeleteProgram(_shader);
  106.             }
  107.  
  108.             // Dispose unmanaged resources (if any)
  109.  
  110.             _disposed = true;
  111.         }
  112.  
  113.         // Add check for disposed state to public methods
  114.         public void WindowResized(int width, int height)
  115.         {
  116.             ThrowIfDisposed();
  117.             _windowWidth = width;
  118.             _windowHeight = height;
  119.         }
  120.  
  121.         // Add helper method to check disposed state
  122.         private void ThrowIfDisposed()
  123.         {
  124.             if (_disposed)
  125.             {
  126.                 throw new ObjectDisposedException(nameof(ImGuiController));
  127.             }
  128.         }
  129.  
  130.         // Update DestroyDeviceObjects to use Dispose
  131.         public void DestroyDeviceObjects()
  132.         {
  133.             ThrowIfDisposed();
  134.             Dispose();
  135.         }
  136.  
  137.         public void CreateDeviceResources()
  138.         {
  139.             _vertexBufferSize = 10000;
  140.             _indexBufferSize = 2000;
  141.  
  142.             int prevVAO = GL.GetInteger(GetPName.VertexArrayBinding);
  143.             int prevArrayBuffer = GL.GetInteger(GetPName.ArrayBufferBinding);
  144.  
  145.             _vertexArray = GL.GenVertexArray();
  146.             GL.BindVertexArray(_vertexArray);
  147.             LabelObject(ObjectLabelIdentifier.VertexArray, _vertexArray, "ImGui");
  148.  
  149.             _vertexBuffer = GL.GenBuffer();
  150.             GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffer);
  151.             LabelObject(ObjectLabelIdentifier.Buffer, _vertexBuffer, "VBO: ImGui");
  152.             GL.BufferData(BufferTarget.ArrayBuffer, _vertexBufferSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
  153.  
  154.             _indexBuffer = GL.GenBuffer();
  155.             GL.BindBuffer(BufferTarget.ElementArrayBuffer, _indexBuffer);
  156.             LabelObject(ObjectLabelIdentifier.Buffer, _indexBuffer, "EBO: ImGui");
  157.             GL.BufferData(BufferTarget.ElementArrayBuffer, _indexBufferSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
  158.  
  159.             RecreateFontDeviceTexture();
  160.  
  161.             string VertexSource = @"#version 330 core
  162.  
  163. uniform mat4 projection_matrix;
  164.  
  165. layout(location = 0) in vec2 in_position;
  166. layout(location = 1) in vec2 in_texCoord;
  167. layout(location = 2) in vec4 in_color;
  168.  
  169. out vec4 color;
  170. out vec2 texCoord;
  171.  
  172. void main()
  173. {
  174.    gl_Position = projection_matrix * vec4(in_position, 0, 1);
  175.    color = in_color;
  176.    texCoord = in_texCoord;
  177. }";
  178.             string FragmentSource = @"#version 330 core
  179.  
  180. uniform sampler2D in_fontTexture;
  181.  
  182. in vec4 color;
  183. in vec2 texCoord;
  184.  
  185. out vec4 outputColor;
  186.  
  187. void main()
  188. {
  189.    outputColor = color * texture(in_fontTexture, texCoord);
  190. }";
  191.  
  192.             _shader = CreateProgram("ImGui", VertexSource, FragmentSource);
  193.             _shaderProjectionMatrixLocation = GL.GetUniformLocation(_shader, "projection_matrix");
  194.             _shaderFontTextureLocation = GL.GetUniformLocation(_shader, "in_fontTexture");
  195.  
  196.             int stride = Unsafe.SizeOf<ImDrawVert>();
  197.             GL.VertexAttribPointer(0, 2, VertexAttribPointerType.Float, false, stride, 0);
  198.             GL.VertexAttribPointer(1, 2, VertexAttribPointerType.Float, false, stride, 8);
  199.             GL.VertexAttribPointer(2, 4, VertexAttribPointerType.UnsignedByte, true, stride, 16);
  200.  
  201.             GL.EnableVertexAttribArray(0);
  202.             GL.EnableVertexAttribArray(1);
  203.             GL.EnableVertexAttribArray(2);
  204.  
  205.             GL.BindVertexArray(prevVAO);
  206.             GL.BindBuffer(BufferTarget.ArrayBuffer, prevArrayBuffer);
  207.  
  208.             CheckGLError("End of ImGui setup");
  209.         }
  210.  
  211.         /// <summary>
  212.         /// Recreates the device texture used to render text.
  213.         /// </summary>
  214.         public void RecreateFontDeviceTexture()
  215.         {
  216.             ImGuiIOPtr io = ImGui.GetIO();
  217.             io.Fonts.GetTexDataAsRGBA32(out IntPtr pixels, out int width, out int height, out int bytesPerPixel);
  218.  
  219.             int mips = (int)Math.Floor(Math.Log(Math.Max(width, height), 2));
  220.  
  221.             int prevActiveTexture = GL.GetInteger(GetPName.ActiveTexture);
  222.             GL.ActiveTexture(TextureUnit.Texture0);
  223.             int prevTexture2D = GL.GetInteger(GetPName.TextureBinding2D);
  224.  
  225.             _fontTexture = GL.GenTexture();
  226.             GL.BindTexture(TextureTarget.Texture2D, _fontTexture);
  227.             GL.TexStorage2D(TextureTarget2d.Texture2D, mips, SizedInternalFormat.Rgba8, width, height);
  228.             LabelObject(ObjectLabelIdentifier.Texture, _fontTexture, "ImGui Text Atlas");
  229.  
  230.             GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, width, height, PixelFormat.Bgra, PixelType.UnsignedByte, pixels);
  231.  
  232.             GL.GenerateMipmap(GenerateMipmapTarget.Texture2D);
  233.  
  234.             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapS, (int)TextureWrapMode.Repeat);
  235.             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureWrapT, (int)TextureWrapMode.Repeat);
  236.  
  237.             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMaxLevel, mips - 1);
  238.  
  239.             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, (int)TextureMagFilter.Linear);
  240.             GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, (int)TextureMinFilter.Linear);
  241.  
  242.             // Restore state
  243.             GL.BindTexture(TextureTarget.Texture2D, prevTexture2D);
  244.             GL.ActiveTexture((TextureUnit)prevActiveTexture);
  245.  
  246.             io.Fonts.SetTexID((IntPtr)_fontTexture);
  247.  
  248.             io.Fonts.ClearTexData();
  249.         }
  250.  
  251.         /// <summary>
  252.         /// Renders the ImGui draw list data.
  253.         /// </summary>
  254.         public void Render()
  255.         {
  256.             if (_frameBegun)
  257.             {
  258.                 _frameBegun = false;
  259.                 ImGui.Render();
  260.                 RenderImDrawData(ImGui.GetDrawData());
  261.             }
  262.         }
  263.  
  264.         /// <summary>
  265.         /// Updates ImGui input and IO configuration state.
  266.         /// </summary>
  267.         public void Update(GameWindow wnd, float deltaSeconds)
  268.         {
  269.             if (_frameBegun)
  270.             {
  271.                 ImGui.Render();
  272.             }
  273.  
  274.             SetPerFrameImGuiData(deltaSeconds);
  275.             UpdateImGuiInput(wnd);
  276.  
  277.             _frameBegun = true;
  278.             ImGui.NewFrame();
  279.         }
  280.  
  281.         /// <summary>
  282.         /// Sets per-frame data based on the associated window.
  283.         /// This is called by Update(float).
  284.         /// </summary>
  285.         private void SetPerFrameImGuiData(float deltaSeconds)
  286.         {
  287.             ImGuiIOPtr io = ImGui.GetIO();
  288.             io.DisplaySize = new System.Numerics.Vector2(
  289.                 _windowWidth / _scaleFactor.X,
  290.                 _windowHeight / _scaleFactor.Y);
  291.             io.DisplayFramebufferScale = _scaleFactor;
  292.             io.DeltaTime = deltaSeconds; // DeltaTime is in seconds.
  293.         }
  294.  
  295.         readonly List<char> PressedChars = [];
  296.  
  297.         private void UpdateImGuiInput(GameWindow wnd)
  298.         {
  299.             ImGuiIOPtr io = ImGui.GetIO();
  300.  
  301.             MouseState MouseState = wnd.MouseState;
  302.             KeyboardState KeyboardState = wnd.KeyboardState;
  303.  
  304.             io.MouseDown[0] = MouseState[MouseButton.Left];
  305.             io.MouseDown[1] = MouseState[MouseButton.Right];
  306.             io.MouseDown[2] = MouseState[MouseButton.Middle];
  307.             io.MouseDown[3] = MouseState[MouseButton.Button4];
  308.             io.MouseDown[4] = MouseState[MouseButton.Button5];
  309.  
  310.             var screenPoint = new Vector2i((int)MouseState.X, (int)MouseState.Y);
  311.             var point = screenPoint;//wnd.PointToClient(screenPoint);
  312.             io.MousePos = new System.Numerics.Vector2(point.X, point.Y);
  313.  
  314.             foreach (Keys key in Enum.GetValues(typeof(Keys)))
  315.             {
  316.                 if (key == Keys.Unknown)
  317.                 {
  318.                     continue;
  319.                 }
  320.                 io.AddKeyEvent(TranslateKey(key), KeyboardState.IsKeyDown(key));
  321.             }
  322.  
  323.             foreach (var c in PressedChars)
  324.             {
  325.                 io.AddInputCharacter(c);
  326.             }
  327.             PressedChars.Clear();
  328.  
  329.             io.KeyCtrl = KeyboardState.IsKeyDown(Keys.LeftControl) || KeyboardState.IsKeyDown(Keys.RightControl);
  330.             io.KeyAlt = KeyboardState.IsKeyDown(Keys.LeftAlt) || KeyboardState.IsKeyDown(Keys.RightAlt);
  331.             io.KeyShift = KeyboardState.IsKeyDown(Keys.LeftShift) || KeyboardState.IsKeyDown(Keys.RightShift);
  332.             io.KeySuper = KeyboardState.IsKeyDown(Keys.LeftSuper) || KeyboardState.IsKeyDown(Keys.RightSuper);
  333.         }
  334.  
  335.         internal void PressChar(char keyChar)
  336.         {
  337.             PressedChars.Add(keyChar);
  338.         }
  339.  
  340.         internal void MouseScroll(Vector2 offset)
  341.         {
  342.             ImGuiIOPtr io = ImGui.GetIO();
  343.  
  344.             io.MouseWheel = offset.Y;
  345.             io.MouseWheelH = offset.X;
  346.         }
  347.  
  348.         private void RenderImDrawData(ImDrawDataPtr draw_data)
  349.         {
  350.             if (draw_data.CmdListsCount == 0)
  351.             {
  352.                 return;
  353.             }
  354.  
  355.             // Get intial state.
  356.             int prevVAO = GL.GetInteger(GetPName.VertexArrayBinding);
  357.             int prevArrayBuffer = GL.GetInteger(GetPName.ArrayBufferBinding);
  358.             int prevProgram = GL.GetInteger(GetPName.CurrentProgram);
  359.             bool prevBlendEnabled = GL.GetBoolean(GetPName.Blend);
  360.             bool prevScissorTestEnabled = GL.GetBoolean(GetPName.ScissorTest);
  361.             int prevBlendEquationRgb = GL.GetInteger(GetPName.BlendEquationRgb);
  362.             int prevBlendEquationAlpha = GL.GetInteger(GetPName.BlendEquationAlpha);
  363.             int prevBlendFuncSrcRgb = GL.GetInteger(GetPName.BlendSrcRgb);
  364.             int prevBlendFuncSrcAlpha = GL.GetInteger(GetPName.BlendSrcAlpha);
  365.             int prevBlendFuncDstRgb = GL.GetInteger(GetPName.BlendDstRgb);
  366.             int prevBlendFuncDstAlpha = GL.GetInteger(GetPName.BlendDstAlpha);
  367.             bool prevCullFaceEnabled = GL.GetBoolean(GetPName.CullFace);
  368.             bool prevDepthTestEnabled = GL.GetBoolean(GetPName.DepthTest);
  369.             int prevActiveTexture = GL.GetInteger(GetPName.ActiveTexture);
  370.             GL.ActiveTexture(TextureUnit.Texture0);
  371.             int prevTexture2D = GL.GetInteger(GetPName.TextureBinding2D);
  372.             Span<int> prevScissorBox = stackalloc int[4];
  373.             unsafe
  374.             {
  375.                 fixed (int* iptr = &prevScissorBox[0])
  376.                 {
  377.                     GL.GetInteger(GetPName.ScissorBox, iptr);
  378.                 }
  379.             }
  380.             Span<int> prevPolygonMode = stackalloc int[2];
  381.             unsafe
  382.             {
  383.                 fixed (int* iptr = &prevPolygonMode[0])
  384.                 {
  385.                     GL.GetInteger(GetPName.PolygonMode, iptr);
  386.                 }
  387.             }
  388.  
  389.             if (GLVersion <= 310 || CompatibilityProfile)
  390.             {
  391.                 GL.PolygonMode(MaterialFace.Front, PolygonMode.Fill);
  392.                 GL.PolygonMode(MaterialFace.Back, PolygonMode.Fill);
  393.             }
  394.             else
  395.             {
  396.                 GL.PolygonMode(MaterialFace.FrontAndBack, PolygonMode.Fill);
  397.             }
  398.  
  399.             // Bind the element buffer (thru the VAO) so that we can resize it.
  400.             GL.BindVertexArray(_vertexArray);
  401.             // Bind the vertex buffer so that we can resize it.
  402.             GL.BindBuffer(BufferTarget.ArrayBuffer, _vertexBuffer);
  403.             for (int i = 0; i < draw_data.CmdListsCount; i++)
  404.             {
  405.                 ImDrawListPtr cmd_list = draw_data.CmdLists[i];
  406.  
  407.                 int vertexSize = cmd_list.VtxBuffer.Size * Unsafe.SizeOf<ImDrawVert>();
  408.                 if (vertexSize > _vertexBufferSize)
  409.                 {
  410.                     int newSize = (int)Math.Max(_vertexBufferSize * 1.5f, vertexSize);
  411.  
  412.                     GL.BufferData(BufferTarget.ArrayBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
  413.                     _vertexBufferSize = newSize;
  414.  
  415.                     Console.WriteLine($"Resized dear imgui vertex buffer to new size {_vertexBufferSize}");
  416.                 }
  417.  
  418.                 int indexSize = cmd_list.IdxBuffer.Size * sizeof(ushort);
  419.                 if (indexSize > _indexBufferSize)
  420.                 {
  421.                     int newSize = (int)Math.Max(_indexBufferSize * 1.5f, indexSize);
  422.                     GL.BufferData(BufferTarget.ElementArrayBuffer, newSize, IntPtr.Zero, BufferUsageHint.DynamicDraw);
  423.                     _indexBufferSize = newSize;
  424.  
  425.                     Console.WriteLine($"Resized dear imgui index buffer to new size {_indexBufferSize}");
  426.                 }
  427.             }
  428.  
  429.             // Setup orthographic projection matrix into our constant buffer
  430.             ImGuiIOPtr io = ImGui.GetIO();
  431.             Matrix4 mvp = Matrix4.CreateOrthographicOffCenter(
  432.                 0.0f,
  433.                 io.DisplaySize.X,
  434.                 io.DisplaySize.Y,
  435.                 0.0f,
  436.                 -1.0f,
  437.                 1.0f);
  438.  
  439.             GL.UseProgram(_shader);
  440.             GL.UniformMatrix4(_shaderProjectionMatrixLocation, false, ref mvp);
  441.             GL.Uniform1(_shaderFontTextureLocation, 0);
  442.             CheckGLError("Projection");
  443.  
  444.             GL.BindVertexArray(_vertexArray);
  445.             CheckGLError("VAO");
  446.  
  447.             draw_data.ScaleClipRects(io.DisplayFramebufferScale);
  448.  
  449.             GL.Enable(EnableCap.Blend);
  450.             GL.Enable(EnableCap.ScissorTest);
  451.             GL.BlendEquation(BlendEquationMode.FuncAdd);
  452.             GL.BlendFunc(BlendingFactor.SrcAlpha, BlendingFactor.OneMinusSrcAlpha);
  453.             GL.Disable(EnableCap.CullFace);
  454.             GL.Disable(EnableCap.DepthTest);
  455.  
  456.             // Render command lists
  457.             for (int n = 0; n < draw_data.CmdListsCount; n++)
  458.             {
  459.                 ImDrawListPtr cmd_list = draw_data.CmdLists[n];
  460.  
  461.                 GL.BufferSubData(BufferTarget.ArrayBuffer, IntPtr.Zero, cmd_list.VtxBuffer.Size * Unsafe.SizeOf<ImDrawVert>(), cmd_list.VtxBuffer.Data);
  462.                 CheckGLError($"Data Vert {n}");
  463.  
  464.                 GL.BufferSubData(BufferTarget.ElementArrayBuffer, IntPtr.Zero, cmd_list.IdxBuffer.Size * sizeof(ushort), cmd_list.IdxBuffer.Data);
  465.                 CheckGLError($"Data Idx {n}");
  466.  
  467.                 for (int cmd_i = 0; cmd_i < cmd_list.CmdBuffer.Size; cmd_i++)
  468.                 {
  469.                     ImDrawCmdPtr pcmd = cmd_list.CmdBuffer[cmd_i];
  470.                     if (pcmd.UserCallback != IntPtr.Zero)
  471.                     {
  472.                         throw new NotImplementedException();
  473.                     }
  474.                     else
  475.                     {
  476.                         GL.ActiveTexture(TextureUnit.Texture0);
  477.                         GL.BindTexture(TextureTarget.Texture2D, (int)pcmd.TextureId);
  478.                         CheckGLError("Texture");
  479.  
  480.                         // We do _windowHeight - (int)clip.W instead of (int)clip.Y because gl has flipped Y when it comes to these coordinates
  481.                         var clip = pcmd.ClipRect;
  482.                         GL.Scissor((int)clip.X, _windowHeight - (int)clip.W, (int)(clip.Z - clip.X), (int)(clip.W - clip.Y));
  483.                         CheckGLError("Scissor");
  484.  
  485.                         if ((io.BackendFlags & ImGuiBackendFlags.RendererHasVtxOffset) != 0)
  486.                         {
  487.                             GL.DrawElementsBaseVertex(PrimitiveType.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (IntPtr)(pcmd.IdxOffset * sizeof(ushort)), unchecked((int)pcmd.VtxOffset));
  488.                         }
  489.                         else
  490.                         {
  491.                             GL.DrawElements(BeginMode.Triangles, (int)pcmd.ElemCount, DrawElementsType.UnsignedShort, (int)pcmd.IdxOffset * sizeof(ushort));
  492.                         }
  493.                         CheckGLError("Draw");
  494.                     }
  495.                 }
  496.             }
  497.  
  498.             GL.Disable(EnableCap.Blend);
  499.             GL.Disable(EnableCap.ScissorTest);
  500.  
  501.             // Reset state
  502.             GL.BindTexture(TextureTarget.Texture2D, prevTexture2D);
  503.             GL.ActiveTexture((TextureUnit)prevActiveTexture);
  504.             GL.UseProgram(prevProgram);
  505.             GL.BindVertexArray(prevVAO);
  506.             GL.Scissor(prevScissorBox[0], prevScissorBox[1], prevScissorBox[2], prevScissorBox[3]);
  507.             GL.BindBuffer(BufferTarget.ArrayBuffer, prevArrayBuffer);
  508.             GL.BlendEquationSeparate((BlendEquationMode)prevBlendEquationRgb, (BlendEquationMode)prevBlendEquationAlpha);
  509.             GL.BlendFuncSeparate(
  510.                 (BlendingFactorSrc)prevBlendFuncSrcRgb,
  511.                 (BlendingFactorDest)prevBlendFuncDstRgb,
  512.                 (BlendingFactorSrc)prevBlendFuncSrcAlpha,
  513.                 (BlendingFactorDest)prevBlendFuncDstAlpha);
  514.             if (prevBlendEnabled) GL.Enable(EnableCap.Blend); else GL.Disable(EnableCap.Blend);
  515.             if (prevDepthTestEnabled) GL.Enable(EnableCap.DepthTest); else GL.Disable(EnableCap.DepthTest);
  516.             if (prevCullFaceEnabled) GL.Enable(EnableCap.CullFace); else GL.Disable(EnableCap.CullFace);
  517.             if (prevScissorTestEnabled) GL.Enable(EnableCap.ScissorTest); else GL.Disable(EnableCap.ScissorTest);
  518.             if (GLVersion <= 310 || CompatibilityProfile)
  519.             {
  520.                 GL.PolygonMode(MaterialFace.Front, (PolygonMode)prevPolygonMode[0]);
  521.                 GL.PolygonMode(MaterialFace.Back, (PolygonMode)prevPolygonMode[1]);
  522.             }
  523.             else
  524.             {
  525.                 GL.PolygonMode(MaterialFace.FrontAndBack, (PolygonMode)prevPolygonMode[0]);
  526.             }
  527.         }
  528.  
  529.         public static void LabelObject(ObjectLabelIdentifier objLabelIdent, int glObject, string name)
  530.         {
  531.             if (KHRDebugAvailable)
  532.                 GL.ObjectLabel(objLabelIdent, glObject, name.Length, name);
  533.         }
  534.  
  535.         static bool IsExtensionSupported(string name)
  536.         {
  537.             int n = GL.GetInteger(GetPName.NumExtensions);
  538.             for (int i = 0; i < n; i++)
  539.             {
  540.                 string extension = GL.GetString(StringNameIndexed.Extensions, i);
  541.                 if (extension == name) return true;
  542.             }
  543.  
  544.             return false;
  545.         }
  546.  
  547.         public static int CreateProgram(string name, string vertexSource, string fragmentSoruce)
  548.         {
  549.             int program = GL.CreateProgram();
  550.             LabelObject(ObjectLabelIdentifier.Program, program, $"Program: {name}");
  551.  
  552.             int vertex = CompileShader(name, ShaderType.VertexShader, vertexSource);
  553.             int fragment = CompileShader(name, ShaderType.FragmentShader, fragmentSoruce);
  554.  
  555.             GL.AttachShader(program, vertex);
  556.             GL.AttachShader(program, fragment);
  557.  
  558.             GL.LinkProgram(program);
  559.  
  560.             GL.GetProgram(program, GetProgramParameterName.LinkStatus, out int success);
  561.             if (success == 0)
  562.             {
  563.                 string info = GL.GetProgramInfoLog(program);
  564.                 Debug.WriteLine($"GL.LinkProgram had info log [{name}]:\n{info}");
  565.             }
  566.  
  567.             GL.DetachShader(program, vertex);
  568.             GL.DetachShader(program, fragment);
  569.  
  570.             GL.DeleteShader(vertex);
  571.             GL.DeleteShader(fragment);
  572.  
  573.             return program;
  574.         }
  575.  
  576.         private static int CompileShader(string name, ShaderType type, string source)
  577.         {
  578.             int shader = GL.CreateShader(type);
  579.             LabelObject(ObjectLabelIdentifier.Shader, shader, $"Shader: {name}");
  580.  
  581.             GL.ShaderSource(shader, source);
  582.             GL.CompileShader(shader);
  583.  
  584.             GL.GetShader(shader, ShaderParameter.CompileStatus, out int success);
  585.             if (success == 0)
  586.             {
  587.                 string info = GL.GetShaderInfoLog(shader);
  588.                 Debug.WriteLine($"GL.CompileShader for shader '{name}' [{type}] had info log:\n{info}");
  589.             }
  590.  
  591.             return shader;
  592.         }
  593.  
  594.         public static void CheckGLError(string title)
  595.         {
  596.             ErrorCode error;
  597.             int i = 1;
  598.             while ((error = (ErrorCode)GL.GetError()) != ErrorCode.NoError)
  599.             {
  600.                 Debug.Print($"{title} ({i++}): {error}");
  601.             }
  602.         }
  603.  
  604.         public static ImGuiKey TranslateKey(Keys key)
  605.         {
  606.             if (key >= Keys.D0 && key <= Keys.D9)
  607.                 return key - Keys.D0 + ImGuiKey._0;
  608.  
  609.             if (key >= Keys.A && key <= Keys.Z)
  610.                 return key - Keys.A + ImGuiKey.A;
  611.  
  612.             if (key >= Keys.KeyPad0 && key <= Keys.KeyPad9)
  613.                 return key - Keys.KeyPad0 + ImGuiKey.Keypad0;
  614.  
  615.             if (key >= Keys.F1 && key <= Keys.F24)
  616.                 return key - Keys.F1 + ImGuiKey.F24;
  617.  
  618.             switch (key)
  619.             {
  620.                 case Keys.Tab: return ImGuiKey.Tab;
  621.                 case Keys.Left: return ImGuiKey.LeftArrow;
  622.                 case Keys.Right: return ImGuiKey.RightArrow;
  623.                 case Keys.Up: return ImGuiKey.UpArrow;
  624.                 case Keys.Down: return ImGuiKey.DownArrow;
  625.                 case Keys.PageUp: return ImGuiKey.PageUp;
  626.                 case Keys.PageDown: return ImGuiKey.PageDown;
  627.                 case Keys.Home: return ImGuiKey.Home;
  628.                 case Keys.End: return ImGuiKey.End;
  629.                 case Keys.Insert: return ImGuiKey.Insert;
  630.                 case Keys.Delete: return ImGuiKey.Delete;
  631.                 case Keys.Backspace: return ImGuiKey.Backspace;
  632.                 case Keys.Space: return ImGuiKey.Space;
  633.                 case Keys.Enter: return ImGuiKey.Enter;
  634.                 case Keys.Escape: return ImGuiKey.Escape;
  635.                 case Keys.Apostrophe: return ImGuiKey.Apostrophe;
  636.                 case Keys.Comma: return ImGuiKey.Comma;
  637.                 case Keys.Minus: return ImGuiKey.Minus;
  638.                 case Keys.Period: return ImGuiKey.Period;
  639.                 case Keys.Slash: return ImGuiKey.Slash;
  640.                 case Keys.Semicolon: return ImGuiKey.Semicolon;
  641.                 case Keys.Equal: return ImGuiKey.Equal;
  642.                 case Keys.LeftBracket: return ImGuiKey.LeftBracket;
  643.                 case Keys.Backslash: return ImGuiKey.Backslash;
  644.                 case Keys.RightBracket: return ImGuiKey.RightBracket;
  645.                 case Keys.GraveAccent: return ImGuiKey.GraveAccent;
  646.                 case Keys.CapsLock: return ImGuiKey.CapsLock;
  647.                 case Keys.ScrollLock: return ImGuiKey.ScrollLock;
  648.                 case Keys.NumLock: return ImGuiKey.NumLock;
  649.                 case Keys.PrintScreen: return ImGuiKey.PrintScreen;
  650.                 case Keys.Pause: return ImGuiKey.Pause;
  651.                 case Keys.KeyPadDecimal: return ImGuiKey.KeypadDecimal;
  652.                 case Keys.KeyPadDivide: return ImGuiKey.KeypadDivide;
  653.                 case Keys.KeyPadMultiply: return ImGuiKey.KeypadMultiply;
  654.                 case Keys.KeyPadSubtract: return ImGuiKey.KeypadSubtract;
  655.                 case Keys.KeyPadAdd: return ImGuiKey.KeypadAdd;
  656.                 case Keys.KeyPadEnter: return ImGuiKey.KeypadEnter;
  657.                 case Keys.KeyPadEqual: return ImGuiKey.KeypadEqual;
  658.                 case Keys.LeftShift: return ImGuiKey.LeftShift;
  659.                 case Keys.LeftControl: return ImGuiKey.LeftCtrl;
  660.                 case Keys.LeftAlt: return ImGuiKey.LeftAlt;
  661.                 case Keys.LeftSuper: return ImGuiKey.LeftSuper;
  662.                 case Keys.RightShift: return ImGuiKey.RightShift;
  663.                 case Keys.RightControl: return ImGuiKey.RightCtrl;
  664.                 case Keys.RightAlt: return ImGuiKey.RightAlt;
  665.                 case Keys.RightSuper: return ImGuiKey.RightSuper;
  666.                 case Keys.Menu: return ImGuiKey.Menu;
  667.                 default: return ImGuiKey.None;
  668.             }
  669.         }
  670.     }
  671. }
Tags: eduengine
Advertisement
Add Comment
Please, Sign In to add comment