Webgl: Rotating object becomes distorted along axes
我在尝试以3D显示三个笛卡尔平面时遇到麻烦,当它们旋转时,这些平面在一个方向(z轴,蓝色)上拉伸,而在另一个方向(x轴,红色)上压缩,就像这些图像显示围绕y旋转一样-轴:
45度:
135度:
我使用gl-matrix库中的mat4.perspective计算透视矩阵:
1 | mat4.perspective(this.pMatrix_, this.vFieldOfView_, this.aspect_, this.near_, this.far_); |
值为:
1 2 3 | private near_ = 0.1; private far_ = 1000.0; private vFieldOfView_ = 60.0 * Math.PI / 180; |
顶点着色器:
1 2 3 | void main(void) { gl_Position = uProjection * uView * uTransform * vec4(aVertexPosition, 1.0); } |
视图矩阵将对象从相机平移了2.0个单位。
1 2 3 4 | let t = new Mat4(); t.array[12] = v.x; t.array[13] = v.y; t.array[14] = v.z; |
我使用此代码生成的矩阵绕y轴旋转平面:
1 2 3 4 5 6 | // identity matrix already set let rad = angle * Math.PI / 180; r.array[0] = Math.cos(rad); r.array[2] = Math.sin(rad); r.array[8] = -1.0 * Math.sin(rad); r.array[10] = Math.cos(rad); |
然后按此顺序将对象的三个变换矩阵相乘:
旋转*平移*比例。曾经使用四元数来处理旋转,但是它们同样发生了扭曲,因此回到了使用旋转矩阵并保持旋转简单的一个轴上。看来我执行的乘法步骤顺序错误,或者未正确使用透视矩阵或符号错误。
更新:
只是为了阐明顶点着色器中某些矩阵的值:
uProjection = pMatrix_ =从??mat.perspective(...)获得的值。
uView = [1、0、0、0、0、1、0、0、0、0、1,-2.0、0、0、0、1],即矩阵在z轴上平移了2个单位。
在此示例中,uTransform应该是身份矩阵。
更新2:
uView实际上是[1、0、0、0、0、1、0、0、0、0、1、0、0、0,-2.0、1]
您已经调换了视图矩阵。 你有
1 2 3 4 | 1 0 0 0 0 1 0 0 0 0 1 0 0 0 -2 1 |
你要:
1 2 3 4 | 1 0 0 0 0 1 0 0 0 0 1 -2 0 0 0 1 |
如果仅使用gl-matrix并使用
请记住,OpenGL矩阵像列向量数组一样存储。 因此索引如下所示:
1 2 3 4 | 0 4 8 12 1 5 9 13 2 6 10 14 3 7 11 15 |
我发现实现的地方出了问题,那就是矩阵乘法。 正确的代码是这样的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static multiply(a: Mat4, b: Mat4, out: Mat4) { let a11 = a.array[0], a12 = a.array[1], a13 = a.array[2], a14 = a.array[3], a21 = a.array[4], a22 = a.array[5], a23 = a.array[6], a24 = a.array[7], a31 = a.array[8], a32 = a.array[9], a33 = a.array[10], a34 = a.array[11], a41 = a.array[12], a42 = a.array[13], a43 = a.array[14], a44 = a.array[15]; for (let i = 0; i < 16; i += 4) { let b1 = b.array[i], b2 = b.array[i + 1], b3 = b.array[i + 2], b4 = b.array[i + 3]; out.array[i] = b1 * a11 + b2 * a21 + b3 * a31 + b4 * a41; out.array[i + 1] = b1 * a12 + b2 * a22 + b3 * a32 + b4 * a42; out.array[i + 2] = b1 * a13 + b2 * a23 + b3 * a33 + b4 * a43; out.array[i + 3] = b1 * a14 + b2 * a24 + b3 * a34 + b4 * a44; } }; |