如何使用OpenGL片段着色器将RGB转换为YUV420

时间:2011-10-26 10:36:59

标签: opengl

我知道如何编码使用片段着色器将平面数据(YUV420图像)转换为打包数据(RGB图像)的着色器,但如何将RGB编码为YUV420。 我不需要YUV420图像进行渲染,而是将其传递给h264压缩代码。

2 个答案:

答案 0 :(得分:8)

来自http://www.fourcc.org/fccyvrgb.php

  

RGB到YUV转换

     

Y =(0.257 * R)+(0.504 * G)+(0.098 * B)+16

     

Cr = V =(0.439 * R) - (0.368 * G) - (0.071 * B)+ 128

     

Cb = U = - (0.148 * R) - (0.291 * G)+(0.439 * B)+ 128

在OpenGL着色器中,最后的常量偏移需要乘以1/256。另外,如果仔细观察,这是一个向量矩阵乘法。您可以通过

来表达这一点
mat4 RGBtoYUV(0.257,  0.439, -0.148, 0.0,
              0.504, -0.368, -0.291, 0.0,
              0.098, -0.071,  0.439, 0.0,
              0.0625, 0.500,  0.500, 1.0 );

YUV = RGBtoYUV * RGB;

http://en.wikipedia.org/wiki/YUV

给出了一些其他公式

答案 1 :(得分:3)

由于YUV像素未打包,您应将多个颜色缓冲区附加到着色器程序(即一个用于亮度,两个用于色度)。

由于色度采样,色度输出缓冲器的大小与亮度输出缓冲器的大小不同。因此,您应测试ARB_framebuffer_object扩展名。如果不可用,您应计算未采样的色度值,并在渲染后对其进行采样。另请注意,着色器中的采样并不容易,因为您必须知道源像素位置,确实要注意纹理坐标。

因此,创建一个framebuffer对象,附加3个renderbuffer对象(或纹理),并将片段着色器输出变量声明为长度为3的vec4数组。

附加缓冲区可以具有RED内部格式,因为它们只存储一个组件。

渲染后,获取渲染缓冲区数据(或纹理数据),根据需要交错YUV图层(可能使用SSE),并完成了自己的工作。

也许你想生成非抽样的色度值。在这种情况下,你应该自己采样色度缓冲,也许混合连续色度值。