使用OpenGL 和 opengl ES 渲染YUV图片文件的QT示例

这篇具有很好参考价值的文章主要介绍了使用OpenGL 和 opengl ES 渲染YUV图片文件的QT示例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

OpenGL ES的示例:

头文件:CPlayWidget.h

#ifndef CPLAYWIDGET_H
#define CPLAYWIDGET_H

#include <QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QOpenGLFunctions>
#include <QOpenGLTexture>
#include <QFile>
#include <QTimer>

#define ATTRIB_VERTEX 3
#define ATTRIB_TEXTURE 4

class CPlayWidget : public QOpenGLWidget, protected QOpenGLFunctions
{
    Q_OBJECT
public:
    CPlayWidget(QWidget* parent);
    ~CPlayWidget();

protected:
    void initializeGL() Q_DECL_OVERRIDE;
    void resizeGL(int w, int h) Q_DECL_OVERRIDE;
    void paintGL() Q_DECL_OVERRIDE;
private:
    GLuint textureUniformY; //y纹理数据位置
    GLuint textureUniformU; //u纹理数据位置
    GLuint textureUniformV; //v纹理数据位置
    GLuint id_y; //y纹理对象ID
    GLuint id_u; //u纹理对象ID
    GLuint id_v; //v纹理对象ID
    QOpenGLTexture* m_pTextureY;  //y纹理对象
    QOpenGLTexture* m_pTextureU;  //u纹理对象
    QOpenGLTexture* m_pTextureV;  //v纹理对象
    QOpenGLShader *m_pVSHader;  //顶点着色器程序对象
    QOpenGLShader *m_pFSHader;  //片段着色器对象
    QOpenGLShaderProgram *m_pShaderProgram; //着色器程序容器
    int m_nVideoW; //视频分辨率宽
    int m_nVideoH; //视频分辨率高
    unsigned char* m_pBufYuv420p;
    QTimer timer;
    FILE* m_pYuvFile;
protected slots:
    void on_timeout();
};

#endif // CPLAYWIDGET_H

cpp文件:CPlayWidget.cpp

默认打开 ./test.yuv文件

#include "CPlayWidget.h"
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QMouseEvent>

CPlayWidget::CPlayWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    textureUniformY = 0;
    textureUniformU = 0;
    textureUniformV = 0;
    id_y = 0;
    id_u = 0;
    id_v = 0;
    m_pBufYuv420p = NULL;
    m_pVSHader = NULL;
    m_pFSHader = NULL;
    m_pShaderProgram = NULL;
    m_pTextureY = NULL;
    m_pTextureU = NULL;
    m_pTextureV = NULL;
    m_pYuvFile = NULL;
    m_nVideoH = 0;
    m_nVideoW = 0;
}

CPlayWidget::~CPlayWidget()
{   // fclose(m_pYuvFile);

    delete [] m_pBufYuv420p;

}

void CPlayWidget::initializeGL()
{ if(NULL == m_pYuvFile)
    {
        // 打开yuv视频文件 注意修改文件路径
        // m_pYuvFile = fopen("/home/enpht/Documents/test/176_144.yuv", "rb");
        m_pYuvFile = fopen("./test.yuv", "rb");
        // 根据yuv视频数据的分辨率设置宽高,demo当中是1080p,这个地方要注意跟实际数据分辨率对应上
        // m_nVideoW = 176;
        // m_nVideoH = 144;
        m_nVideoW = 1920;
        m_nVideoH = 1080;
    }
    //申请内存存一帧yuv图像数据,其大小为分辨率的1.5倍

    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    //现代opengl渲染管线依赖着色器来处理传入的数据
    //着色器:就是使用openGL着色语言(OpenGL Shading Language, GLSL)编写的一个小函数,
    //       GLSL是构成所有OpenGL着色器的语言,具体的GLSL语言的语法需要读者查找相关资料
    //初始化顶点着色器 对象
    m_pVSHader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    //顶点着色器源码
    const char *vsrc = "#version 320 es\n\
        in vec4 vertexIn;\n\
        in vec2 textureIn;\n\
        out vec2 textureOut;\n\
        void main(void)\n\
        {\n\
            gl_Position = vertexIn;\n\
            textureOut = textureIn;\n\
    }";
    //编译顶点着色器程序
    bool bCompile = m_pVSHader->compileSourceCode(vsrc);
    if(!bCompile)
    {
    }
    //初始化片段着色器 功能gpu中yuv转换成rgb
    m_pFSHader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    //片段着色器源码
    const char *fsrc = "#version 320 es\n\
    precision mediump float;\n\
    in vec2 textureOut;\n\
    uniform sampler2D tex_y;\n\
    uniform sampler2D tex_u;\n\
    uniform sampler2D tex_v;\n\
    out vec4 fragColor;\n\
    void main(void)\n\
    {\n\
        vec3 yuv;\n\
        vec3 rgb;\n\
        yuv.x = texture(tex_y, textureOut).r;\n\
        yuv.y = texture(tex_u, textureOut).r - 0.5;\n\
        yuv.z = texture(tex_v, textureOut).r - 0.5;\n\
        rgb = mat3(1.0, 1.0, 1.0,\n\
                   0.0, -0.39465, 2.03211,\n\
                   1.13983, -0.58060, 0.0) * yuv;\n\
        fragColor = vec4(rgb, 1.0);\n\
    }";
    //将glsl源码送入编译器编译着色器程序
    bCompile = m_pFSHader->compileSourceCode(fsrc);
    if(!bCompile)
    {
    }
#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1
    //创建着色器程序容器
    m_pShaderProgram = new QOpenGLShaderProgram;
    //将片段着色器添加到程序容器
    m_pShaderProgram->addShader(m_pFSHader);
    //将顶点着色器添加到程序容器
    m_pShaderProgram->addShader(m_pVSHader);
    //绑定属性vertexIn到指定位置ATTRIB_VERTEX,该属性在顶点着色源码其中有声明
    m_pShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);
    //绑定属性textureIn到指定位置ATTRIB_TEXTURE,该属性在顶点着色源码其中有声明
    m_pShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);
    //链接所有所有添入到的着色器程序
    m_pShaderProgram->link();
    //激活所有链接
    m_pShaderProgram->bind();
    //读取着色器中的数据变量tex_y, tex_u, tex_v的位置,这些变量的声明可以在
    //片段着色器源码中可以看到
    textureUniformY = m_pShaderProgram->uniformLocation("tex_y");
    textureUniformU =  m_pShaderProgram->uniformLocation("tex_u");
    textureUniformV =  m_pShaderProgram->uniformLocation("tex_v");
    // 顶点矩阵
    static const GLfloat vertexVertices[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
         -1.0f, 1.0f,
         1.0f, 1.0f,
    };
    //纹理矩阵
    static const GLfloat textureVertices[] = {
        0.0f,  1.0f,
        1.0f,  1.0f,
        0.0f,  0.0f,
        1.0f,  0.0f,
    };
    //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);
    //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
    glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
    //启用ATTRIB_VERTEX属性的数据,默认是关闭的
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
    glEnableVertexAttribArray(ATTRIB_TEXTURE);
    //分别创建y,u,v纹理对象
    m_pTextureY = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureU = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureV = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureY->create();
    m_pTextureU->create();
    m_pTextureV->create();
    //获取返回y分量的纹理索引值
    id_y = m_pTextureY->textureId();
    //获取返回u分量的纹理索引值
    id_u = m_pTextureU->textureId();
    //获取返回v分量的纹理索引值
    id_v = m_pTextureV->textureId();
    glClearColor(0.3,0.3,0.3,0.0);//设置背景色
    //qDebug("addr=%x id_y = %d id_u=%d id_v=%d\n", this, id_y, id_u, id_v);
    connect(&timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
    timer.setInterval(25);
    timer.start();
}

void CPlayWidget::resizeGL(int w, int h)
{
    if(h == 0)// 防止被零除
    {
        h = 1;// 将高设为1
    }
    //设置视口
    glViewport(0,0, w,h);
}

void CPlayWidget::paintGL()
{
    int nLen = m_nVideoW*m_nVideoH*3/2;
    if(NULL == m_pBufYuv420p)
    {
        m_pBufYuv420p = new unsigned char[nLen];
        qDebug("  Len=%d width=%d height=%d\n",
               nLen, m_nVideoW, m_nVideoH);
    }
    //将一帧yuv图像读到内存中
    if(NULL == m_pYuvFile)
    {
        qFatal("read yuv file err.may be path is wrong!\n");
        return;
    }

//    m_pBufYuv420p+=position;
//    position += nLen;
    // fread(m_pBufYuv420p, 1, nLen, m_pYuvFile);
    fread(m_pBufYuv420p, 1, nLen, m_pYuvFile);

    //加载y数据纹理
     //激活纹理单元GL_TEXTURE0
    glActiveTexture(GL_TEXTURE0);
    //使用来自y数据生成纹理
    glBindTexture(GL_TEXTURE_2D, id_y);
    //使用内存中m_pBufYuv420p数据创建真正的y数据纹理
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW, m_nVideoH, 0, GL_RED, GL_UNSIGNED_BYTE, m_pBufYuv420p);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //加载u数据纹理
    glActiveTexture(GL_TEXTURE1);//激活纹理单元GL_TEXTURE1
    glBindTexture(GL_TEXTURE_2D, id_u);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //加载v数据纹理
    glActiveTexture(GL_TEXTURE2);//激活纹理单元GL_TEXTURE2
    glBindTexture(GL_TEXTURE_2D, id_v);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH*5/4);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //指定y纹理要使用新值 只能用0,1,2等表示纹理单元的索引,这是opengl不人性化的地方
    //0对应纹理单元GL_TEXTURE0 1对应纹理单元GL_TEXTURE1 2对应纹理的单元
    glUniform1i(textureUniformY, 0);
    //指定u纹理要使用新值
    glUniform1i(textureUniformU, 1);
    //指定v纹理要使用新值
    glUniform1i(textureUniformV, 2);
    //使用顶点数组方式绘制图形
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    return;
 }

void CPlayWidget::on_timeout()
{       update();
}

OpenGL 示例:

头文件:CPlayWidget.h  与上面没有差别

cpp文件:只替换了着色器代码:文章来源地址https://www.toymoban.com/news/detail-808080.html

#include "CPlayWidget.h"
#include <QOpenGLTexture>
#include <QOpenGLBuffer>
#include <QMouseEvent>

CPlayWidget::CPlayWidget(QWidget *parent) : QOpenGLWidget(parent)
{
    textureUniformY = 0;
    textureUniformU = 0;
    textureUniformV = 0;
    id_y = 0;
    id_u = 0;
    id_v = 0;
    m_pBufYuv420p = NULL;
    m_pVSHader = NULL;
    m_pFSHader = NULL;
    m_pShaderProgram = NULL;
    m_pTextureY = NULL;
    m_pTextureU = NULL;
    m_pTextureV = NULL;
    m_pYuvFile = NULL;
    m_nVideoH = 0;
    m_nVideoW = 0;
}

CPlayWidget::~CPlayWidget()
{   // fclose(m_pYuvFile);

    delete [] m_pBufYuv420p;

}

void CPlayWidget::initializeGL()
{ if(NULL == m_pYuvFile)
    {
        // 打开yuv视频文件 注意修改文件路径
        // m_pYuvFile = fopen("/home/enpht/Documents/test/176_144.yuv", "rb");
        m_pYuvFile = fopen("./test.yuv", "rb");
        // 根据yuv视频数据的分辨率设置宽高,demo当中是1080p,这个地方要注意跟实际数据分辨率对应上
        // m_nVideoW = 176;
        // m_nVideoH = 144;
        m_nVideoW = 1920;
        m_nVideoH = 1080;
    }
    //申请内存存一帧yuv图像数据,其大小为分辨率的1.5倍

    initializeOpenGLFunctions();
    glEnable(GL_DEPTH_TEST);
    //现代opengl渲染管线依赖着色器来处理传入的数据
    //着色器:就是使用openGL着色语言(OpenGL Shading Language, GLSL)编写的一个小函数,
    //       GLSL是构成所有OpenGL着色器的语言,具体的GLSL语言的语法需要读者查找相关资料
    //初始化顶点着色器 对象
    m_pVSHader = new QOpenGLShader(QOpenGLShader::Vertex, this);
    //顶点着色器源码
#if 0
    // opengles
    const char *vsrc = "#version 320 es\n\
        in vec4 vertexIn;\n\
        in vec2 textureIn;\n\
        out vec2 textureOut;\n\
        void main(void)\n\
        {\n\
            gl_Position = vertexIn;\n\
            textureOut = textureIn;\n\
    }";
#else
    // opengl
    const char *vsrc = "attribute vec4 vertexIn; \
        attribute vec2 textureIn; \
        varying vec2 textureOut;  \
        void main(void)           \
        {                         \
            gl_Position = vertexIn; \
            textureOut = textureIn; \
        }";
#endif
    //编译顶点着色器程序
    bool bCompile = m_pVSHader->compileSourceCode(vsrc);
    if(!bCompile)
    {
    }
    //初始化片段着色器 功能gpu中yuv转换成rgb
    m_pFSHader = new QOpenGLShader(QOpenGLShader::Fragment, this);
    //片段着色器源码

#if 0
    // opengl es:
    const char *fsrc = "#version 320 es\
        varying vec2 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).r; \
            yuv.y = texture2D(tex_u, textureOut).r - 0.5; \
            yuv.z = texture2D(tex_v, textureOut).r - 0.5; \
            rgb = mat3( 1,       1,         1, \
                        0,       -0.39465,  2.03211, \
                        1.13983, -0.58060,  0) * yuv; \
            gl_FragColor = vec4(rgb, 1); \
        }";
#else
    // opengl
    const char *fsrc = "varying vec2 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).r; \
            yuv.y = texture2D(tex_u, textureOut).r - 0.5; \
            yuv.z = texture2D(tex_v, textureOut).r - 0.5; \
            rgb = mat3( 1,       1,         1, \
                        0,       -0.39465,  2.03211, \
                        1.13983, -0.58060,  0) * yuv; \
            gl_FragColor = vec4(rgb, 1); \
        }";

#endif

    //将glsl源码送入编译器编译着色器程序
    bCompile = m_pFSHader->compileSourceCode(fsrc);
    if(!bCompile)
    {
    }
#define PROGRAM_VERTEX_ATTRIBUTE 0
#define PROGRAM_TEXCOORD_ATTRIBUTE 1
    //创建着色器程序容器
    m_pShaderProgram = new QOpenGLShaderProgram;
    //将片段着色器添加到程序容器
    m_pShaderProgram->addShader(m_pFSHader);
    //将顶点着色器添加到程序容器
    m_pShaderProgram->addShader(m_pVSHader);
    //绑定属性vertexIn到指定位置ATTRIB_VERTEX,该属性在顶点着色源码其中有声明
    m_pShaderProgram->bindAttributeLocation("vertexIn", ATTRIB_VERTEX);
    //绑定属性textureIn到指定位置ATTRIB_TEXTURE,该属性在顶点着色源码其中有声明
    m_pShaderProgram->bindAttributeLocation("textureIn", ATTRIB_TEXTURE);
    //链接所有所有添入到的着色器程序
    m_pShaderProgram->link();
    //激活所有链接
    m_pShaderProgram->bind();
    //读取着色器中的数据变量tex_y, tex_u, tex_v的位置,这些变量的声明可以在
    //片段着色器源码中可以看到
    textureUniformY = m_pShaderProgram->uniformLocation("tex_y");
    textureUniformU =  m_pShaderProgram->uniformLocation("tex_u");
    textureUniformV =  m_pShaderProgram->uniformLocation("tex_v");
    // 顶点矩阵
    static const GLfloat vertexVertices[] = {
        -1.0f, -1.0f,
         1.0f, -1.0f,
         -1.0f, 1.0f,
         1.0f, 1.0f,
    };
    //纹理矩阵
    static const GLfloat textureVertices[] = {
        0.0f,  1.0f,
        1.0f,  1.0f,
        0.0f,  0.0f,
        1.0f,  0.0f,
    };
    //设置属性ATTRIB_VERTEX的顶点矩阵值以及格式
    glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, vertexVertices);
    //设置属性ATTRIB_TEXTURE的纹理矩阵值以及格式
    glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, textureVertices);
    //启用ATTRIB_VERTEX属性的数据,默认是关闭的
    glEnableVertexAttribArray(ATTRIB_VERTEX);
    //启用ATTRIB_TEXTURE属性的数据,默认是关闭的
    glEnableVertexAttribArray(ATTRIB_TEXTURE);
    //分别创建y,u,v纹理对象
    m_pTextureY = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureU = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureV = new QOpenGLTexture(QOpenGLTexture::Target2D);
    m_pTextureY->create();
    m_pTextureU->create();
    m_pTextureV->create();
    //获取返回y分量的纹理索引值
    id_y = m_pTextureY->textureId();
    //获取返回u分量的纹理索引值
    id_u = m_pTextureU->textureId();
    //获取返回v分量的纹理索引值
    id_v = m_pTextureV->textureId();
    glClearColor(0.3,0.3,0.3,0.0);//设置背景色
    //qDebug("addr=%x id_y = %d id_u=%d id_v=%d\n", this, id_y, id_u, id_v);
    connect(&timer, SIGNAL(timeout()), this, SLOT(on_timeout()));
    timer.setInterval(25);
    timer.start();
}

void CPlayWidget::resizeGL(int w, int h)
{
    if(h == 0)// 防止被零除
    {
        h = 1;// 将高设为1
    }
    //设置视口
    glViewport(0,0, w,h);
}

void CPlayWidget::paintGL()
{
    int nLen = m_nVideoW*m_nVideoH*3/2;
    if(NULL == m_pBufYuv420p)
    {
        m_pBufYuv420p = new unsigned char[nLen];
        qDebug("  Len=%d width=%d height=%d\n",
               nLen, m_nVideoW, m_nVideoH);
    }
    //将一帧yuv图像读到内存中
    if(NULL == m_pYuvFile)
    {
        qFatal("read yuv file err.may be path is wrong!\n");
        return;
    }

//    m_pBufYuv420p+=position;
//    position += nLen;
    // fread(m_pBufYuv420p, 1, nLen, m_pYuvFile);
    fread(m_pBufYuv420p, 1, nLen, m_pYuvFile);

    //加载y数据纹理
     //激活纹理单元GL_TEXTURE0
    glActiveTexture(GL_TEXTURE0);
    //使用来自y数据生成纹理
    glBindTexture(GL_TEXTURE_2D, id_y);
    //使用内存中m_pBufYuv420p数据创建真正的y数据纹理
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW, m_nVideoH, 0, GL_RED, GL_UNSIGNED_BYTE, m_pBufYuv420p);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //加载u数据纹理
    glActiveTexture(GL_TEXTURE1);//激活纹理单元GL_TEXTURE1
    glBindTexture(GL_TEXTURE_2D, id_u);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //加载v数据纹理
    glActiveTexture(GL_TEXTURE2);//激活纹理单元GL_TEXTURE2
    glBindTexture(GL_TEXTURE_2D, id_v);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, m_nVideoW/2, m_nVideoH/2, 0, GL_RED, GL_UNSIGNED_BYTE, (char*)m_pBufYuv420p+m_nVideoW*m_nVideoH*5/4);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    //指定y纹理要使用新值 只能用0,1,2等表示纹理单元的索引,这是opengl不人性化的地方
    //0对应纹理单元GL_TEXTURE0 1对应纹理单元GL_TEXTURE1 2对应纹理的单元
    glUniform1i(textureUniformY, 0);
    //指定u纹理要使用新值
    glUniform1i(textureUniformU, 1);
    //指定v纹理要使用新值
    glUniform1i(textureUniformV, 2);
    //使用顶点数组方式绘制图形
    glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
    return;
 }

void CPlayWidget::on_timeout()
{       update();
}

到了这里,关于使用OpenGL 和 opengl ES 渲染YUV图片文件的QT示例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包赞助服务器费用

相关文章

  • 【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv

    【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv

    通过Qt opengl不是为了3D绘制,而是为了将视频绘制起来 使用opengl 可以极大降低yuv转rgb的转换开销 1、为什么用QT的opengl 简单,界面可以自动叠加 void paintGL(); // 具体的绘制写在该函数里 void initializeGL(); // 材质初始化 void resizeGL(int width, int height); // 当窗口发生变化(缩放) QO

    2023年04月09日
    浏览(15)
  • 【NET 7.0、OpenGL ES】使用Silk.NET渲染MMD,并实时进行物理模拟。

    【NET 7.0、OpenGL ES】使用Silk.NET渲染MMD,并实时进行物理模拟。

    有关mmd播放器,网上也有许多非常漂亮的实现,如 pmxeditor、saba、blender_mmd_tools等等。。 首先我想先介绍下我参考实现的仓库: sselecirPyM/Coocoo3D: Experimental MMD renderer using DX12 and DXR. (github.com),这是sselecirPyM大神使用NET 6.0和DX12实现的mmd渲染器,支持自定义渲染管线、光照等,感

    2024年02月08日
    浏览(11)
  • IJKPLAYER源码分析-OpenGL ES渲染

    IJKPLAYER在视频render之时,并非简单使用SDL渲染API,而是用了OpenGL ES,再分别在Android和iOS平台做视频的显示; 一言以蔽之,OpenGL ES并不能做到直接在窗口上render并显示,而是需要一个中间媒介。这个中间媒介,将OpenGL ES的render结果,最终输出到窗口上显示; 在Android端,这个中

    2024年04月11日
    浏览(11)
  • python opengl 渲染图片和Obj

    目录 安装:  python opengl 渲染图片和Obj 截图png格式和jpg格式: pip install pyopengl

    2024年02月11日
    浏览(9)
  • OpenGL ES FBO 离屏渲染详解(附项目源码)

    OpenGL ES FBO 离屏渲染详解(附项目源码)

    该原创文章首发于微信公众号:字节流动 FBO(Frame Buffer Object)即帧缓冲区对象,实际上是一个可添加缓冲区的容器,可以为其添加纹理或渲染缓冲区对象(RBO)。 FBO 本身不能用于渲染,只有添加了纹理或者渲染缓冲区之后才能作为渲染目标,它仅且提供了 3 种附着(Attac

    2024年02月12日
    浏览(11)
  • 第三章 OpenGL ES 基础-基础-GLSL渲染纹理

    第三章 OpenGL ES 基础-基础-GLSL渲染纹理

    第一章 OpenGL ES 基础-屏幕、纹理、顶点坐标 第二章 OpenGL ES 基础-GLSL语法简单总结 第三章 OpenGL ES 基础-GLSL渲染纹理 第四章 OpenGL ES 基础-位移、缩放、旋转原理 第五章 OpenGL ES 基础-透视投影矩阵与正交投影矩阵 第六章 OpenGL ES 基础-FBO、VBO理解与运用 第七章 OpenGL ES 基础-输入

    2024年03月18日
    浏览(14)
  • OpenGL ES 绘制一张图片

    OpenGL ES 绘制一张图片

    GLSL 的修饰符与数据类型 GLSL 中变量的修饰符 const:修饰不可被外界改变的常量 attribute:修饰经常更改的变量,只可以在顶点着色器中使用 uniform:修饰不经常更改的变量,可用于顶点着色器和片段着色器 varying:修饰在顶点着色器计算,然后传递到片元着色器中使用的变量

    2024年02月06日
    浏览(7)
  • Qt/QML编程之路:OpenGL的示例(39)

    Qt/QML编程之路:OpenGL的示例(39)

    Qt编程之后,会发现有版本问题,有时候一个示例不同的版本下可能会跑不同,有些Qt5跑不同Qt6已经完善,可以跑通。 我就看到有个关于OpenGL的示例: 这个示例是演示怎么基于OpenGL编程的,但是调试时却发现glViewXXX等gl打头的函数说找不到reference,或者什么link不上之类的错误

    2024年01月19日
    浏览(11)
  • Android OpenGL ES 学习(十三) -离屏渲染FBO(截图)RBO, OES转 FBO

    Android OpenGL ES 学习(十三) -离屏渲染FBO(截图)RBO, OES转 FBO

    Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投屏 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用 VBO、VAO 和 EBO/IBO 优化程序 Android OpenGL ES 学习(七) –

    2024年02月12日
    浏览(8)
  • OpenGL ES 渲染 NV21、NV12、I420、YV12、YUYV、UYVY、I444(建议收藏)

    本文主要讲解常见的 YUV 格式图像渲染方式,如果对 YUV 格式不是很熟悉的同学可以翻看旧文一文掌握 YUV 图像的基本处理,YUV 格式的介绍这里不再展开。 NV21、NV12 可以看成同一种结构,区别只是 uv 的交错排列顺序不同。 渲染 NV21/NV12 格式图像需要使用 2 个纹理,分别用于保

    2024年02月22日
    浏览(10)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包