视图和投影矩阵不起作用

View & Projection Matrices are not working

我正在尝试在我的引擎中实施 MVP 矩阵。 我的模型矩阵工作正常,但我的视图和投影矩阵不起作用。 这是两者的创建:

    public void calculateProjectionMatrix() {
        final float aspect = Display.getDisplayWidth() / Display.getDisplayHeight();
        final float y_scale = (float) ((1f / Math.tan(Math.toRadians(FOV / 2f))) * aspect);
        final float x_scale = y_scale / aspect;
        final float frustum_length = FAR_PLANE - NEAR_PLANE;

        proj.identity();
        proj._m00(x_scale);
        proj._m11(y_scale);
        proj._m22(-((FAR_PLANE + NEAR_PLANE) / frustum_length));
        proj._m23(-1);
        proj._m32(-((2 * NEAR_PLANE * FAR_PLANE) / frustum_length));
        proj._m33(0);
    }

    public void calculateViewMatrix() {
        view.identity();
        view.rotate((float) Math.toRadians(rot.x), Mathf.xRot);
        view.rotate((float) Math.toRadians(rot.y), Mathf.yRot);
        view.rotate((float) Math.toRadians(rot.z), Mathf.zRot);
        view.translate(new Vector3f(pos).mul(-1));
        System.out.println(view);
    }

我要渲染的顶点是: -0.5f, 0.5f, -1.0f, -0.5f, -0.5f, -1.0f, 0.5f, -0.5f, -1.0f, 0.5f, 0.5f, -1.0f

我在上传到着色器之前测试了视图矩阵,它是正确的。

我是这样渲染的:

    ss.bind();
    glEnableVertexAttribArray(0);
    glEnableVertexAttribArray(1);
    glEnableVertexAttribArray(2);
    ss.loadViewProjection(cam);
    ss.loadModelMatrix(Mathf.transformation(new Vector3f(0, 0, 0), new Vector3f(), new Vector3f(1)));
    ss.connectTextureUnits();
    glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
    glDisableVertexAttribArray(0);
    glDisableVertexAttribArray(1);
    glDisableVertexAttribArray(2);
    ss.unbind();

顶点着色器:

#version 330 core

layout(location = 0) in vec3 i_position;
layout(location = 1) in vec2 i_texCoord;
layout(location = 2) in vec3 i_normal;

out vec2 p_texCoord;

uniform mat4 u_proj;
uniform mat4 u_view;
uniform mat4 u_model;

void main() {
    gl_Position = u_proj * u_view * u_model * vec4(i_position, 1.0);
    p_texCoord = i_texCoord;
}

几何必须放在 Viewing frustum 中。视锥之外的所有几何体都被剪裁为非 "visible".
几何图形必须位于 NEAR_PLANEFAR_PLANE 之间。注意,透视投影 NEAR_PLANEFAR_PLANE 必须大于 0:

0 < NEAR_PLANE < FAR_PLANE 

请注意,在视图 space 中,z 轴指向视口之外。查看对象的初始视图矩阵可以定义为:

pos = new Vector3f(0, 0, (NEAR_PLANE + FAR_PLANE)/2f );
rot = new Vector3f(0, 0, 0);

注意,如果到FAR_PLANE的距离很远,那么物体可能很小,几乎看不见。在这种情况下更改初始值:

pos = new Vector3f(0, 0, NEAR_PLANE * 0.99f + FAR_PLANE * 0.01f );
rot = new Vector3f(0, 0, 0);

虽然@Rabbid76 的回答在一般情况下当然是完全正确的,但在这种情况下的实际问题是糟糕的 API 设计(在 JOML 的情况下)和不阅读 Java使用方法的文档。

特别是 Matrix4f._mNN() 方法仅设置相应的矩阵字段,但省略了重新评估内部存储的矩阵属性,以便 accelerate/route 进一步矩阵运算(最显着的是乘法)到更优化的方法时知道关于矩阵的属性,例如 "is it identity"、"does it only represent translation"、"is it a perspective projection"、"is it affine"、"is it orthonormal" 等... 这是 JOML 在大多数情况下应用的优化,可显着提高矩阵乘法的性能。

至于糟糕的 API 设计:这些方法只是 public 以便 class org.joml.internal.MemUtil 访问它们以设置从 NIO 缓冲区读取的矩阵元素。由于 Java 还没有朋友 classes,因此这些 _mNN() 方法一定是 public。然而,它们不适合 public/client 使用。

I've changed this now 和下一个 JOML 版本 1.9.21 将不再公开它们。 为了仍然显式地设置矩阵字段(在大多数情况下不需要像这里这样)仍然可以使用 mNN() 方法,它执行 reevaluate/weaken 矩阵属性以使所有进一步的操作仍然正确,尽管可能非最优。

所以这种情况下的问题实际上是:JOML 仍然认为手动创建的透视投影矩阵是单位矩阵,并且假设是这样会缩短进一步的矩阵乘法。

所以我尝试了一切,发现你不应该将统一位置初始化为 0。 在扩展 ShaderProgram class 的 class 中,我有:

    private int l_TextureSampler = 0;
    private int l_ProjectionMatrix = 0;
    private int l_ViewMatrix = 0;
    private int l_ModelMatrix = 0;

改成这样:

    private int l_TextureSampler;
    private int l_ProjectionMatrix;
    private int l_ViewMatrix;
    private int l_ModelMatrix;

对我有用。