Reputation: 113
Is there a way to draw to the screen using OpenTK/OpenGL in another thread? The code I'm trying to use is
GL.Clear(ClearBufferMask.ColorBufferBit);
GL.ClearColor(Color.Black);
GL.Begin(PrimitiveType.Quads);
GL.Color3(Color.FromArgb(255, 0, 0));
GL.Vertex2(-1, 1);
GL.Color3(Color.FromArgb(0, 255, 0));
GL.Vertex2(1, 1);
GL.Color3(Color.FromArgb(0, 0, 255));
GL.Vertex2(1, -1);
GL.Color3(Color.FromArgb(0, 255, 255));
GL.Vertex2(-1, -1f);
GL.End();
SwapBuffers();
The code above works in the same thread the GameWindow was created in but not when called from another thread.
Upvotes: -1
Views: 3098
Reputation: 11
Here is an example of how this can be achieved by using IGLFWGraphicsContext MakeNoneCurrent() method. Just be careful it is easy to get busy resource exceptions. Also don't forget to stop the thread before disposing game window. And same can be achieved with GLControl.
using OpenTK.Graphics.OpenGL;
using OpenTK.Mathematics;
using OpenTK.Windowing.Desktop;
using OpenTK.Windowing.GraphicsLibraryFramework;
namespace Display.Presentation.Views;
public class MainWindow : GameWindow
{
public MainWindow(GameWindowSettings gameWindowSettings, NativeWindowSettings nativeWindowSettings) : base(gameWindowSettings, nativeWindowSettings)
{
}
// Do the setup when OpenTK is fully loaded.
protected override void OnLoad()
{
base.OnLoad();
this.Context.MakeNoneCurrent(); // Must be called to release thread and make sure you dont call 'Context' on parent thread.
var windowPrt = this.Context.WindowPtr;
new Thread(() =>
{
unsafe
{
var context = new GLFWGraphicsContext((Window*)windowPrt);
context.MakeCurrent();
GL.ClearColor(Color.Aqua);
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
context.SwapBuffers();
context.MakeNoneCurrent(); // Very important to release thread.
}
}).Start();
}
}
public class Test2
{
public Test2()
{
var gameWindowSettings = new GameWindowSettings()
{
UpdateFrequency = 60
};
var nativeWindowSettings = new NativeWindowSettings()
{
Size = new Vector2i(800, 600),
Title = "Game window test title",
};
using var game = new MainWindow(gameWindowSettings, nativeWindowSettings);
game.Run();
}
}
Upvotes: 1
Reputation: 113
I was able to swap the thread OpenGL accepts with this code
thread = new Thread(() =>
{
IGraphicsContext context = new GraphicsContext(GraphicsMode.Default, window.WindowInfo);
context.MakeCurrent(window.WindowInfo);
//Render code here
}).Start();
Upvotes: 4