我无法尝试在3D中显示三个笛卡尔平面,当它们旋转时,平面会在一个方向上拉伸(z轴,蓝色)并在另一个方向上压缩(x轴,红色),就像这些图像一样显示围绕y轴的旋转:
我用gl-matrix库中的mat4.perspective计算透视矩阵:
mat4.perspective(this.pMatrix_, this.vFieldOfView_, this.aspect_, this.near_, this.far_);
值为:
private near_ = 0.1;
private far_ = 1000.0;
private vFieldOfView_ = 60.0 * Math.PI / 180;
顶点着色器:
void main(void) {
gl_Position = uProjection * uView * uTransform * vec4(aVertexPosition, 1.0);
}
视图矩阵将对象2.0单位转换为远离相机。
let t = new Mat4();
t.array[12] = v.x;
t.array[13] = v.y;
t.array[14] = v.z;
我使用从此代码生成的矩阵围绕y轴旋转平面:
// 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,0.0,0,0,0,1]即矩阵在z轴上平移2个单位。
在这个例子中,uTransform应该是单位矩阵。UPDATE2:
uView实际上是[1,0,0,0,0,1,0,0,0,0,1,0,0,0,-2.0,1]
答案 0 :(得分:1)
您已转置了视图矩阵。
1 0 0 0
0 1 0 0
0 0 1 0
0 0 -2 1
你想:
1 0 0 0
0 1 0 0
0 0 1 -2
0 0 0 1
如果你只是坚持使用gl-matrix并使用mat4.translate()
,那么这个错误永远不会发生。这就是为什么我不使用直接阵列访问来创建矩阵的原因,它很容易搞砸。
请记住,OpenGL矩阵的存储方式类似于列向量。所以索引是这样的:
0 4 8 12
1 5 9 13
2 6 10 14
3 7 11 15
答案 1 :(得分:0)
我发现我的实现出错了,就是矩阵乘法。正确的代码是:
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;
}
};