qt5_qml_Opengl_shader 第三弹-----------------------纹理贴图(YUV)

来源:互联网 发布:php开启伪静态 编辑:程序博客网 时间:2024/05/18 03:39

Opengl_under_qml第三弹----------------------纹理贴图(YUV)

本文接上文

Opengl_under_qml第三弹----------------------纹理贴图(YUV

主要通过程序将yuv数据送给shader,通过gpu来转成rgb进而渲染。

 

与上文主要不同的地方还是paint函数,为了容易看懂,没有将其写成多个函数的形式,也没有加测试代码,

 

voidSquircleRenderer::paint()

{

   //initializeGLFunctions();

    initializeOpenGLFunctions();

    if(!m_program){

        m_program=newQOpenGLShaderProgram();

 

 

        m_program->addShaderFromSourceCode(QOpenGLShader::Vertex,

                                          "attributehighpvec4vertexIn;"

                                          "attributehighpvec2textureIn;"

                                          "varyingvec2textureOut;"

                                          "voidmain(void){"

                                          "gl_Position=vertexIn;"

                                          "textureOut=textureIn;}");

 

        m_program->addShaderFromSourceCode(QOpenGLShader::Fragment,

                                          "varyingvec2textureOut;"

                                          "uniformsampler2Dtex_y;"

                                          "uniformsampler2Dtex_u;"

                                          "uniformsampler2Dtex_v;"

                                           "voidmain(void){"

                                          "vec3yuv;"

                                          "vec3rgb;"

                                          "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);}");

 

        m_program->bindAttributeLocation("vertexIn",ATTRIB_VERTEX);

        m_program->bindAttributeLocation("textureIn",ATTRIB_TEXTURE);

 

        m_program->link();

    }

    m_program->bind();

 

 

    staticconstGLfloatvertexVertices[]={

        -1.0f,-1.0f,

        1.0f,-1.0f,

        -1.0f, 1.0f,

        1.0f, 1.0f,

    };

    m_program->setAttributeArray(ATTRIB_VERTEX,GL_FLOAT,vertexVertices,2);

    m_program->enableAttributeArray(ATTRIB_VERTEX);

 

 

    staticconstGLfloattextureVertices[]={

        0.0f, 1.0f,

        1.0f, 1.0f,

        0.0f, 0.0f,

        1.0f, 0.0f,

    };

    m_program->setAttributeArray(ATTRIB_TEXTURE,GL_FLOAT,textureVertices,2);

    m_program->enableAttributeArray(ATTRIB_TEXTURE);

 

 

    GLuintTextureID0=m_program->uniformLocation("tex_y");

    GLuintTextureID1=m_program->uniformLocation("tex_u");

    GLuintTextureID2=m_program->uniformLocation("tex_v");

 

 

    GLuintytexture,utexture,vtexture;

 

 

    glGenTextures(1,&ytexture);

    glBindTexture(GL_TEXTURE_2D,ytexture);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,(GLfloat)GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,(GLfloat)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);

 

 

    glGenTextures(1,&utexture);

    glBindTexture(GL_TEXTURE_2D,utexture);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,(GLfloat)GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,(GLfloat)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);

 

 

    glGenTextures(1,&vtexture);

    glBindTexture(GL_TEXTURE_2D,vtexture);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,(GLfloat)GL_LINEAR);

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,(GLfloat)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);

 

 

    FILE*fp;

    if((fp=fopen("D:/testyuv.yuv","rb"))==NULL)

    {

        printf("cantopenthefile");

        exit(0);

    }

    unsignedchardata[size];

    fread(data,1,size,fp);

    unsignedchar*y=data,*u=y+Pitch,*v=u+(Pitch>>2);//iePITCH*HEIGHT16*1/4

 

    glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_2D,ytexture);

    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,MAIN_TEXTURE_WIDTH,MAIN_TEXTURE_HEIGHT,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,y);

    m_program->setUniformValue(TextureID0,0);

 

 

 

    glActiveTexture(GL_TEXTURE1);

    glBindTexture(GL_TEXTURE_2D,utexture);

    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,MAIN_TEXTURE_WIDTH/2,MAIN_TEXTURE_HEIGHT/2,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,u);

    m_program->setUniformValue(TextureID1,1);

 

 

    glActiveTexture(GL_TEXTURE2);

    glBindTexture(GL_TEXTURE_2D,vtexture);

    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,MAIN_TEXTURE_WIDTH/2,MAIN_TEXTURE_HEIGHT/2,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,v);

    m_program->setUniformValue(TextureID2,2);

 

 

 

    glViewport(0,0,m_viewportSize.width(),m_viewportSize.height());

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLE_STRIP,0,4);

 

    glDisable(GL_DEPTH_TEST);

 

    m_program->disableAttributeArray(ATTRIB_VERTEX);

    m_program->disableAttributeArray(ATTRIB_VERTEX);

 

    fclose(fp);

    m_program->release();

}

 

 

 

先看shader的代码:

首先Vsh:

attributehighpvec4vertexIn;

attributehighpvec2textureIn;

varyingvec2textureOut;

voidmain(void){

  gl_Position=vertexIn;

 textureOut=textureIn;

 

定义了两个attribute变量,一个作为顶点着色器的坐标vertexIn,另一个textureIn用于传给fshtextureOut变量来进行纹理绘制,这里跟上一篇略有不同,原因是我参考的例子不同,应该使按照上一篇只定义一个坐标变量就行了,这里不再修改了。

然后是Fsh。

  varyingvec2textureOut;

uniformsampler2Dtex_y;"

uniformsampler2Dtex_u;"

  uniformsampler2Dtex_v;"

  voidmain(void){"

  vec3yuv;"

  vec3rgb;"

  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);}

 

textureOut是从vsh传递过来的用于绘制纹理的坐标变量,tex_y,tex_u,tex_v是定义的是纹理变量(sampler2D),然后把值给yuv,然后通过一个矩阵的乘法,得到rgb数据,这里和普通的yuv-转rgb是一样的,只不过是放在gpu转换。

 

具体的顶点坐标传值在上一篇文章里介绍了,这里就不在说了。主要说纹理的生成,(其实部分也是和上一篇文章是一样的,都是把buffer data传给sample2d纹理变量,这里把所有的东西(包括读取数据)写到一个流程里了)

  GLuintytexture,utexture,vtexture;//定义纹理id

 

 

    glGenTextures(1,&ytexture); //生成纹理

    glBindTexture(GL_TEXTURE_2D,ytexture);//绑定纹理

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,(GLfloat)GL_LINEAR);//设置纹理参数

    glTexParameterf(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,(GLfloat)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);

然后是读取文件操作: 

 

//读取文件到fp

FILE*fp;

    fp=fopen("D:/testyuv.yuv","rb")

 

//从fp读取数据到data,大小是size,个数是1

    unsignedchardata[size];

    fread(data,1,size,fp);

 

定义指针指向data数据

    unsignedchar*y=data,*u=y+Pitch,*v=u+(Pitch>>2);//iePITCH*HEIGHT16*1/4

 

这里的对yuv数据加以说明,一帧分辨率为Pitch=imagewidth*imageheight的yuv数据,总共的数据量有3*Pitch/2个字节,其中y数据占Pitch个字节,所以程序里有:*u = y + Pitch”,然后u数据,占Pitch/4个字节,所以程序里:*v = u + (Pitch >> 2)”意思就是PITCH*HEIGHT16*1/4,最后v数据占Pitch/4个字节,

这里需要说明的是,文件一旦打开,及执行完

FILE*fp;

    fp=fopen("D:/testyuv.yuv","rb")

第一次fread(data,1,size,fp);就是读取第一帧,在没有执行fclose的前提下,再执行一次fclose,那么就会读取的是下一帧,这个根文件操作有关,具体的就不知道了。

 

然后是纹理绑定数据

glActiveTexture(GL_TEXTURE0);

    glBindTexture(GL_TEXTURE_2D,ytexture);

    glTexImage2D(GL_TEXTURE_2D,0,GL_LUMINANCE,MAIN_TEXTURE_WIDTH,MAIN_TEXTURE_HEIGHT,0,GL_LUMINANCE,GL_UNSIGNED_BYTE,y);

    m_program->setUniformValue(TextureID0,0);

 

跟上一篇文章是一样的,只不过glTexImage2D变量不一样,上一篇是rgb三阶数据绑定到一个纹理变量中,所以第二个变量是GL_RGB这里一次只绑定一阶数据,所以第二个变量设置成GL_LUMINANCE

还有要注意的是大小,对于y数据是MAIN_TEXTURE_WIDTH,MAIN_TEXTURE_HEIGHT但是对于u和v数据就是MAIN_TEXTURE_WIDTH,MAIN_TEXTURE_HEIGHT/2,原因上边已经讲过了。

 

最后就是老一套绘图,

    glViewport(0,0,m_viewportSize.width(),m_viewportSize.height());

    glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

    glDrawArrays(GL_TRIANGLE_STRIP,0,4);

    glDisable(GL_DEPTH_TEST);

 


代码:http://download.csdn.net/detail/u010423298/8699493

0 0
原创粉丝点击