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

论坛 期权论坛 脚本     
匿名网站用户   2020-12-21 09:07   31   0

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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:1136255
帖子:227251
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP