Несоосность рендера и пространства глаз, приводящая к неточному лучевому вещанию - PullRequest
0 голосов
/ 28 апреля 2019

Я какое-то время работал над воксельной игрой, похожей на Minecraft, и решил реализовать размещение и уничтожение блоков с помощью raycasting.Однако я понял, что, стоя очень близко к блоку, блок вращается вокруг себя, а не камеры (или плоскости просмотра).Глазное положение выключено ок.0,5 на любой оси.Я очень уверен, что именно поэтому мои лучевые трансляции не работают точно, и я думаю, что проблема заключается в проецировании.

Я пробовал использовать разные методы проецирования, но все они имеют одинаковый результат.Регулировка положения камеры при создании матрицы вида также не работала и приводила к некоторым странным растяжениям и неправильным поворотам.

Код моей матрицы проекции:

public static Matrix4f createProjectionMatrix (float fov, float aspectRatio, float clipNear, float clipFar) {
    float tanHalfFOV = (float)Math.tan(fov/2);
    float zm = clipFar + clipNear;
    float zp = clipFar - clipNear;

    Matrix4f matrix = new Matrix4f();
    matrix.m00(1.0f / (tanHalfFOV * aspectRatio));
    matrix.m11(1.0f / tanHalfFOV);
    matrix.m22(-zm / zp);
    matrix.m32(-2.0f * clipNear * clipFar / zp);
    matrix.m23(-1.0f);

    return matrix;
}

Код матрицы вида:

public static Matrix4f getViewMatrix () {
    return new Matrix4f().rotateXYZ(rotation).translate(-position.x, -position.y, -position.z);
}

Код шейдера:

#version 400 core

in vec3 worldCoords;
in vec2 textureCoords;

out vec2 passTextureCoords;

uniform mat4 projViewMatrix;

void main () {
    gl_Position = projViewMatrix * vec4(worldCoords, 1.0);

    passTextureCoords = textureCoords;
}

Код рендеринга:

public static void render (ChunkMesh cm) {
    Renderable model = cm.getModel();

    Shaders.CHUNK_MESH_SHADER.activate();
    Shaders.CHUNK_MESH_SHADER.loadToUniform("projViewMatrix", Display.getProjectionMatrix().mul(Camera.getViewMatrix(), new Matrix4f()));

    GL30.glBindVertexArray(model.vaoID);
    GL20.glEnableVertexAttribArray(0);
    GL20.glEnableVertexAttribArray(1);

    GL13.glActiveTexture(GL13.GL_TEXTURE0);
    GL11.glBindTexture(GL11.GL_TEXTURE_2D, BlockTexture.TEXTURE.textureID);

    GL11.glDrawElements(GL11.GL_TRIANGLES, model.vertexCount, GL11.GL_UNSIGNED_INT, 0l);

    GL20.glDisableVertexAttribArray(0);
    GL20.glDisableVertexAttribArray(1);
    GL30.glBindVertexArray(0);

    Shaders.CHUNK_MESH_SHADER.deactivate();
}

Вдоль любой данной оси лучевое вещание работает довольно хорошо, но при обращении между двумя осямиЛучевое вещание выглядит так, будто его происхождение отличается от центра экрана.Так как мой вопрос сосредоточен на смещении, а не на лучевой передаче (что, похоже, работает), я добавлю код только по запросу.Любая помощь приветствуется!

1 Ответ

2 голосов
/ 28 апреля 2019

Это несколько обоснованное предположение, потому что вы точно не указали, что на самом деле является Matrix4f.Но, предполагая некоторые стандартные соглашения, такие как класс Matrix4f от lwjgl, конструктор инициализирует новую матрицу как единицу.Поэтому вам нужно изменить функцию createProjectionMatrix(), добавив

matrix.m33(0.0);

, чтобы явно установить самый последний элемент на ноль, поскольку без него вы фактически устанавливаете w_clip = -z_eye + 1, перемещая центр проекции на 1 единицу вперед тем, где вы думаете, ваша камера.

...