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:

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:

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:

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.

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.

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.

This topic was automatically closed 183 days after the last reply. New replies are no longer allowed.