代碼如下
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();//調用上面渲染類的渲染函數