#include "PlayerGLWidget.h" PlayerGLWidget::PlayerGLWidget(QWidget *parent) : QOpenGLWidget(parent) { } PlayerGLWidget::~PlayerGLWidget() { } /* 刷新一帧 */ void PlayerGLWidget::updateFrame(Image_YUV420& image) { yData = image.yData; uData = image.uData; vData = image.vData; update(); } void PlayerGLWidget::initShaders() { // 顶点着色器 const char *vshader = R"( #version 330 core layout(location = 0) in vec4 vertexIn; layout(location = 1) in vec2 textureIn; out vec2 textureOut; void main(void) { gl_Position = vertexIn; textureOut = textureIn; })"; // 片段着色器(YUV420P 转 RGB) const char *fshader = R"( #version 330 core in vec2 textureOut; out vec4 fragColor; uniform sampler2D tex_y; uniform sampler2D tex_u; uniform sampler2D tex_v; void main(void) { float y = texture(tex_y, textureOut).r; float u = texture(tex_u, textureOut).r - 0.5; float v = texture(tex_v, textureOut).r - 0.5; float r = y + 1.403 * v; float g = y - 0.344 * u - 0.714 * v; float b = y + 1.770 * u; fragColor = vec4(r, g, b, 1.0); })"; // 创建着色器程序 program.addShaderFromSourceCode(QOpenGLShader::Vertex, vshader); program.addShaderFromSourceCode(QOpenGLShader::Fragment, fshader); program.link(); } void PlayerGLWidget::initTextures() { // 创建 YUV 纹理 textureY = new QOpenGLTexture(QOpenGLTexture::Target2D); textureU = new QOpenGLTexture(QOpenGLTexture::Target2D); textureV = new QOpenGLTexture(QOpenGLTexture::Target2D); textureY->create(); textureU->create(); textureV->create(); } // void PlayerGLWidget::initVertex() // { // } // void PlayerGLWidget::initFrameBuffer() // { // } void PlayerGLWidget::renderYUV420P() { if (yData.isEmpty() || uData.isEmpty() || vData.isEmpty()) return; // 绑定纹理 textureY->bind(0); textureU->bind(1); textureV->bind(2); // 上传 YUV 数据到纹理 textureY->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, yData.constData()); textureU->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, uData.constData()); textureV->setData(QOpenGLTexture::Red, QOpenGLTexture::UInt8, vData.constData()); // 绑定着色器程序 program.bind(); program.setUniformValue("tex_y", 0); program.setUniformValue("tex_u", 1); program.setUniformValue("tex_v", 2); // 绘制矩形 static const GLfloat vertices[] = { -1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 0.0f, -1.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f }; static const GLfloat texCoords[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, vertices); glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texCoords); glEnableVertexAttribArray(0); glEnableVertexAttribArray(1); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); program.release(); } void PlayerGLWidget::initializeGL() { initializeOpenGLFunctions(); glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // 初始化着色器 initShaders(); initTextures(); } void PlayerGLWidget::resizeGL(int w, int h) { glViewport(0, 0, w, h); } void PlayerGLWidget::paintGL() { glClear(GL_COLOR_BUFFER_BIT); // 渲染 YUV 数据 renderYUV420P(); }