【问题标题】:How to correctly map texture when doing perspective warping in glsl using opengl es 2.0使用opengl es 2.0在glsl中进行透视变形时如何正确映射纹理
【发布时间】:2016-03-11 23:54:51
【问题描述】:

我正在尝试使用顶点着色器和片段着色器创建一个四角透视效果。

我设置顶点位置信息来绘制一个类似形状的透视图,然后在其上映射我的纹理。但不知何故,纹理没有正确映射。

这里有两张图片来说明问题。

我从post 中找到了一些信息,texture2DProj 可能是正确的答案,但我不太明白它是如何工作的。我试图做这样的事情,

    varying lowp vec4 TexCoordOut;
    uniform sampler2D Texture;

    void main(void) {
        gl_FragColor = texture2DProj(Texture, TexCoordOut);
    }

对于TexCoordOut,我通过了

{1, 0, 0, 1}
{1, 1, 0, 1}
{0, 1, 0, 1}
{0, 0, 0, 1}

到顶点着色器,并将其变为片段着色器。但结果是一样的。

我只知道如何将texture2Dvec2 一起使用,如何让我的纹理坐标的其他两个分量与texture2DProj 一起使用?

【问题讨论】:

    标签: opengl-es glsl shader texture-mapping perspective


    【解决方案1】:

    如果你真的想使用texture2DProj那么你可以将W坐标从位置复制到纹理坐标。例如:

    uniform mat4 uPrj;
    attribute vec2 aXY;
    attribute vec2 aST;
    varying vec4 st;
    void main(void) {
        vec4 pos=uPrj*vec4(aXY,0.0,1.0);
        gl_Position=pos;
        st=vec4(aST,0.0,pos.w);
    
        st.xy*=pos.w; // Not sure if this is needed with texture2DProj
    }
    

    但是,我通过将四边形拆分为一个由较小的四边形组成的网格,然后将每个小四边形拆分为两个三角形,从而解决了透视纹理的问题。然后你可以像这样使用 GLSL 代码:

    uniform mat4 uPrj;
    attribute vec2 aST;  // Triangles in little squares in range [0,1].
    varying vec2 st;
    void main(void) {
        vec2 xy=aST*2.0-1.0; // Convert from range [0,1] to range [-1,-1] for vertices.
        gl_Position=uPrj*vec4(xy,0.0,1.0);
        st=aST;
    }
    

    上述代码运行速度足够快(甚至可能比 texture2DProj 还快),因为片段着色器运行相同数量的像素,而片段着色器可以使用更简单的 texture2D 方法(无需片段投影)。

    您可以为每个四边形重复使用 aST 中的三角形网络。以下是我在 JavaScript 中制作 aST 的方法:

            var nCell = 32;
            var nVertex = nCell * nCell * 6;
            var arST = prog._arST = new Float32Array(nVertex * 2);
            var k = 0;
            for (var j = 0; j < nCell; j++) {
                var j0 = j / nCell;
                var j1 = (j + 1) / nCell;
                for (var i = 0; i < nCell; i++) {
                    var i0 = i / nCell;
                    var i1 = (i + 1) / nCell;
                    arST[k++] = i0;
                    arST[k++] = j0;
                    arST[k++] = i1;
                    arST[k++] = j0;
                    arST[k++] = i0;
                    arST[k++] = j1;
                    arST[k++] = i0;
                    arST[k++] = j1;
                    arST[k++] = i1;
                    arST[k++] = j0;
                    arST[k++] = i1;
                    arST[k++] = j1;
                }
            }
            gl.bindBuffer(gl.ARRAY_BUFFER, prog._bufferST);
            gl.bufferData(gl.ARRAY_BUFFER, prog._arST, gl.STATIC_DRAW);
    

    【讨论】:

      【解决方案2】:

      我怀疑问题在于您的输入坐标正在渲染 2D 形状,而不是 3D 形状(即所有 4 个顶点都有一个恒定的 Z 值)。

      不是渲染 2D 形状,而是渲染一个在 3D 中倾斜的正方形,并且变化的插值将为您进行透视正确划分。然后您可以使用普通的 texture2D() 操作。

      在这种情况下,您可能不希望使用投影纹理 - 您可以 - 但它不必要地复杂(您仍然需要为纹理坐标生成适当的“w”值才能使透视分割正常工作,所以您也可以只需对每个顶点执行此操作,然后使用不同的插值器来完成繁重的工作)。

      【讨论】:

      • 您好 Isogen74,感谢您的评论。问题是我必须在 2D 中绘制正方形,因为我只有 4 个顶点的 xy 坐标。它们看起来像是在 3D 空间中,但它们只是 2D 形状。我需要使用这些 2D 坐标来实现透视扭曲效果。你能给我一些关于如何计算纹理坐标的w值的想法吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-03-14
      • 1970-01-01
      • 2012-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多