【问题标题】:Projective interpolation of textures in 2D trapeziums with OpenGL使用 OpenGL 对 2D 梯形中的纹理进行投影插值
【发布时间】:2014-10-13 02:38:29
【问题描述】:

我必须将一个物理立方体与我计算机上的投影仪显示的图像进行映射。我立即意识到使用 3D 立方体和相机投影来尝试将虚拟图像拟合到真实对象上的问题,因此我决定简化问题并使用立方体的 2D 表示并在 2D 空间中移动每个顶点直到它适合对象。该软件现在已经完成,除了一个小细节:纹理。

我正在使用 LWJGL,我的数据结构基于他们文档中的一些示例。

我使用 7 个顶点来表示 2D 空间中真实立方体的 3 个可见面,这会创建覆盖每个面的 3 个梯形(或不规则四边形),我将它们映射到您在此看到的 ST(或 UV)坐标图片,记住这都是二维的:

这是一个代码块,我将顶点数据加载到缓冲区中,它全部保存到 VBO 中,顺序为 XYZWRGBASTPQ(注意 Z 始终为 0,PQ 默认为 0,1):

vertices = new VertexData[7];
vertices[0] = new VertexData().setXY(0, 0).setST(0.5f, 0.5f);
vertices[1] = new VertexData().setXY(0.5f, 1f/3).setST(0.5f, 0);
vertices[2] = new VertexData().setXY(0, 2f/3).setST(0, 0);
vertices[3] = new VertexData().setXY(-0.5f, 1f/3).setST(0, 0.5f);
vertices[4] = new VertexData().setXY(-0.5f, -1f/3).setST(0, 1);
vertices[5] = new VertexData().setXY(0, -2f/3).setST(0.5f, 1);
vertices[6] = new VertexData().setXY(0.5f, -1f/3).setST(1, 1);

0是六边形的中心,从1-6,从右上角逆时针,画成三角形扇形。

梯形仍然是平行四边形时一切正常,这是另一个纹理测试:

但问题是当边不相等时,纹理会投影到三角形上,所以当它尝试投影纹理时,它看起来不像预期的那样:

我阅读了很多关于这个主题的内容,其中一些:

Getting to know the Q texture coordinate...

Perspective correct texturing of trapezoid in OpenGL ES 2.0

Quadrilateral Interpolation, Part 1

到目前为止,我还没有解决这个问题,我只知道这与纹理的 Q 坐标有关。

我的顶点着色器是最低限度的:

#version 150 core

in vec4 in_color;
in vec4 in_position;
in vec4 in_texture;

out vec4 pass_color;
out vec4 pass_texture;

void main(void) {
    pass_color = in_color;
    pass_texture = in_texture;
    gl_Position = in_position;
}

而且我的片段着色器非常简单,现在我使用的是 textureProj,因为我试图摆弄 Q 坐标。

#version 330 core

in vec4 pass_color;
in vec4 pass_texture;
out vec4 color;

uniform sampler2D texture_diffuse;

void main(void) {
    color = pass_color;
    color = textureProj(texture_diffuse, pass_texture);
}

我愿意发布每段代码以备不时之需。我只需要朝着正确的方向前进。

【问题讨论】:

  • 您的顶点需要适当的深度值(添加 z 维度)以允许透视插值。顺便说一句,您的线框模型看起来不对(与上面的立方体图像相反)。
  • 没必要,我已经解决了,稍后我会发布我的解决方案。谢谢!

标签: opengl 2d glsl lwjgl texture-mapping


【解决方案1】:

所以,在我stumbled upon a solution 潜伏在互联网上之后,不幸的是,我对三角形扇形进行 UV 映射的方式与它不兼容,所以我不得不将我的三角形扇形转换为一组 3 个由两个三角形组成的四边形,我通过复制面之间的共享顶点来做到这一点:

VertexData[] vertices = new VertexData[12];
int i = 0;
for(VertexData vert : oldVertices){
    vertices[i++] = new VertexData(vert);
}
vertices[7] = new VertexData(vertices[1]);
vertices[7].setST(1, 0.5f);

vertices[8] = new VertexData(vertices[0]);
vertices[9] = new VertexData(vertices[3]);
vertices[10] = new VertexData(vertices[0]);
vertices[11] = new VertexData(vertices[5]);

int[][] faces = {
    {0, 1, 2, 3},
    {4, 11, 10, 9},
    {6, 7, 8, 5}
};

if(qMapping) TextureUtils.qMapFaces(vertices, faces);

有了这些信息,我现在可以使用 BitLush 的算法,它基本上根据每个面的对角线的差异计算 Q 坐标插值:

public static void qMapFaces(VertexData[] vertices, int[][] faces){
    for(int[] face : faces){
        VertexData[] verts = new VertexData[4];
        int j = 0;
        for(int i : face){
            verts[j++] = vertices[i];
        }

        float ax = verts[2].getXYZ()[0] - verts[0].getXYZ()[0];
        float ay = verts[2].getXYZ()[1] - verts[0].getXYZ()[1];
        float bx = verts[3].getXYZ()[0] - verts[1].getXYZ()[0];
        float by = verts[3].getXYZ()[1] - verts[1].getXYZ()[1];

        float cross = ax * by - ay * bx;

        if(cross != 0) {
            float cx = verts[0].getXYZ()[0] - verts[1].getXYZ()[0];
            float cy = verts[0].getXYZ()[1] - verts[1].getXYZ()[1];

            float s = (ax * cy - ay * cx) / cross;

            if(s > 0 && s < 1){
                float t = (bx * cy - by * cx) / cross;

                if(t > 0 && t < 1){
                    float[] qi = new float[4];
                    qi[0] = 1 / (1 - t);
                    qi[1] = 1 / (1 - s);
                    qi[2] = 1 / t;
                    qi[3] = 1 / s;

                    int q = 0;
                    for(VertexData vertex : verts){
                        float[] stpq = vertex.getSTPQ();
                        vertex.setSTPQ(stpq[0] * qi[q], stpq[1] * qi[q], 0, qi[q]);
                        q++;
                    }
                }
            }
        }
    }
}

插值 Q 坐标后,投影得到很大改善,但因为我无法同时控制两个面的插值,所以纹理在边缘对齐不太好。这对我的项目来说不是问题,但如果有人找到解决方法,请联系我!!

【讨论】:

    【解决方案2】:

    你应该把你的三角形一分为二,然后你就可以线性插值了。

    【讨论】:

      猜你喜欢
      • 2016-01-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-09
      • 2014-11-17
      • 2011-08-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多