代碼庫--基於QT的OPENGL渲染YUV

昨天花了一天的時間來整理這塊的業務,因爲自己做QT的時間也不長.

上來我們就直接說重點了:

首先在pro文件中,我們必須指定使用opengl庫:

QT       += opengl
LIBS     += -L./libs -lopengl32

在QT中我是直接創建了一個控件,讓這個控件繼承QOpenGLWidget。

同時還必須繼承QOpenGLFunctions,這樣我們就可以使用: opengl 的相關 functions功能,比如glViewport等等.

#ifndef YUVGLWEIGHT_H
#define YUVGLWEIGHT_H

#include <QtWidgets/QOpenGLWidget>
#include <QOpenGLShaderProgram>
#include <QGLShader>
#include <QOpenGLFunctions>
#include <QOpenGLContext>

class YUVGLWeight : public QOpenGLWidget ,QOpenGLFunctions
{
    Q_OBJECT
public:
    explicit YUVGLWeight(QWidget *parent = nullptr);

protected:
    virtual void initializeGL();
    virtual void resizeGL(int w, int h);
    virtual void paintGL();

private:
    int screen_w;
    int screen_h;

    QOpenGLContext *context_;
    QOpenGLShaderProgram program_;
    GLuint attr_pos;
    GLuint attr_uv;

    GLuint sam_y;
    GLuint sam_u;
    GLuint sam_v;
    GLuint samplerConvertMatrix;

    //for test
    GLuint sam_rgb;

    GLuint textures_[3];

    // 類是用來繼承的,不是用來進行初始化的
 //   QOpenGLFunctions glFunctions_;

    //解碼成功後的寬高
    int srcW_ = 352,srcH_ = 288;

signals:

public slots:
};

#endif // YUVGLWEIGHT_H

再看實現類,我們實現類的目的是把yuv渲染出來:

#include "yuvglweight.h"
#include <QDebug>
#include <QGLFormat>
#include <QtOpenGL>


const char *vertexShaderStr =

        "attribute vec3 position;                       \n"
        "attribute vec2 texcoord;                       \n"

        "varying vec2  v_texcoord;                      \n"

        "void main()                                    \n"
        "{                                              \n"
        "  v_texcoord =  texcoord ;                     \n"
        "  gl_Position = vec4(position , 1.0) ;         \n"
        "}                                              \n"

        ;

const char *fragShaderStr =


        "varying vec2 v_texcoord;                       \n"
        "uniform sampler2D  y_sampler;                  \n"
        "uniform sampler2D  u_sampler;                  \n"
        "uniform sampler2D  v_sampler;                  \n"
        "uniform mat3 colorConversionMatrix;            \n"

        "uniform sampler2D  rgb_sampler;                \n"


        "void main()                                    \n"
        "{                                              \n"
//        "  vec3 yuv;                                    \n"
//        "  vec3 rgb;                                    \n"

//        "  yuv.x = texture2D(y_sampler,v_texcoord).r - (16.0/255.0);            \n"
//        "  yuv.yz = texture2D(u_sampler,v_texcoord).rg - vec2(0.5,0.5);        \n"

//        "  rgb = colorConversionMatrix * yuv;                                   \n"
//        "  gl_FragColor = vec4(rgb,1.0);                      \n"

// //       " gl_FragColor = vec4( texture2D(rgb_sampler,v_texcoord).rgb , 1.0 );                     \n"

        "  float y,u,v,r,g,b;                               \n"
        "  y = texture2D(y_sampler,v_texcoord).r;           \n"
        "  u = texture2D(u_sampler,v_texcoord).r;           \n"
        "  v = texture2D(v_sampler,v_texcoord).r;           \n"
        "  y = 1.16438355 * (y - 0.0625);                   \n"
        "  u = u - 0.5;                                     \n"
        "  v = v - 0.5;                                     \n"
        "  r = clamp(y + 1.596 * v, 0.0, 1.0);              \n"
        "  g = clamp(y - 0.391 * u - 0.813 * v, 0.0, 1.0);              \n"
        "  b = clamp(y + 2.018 * u, 0.0, 1.0);              \n"
        "  gl_FragColor = vec4(r,g,b,1.0) ;                 \n"

        "}                                                                      \n"
        ;


YUVGLWeight::YUVGLWeight(QWidget *parent) : QOpenGLWidget(parent)
{

}


void YUVGLWeight::initializeGL()
{
    //初始化opengl模塊
    QGLFormat format;
    format.setVersion(2,2);
    format.setProfile(QGLFormat::CoreProfile);

    initializeOpenGLFunctions();

//    context_ = new QOpenGLContext();
//    context_->create();
//    context_->makeCurrent(this);


    //1.編譯shader模塊
    program_.addShaderFromSourceCode(QOpenGLShader::Vertex,vertexShaderStr);
    program_.addShaderFromSourceCode(QOpenGLShader::Fragment,fragShaderStr);

    program_.link();
    program_.bind();


    attr_pos = program_.attributeLocation("position");
    attr_uv = program_.attributeLocation("texcoord");

    sam_y = program_.uniformLocation("y_sampler");
    sam_u = program_.uniformLocation("u_sampler");
    sam_v = program_.uniformLocation("v_sampler");

    samplerConvertMatrix = program_.uniformLocation("colorConversionMatrix");

    sam_rgb = program_.uniformLocation("rgb_sampler");

    qDebug() << "position :" << attr_pos ;
    qDebug() << "texcoord_ :" << attr_uv ;
    qDebug() << "sam y_:"<< sam_y ;
    qDebug() << "sam_u:" << sam_u ;
    qDebug() << "sam_v:" << sam_v ;
    qDebug() << "convert matrix:" << samplerConvertMatrix ;



    //讀取yuv的數據

    uint8_t * pbuf = new uint8_t [srcW_ * srcH_ * 3  / 2] ;
    FILE *fs = fopen("d://akiyo_cif.yuv" , "rb+");
    fread(pbuf,srcW_ * srcH_ * 3  / 2 , 1,fs);
    fclose(fs);

    glGenTextures(3,textures_);

    glActiveTexture(GL_TEXTURE0);
    glBindTexture(GL_TEXTURE_2D,textures_[0]);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_,srcH_,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf);


    glActiveTexture(GL_TEXTURE1);
    glBindTexture(GL_TEXTURE_2D,textures_[1]);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_>>1,srcH_>>1,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf + srcW_ * srcH_);


    glActiveTexture(GL_TEXTURE2);
    glBindTexture(GL_TEXTURE_2D,textures_[2]);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,srcW_>>1,srcH_>>1,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,pbuf + srcW_ * srcH_ + srcW_ * srcH_ / 4);

    delete[] pbuf;
    pbuf = NULL;

    glActiveTexture(0);
    glBindTexture(GL_TEXTURE_2D,0);



}

void YUVGLWeight::resizeGL(int w, int h)
{
    screen_w = w;
    screen_h = h;
    qDebug()<< "resize gl:" << w ;
}


void YUVGLWeight::paintGL()
{
    glClearColor(1.0f,0.0f,0.0f,1.0f);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glViewport(0,0,screen_w,screen_h);

    qDebug() << "program object:" << program_.programId() ;

    glUseProgram(program_.programId());


    GLfloat arrays[6 * 5] =
    {
        //第一個三角形 -- 逆時針
        -1.0f,-1.0f,0.0f , 0.0f,1.0f , // bottom left
        1.0f ,-1.0f,0.0f , 1.0f,1.0f , // bottom right
        1.0f,1.0f,0.0f,    1.0f,0.0f , // top right

        // 第二個三角形
        1.0f,1.0f,0.0f,    1.0f,0.0f , // top right
        -1.0f,1.0f,0.0f,    0.0f,0.0f ,// top left
        -1.0f,-1.0f,0.0f , 0.0f,1.0f , // bottom left
    };

   glEnableVertexAttribArray(attr_pos);
   glVertexAttribPointer(
                                    attr_pos ,
                                    3,
                                    GL_FLOAT,
                                    GL_FALSE,
                                    5 * sizeof( GL_FLOAT ) ,
                                    arrays);


   glEnableVertexAttribArray(attr_uv);
   glVertexAttribPointer(
                                    attr_uv ,
                                    2,
                                    GL_FLOAT,
                                    GL_FALSE,
                                    5 * sizeof( GL_FLOAT ) ,
                                    &arrays[3] ); //注意這裏千萬不要使用: arrays + 3 * sizeof(GLFloat),因爲arrays的是float類型,移位的時候,是按float進行移位的.


   glActiveTexture(GL_TEXTURE0);
   glBindTexture(GL_TEXTURE_2D,textures_[0]);

   glActiveTexture(GL_TEXTURE1);
   glBindTexture(GL_TEXTURE_2D,textures_[1]);

   glActiveTexture(GL_TEXTURE2);
   glBindTexture(GL_TEXTURE_2D,textures_[2]);

   const GLfloat kColorConversion709[] = {
       1.164f,  1.164f, 1.164f,
       0.0f, -0.213f, 2.112f,
       1.793f, -0.533f,   0.0f,
   };


   glUniform1i(sam_y,0);
   glUniform1i(sam_u,1);
   glUniform1i(sam_v,2);
   glUniformMatrix3fv(samplerConvertMatrix, 1, GL_FALSE, kColorConversion709);
   glUniform1i(sam_rgb , 2);


   glDrawArrays(GL_TRIANGLES,0,6);

}



最終的渲染效果如下:

yuv圖片下載地址:
http://trace.eas.asu.edu/yuv/index.html
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章