感谢您阅读此问题!
我以前使用的程序具有主窗口形式。当我单击按钮时,另一个线程将创建Gamewindow
表单,该表单显示来自Camera的帧数据。 OnUpdateFrame()
,OnRenderFrame()
被自动调用,并在创建的窗口中处理数据和渲染。
我正在研究此软件的更新愿景,该软件的主窗口形式为glControl
。
是的,我使用的是glControl
而不是Gamewindow
。但是问题是..
由于“主窗口”表单需要处理用户输入,因此我必须在另一个线程中控制glControl
,该线程不断更新和呈现Frame数据。但是glControl
以创建并显示的主窗口形式显示。在另一个线程中操作的glControl
不会应用于主窗口形式。 (我只能在其他线程代码中使用glControl.Swapbuffers()
或.invalidate()
)
我发现一条信息,指出glControl
仅在一个线程中受到控制。因此,如何在使用glControl
表单时自动在Mainwindow
上渲染帧数据。
我尝试过GL。函数使用timer来更新渲染帧数据,但该计时器也是另一个线程,因此更改不会应用于Main表单中的glControl
。
并且我尝试在另一个线程中新建并创建glControl
,但是在使用GL时它显示了异常。函数(:调用线程中没有GraphicsContext)
我该如何解决这个问题?
==========
这是我尝试的一种方法,发现它不起作用。.计时器线程调用的RenderFrame()不能在glControl1上显示任何内容,即使以为glcontrol1.Invalidate()也会定期调用。
实际上,在以前使用gamewindow时,OnRenderFrame()会定期出现并在窗口中显示对象。但是我该如何在主窗口窗体的glControl上执行此操作。主线程可以定期调用RenderFrame()吗?看来计时器也是一个线程,所以计时器线程调用的RenderFrame()无法正常工作。
public partial class MainWindowForm : Form
{
System.Timers.Timer glControlTimer;
...
private void InitializeComponent()
{
glcontrol1 = new OpenTK.GLControl();
...
}
private void btShowLive2_Click(object sender, EventArgs e)
{
...
oHandleGLControl = new HandleGLControl(glcontrol1);
glControlTimer = new System.Timers.Timer(300);
glControlTimer.Elapsed += TimerElapsed;
glControlTimer.Start();
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
oHandleGLControl.UpdateFrame(); //processing frame data
oHandleGLControl.RenderFrame(); //rendering
glcontrol1.Invalidate();
...
}
}
public class HandleGLControl
{
public void UpdateFrame()
{...
}
public void RenderFrame()
{
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
GL.PushMatrix();
GL.MatrixMode(MatrixMode.Modelview);
GL.Translate(-cameraPosition[0], -cameraPosition[1], -cameraPosition[2]);
GL.Rotate(g_pitch, 1.0f, 0.0f, 0.0f);
GL.Rotate(g_heading, 0.0f, 0.0f, 1.0f);
....
}
...
}
答案 0 :(得分:1)
前一阵子,我遇到了同样的问题,而您面临的问题与OpenGL上下文有关,特别是OpenGL上下文只能绑定到一个线程这一事实。
但是,尽管大家普遍认为,该线程不必一定是主窗口线程,它可以是您想要的任何线程。
这个过程很简单但很精致:
在OpenTK中,这是我的操作方式:
private void glcontrol1_Load(object sender, EventArgs e){
glcontrol1.Context.MakeCurrent(null); //Unbinds the context from the current thread.
Thread renderThread = new Thread(() => {
glcontrol1.Context.MakeCurrent(glcontrol1.WindowInfo); //Bimds the OpenGL context to this new thread
while(DoRender) { RenderFrame(); }
}
renderThread.Start();
}
您也可以将glcontrol1.SwapBuffers()
调用放入RenderFrame()方法中,到目前为止,它没有给我带来任何问题。
作为建议,我将在不同的线程上运行UpdateFrame()和RenderFrame()方法,以免将更新逻辑限制为程序的帧速率。