我写了一个小应用程序,用手绘光标替换光标。因此我使用了 QOpenGlWidget。对于动画,我使用 frameSwapped 信号:
connect(this, SIGNAL(frameSwapped()), this, SLOT(update()));
到目前为止,我没有使用任何特定的 OpenGL 函数,所以我只是将paintevent 模拟覆盖为经典的 QWidget。
当仅使用 QPainter 进行绘图时,也可以像对普通小部件一样进行绘图:通过重新实现 paintEvent()。
void Widget::paintEvent(QPaintEvent* event) {
// Draw Cursor
POINT LpPoint;
GetCursorPos(&LpPoint);
QPoint CursorPos(LpPoint.x, LpPoint.y);
CursorPos = mapFromGlobal(CursorPos);
QPainter Painter(this);
Painter.drawEllipse(CursorPos, 20, 20);
}
我以 240 fps 的速度拍摄了结果,并发现我绘制的光标在 windows 光标后面 2 帧。这并不重要,根本没有滞后。但只有一帧会很棒。如果我能够量化滞后,那就太好了。这样我就知道它是一帧 +- 渲染的持续时间。我已经读过这个,但我对 OpenGL 不太熟悉。而且我认为我不能将它与 QOpenGlWidget 一起使用。也许有人知道如何将延迟减少到只有一帧。
更新 1:我做了一些研究并尝试了很多并取得了一定的成功。我的最新版本:
connect(this, SIGNAL(frameSwapped()), this, SLOT(animate()));
void Widget::animate() {
makeCurrent();
QOpenGLFunctions* f = QOpenGLContext::currentContext()->functions();
f->glFinish();
//std::this_thread::sleep_for(std::chrono::milliseconds(12));
update();
}
我使用 glFinish() 来同步 CPU 和 GPU。现在绘制的光标大约落后一帧。有时它甚至比一帧还要好。但是有跳帧,所以绘制的光标根本不动。总体上没有一致性。我仍然很难理解 OpenGL 是如何更新的。也许更多信息:setIntervall
设置为 1 并且它是双缓冲的。我想也许不知道 Qt 究竟做了什么是个问题。调用update
只安排更新,我无法控制缓冲区的交换方式。也许有人在这些问题上有更多的经验。我可以说每 16 毫秒调用一次paintevent/paintGL。我添加了std::this_thread::sleep_for(std::chrono::milliseconds(12));
减少渲染和实际鼠标位置之间的延迟。这有助于减少平均延迟。但对我来说,几乎不可能对下一帧会发生什么做出可靠的预测。
更新 2:我在Qt 论坛 上发布了一个类似的问题。尽管它不是一个直接的答案,但它包含一些有用的信息。