OpenGL Yuv411打包到rgb着色器,循环坏像素

时间:2017-11-19 09:40:19

标签: opengl glsl yuv

Y尝试使用着色器从GiGE Vision相机转换YUV411packed图像。 YUV411封装的像素缓冲区为U1Y1Y2V1Y3Y4,因此4个像素为6个字节。 我以GL_TEXTURE_RECTANGLE上传缓冲区,像素格式为GL_RG8。

顶点着色器非常简单:

#version 130

uniform vec2 texSize;
in  vec4 position;
in  vec2 texCoord;
out vec2  vTexCoord;


void main()
{
    vTexCoord = texCoord * texSize;
    gl_Position = position;
}

片段着色器

#version 130

uniform sampler2DRect tex;
uniform int stride;
in      vec2 vTexCoord;
out     vec4 rgb;

/*
   R = 1.164(Y - 0.0625)                  + 1.596(V - 0.5) = (1.164 * Y)               + (1.596 * V) - 0.8827
   G = 1.164(Y - 0.0625) - 0.391(U - 0.5) - 0.813(V - 0.5) = (1.164 * Y) - (0.391 * U) - (0.813 * V) + 0.5173
   B = 1.164(Y - 0.0625) + 2.018(U - 0.5)                  = (1.164 * Y) + (2.018 * U) - 1.0937
*/
const   mat4 YUVtoRGB = mat4( 1.1640,  1.1640,  1.1640, 0.0,
                              0.0000, -0.3910,  2.0180, 0.0,
                              1.5960, -0.8130,  0.0000, 0.0,
                              -0.8827,  0.5173, -1.0937, 1.0);

vec2 fetch(vec2 coord)
{
    return texture2DRect(tex, coord).rg;
}

void main()
{
    int offsetX, quark;
    ivec2 iCoord = ivec2(floor(vTexCoord));


    offsetX = (iCoord.y * stride) + iCoord.x;

    quark = 3 * (offsetX / 4);

    int x = quark % stride;
    int y = quark / stride;
    vec2 srcTexCoord = vec2(x , y);

    vec4 yuv = vec4(0.5, fetch(srcTexCoord).r, fetch(srcTexCoord + vec2(1.0, 0.0)).g, 1.0);


    switch (offsetX % 4) {
    case 0:
        yuv.r = fetch(srcTexCoord).g;
        break;
    case 1:
        yuv.r = fetch(srcTexCoord + vec2(1.0, 0.0)).r;
        break;
    case 2:
        yuv.r = fetch(srcTexCoord + vec2(2.0, 0.0)).r;
        break;
    case 3:
        yuv.r = fetch(srcTexCoord + vec2(2.0, 0.0)).g;
        break;
    }

    rgb = clamp(YUVtoRGB * yuv, 0.0, 1.0);
}

结果Yuv411包装为RGB

Yuv411packed to RGB

正如你所看到的,我有一个坏像素周期。我无法找到我的错误。将不胜感激。

1 个答案:

答案 0 :(得分:0)

为了解决我的问题,我使用了另一种方法。 纹理现在上传为GL_R8,但大小被修改为(宽* 1.5,高)。 视口是(宽*高)

顶点着色器

#version 130

uniform vec2 texSize;
in  vec4 position;
in  vec2 texCoord;
out vec2 vTexCoord;

void main()
{
    vTexCoord = texCoord * texSize;
    gl_Position = position;
}

片段着色器

#version 130

uniform sampler2DRect tex;
in      vec2 vTexCoord;
out     vec4 rgb;

/*
   R = 1.164(Y - 0.0625)                  + 1.596(V - 0.5) = (1.164 * Y)               + (1.596 * V) - 0.8827
   G = 1.164(Y - 0.0625) - 0.391(U - 0.5) - 0.813(V - 0.5) = (1.164 * Y) - (0.391 * U) - (0.813 * V) + 0.5173
   B = 1.164(Y - 0.0625) + 2.018(U - 0.5)                  = (1.164 * Y) + (2.018 * U) - 1.0937
*/
const   mat4 YUVtoRGB = mat4( 1.1640,  1.1640,  1.1640, 0.0,
                              0.0000, -0.3910,  2.0180, 0.0,
                              1.5960, -0.8130,  0.0000, 0.0,
                             -0.8827,  0.5173, -1.0937, 1.0);

void main()
{
    float xcoord = floor(vTexCoord.x);
    float quarkIndex = mod(xcoord, 4.0);
    vec2 coord = vec2(0.5 + (6.0 * floor(xcoord / 4.0)), vTexCoord.y);
    vec4 yuv = (quarkIndex<1.0)?vec4(texture2DRect(tex, coord+vec2(1.0, 0.0)).r, texture2DRect(tex, coord).r, texture2DRect(tex, coord+vec2(3.0, 0.0)).r, 1.0)
              :(quarkIndex<2.0)?vec4(texture2DRect(tex, coord+vec2(2.0, 0.0)).r, texture2DRect(tex, coord).r, texture2DRect(tex, coord+vec2(3.0, 0.0)).r, 1.0)
              :(quarkIndex<3.0)?vec4(texture2DRect(tex, coord+vec2(4.0, 0.0)).r, texture2DRect(tex, coord).r, texture2DRect(tex, coord+vec2(3.0, 0.0)).r, 1.0)
                               :vec4(texture2DRect(tex, coord+vec2(5.0, 0.0)).r, texture2DRect(tex, coord).r, texture2DRect(tex, coord+vec2(3.0, 0.0)).r, 1.0);

    rgb = clamp(YUVtoRGB * yuv, 0.0, 1.0);

}

YUV411到RGB现在工作正常,但我不知道为什么第一种方法不起作用。