From 417915e86100b0388111010367d194c215a28e88 Mon Sep 17 00:00:00 2001 From: emil28092005 Date: Wed, 17 Jun 2026 20:14:15 +0300 Subject: [PATCH] feat: switch default backend to Silk.NET OpenGL - OpenGLRenderContext: Initialize() + CreateOpenGL() for non-blocking - OpenGLWindow: Initialize() instead of Run(), CreateGL() method - Program.cs: default backend is now 'opengl', SwapBuffers per frame - ImGui guarded: only initialized for RaylibRenderer, ObjectManipulator checks _imGuiAvailable before calling ImGui.GetIO() - 66/66 tests, 145 FPS with OpenGL backend --- imgui.ini | 2 +- src/CortexEngine.App/CortexEngine.App.csproj | 1 + src/CortexEngine.App/ObjectManipulator.cs | 6 +++- src/CortexEngine.App/Program.cs | 29 ++++++++++++------- .../OpenGLRenderContext.cs | 20 ++++++------- src/Engine.Graphics.OpenGL/OpenGLWindow.cs | 5 ++++ 6 files changed, 40 insertions(+), 23 deletions(-) diff --git a/imgui.ini b/imgui.ini index 6d24b31..5a1a38d 100644 --- a/imgui.ini +++ b/imgui.ini @@ -14,7 +14,7 @@ Size=250,398 Collapsed=0 [Window][Inspector] -Pos=36,302 +Pos=112,297 Size=300,425 Collapsed=0 diff --git a/src/CortexEngine.App/CortexEngine.App.csproj b/src/CortexEngine.App/CortexEngine.App.csproj index f04bd6b..0e30318 100644 --- a/src/CortexEngine.App/CortexEngine.App.csproj +++ b/src/CortexEngine.App/CortexEngine.App.csproj @@ -26,6 +26,7 @@ + diff --git a/src/CortexEngine.App/ObjectManipulator.cs b/src/CortexEngine.App/ObjectManipulator.cs index 2466776..a7271af 100644 --- a/src/CortexEngine.App/ObjectManipulator.cs +++ b/src/CortexEngine.App/ObjectManipulator.cs @@ -28,10 +28,14 @@ public sealed class ObjectManipulator /// Process input for object picking and dragging. /// Returns true if input was consumed (ImGui should be ignored). /// + private bool _imGuiAvailable; + + public void SetImGuiAvailable(bool available) => _imGuiAvailable = available; + public bool ProcessInput(World world, Camera camera, IInputState input) { // Skip if ImGui is capturing mouse - if (ImGuiNET.ImGui.GetIO().WantCaptureMouse) + if (_imGuiAvailable && ImGuiNET.ImGui.GetIO().WantCaptureMouse) { _isDragging = false; return false; diff --git a/src/CortexEngine.App/Program.cs b/src/CortexEngine.App/Program.cs index c6a0239..98f6547 100644 --- a/src/CortexEngine.App/Program.cs +++ b/src/CortexEngine.App/Program.cs @@ -11,6 +11,7 @@ using Engine.Core; using Engine.Core.Components; using Engine.Graphics; using Engine.Graphics.Loaders; +using Engine.Graphics.OpenGL; using Engine.Graphics.RaylibBackend; using Engine.Graphics.Vulkan; using Engine.Physics; @@ -43,19 +44,22 @@ class Program RaylibBackendRegistrar.EnsureRegistered(); VulkanBackendRegistrar.EnsureRegistered(); - using var renderContext = RenderBackendFactory.Create("raylib", 1280, 720, enableValidation: false); + OpenGLBackendRegistrar.EnsureRegistered(); + using var renderContext = RenderBackendFactory.Create("opengl", 1280, 720, enableValidation: false); var window = renderContext.Window; var input = window.Input; using var renderer = renderContext.CreateRenderer(); - // ImGui editor layer - var imGuiLayer = new ImGuiLayer(); + // ImGui editor layer (Raylib only) + ImGuiLayer? imGuiLayer = null; var objectManipulator = new ObjectManipulator(); - if (!cameraTour) + objectManipulator.SetImGuiAvailable(false); + if (!cameraTour && renderer is RaylibRenderer rlRenderer) { + imGuiLayer = new ImGuiLayer(); imGuiLayer.Initialize(); - if (renderer is RaylibRenderer rlRenderer) - rlRenderer.ImGuiLayer = imGuiLayer; + rlRenderer.ImGuiLayer = imGuiLayer; + objectManipulator.SetImGuiAvailable(true); } var (modelPath, mcpPort) = ParseArgs(args); @@ -283,15 +287,18 @@ class Program } // Feed frame data to ImGui before rendering. - imGuiLayer.SetFrameData(world, timing, currentFps); + if (imGuiLayer != null) + imGuiLayer.SetFrameData(world, timing, currentFps); - // Sync selection between manipulator and ImGui - if (objectManipulator.IsDragging && !string.IsNullOrEmpty(objectManipulator.SelectedEntityName)) - imGuiLayer.SetSelectedEntity(objectManipulator.SelectedEntityName); + objectManipulator.SetImGuiAvailable(imGuiLayer != null); renderer.RenderWorld(world); queue.CompletePendingScreenshots(); + // Swap buffers for OpenGL backend + if (renderContext is OpenGLRenderContext glCtx2) + glCtx2.SwapBuffers(); + frames++; if (timing.TotalTime - lastFpsTime >= 1.0) { @@ -303,7 +310,7 @@ class Program } Console.WriteLine("Shutting down..."); - imGuiLayer.Dispose(); + imGuiLayer?.Dispose(); #if !RELEASE_AOT if (mcpApp != null) await mcpApp.StopAsync(); diff --git a/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs b/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs index 6d4c539..538accd 100644 --- a/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs +++ b/src/Engine.Graphics.OpenGL/OpenGLRenderContext.cs @@ -1,7 +1,9 @@ using Engine.Core; using Engine.Graphics; using Silk.NET.OpenGL; +using Silk.NET.Windowing; using SilkWindow = Silk.NET.Windowing.IWindow; +using CoreIWindow = Engine.Core.IWindow; namespace Engine.Graphics.OpenGL; @@ -12,16 +14,15 @@ public sealed class OpenGLRenderContext : IRenderContext private OpenGLRenderer? _renderer; private bool _disposed; - public IWindow Window => _window; + public CoreIWindow Window => _window; public OpenGLRenderContext(int width, int height, bool enableValidation = false) { _window = new OpenGLWindow("Cortex Engine (OpenGL)", width, height); - } - - public void OnLoad() - { - _gl = _window.SilkView.CreateOpenGL(); + // Initialize() triggers the Load callback which creates the GL context + _window.SilkView.Initialize(); + // After Initialize, CreateOpenGL should work + _gl = _window.CreateGL(); _window.OnLoad(); } @@ -31,10 +32,9 @@ public sealed class OpenGLRenderContext : IRenderContext return _renderer; } - public void Resize(int width, int height) - { - _renderer?.SetScreenSize(width, height); - } + public void Resize(int width, int height) => _renderer?.SetScreenSize(width, height); + + public void SwapBuffers() => _window.SilkView.SwapBuffers(); public void Dispose() { diff --git a/src/Engine.Graphics.OpenGL/OpenGLWindow.cs b/src/Engine.Graphics.OpenGL/OpenGLWindow.cs index 854e642..3bf832c 100644 --- a/src/Engine.Graphics.OpenGL/OpenGLWindow.cs +++ b/src/Engine.Graphics.OpenGL/OpenGLWindow.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using Engine.Core; using Silk.NET.Input; +using Silk.NET.OpenGL; using Silk.NET.Windowing; using SilkWindow = Silk.NET.Windowing.IWindow; @@ -31,6 +32,8 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable _silkWindow = Window.Create(options); _silkWindow.Closing += () => _shouldClose = true; + // Initialize without Run() — enables non-blocking event loop + _silkWindow.Initialize(); } public void OnLoad() @@ -39,6 +42,8 @@ public sealed class OpenGLWindow : Engine.Core.IWindow, IDisposable _input.Initialize(inputContext); } + public GL CreateGL() => _silkWindow.CreateOpenGL(); + public void PumpEvents() => _silkWindow.DoEvents(); public void Close() => _shouldClose = true; public string[] GetRequiredVulkanExtensions() => Array.Empty();