具有 OpenTK 的多个 IGraphicsContext/在单个 window 中使用多个 OpenGL 上下文

Multiple IGraphicsContext with OpenTK / using multiple OpenGL contexts in a single window

我想做的事情:

主要目标:同时使用 SkiaSharp 和 OpenTK。渲染 2D 和 3D。

问题是什么:SkiaSharp 弄乱了 OpenGL 的状态,所以如果不保存和恢复一些状态我就不能将它用于 3D。

旧解决方案(OpenGL < 4):我使用 GL.PushClientAttrib(ClientAttribMask.ClientAllAttribBits); + 一些附加值(saved/restored 它们)。

现在我读到这不是最好的解决方案,OpenGL 4 不再有 GL.PushClientAttrib。通常的方法似乎是您应该使用单独的 OpenGL 上下文。

已经看过:

我没有使用 GLControl,因为我没有使用 WinForms。所以这不是很有帮助。我尝试了什么:

internal class Program
{

    public static void Main(string[] args)
    {
        new Program().Run();
    }

    private readonly GameWindow _gameWindow;
    private IGraphicsContext _context2;

    private GlObject _glObject;
    private int _programId;

    private GlObject _glObject2;
    private int _programId2;

    public Program()
    {
        _gameWindow = new GameWindow(800,600,
            GraphicsMode.Default, "", GameWindowFlags.Default, 
            DisplayDevice.Default, 
            4, 2, GraphicsContextFlags.ForwardCompatible);

        _gameWindow.Resize += OnResize;
        _gameWindow.RenderFrame += OnRender;
        _gameWindow.Load += OnLoad;
    }

    public void Run()
    {
        _gameWindow.Run();
    }

    private void OnLoad(object sender, EventArgs e)
    {
        _programId = ShaderFactory.CreateShaderProgram();
        _glObject = new GlObject(new[]
        {
            new Vertex(new Vector4(-0.25f, 0.25f, 0.5f, 1f), Color4.Black),
            new Vertex(new Vector4(0.0f, -0.25f, 0.5f, 1f), Color4.Black),
            new Vertex(new Vector4(0.25f, 0.25f, 0.5f, 1f), Color4.Black),
        });

        _context2 = new GraphicsContext(GraphicsMode.Default, _gameWindow.WindowInfo, 4, 2,
            GraphicsContextFlags.Default);
        _context2.MakeCurrent(_gameWindow.WindowInfo);

        _programId2 = ShaderFactory.CreateShaderProgram();
        _glObject2 = new GlObject(new[]
        {
            new Vertex(new Vector4(-0.25f, 0.25f, 0.5f, 1f), Color4.Yellow),
            new Vertex(new Vector4(0.0f, -0.25f, 0.5f, 1f), Color4.Yellow),
            new Vertex(new Vector4(0.25f, 0.25f, 0.5f, 1f), Color4.Yellow),
        });

        _gameWindow.MakeCurrent();
    }

    private void OnRender(object sender, FrameEventArgs e)
    {
        _gameWindow.Context.MakeCurrent(_gameWindow.WindowInfo);
        GL.Viewport(0, 0, _gameWindow.Width, _gameWindow.Height);
        GL.ClearColor(0.3f,0.1f,0.1f,1);
        GL.Clear(ClearBufferMask.ColorBufferBit);

        GL.UseProgram(_programId);
        _glObject.Render();

        GL.Flush();
        _gameWindow.SwapBuffers();


        // i tried different combinations here
        // as i read GL.Clear will always clear the whole window
        _context2.MakeCurrent(_gameWindow.WindowInfo);
        GL.Viewport(10,10,100,100);
        //GL.ClearColor(0f, 0.8f, 0.1f, 1);
        //GL.Clear(ClearBufferMask.ColorBufferBit);

        GL.UseProgram(_programId2);
        _glObject2.Render();

        GL.Flush();
        _context2.SwapBuffers();
    }

    private void OnResize(object sender, EventArgs e)
    {
        var clientRect = _gameWindow.ClientRectangle;
        GL.Viewport(0, 0, clientRect.Width, clientRect.Height);
    }


}

顶点着色器:

#version 450 core

layout (location = 0) in vec4 position;
layout (location = 1) in vec4 color;
out vec4 vs_color;

void main(void)
{
    gl_Position = position;
    vs_color = color;
}

片段着色器:

#version 450 core
in vec4 vs_color;
out vec4 color;

void main(void)
{
    color = vs_color;
}

在单个上下文中工作正常,当我使用两个上下文时发生的情况是:第一个上下文得到渲染但闪烁。根本看不到第二个三角形(据我了解 GL.Viewport 它应该在屏幕的左下角可见)。

您可以通过回答以下一个或多个问题来帮助我:

  1. 有没有其他方法可以恢复原来的上下文
  2. 是否有另一种方法可以在屏幕的一部分上使用硬件加速进行渲染,最好为特定区域指定 OpenGL 状态
  3. 如何获得上述解决方案以我想要的方式工作(没有闪烁,但 window 的较小部分内的屏幕较小)

在尝试了更多组合后,成功的方法是:

仅在渲染中最后使用的上下文中调用 SwapBuffers(即使您使用了 3 个上下文)。这样就不会出现闪烁,并且渲染似乎工作正常。状态似乎是相互独立的。