开发者

Problem glTexGen in Open GL ES 2.0

I have a problem somehow similar to this post : glTexGen in OpenGL ES 2.0

I've looked up on the web a couple of other websites without finding out how to solve my issue.

Basically, I want to map a texture onto a 2D quad after having set up an orthographic projection. The problem I have开发者_如何转开发 is that the texture is distorted as you can see on this picture where I used a coloured pattern instead of a texture:

Problem glTexGen in Open GL ES 2.0

I would like the lines of the texture to stay straight on the quad, but as you can see, they are distorted. I guess that I should modify the vertex shader in order for the texture coordinates to map the quad but I can't figure out how.

Thanks a lot, Jim


what you need is a different kind of interpolation (I believe that would be quadratic interpolation), because in this case (edge lengths in space do not correspond with edge lengths in texture), linear interpolation won't cut it.

It is unfortunately rather complex task to do in OpenGL (very simple using software rasterization, though). You are trying to find a transform of an arbitrary quad in screenspace onto a unit square in texture space. You can find complete solution of your problem here: http://alumni.media.mit.edu/~cwren/interpolator/ This would get you a matrix by which you need to multiply screenspace coordinates to get correct texture coordinates (in fragment shader).

As that involves rather nasty math, i would suggest a simple solution which actually kind of works for simple static cases (requires manual tweaking). The texture coordinate calculated in vertex shader is actually only off on the center edge, the rest is correct. Assuming your texcoords are (0, 0), (1, 0), (1, 1) and (0, 1), The correction factor is:

u * v // for the first triangle
(1 - u) * (1 - v) // for the second triangle

You need to estimate the correction vector, and then put it all together. I tested using a simple C++ OpenGL app, 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(a.x, a.y);
glTexCoord4f(tb.x, tb.y, t_corr.x, t_corr.y);
glVertex2f(b.x, b.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);

glMultiTexCoord2f(GL_TEXTURE1, 0, 1); // second triangle
glTexCoord4f(ta.x, ta.y, t_corr.x, t_corr.y);
glVertex2f(a.x, a.y);
glTexCoord4f(tc.x, tc.y, t_corr.x, t_corr.y);
glVertex2f(c.x, c.y);
glTexCoord4f(td.x, td.y, t_corr.x, t_corr.y);
glVertex2f(d.x, d.y);
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; // just copy coords, nothing else to do
}

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);
}

This is very simple, but by adjusting the correction vector properly, you can make this into that: http://www.luki.webzdarma.cz/up/deskew.png

Another option is to do this with a real quad in 3D and manually rotate it to such position that it looks like your 2D quad. Or devise "depth" texture coordinates for your quad, calculate 1/depth in vertex shader, interpolate (u/depth, v/depth, 1/depth), and divide by interpolated 1/depth later on in fragment shader to get good values. While this might seem simple, note it is quite hard to come up with good depth values.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜