Матрицы просмотра и проекции не работают - PullRequest
1 голос
/ 17 января 2020

Я пытаюсь внедрить матрицы 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.5 f, -0,5f, -1,0f, 0,5f, 0,5f, -1,0f

I Проверена матрица представления перед загрузкой в ​​шейдер, и она верна.

Вот как я рендер:

    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;
}

Ответы [ 3 ]

3 голосов
/ 17 января 2020

Хотя ответ @ Rabbid76, конечно, в целом совершенно прав, в данном случае реальная проблема - это сочетание плохого проектирования API (в случае JOML) и не чтения JavaDocs используемых методов.

В частности, методы Matrix4f._mNN () устанавливают только соответствующее поле матрицы, но пропускают переоценку свойств матрицы, хранимых внутри, чтобы ускорить / направить дальнейшие операции над матрицами (в частности, умножение) на более оптимизированные методы. когда зная о свойствах матрицы, таких как «является ли она идентичностью», «представляет ли она только перевод», «является ли она перспективной проекцией», «является ли она аффинной», «является ли она ортонормированной» et c .. Это оптимизация, которую JOML применяет в большинстве случаев, чтобы значительно повысить производительность умножения матриц.

Что касается плохого проектирования API: эти методы доступны только для c, чтобы класс org.joml.internal.MemUtil мог получить к ним доступ. их для установки элементов матрицы, считываемых из буферов NIO. Поскольку Java (пока) не имеет классов-друзей, по этой причине эти методы _mNN () должны быть опубликованы c. Однако они не предназначены для публичного / клиентского использования.

Я изменил это сейчас , и следующая версия JOML 1.9.21 больше не будет их выставлять. Для того, чтобы установить поля матрицы по-прежнему явно (не обязательно в большинстве случаев, подобных этим здесь), можно по-прежнему использовать методы mNN () , которые переоценивают / ослабляют свойства матрицы, чтобы сделать все дальнейшие операции по-прежнему правильными, хотя, вероятно, неоптимальный.

Таким образом, проблема в этом случае на самом деле: JOML по-прежнему считает, что созданная вручную матрица перспективной проекции является единичной матрицей и будет сокращать дальнейшие умножения матриц, если это так.

1 голос
/ 17 января 2020

Геометрия должна быть в Просмотр усеченного . Вся геометрия, находящаяся вне поля зрения, обрезается и не «видна».
Геометрия должна быть расположена между NEAR_PLANE и FAR_PLANE. Обратите внимание, что при перспективной проекции NEAR_PLANE и FAR_PLANE должны быть больше 0:

0 < NEAR_PLANE < FAR_PLANE 

Обратите внимание, что в пространстве вида ось 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);
0 голосов
/ 18 января 2020

Итак, я попробовал все и обнаружил, что вы не должны инициализировать единообразные местоположения до 0. В классе, который расширяет класс ShaderProgram, у меня было:

    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;

Работал на меня.

...