这是我生成透视矩阵的代码:
public static Matrix4f orthographicMatrix(float left, float right, float bot,
float top, float far, float near) {
// construct and return matrix
Matrix4f mat = new Matrix4f();
mat.m00 = 2 / (right - left);
mat.m11 = 2 / (top - bot);
mat.m22 = -2 / (far - near);
mat.m30 = -((right + left) / (right - left));
mat.m31 = -((top + bot) / (top - bot));
mat.m32 = -((far + near) / (far - near));
mat.m33 = 1;
return mat;
}
public static Matrix4f projectionMatrix(float fovY, float aspect,
float near, float far) {
// compute values
float yScale = (float) ((float) 1 / Math.tan(Math.toRadians(fovY / 2)));
float xScale = yScale / aspect;
float zDistn = near - far;
// construct and return matrix
Matrix4f mat = new Matrix4f();
mat.m00 = xScale;
mat.m11 = yScale;
mat.m22 = far / zDistn;
mat.m23 = (near * far) / zDistn;
mat.m32 = -1;
mat.m33 = 0;
return mat;
}
在我的程序中,首先以正交透视渲染一个正方形,然后以投影透视渲染一个正方形。
但是这是我的问题 - 当我的着色器按以下顺序进行乘法时:
gl_Position = mvp * vec4(vPos.xyz, 1);
仅显示使用投影透视渲染的正方形。但是当按以下顺序进行乘法时:
gl_Position = vec4(vPos.xyz, 1) * mvp;
仅显示正交透视渲染的正方形!显然我的问题是,在给定一定的乘法顺序的情况下,一次只显示一个方 block 。
最佳答案
乘法顺序问题表明您在矩阵中存储分量的顺序存在问题。
mat * vec
相当于 vec * transpose (mat)
换句话来说,如果您使用的是行主矩阵(就 GL 而言,它们实际上是转置 (mat)
)而不是列主矩阵,您需要反转顺序你的矩阵乘法。这也适用于复合乘法,您必须反转整个乘法顺序。这就是为什么 D3D(行优先)和 OpenGL(列优先)之间的缩放、旋转和平移顺序是向后的。
因此,当您构建 MVP 矩阵时,它应该如下所示:
投影 * View * 模型
(OpenGL)
模型 * View * 投影
(Direct3D)
正如 OpenGL 使用的那样,列主矩阵乘法应该从右到左读取。也就是说,您从对象空间位置(最右侧)开始,然后转换到剪辑空间(最左侧)。
换句话说,这是变换顶点的正确方法......
gl_Position = ModelViewProjectionMatrix * position;
~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~
clip space object space to clip space obj space
关于OpenGL - 自定义透视矩阵和着色器的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20407900/