代码如下
YUV420P_Render.h
#ifndef YUV420P_RENDER_H #define YUV420P_RENDER_H #include <QObject> #include <QOpenGLWidget> #include <QOpenGLFunctions> #include <QOpenGLShaderProgram> class YUV420P_Render: protected QOpenGLFunctions { public: YUV420P_Render(); ~YUV420P_Render(); //初始化gl void initialize(); //刷新显示 void render(uchar* py,uchar* pu,uchar* pv,int width,int height,int type); void render(uchar* ptr,int width,int height,int type); private: //shader程序 QOpenGLShaderProgram m_program; //shader中yuv变量地址 GLuint m_textureUniformY, m_textureUniformU , m_textureUniformV; //创建纹理 GLuint m_idy , m_idu , m_idv; }; #endif // YUV420P_RENDER_H
YUV420P_Render.cpp
#include "YUV420P_Render.h" #include <QDebug> #include <QTimer> #define ATTRIB_VERTEX 0 #define ATTRIB_TEXTURE 1 YUV420P_Render::YUV420P_Render() { } YUV420P_Render::~YUV420P_Render() { } //初始化gl void YUV420P_Render::initialize() { qDebug() << "initializeGL"; //初始化opengl (QOpenGLFunctions继承)函数 initializeOpenGLFunctions(); //顶点shader const char *vString = "attribute vec4 vertexPosition;\ attribute vec2 textureCoordinate;\ varying vec2 texture_Out;\ void main(void)\ {\ gl_Position = vertexPosition;\ texture_Out = textureCoordinate;\ }"; //片元shader const char *tString = "varying vec2 texture_Out;\ uniform sampler2D tex_y;\ uniform sampler2D tex_u;\ uniform sampler2D tex_v;\ void main(void)\ {\ vec3 YUV;\ vec3 RGB;\ YUV.x = texture2D(tex_y, texture_Out).r;\ YUV.y = texture2D(tex_u, texture_Out).r - 0.5;\ YUV.z = texture2D(tex_v, texture_Out).r - 0.5;\ RGB = mat3(1.0, 1.0, 1.0,\ 0.0, -0.39465, 2.03211,\ 1.13983, -0.58060, 0.0) * YUV;\ gl_FragColor = vec4(RGB, 1.0);\ }"; //m_program加载shader(顶点和片元)脚本 //片元(像素) qDebug()<<m_program.addShaderFromSourceCode(QOpenGLShader::Fragment, tString); //顶点shader qDebug() << m_program.addShaderFromSourceCode(QOpenGLShader::Vertex, vString); //设置顶点位置 m_program.bindAttributeLocation("vertexPosition",ATTRIB_VERTEX); //设置纹理位置 m_program.bindAttributeLocation("textureCoordinate",ATTRIB_TEXTURE); //编译shader qDebug() << "m_program.link() = " << m_program.link(); qDebug() << "m_program.bind() = " << m_program.bind(); //传递顶点和纹理坐标 //顶点 static const GLfloat ver[] = { -1.0f,-1.0f, 1.0f,-1.0f, -1.0f, 1.0f, 1.0f,1.0f // -1.0f,-1.0f, // 0.9f,-1.0f, // -1.0f, 1.0f, // 0.9f,1.0f }; //纹理 static const GLfloat tex[] = { 0.0f, 1.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f }; //设置顶点,纹理数组并启用 glVertexAttribPointer(ATTRIB_VERTEX, 2, GL_FLOAT, 0, 0, ver); glEnableVertexAttribArray(ATTRIB_VERTEX); glVertexAttribPointer(ATTRIB_TEXTURE, 2, GL_FLOAT, 0, 0, tex); glEnableVertexAttribArray(ATTRIB_TEXTURE); //从shader获取地址 m_textureUniformY = m_program.uniformLocation("tex_y"); m_textureUniformU = m_program.uniformLocation("tex_u"); m_textureUniformV = m_program.uniformLocation("tex_v"); //创建纹理 glGenTextures(1, &m_idy); //Y glBindTexture(GL_TEXTURE_2D, m_idy); //放大过滤,线性插值 GL_NEAREST(效率高,但马赛克严重) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //U glGenTextures(1, &m_idu); glBindTexture(GL_TEXTURE_2D, m_idu); //放大过滤,线性插值 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //V glGenTextures(1, &m_idv); glBindTexture(GL_TEXTURE_2D, m_idv); //放大过滤,线性插值 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); } //刷新显示 void YUV420P_Render::render(uchar* py,uchar* pu,uchar* pv,int width,int height,int type) { glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_idy); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,py); //与shader 关联 glUniform1i(m_textureUniformY, 0); glActiveTexture(GL_TEXTURE0+1); glBindTexture(GL_TEXTURE_2D, m_idu); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, pu); //与shader 关联 glUniform1i(m_textureUniformU,1); glActiveTexture(GL_TEXTURE0+2); glBindTexture(GL_TEXTURE_2D, m_idv); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, pv); //与shader 关联 glUniform1i(m_textureUniformV, 2); glDrawArrays(GL_TRIANGLE_STRIP,0,4); qDebug() << "paintGL"; } void YUV420P_Render::render(uchar* ptr,int width,int height,int type) { glClearColor(0.0f, 0.0f, 0.0f, 1.0f); glClear(GL_COLOR_BUFFER_BIT); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, m_idy); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width, height, 0, GL_RED, GL_UNSIGNED_BYTE,ptr); //与shader 关联 glUniform1i(m_textureUniformY, 0); glActiveTexture(GL_TEXTURE0+1); glBindTexture(GL_TEXTURE_2D, m_idu); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, ptr+width*height); //与shader 关联 glUniform1i(m_textureUniformU,1); glActiveTexture(GL_TEXTURE0+2); glBindTexture(GL_TEXTURE_2D, m_idv); //修改纹理内容(复制内存内容) glTexImage2D(GL_TEXTURE_2D, 0, GL_RED, width/2, height/2, 0, GL_RED, GL_UNSIGNED_BYTE, ptr+width*height*5/4); //与shader 关联 glUniform1i(m_textureUniformV, 2); glDrawArrays(GL_TRIANGLE_STRIP,0,4); qDebug() << "paintGL"; }
最后写一个窗口类继承 QOpenGLWidget
重写两个函数
void initializeGL(); //调用上面渲染类的初始化函数
void paintGL();//调用上面渲染类的渲染函数