如果你真的想使用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);