上一篇中我们提到先在iOS端将NV12先转换成YUV,再传入Unity中转换成RGB,由于在iOS端转换过程是在CPU中进行的,效率较慢,一帧图像数据大概消耗20ms左右。因为Unity的shader转换是在GPU中进行,效率高,所以考虑将这一步骤也挪到Unity中进行。
需要更改的有两个步骤:
- 将数据拷贝到显存
// 将数据拷贝到显存
glBindTexture(GL_TEXTURE_2D, tex[0]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, pData0);
glBindTexture(GL_TEXTURE_2D, tex[1]);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, w/2, h/2, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, pData1);
注意GL_LUMINANCE_ALPHA参数,我们先来看看百度对于glTexImage2D方法的介绍。
这是一个OpenGL函数(以下叙述以OpenGL ES2.0为例)。
函数原型:
GL_APICALL void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLenum internalformat,
GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const void* pixels);
参数说明:
target 指定目标纹理,这个值必须是GL_TEXTURE_2D。
level 执行细节级别。0是最基本的图像级别,n表示第N级贴图细化级别。
internalformat 指定纹理中的颜色组件。可选的值有GL_ALPHA,GL_RGB,GL_RGBA,GL_LUMINANCE, GL_LUMINANCE_ALPHA 等几种。
width 指定纹理图像的宽度,必须是2的n次方。纹理图片至少要支持64个材质元素的宽度
height 指定纹理图像的高度,必须是2的m次方。纹理图片至少要支持64个材质元素的高度
border 指定边框的宽度。必须为0。
format 像素数据的颜色格式, 不需要和internalformatt取值必须相同。可选的值参考internalformat。
type 指定像素数据的数据类型。可以使用的值有GL_UNSIGNED_BYTE,GL_UNSIGNED_SHORT_5_6_5,GL_UNSIGNED_SHORT_4_4_4_4,GL_UNSIGNED_SHORT_5_5_5_1。
pixels 指定内存中指向图像数据的指针
internalformat 指定纹理中的颜色组件。因为在上一篇中我们每个数据只包含Y、U、V中的一个方向的分量,所以我们使用GL_ALPHA,同理在shader中取值时也是通过alpha通道取值。这一次NV12格式的数据UV方向分量在一起,所以我们使用GL_LUMINANCE_ALPHA,灰度值和Alpha值,将U、V分别存入RGB和A中。
- 使用shader将NV12转换为RGB
fixed4 yuv;
yuv.x = tex2D(_MainTexU, i.uv).a;
yuv.y = tex2D(_MainTexUV, i.uv).rgb - 0.5;
yuv.z = tex2D(_MainTexUV, i.uv).a - 0.5;
c.r = yuv.x + 1.403*yuv.z;
c.g = yuv.x - 0.344*yuv.y - 0.714*yuv.z;
c.b = yuv.x + 1.770*yuv.y;
注意在取值时从rgb通道取出U方向分量,alpha通道取出V方向分量。
网友评论