OpenGL - 自定义透视矩阵和着色器的问题

标签 opengl matrix glsl lwjgl

这是我生成透视矩阵的代码:

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/

相关文章:

java - libgdx 桌面应用程序屏幕闪烁

c - MPI 收集以错误的顺序返回结果

scala - Scalala 是否提供了将向量插入矩阵的直接方法?

c++ - GLSL 着色器不适用于 AMD/ATI,但适用于 NVIDIA

opengl - 在着色器中访问时,OpenGL如何决定使用MAG_FILTER和MIN_Filter?

linux - 在 Linux 上安装 Freeglut

c++ - 球体纹理映射(opengl 和 c++)

c++ - 为什么所有 openGL 对象都存储在 GLuints 中?

.net - 点积函数

opengl - GLSL:当前绘制调用中的图元数量