Open GL ES 2.0 中的 glTexGen 问题

发布于 2024-11-08 05:59:58 字数 405 浏览 0 评论 0原文

我有一个与这篇文章类似的问题: OpenGL ES 2.0 中的glTexGen

我在网上查找了一些其他网站却没有找到如何解决我的问题。

基本上,我想在设置正交投影后将纹理映射到 2D 四边形上。我遇到的问题是纹理扭曲,正如您在这张图片中看到的那样,我使用彩色图案而不是纹理:

在此处输入图像描述

我希望纹理的线条在四边形上保持笔直,但正如您所看到的,它们是扭曲的。我想我应该修改顶点着色器以便纹理坐标映射四边形,但我不知道如何做。

多谢, 吉姆

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:

enter image description here

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

累赘 2024-11-15 05:59:58

你需要的是一种不同类型的插值(我相信这将是二次插值),因为在这种情况下(空间中的边缘长度与纹理中的边缘长度不对应),线性插值不会削减它。

不幸的是,在 OpenGL 中这是一项相当复杂的任务(尽管使用软件光栅化非常简单)。您正在尝试找到屏幕空间中的任意四边形到纹理空间中的单位正方形的变换。您可以在这里找到问题的完整解决方案:http://alumni.media.mit.edu /~cwren/interpolator/ 这将为您提供一个矩阵,您需要乘以屏幕空间坐标才能获得正确的纹理坐标(在片段着色器中)。

由于这涉及相当讨厌的数学,我建议一个简单的解决方案,它实际上适用于简单的静态情况(需要手动调整)。顶点着色器中计算出的纹理坐标实际上只在中心边缘上有​​偏差,其余都是正确的。假设你的纹理坐标是 (0, 0), (1, 0), (1, 1) 和 (0, 1),校正因子是:

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

你需要估计校正向量,然后把它们放在一起。我使用一个简单的 C++ OpenGL 应用程序进行了测试,我绘制了以下内容:

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

顶点着色器如下所示:

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
}

片段着色器:

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

这非常简单,但是通过正确调整校正向量,您可以将其变为: http://www.luki.webzdarma.cz/up/deskew.png

另一种选择是这与一个真实的 3D 四边形,然后手动将其旋转到看起来像 2D 四边形的位置。或者为您的四边形设计“深度”纹理坐标,在顶点着色器中计算 1/深度,进行插值(u/深度、v/深度、1/深度),然后除以稍后在片段着色器中插值的 1/深度以获得良好的值。虽然这看起来很简单,但请注意,很难得出良好的深度值。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文