具有 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 它应该在屏幕的左下角可见)。
您可以通过回答以下一个或多个问题来帮助我:
- 有没有其他方法可以恢复原来的上下文
- 是否有另一种方法可以在屏幕的一部分上使用硬件加速进行渲染,最好为特定区域指定 OpenGL 状态
- 如何获得上述解决方案以我想要的方式工作(没有闪烁,但 window 的较小部分内的屏幕较小)
在尝试了更多组合后,成功的方法是:
仅在渲染中最后使用的上下文中调用 SwapBuffers(即使您使用了 3 个上下文)。这样就不会出现闪烁,并且渲染似乎工作正常。状态似乎是相互独立的。
我想做的事情:
主要目标:同时使用 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 它应该在屏幕的左下角可见)。
您可以通过回答以下一个或多个问题来帮助我:
- 有没有其他方法可以恢复原来的上下文
- 是否有另一种方法可以在屏幕的一部分上使用硬件加速进行渲染,最好为特定区域指定 OpenGL 状态
- 如何获得上述解决方案以我想要的方式工作(没有闪烁,但 window 的较小部分内的屏幕较小)
在尝试了更多组合后,成功的方法是:
仅在渲染中最后使用的上下文中调用 SwapBuffers(即使您使用了 3 个上下文)。这样就不会出现闪烁,并且渲染似乎工作正常。状态似乎是相互独立的。