From 44e916056b10b5f425a1a89122598e13da3bcc1e Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Mon, 24 Mar 2025 22:15:59 +0200 Subject: [PATCH 1/6] Temp --- Core/Renderers/Renderer.cs | 1 + Core/Shaders/LampShader.cs | 11 ++- Core/Shaders/LightingShader.cs | 32 +++++--- Core/Shaders/Shader.cs | 16 ++-- Core/Shaders/UIShader.cs | 5 +- Core/SilkWindow.cs | 30 +++++-- Core/Textures/TextureService.cs | 2 +- Core/Window.cs | 31 ++++---- Editor/EditorWindow.cs | 79 +++++++++++-------- Editor/Windows/ImGuiWindowBase.cs | 46 ++++++----- .../MultipleWindows/MultipleWindows.csproj | 17 ++++ Examples/MultipleWindows/Program.cs | 45 +++++++++++ SharpEngine.sln | 11 ++- 13 files changed, 226 insertions(+), 100 deletions(-) create mode 100644 Examples/MultipleWindows/MultipleWindows.csproj create mode 100644 Examples/MultipleWindows/Program.cs diff --git a/Core/Renderers/Renderer.cs b/Core/Renderers/Renderer.cs index 9532509..ae52bed 100644 --- a/Core/Renderers/Renderer.cs +++ b/Core/Renderers/Renderer.cs @@ -41,6 +41,7 @@ public Renderer(CameraView camera, ISettings settings, Scene scene) : base(setti _camera = camera; _scene = scene; + // TODO: These should be refactored out. The minimum build shouldn't need to use these. _lightingShader = new LightingShader(); _lampShader = new LampShader(); } diff --git a/Core/Shaders/LampShader.cs b/Core/Shaders/LampShader.cs index ced37b6..aa63ddb 100644 --- a/Core/Shaders/LampShader.cs +++ b/Core/Shaders/LampShader.cs @@ -1,4 +1,4 @@ -using SharpEngine.Core.Entities.Properties; +using SharpEngine.Core.Entities.Properties; using SharpEngine.Core.Extensions; using Silk.NET.OpenGL; @@ -22,9 +22,12 @@ public override bool SetAttributes() if (!base.SetAttributes()) return false; - var positionLocation = (uint)Shader!.GetAttribLocation(ShaderAttributes.Pos); - Window.GL.EnableVertexAttribArray(positionLocation); - Window.GL.VertexAttribPointer(positionLocation, 3, VertexAttribPointerType.Float, false, VertexData.Stride, 0); + if (!Shader!.TryGetAttribLocation(ShaderAttributes.Pos, out int positionLocation)) + return false; + + var positionLocationUint = (uint)positionLocation; + Window.GL.EnableVertexAttribArray(positionLocationUint); + Window.GL.VertexAttribPointer(positionLocationUint, 3, VertexAttribPointerType.Float, false, VertexData.Stride, 0); return true; } diff --git a/Core/Shaders/LightingShader.cs b/Core/Shaders/LightingShader.cs index 340a003..5ab80f1 100644 --- a/Core/Shaders/LightingShader.cs +++ b/Core/Shaders/LightingShader.cs @@ -1,6 +1,7 @@ -using SharpEngine.Core.Entities.Properties; +using SharpEngine.Core.Entities.Properties; using SharpEngine.Core.Extensions; using Silk.NET.OpenGL; +using System; namespace SharpEngine.Core.Shaders; @@ -22,17 +23,26 @@ public override bool SetAttributes() if (!base.SetAttributes()) return false; - var positionLocation = (uint)Shader!.GetAttribLocation(ShaderAttributes.Pos); - Window.GL.EnableVertexAttribArray(positionLocation); - Window.GL.VertexAttribPointer(positionLocation, VertexData.VerticesSize, VertexAttribPointerType.Float, false, VertexData.Stride, 0); - - var normalLocation = (uint)Shader.GetAttribLocation(ShaderAttributes.Normal); - Window.GL.EnableVertexAttribArray(normalLocation); - Window.GL.VertexAttribPointer(normalLocation, VertexData.NormalsSize, VertexAttribPointerType.Float, false, VertexData.Stride, VertexData.NormalsOffset); + if (!Shader!.TryGetAttribLocation(ShaderAttributes.Pos, out int positionLocation)) + return false; - var texCoordLocation = (uint)Shader.GetAttribLocation(ShaderAttributes.TexCoords); - Window.GL.EnableVertexAttribArray(texCoordLocation); - Window.GL.VertexAttribPointer(texCoordLocation, VertexData.TexCoordsSize, VertexAttribPointerType.Float, false, VertexData.Stride, VertexData.TexCoordsOffset); + var positionLocationUint = (uint)positionLocation; + Window.GL.EnableVertexAttribArray(positionLocationUint); + Window.GL.VertexAttribPointer(positionLocationUint, VertexData.VerticesSize, VertexAttribPointerType.Float, false, VertexData.Stride, 0); + + if (!Shader!.TryGetAttribLocation(ShaderAttributes.Normal, out int normalLocation)) + return false; + + var normalLocationUint = (uint)normalLocation; + Window.GL.EnableVertexAttribArray(normalLocationUint); + Window.GL.VertexAttribPointer(normalLocationUint, VertexData.NormalsSize, VertexAttribPointerType.Float, false, VertexData.Stride, VertexData.NormalsOffset); + + if (!Shader!.TryGetAttribLocation(ShaderAttributes.Normal, out int texCoordLocation)) + return false; + + var texCoordLocationUint = (uint)texCoordLocation; + Window.GL.EnableVertexAttribArray(texCoordLocationUint); + Window.GL.VertexAttribPointer(texCoordLocationUint, VertexData.TexCoordsSize, VertexAttribPointerType.Float, false, VertexData.Stride, VertexData.TexCoordsOffset); return true; } diff --git a/Core/Shaders/Shader.cs b/Core/Shaders/Shader.cs index 4c7b94a..fb02337 100644 --- a/Core/Shaders/Shader.cs +++ b/Core/Shaders/Shader.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.IO; using System.Collections.Generic; @@ -166,14 +166,18 @@ public void Use() /// Checks if the shader attribute exists within the current shader. /// /// The name of the attribute that's being looked for. - /// If the attribute exists, the location of the attribute in the shader; otherwise -1. - public int GetAttribLocation(string attribName) + /// Outputs the location of the attribute in the shader if found; otherwise -1. + /// If the attribute exists, ; otherwise, . + public bool TryGetAttribLocation(string attribName, out int location) { - int location = Window.GL.GetAttribLocation(Handle, attribName); - if (location == -1) + location = Window.GL.GetAttribLocation(Handle, attribName); + if (location == ShaderAttributes.AttributeLocationNotFound) + { Console.WriteLine($"Attribute '{attribName}' not found in shader program."); + return false; + } - return location; + return true; } // Uniform setters diff --git a/Core/Shaders/UIShader.cs b/Core/Shaders/UIShader.cs index 9e049a1..126b2fe 100644 --- a/Core/Shaders/UIShader.cs +++ b/Core/Shaders/UIShader.cs @@ -14,10 +14,9 @@ public UIShader() public override bool SetAttributes() { if (!base.SetAttributes()) - return false; + return false; - var vertexLocation = Shader!.GetAttribLocation(ShaderAttributes.Pos); - if (vertexLocation == ShaderAttributes.AttributeLocationNotFound) + if (!Shader!.TryGetAttribLocation(ShaderAttributes.Pos, out int vertexLocation)) return false; uint vertexLocationUInt = (uint)vertexLocation; diff --git a/Core/SilkWindow.cs b/Core/SilkWindow.cs index 23989da..cbb0cb8 100644 --- a/Core/SilkWindow.cs +++ b/Core/SilkWindow.cs @@ -1,20 +1,24 @@ -using SharpEngine.Core.Enums; -using Silk.NET.Core; +using Silk.NET.Core; using Silk.NET.Core.Contexts; using Silk.NET.Input; using Silk.NET.Maths; using Silk.NET.Windowing; +using MouseButton = Silk.NET.Input.MouseButton; + using StbImageSharp; + using System; using System.IO; using System.Numerics; -using MouseButton = Silk.NET.Input.MouseButton; namespace SharpEngine.Core; /// -/// Represents a class abstraction for the interface. +/// Represents an abstraction for the interface. /// +/// +/// For window initialization, see . +/// public abstract class SilkWindow : IWindow { /// @@ -154,6 +158,9 @@ public string Title /// public event Action? Render; + /// Raised after the scene has been rendered. + public event Action? OnAfterRender; + /// An event executed when the window has loaded. public event Action? OnLoaded; @@ -173,12 +180,25 @@ public IWindow CurrentWindow } /// + // [Obsolete("Use the 'Create' implementation instead.")] public IWindow CreateWindow(WindowOptions opts) { + if (CurrentWindow is not null) + throw new InvalidOperationException("Window already created for this instance."); + CurrentWindow = Silk.NET.Windowing.Window.Create(opts); return CurrentWindow; } + public static T Create(WindowOptions opts) where T : SilkWindow, new() + { + var instance = new T(); + var winndow = instance.CreateWindow(opts); + + instance.CurrentWindow = winndow; + return instance; + } + /// protected virtual void Dispose(bool disposing) { } @@ -260,7 +280,7 @@ public virtual void OnLoad() /// Handles operations needed to be executed after the renderers are finished. /// /// Time since the last frame. - protected virtual void AfterRender(double deltaTime) { } + protected virtual void AfterRender(double deltaTime) => OnAfterRender?.Invoke(deltaTime); /// /// Handles operations needed to be executed before the renderers are executed. diff --git a/Core/Textures/TextureService.cs b/Core/Textures/TextureService.cs index ae0e056..89b4bcf 100644 --- a/Core/Textures/TextureService.cs +++ b/Core/Textures/TextureService.cs @@ -1,4 +1,4 @@ -using StbImageSharp; +using StbImageSharp; using System.IO; using System.Collections.Generic; diff --git a/Core/Window.cs b/Core/Window.cs index 29e9936..a26cfe0 100644 --- a/Core/Window.cs +++ b/Core/Window.cs @@ -1,4 +1,4 @@ -using SharpEngine.Core.Entities.Properties.Meshes; +using SharpEngine.Core.Entities.Properties.Meshes; using SharpEngine.Core.Entities.Views; using SharpEngine.Core.Entities.Views.Settings; using SharpEngine.Core.Enums; @@ -7,23 +7,20 @@ using SharpEngine.Core.Renderers; using SharpEngine.Core.Scenes; using SharpEngine.Core.Shaders; -using Silk.NET.Core; -using Silk.NET.GLFW; +using Shader = SharpEngine.Core.Shaders.Shader; + using Silk.NET.Input; using Silk.NET.Maths; using Silk.NET.OpenGL; using Silk.NET.OpenGL.Extensions.ImGui; using Silk.NET.Windowing; -using StbImageSharp; +using MouseButton = Silk.NET.Input.MouseButton; + using System; using System.Collections.Generic; -using System.IO; using System.Linq; using System.Numerics; -using System.Runtime.InteropServices; using System.Threading.Tasks; -using MouseButton = Silk.NET.Input.MouseButton; -using Shader = SharpEngine.Core.Shaders.Shader; namespace SharpEngine.Core; @@ -32,7 +29,7 @@ namespace SharpEngine.Core; /// public class Window : SilkWindow { - private readonly ISettings _settings; + private readonly IViewSettings _settings; private readonly CameraView _camera; private bool _initialized; @@ -69,6 +66,7 @@ public class Window : SilkWindow /// The OpenGL context for this window. public static GL GetGL() => GL; private static void SetGL(GL gl) => GL = gl; + public Window() { } /// /// Initializes a new instance of . @@ -81,8 +79,6 @@ public Window(CameraView camera, Scene scene, IViewSettings settings) Scene = scene; _settings = settings; _camera = camera; - - Initialize(settings.WindowOptions); } /// @@ -94,14 +90,14 @@ public Window(Scene scene, IViewSettings settings) { Scene = scene; _settings = settings; - _camera = new(Vector3.One, new DefaultViewSettings()); - - Initialize(settings.WindowOptions); + _camera = new(Vector3.One, settings); } - private void Initialize(WindowOptions options) + private bool _windowInitialized; + + public void Initialize() where T : SilkWindow, new() { - CurrentWindow = CreateWindow(options); + CurrentWindow = SilkWindow.Create(_settings.WindowOptions); CurrentWindow.Update += OnUpdateFrame; CurrentWindow.Render += RenderFrame; CurrentWindow.Resize += OnResize; @@ -112,6 +108,9 @@ private void Initialize(WindowOptions options) /// public override void Run(Action onFrame) { + if (!_windowInitialized) + throw new Exception("Window not been initialized for this instance. Try calling 'window.Initialize()' first."); + try { base.Run(onFrame); diff --git a/Editor/EditorWindow.cs b/Editor/EditorWindow.cs index 92fe757..f5bc365 100644 --- a/Editor/EditorWindow.cs +++ b/Editor/EditorWindow.cs @@ -24,6 +24,8 @@ public class EditorWindow : Window private ContextMenuWindow? _contextMenuWindow; private ActionsMenuWindow? _actionsMenuWindow; + public EditorWindow() { } + /// /// Initializes an editor window with a specified scene and view settings. /// @@ -40,48 +42,55 @@ public override void OnLoad() { base.OnLoad(); - // Test only: remove later. - var cube = PrimitiveFactory.Create(PrimitiveType.Cube, new Vector3(3, 1, 1)); - cube.Name = "test"; - - Scene.Root.Children.Add(cube); - - // Get all types that inherit from ImGuiWindowBase - var windowTypes = Assembly.GetExecutingAssembly() - .GetTypes() - .Where(t => t.IsSubclassOf(typeof(ImGuiWindowBase)) && !t.IsAbstract) - .ToArray(); - - // Initialize all ImGuiWindowBase implementations - for (int i = 0; i < windowTypes.Length; i++) + try { - try - { - var type = windowTypes[i]; - var window = Activator.CreateInstance(type) ?? - throw new InvalidOperationException($"Error initializing window: {type}"); + // Test only: remove later. + var cube = PrimitiveFactory.Create(PrimitiveType.Cube, new Vector3(3, 1, 1)); + cube.Name = "test"; - var windowBase = (ImGuiWindowBase)window; - windowBase.SetScene(Scene); - windowBase.SetProject(_project); + Scene.Root.Children.Add(cube); - _windows.Add(windowBase); - } - catch (Exception e) + // Get all types that inherit from ImGuiWindowBase + var windowTypes = Assembly.GetExecutingAssembly() + .GetTypes() + .Where(t => t.IsSubclassOf(typeof(ImGuiWindowBase)) && !t.IsAbstract) + .ToArray(); + + // Initialize all ImGuiWindowBase implementations + for (int i = 0; i < windowTypes.Length; i++) { - Debug.LogInformation(e.Message, e); + try + { + var type = windowTypes[i]; + var window = Activator.CreateInstance(type) ?? + throw new InvalidOperationException($"Error initializing window: {type}"); + + var windowBase = (ImGuiWindowBase)window; + windowBase.SetScene(Scene); + windowBase.SetProject(_project); + + _windows.Add(windowBase); + } + catch (Exception e) + { + Debug.LogInformation(e.Message, e); + } } - } - _contextMenuWindow = (ContextMenuWindow?)_windows.FirstOrDefault(w => w.GetType() == typeof(ContextMenuWindow)); - if (_contextMenuWindow is null) - Debug.LogInformation("ContextMenuWindow not found."); + _contextMenuWindow = (ContextMenuWindow?)_windows.FirstOrDefault(w => w.GetType() == typeof(ContextMenuWindow)); + if (_contextMenuWindow is null) + Debug.LogInformation("ContextMenuWindow not found."); - _actionsMenuWindow = (ActionsMenuWindow?)_windows.FirstOrDefault(w => w.GetType() == typeof(ActionsMenuWindow)); - if (_actionsMenuWindow is null) - Debug.LogInformation("ActionsMenuWindow not found."); - else - _actionsMenuWindow.OnSceneLoaded += SetScene; + _actionsMenuWindow = (ActionsMenuWindow?)_windows.FirstOrDefault(w => w.GetType() == typeof(ActionsMenuWindow)); + if (_actionsMenuWindow is null) + Debug.LogInformation("ActionsMenuWindow not found."); + else + _actionsMenuWindow.OnSceneLoaded += SetScene; + } + catch (Exception e) + { + Debug.LogInformation(e.Message, e); + } } /// diff --git a/Editor/Windows/ImGuiWindowBase.cs b/Editor/Windows/ImGuiWindowBase.cs index d1579bb..c48c182 100644 --- a/Editor/Windows/ImGuiWindowBase.cs +++ b/Editor/Windows/ImGuiWindowBase.cs @@ -1,7 +1,13 @@ using ImGuiNET; using Launcher.UI; +using SharpEngine.Core.Entities.Views.Settings; using SharpEngine.Core.Scenes; +using Silk.NET.Input; +using Silk.NET.Maths; +using Silk.NET.OpenGL; +using Silk.NET.OpenGL.Extensions.ImGui; using Silk.NET.Windowing; +using System.Threading; namespace SharpEngine.Editor.Windows { @@ -56,14 +62,8 @@ public void RenderWindow() // Check docking state bool isDocked = ImGui.IsWindowDocked(); - if (_previousDockingStates.TryGetValue(Name, out bool wasDocked)) - { - if (wasDocked && !isDocked) - { - // Window was undocked - OnWindowUndocked(); - } - } + if (_previousDockingStates.TryGetValue(Name, out bool wasDocked) && wasDocked && !isDocked) + OnWindowUndocked(); // Update previous docking state _previousDockingStates[Name] = isDocked; @@ -82,20 +82,30 @@ protected virtual void OnWindowUndocked() private void CreateSilkWindow() { - // TODO: Use the Core window. - var window = Window.Create(WindowOptions.Default with + try { - Title = Name - }); + var thread = new Thread(() => + { - window.Load += () => - { - // TODO: Initialize the ImGui context like we do in the Core window. - }; + var window = new Core.Window(new(), new DefaultViewSettings()); - window.Render += delta => Render(); + window.Closing += () => _previousDockingStates[Name] = false; + window.OnAfterRender += deltaTime => + { + ImGui.Begin(Name, ImGuiWindowFlags); + Render(); + ImGui.End(); + }; - window.Run(); + window.Run(); + }); + + thread.Start(); + } + catch (Exception ex) + { + Console.WriteLine($"Failed to create window: {ex.Message}"); + } } /// diff --git a/Examples/MultipleWindows/MultipleWindows.csproj b/Examples/MultipleWindows/MultipleWindows.csproj new file mode 100644 index 0000000..f87a3eb --- /dev/null +++ b/Examples/MultipleWindows/MultipleWindows.csproj @@ -0,0 +1,17 @@ + + + + Exe + net8.0 + enable + enable + true + + + + + + + + + diff --git a/Examples/MultipleWindows/Program.cs b/Examples/MultipleWindows/Program.cs new file mode 100644 index 0000000..73a0908 --- /dev/null +++ b/Examples/MultipleWindows/Program.cs @@ -0,0 +1,45 @@ +using Silk.NET.Core.Native; +using Silk.NET.GLFW; +using Silk.NET.OpenGL; +using Silk.NET.Windowing; + +internal class Program +{ + static void Main() + { + var options1 = WindowOptions.Default with { Title = "Window 1", WindowClass = "MyWindowClass1" }; + var options2 = WindowOptions.Default with { Title = "Window 2", WindowClass = "MyWindowClass2" }; + + var window1 = Window.Create(options1); + var window2 = Window.Create(options2); + + StartWindow(window1); + StartWindow(window2); + } + + static void StartWindow(IWindow window) + { + var thread = new Thread(() => + { + window.Load += () => + { + Console.WriteLine($"Hello from window: " + window.Title); + + var gl = GL.GetApi(window); + + unsafe + { + var versionPtr = gl.GetString(StringName.Version); + string? version = SilkMarshal.PtrToString((nint)versionPtr); + Console.WriteLine($"OpenGL version: {version}"); + } + + }; + + window.Run(); + }); + + thread.SetApartmentState(ApartmentState.STA); + thread.Start(); + } +} diff --git a/SharpEngine.sln b/SharpEngine.sln index 71f591f..8989e1a 100644 --- a/SharpEngine.sln +++ b/SharpEngine.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio Version 17 -VisualStudioVersion = 17.14.35906.104 d17.14 +VisualStudioVersion = 17.14.35906.104 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SharpEngine.Core", "Core\SharpEngine.Core.csproj", "{9A1984BA-6D84-374A-8BF0-A26A6493FEA9}" EndProject @@ -24,6 +24,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution README.md = README.md EndProjectSection EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipleWindows", "Examples\MultipleWindows\MultipleWindows.csproj", "{0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -70,6 +72,12 @@ Global {1BEC06D8-094D-8BC2-288E-E2C4C13F3D2E}.LauncherNonWindows|Any CPU.Build.0 = Debug|Any CPU {1BEC06D8-094D-8BC2-288E-E2C4C13F3D2E}.Release|Any CPU.ActiveCfg = Release|Any CPU {1BEC06D8-094D-8BC2-288E-E2C4C13F3D2E}.Release|Any CPU.Build.0 = Release|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.LauncherNonWindows|Any CPU.ActiveCfg = Release|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.LauncherNonWindows|Any CPU.Build.0 = Release|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -77,5 +85,6 @@ Global GlobalSection(NestedProjects) = preSolution {E8A75C3B-1D82-8B30-C854-AD35FB123CDC} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F} {1BEC06D8-094D-8BC2-288E-E2C4C13F3D2E} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F} + {0AF16D15-5BD2-4FED-9C6A-227DE6A56C5E} = {B36A84DF-456D-A817-6EDD-3EC3E7F6E11F} EndGlobalSection EndGlobal From fce8dcfcf51f7bc35029cbb9db9bcf8d70b33aa3 Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Mon, 24 Mar 2025 23:55:55 +0200 Subject: [PATCH 2/6] Fix --- Core/Shaders/LightingShader.cs | 2 +- Core/Window.cs | 7 +++++-- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Core/Shaders/LightingShader.cs b/Core/Shaders/LightingShader.cs index 5ab80f1..8ddd2af 100644 --- a/Core/Shaders/LightingShader.cs +++ b/Core/Shaders/LightingShader.cs @@ -37,7 +37,7 @@ public override bool SetAttributes() Window.GL.EnableVertexAttribArray(normalLocationUint); Window.GL.VertexAttribPointer(normalLocationUint, VertexData.NormalsSize, VertexAttribPointerType.Float, false, VertexData.Stride, VertexData.NormalsOffset); - if (!Shader!.TryGetAttribLocation(ShaderAttributes.Normal, out int texCoordLocation)) + if (!Shader!.TryGetAttribLocation(ShaderAttributes.TexCoords, out int texCoordLocation)) return false; var texCoordLocationUint = (uint)texCoordLocation; diff --git a/Core/Window.cs b/Core/Window.cs index a26cfe0..af4cd49 100644 --- a/Core/Window.cs +++ b/Core/Window.cs @@ -79,6 +79,7 @@ public Window(CameraView camera, Scene scene, IViewSettings settings) Scene = scene; _settings = settings; _camera = camera; + Initialize(); } /// @@ -91,13 +92,15 @@ public Window(Scene scene, IViewSettings settings) Scene = scene; _settings = settings; _camera = new(Vector3.One, settings); + Initialize(); } private bool _windowInitialized; - public void Initialize() where T : SilkWindow, new() + // public void Initialize() where T : SilkWindow, new() + private void Initialize() { - CurrentWindow = SilkWindow.Create(_settings.WindowOptions); + CurrentWindow = CreateWindow(_settings.WindowOptions); CurrentWindow.Update += OnUpdateFrame; CurrentWindow.Render += RenderFrame; CurrentWindow.Resize += OnResize; From 54339fbaffdfd1906d4cfd6c8a8e6d7a2adeae6f Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Tue, 25 Mar 2025 11:35:59 +0200 Subject: [PATCH 3/6] Fix UI element rendering --- Core/Entities/UIElement.cs | 37 +++++++++++++++++++++++------------- Core/Renderers/Renderer.cs | 2 ++ Core/Renderers/UIRenderer.cs | 8 +++++++- Core/SharpEngine.Core.csproj | 1 + 4 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Core/Entities/UIElement.cs b/Core/Entities/UIElement.cs index 2ba6372..d7dd921 100644 --- a/Core/Entities/UIElement.cs +++ b/Core/Entities/UIElement.cs @@ -20,7 +20,7 @@ public class UIElement : SceneNode public UIElement(string name) { Name = name; - Mesh = MeshService.Instance.LoadMesh("plane", Primitives.Plane.Mesh); + // Mesh = MeshService.Instance.LoadMesh("plane", Primitives.Plane.Mesh); } private readonly UIShader _uIShader = new(); @@ -33,7 +33,7 @@ public UIElement(string name) // TODO: Use actual mesh /// Gets or sets the mesh of the UI element. - public Mesh Mesh { get; set; } = new(); + public Mesh Mesh { get; set; } // = new(); private readonly float[] _vertices = [ @@ -56,33 +56,44 @@ public UIElement(string name) public void Initialize() { _vertexArrayObject = Window.GL.GenVertexArray(); - Window.GL.BindVertexArray(_vertexArrayObject); + Bind(); InitializeBuffers(); } - private void InitializeBuffers() + public void Bind() + { + Window.GL.BindVertexArray(_vertexArrayObject); + } + + private unsafe void InitializeBuffers() { - var vertexBufferObject = Window.GL.GenBuffer(); - Window.GL.BindBuffer(GLEnum.ArrayBuffer, vertexBufferObject); - Window.GL.BufferData(GLEnum.ArrayBuffer, (uint)_vertices.Length * sizeof(float), _vertices, GLEnum.StaticDraw); + fixed (float* vertexDataPtr = &_vertices[0]) + { + var vertexBufferObject = Window.GL.GenBuffer(); + Window.GL.BindBuffer(GLEnum.ArrayBuffer, vertexBufferObject); + Window.GL.BufferData(GLEnum.ArrayBuffer, (nuint)(_vertices.Length * sizeof(float)), vertexDataPtr, GLEnum.StaticDraw); + } + + fixed (void* indicieDataPtr = &_indices[0]) + { + var elementBufferObject = Window.GL.GenBuffer(); + Window.GL.BindBuffer(GLEnum.ElementArrayBuffer, elementBufferObject); + Window.GL.BufferData(GLEnum.ElementArrayBuffer, (nuint)(_indices.Length * sizeof(uint)), indicieDataPtr, GLEnum.StaticDraw); + } - var elementBufferObject = Window.GL.GenBuffer(); - Window.GL.BindBuffer(GLEnum.ElementArrayBuffer, elementBufferObject); - Window.GL.BufferData(GLEnum.ElementArrayBuffer, (uint)_indices.Length * sizeof(uint), _indices, GLEnum.StaticDraw); } /// /// Render the UI element. /// - public override Task Render() + public unsafe override Task Render() { Window.GL.BindVertexArray(_vertexArrayObject); _uIShader.Shader.SetMatrix4(ShaderAttributes.Model, Transform.ModelMatrix); - uint a = 0; - Window.GL.DrawElements(PrimitiveType.Triangles, (uint)_indices.Length, DrawElementsType.UnsignedInt, ref a); + Window.GL.DrawElements(PrimitiveType.Triangles, (uint)_indices.Length, DrawElementsType.UnsignedInt, null); return Task.CompletedTask; } diff --git a/Core/Renderers/Renderer.cs b/Core/Renderers/Renderer.cs index ae52bed..def92a7 100644 --- a/Core/Renderers/Renderer.cs +++ b/Core/Renderers/Renderer.cs @@ -49,6 +49,8 @@ public Renderer(CameraView camera, ISettings settings, Scene scene) : base(setti /// public override Task Render() { + return Task.CompletedTask; + try { Window.GL.Enable(EnableCap.DepthTest); diff --git a/Core/Renderers/UIRenderer.cs b/Core/Renderers/UIRenderer.cs index 11e2165..6a99c4d 100644 --- a/Core/Renderers/UIRenderer.cs +++ b/Core/Renderers/UIRenderer.cs @@ -41,7 +41,7 @@ public override void Initialize() _uiShader.Shader.Use(); - //_scene.UIElements.Add(new UIElement("uiElement")); + _scene.UIElements.Add(new UIElement("uiElement")); _scene.Iterate(_scene.UIElements, elem => elem.Initialize()); @@ -61,9 +61,15 @@ public override Task Render() Window.GL.Disable(EnableCap.DepthTest); Window.GL.DepthFunc(DepthFunction.Less); + foreach (var item in _scene.UIElements) + { + item.Bind(); + } + _uiShader.Shader.Use(); var uiElementRenderTasks = _scene.IterateAsync(_scene.UIElements, elem => elem.Render()); + return Task.WhenAll(uiElementRenderTasks); } catch (Exception ex) diff --git a/Core/SharpEngine.Core.csproj b/Core/SharpEngine.Core.csproj index e93fd8f..869bade 100644 --- a/Core/SharpEngine.Core.csproj +++ b/Core/SharpEngine.Core.csproj @@ -16,6 +16,7 @@ $(AssemblyName).NET Debug;Release;LauncherNonWindows + true From 8cbc8a4b2d084f59c65414581ff0a325d281570a Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Tue, 25 Mar 2025 11:41:28 +0200 Subject: [PATCH 4/6] Use safe code --- Core/Entities/UIElement.cs | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) diff --git a/Core/Entities/UIElement.cs b/Core/Entities/UIElement.cs index d7dd921..7728510 100644 --- a/Core/Entities/UIElement.cs +++ b/Core/Entities/UIElement.cs @@ -66,22 +66,15 @@ public void Bind() Window.GL.BindVertexArray(_vertexArrayObject); } - private unsafe void InitializeBuffers() + private void InitializeBuffers() { - fixed (float* vertexDataPtr = &_vertices[0]) - { - var vertexBufferObject = Window.GL.GenBuffer(); - Window.GL.BindBuffer(GLEnum.ArrayBuffer, vertexBufferObject); - Window.GL.BufferData(GLEnum.ArrayBuffer, (nuint)(_vertices.Length * sizeof(float)), vertexDataPtr, GLEnum.StaticDraw); - } - - fixed (void* indicieDataPtr = &_indices[0]) - { - var elementBufferObject = Window.GL.GenBuffer(); - Window.GL.BindBuffer(GLEnum.ElementArrayBuffer, elementBufferObject); - Window.GL.BufferData(GLEnum.ElementArrayBuffer, (nuint)(_indices.Length * sizeof(uint)), indicieDataPtr, GLEnum.StaticDraw); - } + var vertexBufferObject = Window.GL.GenBuffer(); + Window.GL.BindBuffer(GLEnum.ArrayBuffer, vertexBufferObject); + Window.GL.BufferData(GLEnum.ArrayBuffer, _vertices, GLEnum.StaticDraw); + var elementBufferObject = Window.GL.GenBuffer(); + Window.GL.BindBuffer(GLEnum.ElementArrayBuffer, elementBufferObject); + Window.GL.BufferData(GLEnum.ElementArrayBuffer, _indices, GLEnum.StaticDraw); } /// From 77e8b05e36755d1d88dc8120f9b9d88bdc8e913b Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Tue, 25 Mar 2025 11:49:05 +0200 Subject: [PATCH 5/6] One more unsafe fix --- Core/Entities/UIElement.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Core/Entities/UIElement.cs b/Core/Entities/UIElement.cs index 7728510..1664569 100644 --- a/Core/Entities/UIElement.cs +++ b/Core/Entities/UIElement.cs @@ -4,6 +4,7 @@ using SharpEngine.Core.Shaders; using Silk.NET.OpenGL; +using System; using System.Threading.Tasks; namespace SharpEngine.Core.Entities; @@ -80,13 +81,13 @@ private void InitializeBuffers() /// /// Render the UI element. /// - public unsafe override Task Render() + public override Task Render() { Window.GL.BindVertexArray(_vertexArrayObject); _uIShader.Shader.SetMatrix4(ShaderAttributes.Model, Transform.ModelMatrix); - Window.GL.DrawElements(PrimitiveType.Triangles, (uint)_indices.Length, DrawElementsType.UnsignedInt, null); + Window.GL.DrawElements(PrimitiveType.Triangles, (uint)_indices.Length, DrawElementsType.UnsignedInt, []); return Task.CompletedTask; } From f543d945271128db494d09abf46a78e3a23af00d Mon Sep 17 00:00:00 2001 From: Antti Veikkolainen Date: Tue, 25 Mar 2025 12:00:08 +0200 Subject: [PATCH 6/6] Added error logging --- Core/Renderers/Renderer.cs | 2 -- Core/Renderers/UIRenderer.cs | 2 ++ Core/Shaders/Shader.cs | 49 ++++++++++++++++++++++++++---------- Core/SharpEngine.Core.csproj | 8 +----- 4 files changed, 39 insertions(+), 22 deletions(-) diff --git a/Core/Renderers/Renderer.cs b/Core/Renderers/Renderer.cs index def92a7..ae52bed 100644 --- a/Core/Renderers/Renderer.cs +++ b/Core/Renderers/Renderer.cs @@ -49,8 +49,6 @@ public Renderer(CameraView camera, ISettings settings, Scene scene) : base(setti /// public override Task Render() { - return Task.CompletedTask; - try { Window.GL.Enable(EnableCap.DepthTest); diff --git a/Core/Renderers/UIRenderer.cs b/Core/Renderers/UIRenderer.cs index 6a99c4d..47a6e4c 100644 --- a/Core/Renderers/UIRenderer.cs +++ b/Core/Renderers/UIRenderer.cs @@ -56,6 +56,8 @@ private void InitializeVertexArrays() /// public override Task Render() { + return Task.CompletedTask; + try { Window.GL.Disable(EnableCap.DepthTest); diff --git a/Core/Shaders/Shader.cs b/Core/Shaders/Shader.cs index fb02337..0ae4049 100644 --- a/Core/Shaders/Shader.cs +++ b/Core/Shaders/Shader.cs @@ -31,7 +31,7 @@ public class Shader /// /// The vertex shader full path. /// The fragment shader full path. - /// The identfier name of the shader. + /// The identifier name of the shader. public Shader(string vertPath, string fragPath, string name) { Name = name; @@ -44,10 +44,16 @@ public Shader(string vertPath, string fragPath, string name) // Load and compile shader if (!LoadShader(ShaderType.VertexShader, vertPath, out uint vertexShader)) + { + Console.WriteLine("Unable to load vertex shader."); return; + } if (!LoadShader(ShaderType.FragmentShader, fragPath, out uint fragmentShader)) + { + Console.WriteLine("Unable to load fragment shader."); return; + } // These two shaders must then be merged into a shader program, which can then be used by OpenGL. // To do this, create a program... @@ -59,7 +65,11 @@ public Shader(string vertPath, string fragPath, string name) Window.GL.AttachShader(Handle, fragmentShader); // And then link them together. - LinkProgram(Handle); + if (!LinkProgram(Handle)) + { + Console.WriteLine("Unable to link shader program."); + return; + } // When the shader program is linked, it no longer needs the individual shaders attached to it; the compiled code is copied into the shader program. // Detach them, and then delete them. @@ -91,7 +101,12 @@ private static bool LoadShader(ShaderType shaderType, string shaderPath, out uin // GL.CreateShader will create an empty shader (obviously). The ShaderType enum denotes which type of shader will be created. shader = Window.GL.CreateShader(shaderType); Window.GL.ShaderSource(shader, shaderSource); - CompileShader(shader); + + if (!CompileShader(shader)) + { + Console.WriteLine($"Unable to load {shaderType} shader from '{shaderPath}'."); + return false; + } return true; } @@ -102,7 +117,7 @@ private void GetUniformLocations() Window.GL.GetProgram(Handle, GLEnum.ActiveUniforms, out var numberOfUniforms); // Next, allocate the dictionary to hold the locations. - _uniformLocations = new Dictionary(); + _uniformLocations = []; // Loop over all the uniforms, for (uint i = 0; i < numberOfUniforms; i++) @@ -129,31 +144,39 @@ private static string ProcessIncludes(string shaderCode, string directory) }); } - private static void CompileShader(uint shader) + private static bool CompileShader(uint shader) { // Try to compile the shader Window.GL.CompileShader(shader); // Check for compilation errors - Window.GL.GetShader(shader, GLEnum.CompileStatus, out var code); - if (code != (int)GLEnum.True) + Window.GL.GetShader(shader, GLEnum.CompileStatus, out var statusCode); + if (statusCode != (int)GLEnum.True) { // We can use `GL.GetShaderInfoLog(shader)` to get information about the error. var infoLog = Window.GL.GetShaderInfoLog(shader); - throw new InvalidOperationException($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}"); + Console.WriteLine($"Error occurred whilst compiling Shader({shader}).\n\n{infoLog}"); + + return false; } + + return true; } - private static void LinkProgram(uint program) + private static bool LinkProgram(uint program) { Window.GL.LinkProgram(program); - - Window.GL.GetProgram(program, GLEnum.LinkStatus, out var code); - if (code != (int)GLEnum.True) + Window.GL.GetProgram(program, GLEnum.LinkStatus, out var statusCode); + + if (statusCode != (int)GLEnum.True) { string infoLog = Window.GL.GetProgramInfoLog(program); - throw new InvalidOperationException($"Error occurred whilst linking Program({program}): {infoLog}"); + Console.WriteLine($"Error occurred whilst linking Program({program}): {infoLog}"); + + return false; } + + return true; } /// diff --git a/Core/SharpEngine.Core.csproj b/Core/SharpEngine.Core.csproj index 869bade..1489ce2 100644 --- a/Core/SharpEngine.Core.csproj +++ b/Core/SharpEngine.Core.csproj @@ -3,10 +3,6 @@ Everything needed to build games using a purely C# game engine. - AnyCPU;x64;x86 $(GenerateNuGetPackages) https://github.com/Av3boy/SharpEngine @@ -15,9 +11,7 @@ $(AssemblyName).NET - Debug;Release;LauncherNonWindows - true - + Debug;Release;LauncherNonWindows