6

I am using OpenGL ES in Android programming, when I transform YUV(NV21) to RGB in shader, like:

vec3 yuv = vec3(
        (texture2D(u_TextureY, vTextureCoord).r - 0.0625),
        texture2D(u_TextureUV, vTextureCoord).a - 0.5,
        texture2D(u_TextureUV, vTextureCoord).r - 0.5
    );

then I'll get YUV data that seperating from u_TextureY and u_TextureUV.

I know that NV21 format is like: YYYYYY...UVUV... BUT how can I transform YUYV422 to RGB? So, my problem is what do "r" and "a" mean in texture2D(u_TextureY, vTextureCoord).r and .a ? then I can find the way to do YUYV422->RGB.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
Shuyun6
  • 191
  • 1
  • 15
  • If you are using [tag:opengl-es], then use that tag instead of desktop [tag:opengl]. – BDL Dec 06 '17 at 10:28
  • @Selvin: For a vec4 in glsl, r always means [0], [1] means g and so on. (a)lpha is always [3]. `.a` is also not a synonym for `.x`. It is equivalent to `.w`. – BDL Dec 06 '17 at 10:36
  • @BDL my bad ... I had play with glsl long time ago – Selvin Dec 06 '17 at 10:40

2 Answers2

8

The return type of texture2D is vec4. In GLSL the components of the vector can be separately accessed:

See the The OpenGL Shading Language specification:

5.5 Vector and Scalar Components and Length

The names of the components of a vector or scalar are denoted by a single letter. As a notational convenience, several letters are associated with each component based on common usage of position, color or texture coordinate vectors. The individual components can be selected by following the variable name with period ( . ) and then the component name.

The component names supported are:

  • {x, y, z, w} Useful when accessing vectors that represent points or normals

  • {r, g, b, a} Useful when accessing vectors that represent colors

  • {s, t, p, q} Useful when accessing vectors that represent texture coordinates

The order of the components can be different to swizzle them, or replicated:

vec4 pos = vec4(1.0, 2.0, 3.0, 4.0);
vec4 swiz= pos.wzyx; // swiz = (4.0, 3.0, 2.0, 1.0)
vec4 dup = pos.xxyy; // dup = (1.0, 1.0, 2.0, 2.0)
float f = 1.2;
vec4 dup = f.xxxx; // dup = (1.2, 1.2, 1.2, 1.2)


This means, that .r gives the 1st component of the vec4 and .a gives the 4th component of the vec4.

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
4

OK, I have solved it. The answer from @Rabbid76 is great, so we know .r and .a are from {r, g, b, a}. My question is not just what is .r.a, it's why is .r.a .

I solved the problem starting from this answer enter link description here

glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_LUMINANCE, 
width, height, 0, GL20.GL_LUMINANCE, GL20.GL_UNSIGNED_BYTE, buffer_y);

by setting GL_LUMINANCE, OpenGL puts this byte into R,G and B components of the texture. So we can use .r to get Y values, also .g or .b.

glTexImage2D(GL20.GL_TEXTURE_2D, 0, GL20.GL_LUMINANCE_ALPHA, 
width/2, height/2, 0, GL20.GL_LUMINANCE_ALPHA, GL20.GL_UNSIGNED_BYTE, 
buffer_uv);

by setting GL_LUMINANCE_ALPHA, OpenGL puts the first byte 'V' into r/g/b components, and puts the second byte 'U' into a component. So we can use .a to get U, and .r to get V(.g or .b is ok).

As we know that NV21 format is like YYYY...UVUV... It seems like 'U' is the first byte in UV texture.

buffer_uv = ByteBuffer.allocateDirect(width * height * 4)
            .order(ByteOrder.nativeOrder());

buffer_uv is order with ByteOrder.nativeOrder(), retrieves the native byte order of the underlying platform. From enter link description here That means the UV values(...UVUV...) are read from native buffer by native byte order like ...VUVU... , it's reverse.

Shuyun6
  • 191
  • 1
  • 15