what you need is a different type of interpolation (I think it will be quadratic interpolation), because in this case (the lengths of the edges in space do not match the lengths of the edges in the texture), linear interpolation will not crop it.
Unfortunately, a rather difficult task in OpenGL (very simple using software rasterization). You are trying to find the transformation of an arbitrary square in the screen space to a unit square in the texture space. You can find a complete solution to your problem here: http://alumni.media.mit.edu/~cwren/interpolator/ This will give you a matrix by which you need to multiply the screen coordinates in order to get the correct coordinate texture (in the fragment shader).
Since this is due to a rather unpleasant math, I would suggest a simple solution that actually works for simple static cases (manual configuration required). The texture coordinate calculated in the vertex shader is actually disabled only at the central edge, and the rest is correct. Suppose your texcoords (0, 0), (1, 0), (1, 1) and (0, 1), Correction factor:
u * v
You need to evaluate the correction vector, and then put it all together. I tested with a simple C ++ OpenGL application, I draw the following:
Vector2f ta(0, 1), tb(1, 1), tc(1, 0), td(0, 0); Vector2f a(-.1f, 1), b(1, .7f), c(1, .1f), d(0, 0); // quad texcoords and vertices Vector2f t_corr(-.01f, .5f); // correction for the above quad glBegin(GL_TRIANGLES); glMultiTexCoord2f(GL_TEXTURE1, 1, -1); // first triangle glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y); glVertex2f(ax, ay); glTexCoord4f(tb.x, tb.y, t_corr.x, t_corr.y); glVertex2f(bx, by); glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y); glVertex2f(cx, cy); glMultiTexCoord2f(GL_TEXTURE1, 0, 1); // second triangle glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y); glVertex2f(ax, ay); glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y); glVertex2f(cx, cy); glTexCoord4f(td.x, td.y, t_corr.x, t_corr.y); glVertex2f(dx, dy); glEnd();
And the vertex shader looks like this:
void main() { gl_Position = ftransform(); gl_FrontColor = gl_Color; gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[1] = gl_MultiTexCoord1;
Fragment Shader:
uniform sampler2D sam; void main() { vec2 corr = vec2(gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].x, gl_TexCoord[1].x + gl_TexCoord[1].y * gl_TexCoord[0].y); gl_FragColor = texture2D(sam, gl_TexCoord[0].xy + gl_TexCoord[0].zw * corr.x * corr.y); }
It is very simple, but by correctly adjusting the correction vector, you can do it as follows: http://www.luki.webzdarma.cz/up/deskew.png
Another option is to do this with a real square in 3D and manually rotate it to a position so that it looks like your 2D quad. Or develop the βdepthβ texture coordinates for your ATV, calculate 1 / depth in the vertex shader, interpolate (u / depth, v / depth, 1 / depth) and separate by interpolating 1 / depth later in the fragment shader to get good values, Although this may seem simple, note that itβs rather difficult to find good depths.