QOpenGLWidget视频画面上绘制矩形框
一、QPainter绘制
在QOpenGLWidget中可以绘制,并且和OpenGL的内容叠在一起。paintGL里面绘制完视频后,解锁资源,再用QPainter绘制矩形框。这种方式灵活性最好。
void VideoGLWidget::paintGL() {
glClear(GL_COLOR_BUFFER_BIT);
m_program.bind();
//绘制视频数据
// 解绑VAO
glBindVertexArray(0);
m_program.release();
// ----------------- 绘制矩形框 -----------------
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing);
painter.setPen(QPen(QColor(Qt::red), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
QRectF drawRect = QRectF(0, 0, width() * 0.5, height() * 0.5);
painter.drawRect(drawRect);
painter.end();
}
二、OpenGL绘制
通过不同的QOpenGLShaderProgram,可以指定不同的着色器程序来实现矩形的绘制。
1)边框颜色参数要通过Uniform传递给OpenGL的顶点着色器。
2)动态矩形顶点缓冲更新,坐标归一化到OpenGL坐标系,顶点数据更新VBO
void VideoGLWidget::updateRectBuffer() {
if (m_rects.isEmpty()) return;
// 将 QRectF 转换为归一化坐标(-1 到 1)
QVector<float> vertices;
for (const QRectF &rect : m_rects) {
float x1 = (rect.x() / m_videoSize.width()) * 2 - 1;
float y1 = 1 - (rect.y() / m_videoSize.height()) * 2;
float x2 = ((rect.x() + rect.width()) / m_videoSize.width()) * 2 - 1;
float y2 = 1 - ((rect.y() + rect.height()) / m_videoSize.height()) * 2;
// 每个矩形由 4 条线段组成(每条线段 2 个点)
vertices << x1 << y1 << x2 << y1; // 上边
vertices << x2 << y1 << x2 << y2; // 右边
vertices << x2 << y2 << x1 << y2; // 下边
vertices << x1 << y2 << x1 << y1; // 左边
}
// 更新 VBO
glBindBuffer(GL_ARRAY_BUFFER, m_rectVBO);
glBufferData(GL_ARRAY_BUFFER, vertices.size() * sizeof(float),
ver