您的位置:首页 > 其它

用Shader实现的YUV到RGB转换:使用3重纹理实现

2008-12-22 13:06 465 查看
上一篇中,我是用一个RGB格式的纹理来存储每一帧的画面,其中纹理为m_FrameWidth * m_FrameHeight大小,这样,在内存中,就必须要先对YUV的数据进行排序,然后才能当做RGB的数据格式传给纹理内存。我们发现对一个很大帧的图片进行数据重新排序会花费很多时间,为了减少这个时间,当然可以用汇编语言来进行这个排序的操作。然而,有一种更好的方法。
我们发现在上一次所用到的YUV420数据格式是一种平面格式,他的数据排列十分有规律,这里,考虑用3重纹理来实现他的转换。

先定义3个纹理,格式都为GL_LUMINANCE格式,其中一个纹理的大小为m_FrameWidth * m_FrameHeight,这是用来存放Y数据的,另两个纹理的大小为(m_FrameWidth / 2) * (m_FrameHeight / 2),分别用来存放U和V数据。好啦,我们可以直接使用内存拷贝memcpy()函数分别将YUV的数据拷出来,再生成纹理。

那么frame shader中的程序就要改成:

uniform sampler2D yTexture;

uniform sampler2D uTexture;

uniform sampler2D vTexture;

void main()

{

float yuv0 = (texture2D(yTexture,gl_TexCoord[0].st)).r;

float yuv1 = (texture2D(uTexture,gl_TexCoord[0].st)).r;

float yuv2 = (texture2D(vTexture,gl_TexCoord[0].st)).r;

vec4 color;

color.r = yuv0 + 1.4022 * yuv2 - 0.7011;

color.r = (color.r < 0.0) ? 0.0 : ((color.r > 1.0) ? 1.0 : color.r);

color.g = yuv0 - 0.3456 * yuv1 - 0.7145 * yuv2 + 0.53005;

color.g = (color.g < 0.0) ? 0.0 : ((color.g > 1.0) ? 1.0 : color.g);

color.b = yuv0 + 1.771 * yuv1 - 0.8855;

color.b = (color.b < 0.0) ? 0.0 : ((color.b > 1.0) ? 1.0 : color.b);

gl_FragColor = color;

}

其中需要注意的两点是:

1: uniform的值是要在每次绘制前调用的。

m_loc=glGetUniformLocation(m_Program,"yTexture");

glUniform1i(m_loc,0); /* Bind Utex to texture unit 1 */

m_loc=glGetUniformLocation(m_Program,"uTexture");

glUniform1i(m_loc,1); /* Bind Utex to texture unit 1 */

m_loc=glGetUniformLocation(m_Program,"vTexture");

glUniform1i(m_loc,2); /* Bind Utex to texture unit 1 */

m_Program就是shader的程序。

2:在使用shader和多重纹理之前,都要进行初始化:glewInit();
另外补上用汇编语言实现重排序的代码:

int m = m_FrameWidth * m_FrameHeight;

int l = (m_FrameWidth / 2) * (m_FrameHeight / 2);

unsigned char * pyuv = m_y;

unsigned char * ptemp = cTemp[0];

__asm

{

mov ecx, m

mov ebx, ptemp

mov edx, pyuv

label_y:

mov al, [ebx]

mov [edx], al

add ebx, 1

add edx, 1

dec ecx

jnz label_y

}

pyuv = m_u;

ptemp = cTemp[1];

__asm

{

mov ecx, l

mov ebx, ptemp

mov edx, pyuv

label_u:

mov ah, [ebx]

mov [edx], ah

add ebx, 1

add edx, 1

dec ecx

jnz label_u

}

pyuv = m_v;

ptemp = cTemp[2];

__asm

{

mov ecx, l

mov ebx, ptemp

mov edx, pyuv

label_v:

mov al, [ebx]

mov [edx], al

add ebx, 1

add edx, 1

dec ecx

jnz label_v

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐