简短的回答:Open GL 绘图QOpenGLWidget
应该发生在QOpenGLWidget::paintGL()
.
当调用 OpenGL 命令时,一个前提条件是相应的命令。 OpenGL 上下文之前已被激活。这是什么QOpenGLWidget::paintGL() https://doc.qt.io/qt-5/qopenglwidget.html#paintGL确保:
无需致电makeCurrent() https://doc.qt.io/qt-5/qopenglwidget.html#makeCurrent因为当这个函数被调用时,这已经完成了。
在调用此函数之前,上下文和帧缓冲区已绑定,并且通过调用 glViewport() 设置视口。
顺便提一句。另一个先决条件是分别。 OpenGL 上下文已经创建完毕。
为了了解更多相关信息,我进行了更深入的研究——QOpenGLWidget::paintEvent() https://code.woboq.org/qt5/qtbase/src/widgets/kernel/qopenglwidget.cpp.html#_ZN13QOpenGLWidget10paintEventEP11QPaintEvent(在 woboq.org 上):
void QOpenGLWidget::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e);
Q_D(QOpenGLWidget);
if (!d->initialized)
return;
if (updatesEnabled())
d->render();
}
只要初始化尚未完成,绘制事件就不会执行任何操作。 (我没有深入挖掘,但我确信初始化涉及调用QOpenGLWidget::initializeGL()
.)
绘制事件请求渲染。
眼睛跟随代码(严格来说:鼠标点击),d->render()
calls QOpenGLWidgetPrivate::render()
这又调用finallyQOpenGLWidgetPrivate::invokeUserPaint()
我们在这里:
void QOpenGLWidgetPrivate::invokeUserPaint()
{
Q_Q(QOpenGLWidget);
QOpenGLContext *ctx = QOpenGLContext::currentContext();
Q_ASSERT(ctx && fbo);
QOpenGLFunctions *f = ctx->functions();
QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = fbo->handle();
f->glViewport(0, 0, q->width() * q->devicePixelRatioF(), q->height() * q->devicePixelRatioF());
inPaintGL = true;
// vvvvvvvvvvvv
q->paintGL();
// ^^^^^^^^^^^^
inPaintGL = false;
flushPending = true;
QOpenGLContextPrivate::get(ctx)->defaultFboRedirect = 0;
}
(评论是我的。)
So, if QOpenGLWidget::paintEvent()
超载,那么它应该调用paintEvent()
基类的。 (否则OpenGL渲染肯定会中断。)
最后,当我更改几何图形时如何强制重新渲染图形?我应该调用什么方法?
这实际上在描述中得到了回答QOpenGLWidget
:
如果您需要从paintGL()以外的地方触发重绘(一个典型的例子是使用计时器来动画场景),您应该调用小部件的update() https://doc.qt.io/qt-5/qwidget.html#update安排更新的功能。
万一我误解了OP的意图,实际的问题是放在哪里QPainter
画入QOpenGLWidget
– 我曾经写过一个答案SO:在特定时间在 qglwidget 上绘制一个矩形 https://stackoverflow.com/a/42420804/7478597关于混合 OpenGL 命令和QPainter
画入paintGL()
.