Part of the Khronos Group
OpenGL.org

The Industry's Foundation for High Performance Graphics

from games to virtual reality, mobile phones to supercomputers

Results 1 to 2 of 2

Thread: YUY2/YUYV Shader giving diffuse output

  1. #1
    Newbie Newbie
    Join Date
    Feb 2017
    Posts
    1

    YUY2/YUYV Shader giving diffuse output

    Hi there.

    In reference to my stackoverflow post which did not have the response I'd liked it to have I want to repeat my question here.

    So I'm fetching YUY2/YUYV frames from a v4l2 device. The dimension of the texture I receive is (width, height) = (1920, 1200). I'll upload the texture to GL like this:

    Code :
    glGenTextures(1, &glTextureId);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, stride);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width/2, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, buffer);

    I'm placing the texture within an arbitrary but convex quadrilateral. I'm using texture mapping to display the texture perspectively corrected. In my following example I'm using a very simple example in which the quad just covers the whole window. which means the coord for the vertices are C1=(0,0), C2=(1,0), C3=(1,1) and C4=(0,1). The UV Coord for each are (u,v,t,w)(C1) = (0,0,0,2), (u,v,t,w)(C2) = (2,0,0,2), (u,v,t,w)(C3) = (2,2,0,2) and (u,v,t,w)(C4) = (0,2,0,2).

    One question here: I see that the UV coords for each of the vertices defining the quad are given like above. How are the UVs calculated for any of the others vertices, not belonging to the defining ones, of the quad (any convex combination of C1, ..., C4)?

    Thats my vertex shader:

    Code :
    uniform mediump mat4  modelMatrix;
     
    in      lowp vec4  position // the C's are put in here;
    in      highp vec4  texcoord_with_q // the coordesponding tex coord are put in here; 
     
    out     highp vec4  tex_coord_with_q_out;
     
    void main() {
        tex_coord_with_q_out = texcoord_with_q;
        gl_Position =  modelMatrix * position;
    }

    and the fragment shader:

    Code :
    uniform lowp sampler2D src_tex_unit0; // the texture
     
    const lowp vec3 offset = vec3(-0.0625, -0.5, -0.5);
    const mediump mat3 converter = mat3(
                    1.164, 1.164, 1.164,
                    0.000,-0.391, 2.018,
                    1.596,-0.813, 0.000
                    );
     
    void main() {
           //get normed uv
           highp vec2 uv  = vec2(tex_coord_with_q_out.x/tex_coord_with_q_out.w, tex_coord_with_q_out.y/tex_coord_with_q_out.w);
           //get corresponding normed vertex coordinate
           highp vec2 xy  = (1.0 - uv.x) * (1.0 - uv.y) * corners[0] + uv.x * (1.0 - uv.y) * corners[1] + uv.x * uv.y * corners[2] + (1.0 - uv.x) * uv.y * corners[3];
           //get the vertex position on the left border of the quad for xy (0y)
           highp vec2 xleft  = (1.0 - uv.y) * corners[0] + uv.y * corners[3];
           //get the vertex position on the right border of the quad for xy (1y)
           highp vec2 xright = (1.0 - uv.y) * corners[1] + uv.y * corners[2];
           //get the vertex position on the top border of the quad for xy (x0)
           highp vec2 ytop   = (1.0 - uv.x) * corners[0] + uv.x * corners[1];
           //get the vertex position on the bottom of the quad for xy (x1)
           highp vec2 ybottom= uv.x * corners[2] + (1.0 - uv.x) * corners[3];
     
           //calc dist between 0y and 1y in pixel
           //resolution is the size of the window. could be anything like (640, 480)
           highp float hDist = distance(xleft * resolution,  xright * resolution);
           //calc dist between x0 and x1 in pixel
           highp float vDist = distance(ytop  * resolution, ybottom * resolution);
     
           //determine if current tex coord is odd or even
           float horizontalStep = mod(uv.x * hDist, 2.0);
           float verticalStep   = mod(uv.y * vDist, 2.0);
     
           //0 if even, 1 if odd
           float h = step(1.0, horizontalStep);
     
           //calc current tex value
           highp vec4 curr = textureProj(src_tex_unit0, tex_coord_with_q_out);
           highp vec4 prev = textureProj(src_tex_unit0, vec4(tex_coord_with_q_out.x-0.001, tex_coord_with_q_out.y, tex_coord_with_q_out.z, tex_coord_with_q_out.w));
           highp vec3 yuv;
     
        //     yuv = mix(curr.xyw, curr.zyw, h) + offset;
     
           //if pixel is even take first Y
           if (h == 0.0) {
               gl_FragColor = vec4(converter * (curr.xyw + offset), 1.0);
           //if pixel is odd take second Y
           } else {
               gl_FragColor = vec4(converter * (curr.zyw + offset), 1.0);
           }
     
    }

    Thats the result: my shader while it's supposed to look like that. You can best the difference in the letters in the textarea in the back but everywhere else as well.

    Anyone has any idea on what might be wrong?

    Another question would be how to calculate the tex coord for the pixel left or right of the current one?

    Appreciate any idea.

  2. #2
    Senior Member OpenGL Guru
    Join Date
    Jun 2013
    Posts
    2,790
    Quote Originally Posted by plazmakeks View Post
    One question here: I see that the UV coords for each of the vertices defining the quad are given like above. How are the UVs calculated for any of the others vertices, not belonging to the defining ones, of the quad (any convex combination of C1, ..., C4)?
    If you're using GL_QUADS, rasterisation is pretty much undefined. A quad will probably be split into two triangles, but it's unspecified which diagonal will be used. For triangles, the x, y and w components for the three vertices define an invertible projective mapping between screen coordinates and barycentric coordinates. In turn, barycentric coordinates are used to blend the attribute values at the vertices to provide a value for each fragment.

    Quote Originally Posted by plazmakeks View Post
    Another question would be how to calculate the tex coord for the pixel left or right of the current one?
    If you have dFdx() available (it isn't standard in OpenGL ES 2), then texcoord±dFdx(texcoord) will provide an approximate value. Otherwise, you'd need to make enough information about the mapping between screen coordinates and texture coordinates available to the fragment shader to calculate it.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •