【问题标题】:Problem glTexGen in Open GL ES 2.0Open GL ES 2.0 中的 glTexGen 问题
【发布时间】:2011-05-18 15:05:41
【问题描述】:

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

我在网上查找了其他几个网站,但没有找到解决问题的方法。

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

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

非常感谢, 吉姆

【问题讨论】:

    标签: opengl-es opengl-es-2.0 opengl-to-opengles


    【解决方案1】:

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

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

    由于这涉及到相当讨厌的数学,我建议一个简单的解决方案,它实际上适用于简单的静态情况(需要手动调整)。 vertex shader中计算的纹理坐标实际上只在中心边缘off,其余都是正确的。假设你的 texcoords 是 (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/深度以获得好的值.虽然这看起来很简单,但请注意,很难得出好的深度值。

    【讨论】:

    • 感谢您对如何获得预期结果的非常详细的回答。
    猜你喜欢
    • 2011-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-26
    • 1970-01-01
    • 2014-03-06
    • 1970-01-01
    相关资源
    最近更新 更多