Qt在视频画面上绘制动态矩形 转载的文章 感觉有学习的价值
Qt在视频画面上绘制动态矩形
说明
Qt可以通过QOpenGLWidget使用OpenGL渲染显示视频,在渲染的视频画面上,有可能需要绘制一些几何图案。目前试了3种不同的方式在画面上绘制矩形,记录下过程。
通过QPainter绘制
Qt的绘制函数paintEvent(QPaintEvent *event)
在QOpenGLWidget中可以绘制,并且和OpenGL的内容叠在一起,只需要在绘制之前先调用下基类的paintEvent(QPaintEvent *event)
即可,可以理解为先在画布上画好视频,再在画布上画个矩形。这种方式灵活性最好。
void RenderWidget::paintEvent(QPaintEvent *event)
{
QOpenGLWidget::paintEvent(event);
qreal offset = sin(m_nCount * 0.1); //m_nCount是渲染的帧数
QPainter painter(this);
painter.setRenderHints(QPainter::SmoothPixmapTransform);
painter.save();
painter.setPen(QPen(QColor("#4FE3C1"), 1, Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
painter.drawRect(QRectF(width() * offset, height() * 0.7, width() * 0.25, height() * 0.25));
painter.restore();
}
通过OpenGL绘制
通过不同的QOpenGLShaderProgram,可以指定不同的着色器程序来实现矩形的绘制。这种方式绘制的时候,偏移量这些变化参数要通过Uniform传递给OpenGL的顶点着色器,如果图形复杂或者带3D可以考虑。
void RenderWidget::initializeGL()
{
initializeOpenGLFunctions();
const char *vsrc =
"attribute vec4 vertexIn; \
attribute vec4 textureIn; \
varying vec4 textureOut; \
void main(void) \
{ \
gl_Position = vertexIn; \
textureOut = textureIn; \
}";
const char *fsrc =
"varying mediump vec4 textureOut;\
uniform sampler2D tex_y; \
uniform sampler2D tex_u; \
uniform sampler2D tex_v; \
void main(void) \
{ \
vec3 yuv; \
vec3 rgb; \
yuv.x = texture2D(tex_y, textureOut.st).r; \
yuv.y = texture2D(tex_u, textureOut.st).r - 0.5; \
yuv.z = texture2D(tex_v, textureOut.st).r - 0.5; \
rgb = mat3( 1, 1, 1, \
0, -0.39465, 2.03211, \
1.13983, -0.58060, 0) * yuv; \
gl_FragColor = vec4(rgb, 1); \
}";
const char *rcvsrc = "#version 330 core\n \
layout(location = 0) in vec3 aPos;\n \
uniform vec2 offsetP; \
void main(){\n \
gl_Position = vec4(aPos.x + offsetP.x, aPos.y + offsetP.y, aPos.z, 1.0f);\n \
}\n ";
const char *rcfsrc = "#version 330 core\n \
out vec4 FragColor;\n \
void main(){\n \
FragColor = vec4(1.0f, 0.0f, 0.0f, 1.0f);\n \
}\n ";
videoProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Vertex,vsrc);
videoProgram.addCacheableShaderFromSourceCode(QOpenGLShader::Fragment,fsrc);
videoProgram.link();
rcProgram.addShaderFromSourceCode(QOpenGLShader::Vertex,rcvsrc);
rcProgram.addShaderFromSourceCode(QOpenGLShader::Fragment,rcfsrc);
rcProgram.link();
{
QOpenGLVertexArrayObject::Binder vaoBind(&rcvao);
GLfloat rcPoints[]{
0.25f, 0.25f, 0.0f, // top right
0.25f, -0.25f, 0.0f, // bottom right
-0.25f, -0.25f, 0.0f, // bottom left
-0.25f, 0.25f, 0.0f, // top left
};
rcvbo.create();
rcvbo.bind();
rcvbo.allocate(rcPoints, sizeof(rcPoints));
int attr = -1;
attr = rcProgram.attributeLocation("aPos");
rcProgram.setAttributeBuffer(attr, GL_FLOAT, 0, 3, sizeof(GLfloat) * 3);
rcProgram.enableAttributeArray(attr);
rcvbo.release();
}
{
QOpenGLVertexArrayObject::Binder vaoBind(&vao);
GLfloat points[]{
-1.0f, 1.0f,
1.0f, 1.0f,
1.0f, -1.0f,
-1.0f, -1.0f,
0.0f,0.0f,
1.0f,0.0f,
1.0f,1.0f,
0.0f,1.0f
};
vbo.create();
vbo.bind();
vbo.allocate(points,sizeof(points));
m_pTextureY = std::make_unique<QOpenGLTexture