我在我的 WPF 应用程序的 WindowsFormsHost 中嵌入了一个 OpenTK GLControl。我想不断更新和渲染它。在 Winforms 中,一个解决方案是将 UpdateAndRender 方法附加到 Application.Idle 事件,但在 WPF 中没有这样的事情。
那么更新我的场景和 GLControl 的最佳方法是什么(60FPS)?
我在我的 WPF 应用程序的 WindowsFormsHost 中嵌入了一个 OpenTK GLControl。我想不断更新和渲染它。在 Winforms 中,一个解决方案是将 UpdateAndRender 方法附加到 Application.Idle 事件,但在 WPF 中没有这样的事情。
那么更新我的场景和 GLControl 的最佳方法是什么(60FPS)?
你可以使用Invalidate()
它。这会导致GLControl
重绘它的内容。
如果在最后调用它,Paint()
可能会阻止其他 WPF 控件的某些 UI 呈现。
WPF 提供了每帧渲染事件:CompositionTarget.Rendering
. 在 WPF 想要呈现内容之前调用此事件。订阅它并调用 Invalidate:
public YourConstructor()
{
//...
CompositionTarget.Rendering += CompositionTarget_Rendering;
}
void CompositionTarget_Rendering(object sender, EventArgs e)
{
_yourControl.Invalidate();
}
如果您不再使用它,则需要取消订阅(以避免内存泄漏)。
这是一个如何:使用MSDN 中的 CompositionTarget 在每帧间隔上渲染。
我使用GLControl
这种方法,效果很好。我没有检查我有多少 FPS,但感觉很流畅。
你也可以看看这个:为什么WPF中的帧率不规则并且不限于显示器刷新?
您可以使用 System.Timers.Timer 来控制调用渲染代码的频率。在包含 GLControl-in-WindowsFormsHost 的窗口中,声明一个private System.Timers.Timer _timer;
,然后当您准备好启动渲染循环时,设置计时器间隔和它的事件处理程序,然后启动它,如下例所示:
private void btnLoadModel_Click(object sender, RoutedEventArgs e)
{
LoadModel(); // do whatever you need to do to prepare your scene for rendering
_timer = new System.Timers.Timer(10.0); // in milliseconds - you might have to play with this value to throttle your framerate depending on how involved your update and render code is
_timer.Elapsed += TimerElapsed;
_timer.Start();
}
private void TimerElapsed(object sender, ElapsedEventArgs e)
{
UpdateModel(); // this is where you'd do whatever you need to do to update your model per frame
// Invalidate will cause the Paint event on your GLControl to fire
_glControl.Invalidate(); // _glControl is obviously a private reference to the GLControl
}
您显然需要添加using System.Timers
到您的使用中。