1

我在我的 WPF 应用程序的 WindowsFormsHost 中嵌入了一个 OpenTK GLControl。我想不断更新和渲染它。在 Winforms 中,一个解决方案是将 UpdateAndRender 方法附加到 Application.Idle 事件,但在 WPF 中没有这样的事情。

那么更新我的场景和 GLControl 的最佳方法是什么(60FPS)?

4

2 回答 2

2

你可以使用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中的帧率不规则并且不限于显示器刷新?

于 2014-10-01T07:37:55.193 回答
2

您可以使用 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到您的使用中。

于 2012-07-26T19:38:04.150 回答