Перспективная проекция, инвертирующая ось x (glm::perspective)

Когда я использую перспективную проекцию в OpenGL, моя ось X инвертируется, как показано на изображении ниже. Приведенный ниже код может быть недействительным, потому что я сильно изменил его, чтобы сделать его менее неясным. Это может не сработать, так что имейте это в виду. Вот код и вершины:

 typedef struct{
   float x;
   float y;
   float z;
 } vertex_t;

  glm::vec3 position = glm::vec3(0, 0, 0);
  glm::vec3 look_at = glm::vec3(0, 0, 1);

  glm::mat4 projectionMatrix = glm::perspective(45.0f, (float)800 / (float)600, 0.1f, 100.f); 
  glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, 5.0f));
  glm::mat4 viewMatrix = glm::lookAt(
    position, 
    look_at,
    glm::vec3(0, 1, 0) 
  );

  vertex_t data[3] = {
    {-0.5,  0.5, -0.5f},
    { 0.5,  0.5, -0.5f},
    {-0.5, -0.5, -0.5f},
  };

  unsigned int indices[3] = {
    0, 1, 2
  };

 glm::mat4 mvp = projectionMatrix * viewMatrix * modelMatrix; //This is passed in as the uniform u_MVP later

Это вершинный шейдер:

#version 330 core

layout(location = 0) in vec4 position;

uniform mat4 u_MVP;

void main(){
  gl_Position = u_MVP * position;
}

И это выход. Как видите, он не соответствует предоставленным вершинам. введите здесь описание изображения

Если вам нужен весь код или вы хотите, чтобы я предоставил исходную версию, дайте мне знать. Спасибо!

ОБНОВЛЕНИЕ: я пробовал использовать отрицательную ось Z, и это не сработало. Вот код:

  position = glm::vec3(0, 0, 0);
  look_at = glm::vec3(0, 0, -1);

  
  glm::mat4 projectionMatrix = glm::perspective(45.0f, (float)800 / (float)600, 0.1f, 100.f); 
  glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));
  viewMatrix = glm::lookAt(
    position,
    look_at, 
    glm::vec3(0, 1, 0)  // Tilt/rotation (unclear) set y to -1 for upside down view
  );

person Serket    schedule 28.11.2020    source источник
comment
Я думаю, что ваша проблема может быть связана с вашей камерой, а не с вашей проекционной матрицей. Происходит то, что вы смотрите на него сзади, поэтому кажется, что x перевернут. Помните, что OpenGL использует правостороннюю систему координат, а это означает, что ось Z направлена ​​из экрана к вам. Представьте свой треугольник на экране. Вы переводите его на 5 (~5 шагов от экрана), и ваша камера (на экране) смотрит в этом направлении. Отсюда и выход. Что вам нужно, так это модель, сдвинутая на -5, и камера, смотрящая в отрицательном направлении.   -  person Beko    schedule 28.11.2020
comment
@Беко спасибо! не могли бы вы опубликовать это как ответ?   -  person Serket    schedule 28.11.2020
comment
Нп, Rabbid уже ответил на него, так что не надо.   -  person Beko    schedule 28.11.2020
comment
@ Беко Ты прав. Мы обнаружили ту же проблему (почти одновременно). Не оставляйте комментарии, а оставляйте ответы. На самом деле ваш комментарий является ответом.   -  person Rabbid76    schedule 28.11.2020
comment
@ Rabbid76 Да, почти одновременно. Буду иметь в виду (:   -  person Beko    schedule 28.11.2020
comment
@Beko У меня черный экран, треугольник не появляется. Но чем выше число по оси Z, тем дальше уходит треугольник, предполагая, что это левосторонняя система. Что не так?   -  person Serket    schedule 28.11.2020
comment
Не знаю, мне кажется нормально. В вашем шейдере у вас есть position как vec4, возможно, стоит проверить. Сделайте его vec3 в шейдере и измените calc на u_MVP * vec4(position, 1.0) и посмотрите, изменит ли это что-нибудь. Редактировать: и то, что вы говорите, не имеет ничего общего с LHS/RHS. Разница заключается только в направлении, в котором указывает ось Z.   -  person Beko    schedule 28.11.2020


Ответы (1)


Ось X не инвертируется из-за матрицы проекции, но инвертируется из-за матрицы вида.

glm::vec3 position = glm::vec3(0, 0, 0);
glm::vec3 look_at = glm::vec3(0, 0, 1);
glm::mat4 viewMatrix = glm::lookAt(position, look_at, glm::vec3(0, 1, 0));

Пространство просмотра представляет собой правостороннюю систему, где ось X указывает на вправо, а ось Y указывает вверх. Ось Z направлена ​​за пределы поля зрения (обратите внимание, что в правосторонней системе ось Z является перекрестным произведением оси X и оси Y).

Следовательно, вы смотрите на треугольник сзади.

Измените матрицу модели и матрицу представления. Сдвиньте треугольник вдоль отрицательной оси Z. Определите линию обзора, указывающую в отрицательном направлении по оси Z:

glm::mat4 modelMatrix = glm::translate(glm::mat4(1.0f), glm::vec3(0.0f, 0.0f, -5.0f));

glm::vec3 position = glm::vec3(0, 0, 0);
glm::vec3 look_at = glm::vec3(0, 0, -1);
glm::mat4 viewMatrix = glm::lookAt(position, look_at, glm::vec3(0, 1, 0));

Расстояния до ближней и дальней плоскости должны быть положительными значениями, а единица измерения угла для glm::perspective яркий:

0 < near < far

glm::mat4 projectionMatrix = glm::perspective(45.0f, (float)800 / (float)600, -0.1f, -100.f);

glm::mat4 projectionMatrix = glm::perspective(
    glm::radians(45.0f), 800.0f/600.0f, 0.1f, 100.f); 
person Rabbid76    schedule 28.11.2020
comment
У меня черный экран, треугольник не появляется. Но чем выше число по оси Z, тем дальше уходит треугольник, предполагая, что это левосторонняя система. Что не так? - person Serket; 28.11.2020
comment
изменил их обоих, когда позиция z отрицательна, я ничего не вижу. - person Serket; 28.11.2020
comment
Я добавил код, не могли бы вы взглянуть? - person Serket; 28.11.2020
comment
Я пробовал с положительными значениями, то же самое - person Serket; 28.11.2020
comment
Это не работает для меня. Я сузил проблему до этой строки: look_at = glm::vec3(0, 0, -1);. Когда это выглядит при z = 1, все в порядке (в том числе, когда modelMatrix имеет значение -5 z), но когда оно равно отрицательному 1, я ничего не вижу. - person Serket; 28.11.2020
comment
Все еще не работает. Как будто я не могу смотреть на отрицательную ось Z - person Serket; 28.11.2020
comment
Я понял еще кое-что: если положение камеры (по оси Z) больше, чем положение look_at (по оси Z), экран становится черным. - person Serket; 28.11.2020
comment
Не могли бы вы добавить свой рабочий код в ответ? остальное сам разберусь - person Serket; 28.11.2020
comment
@Serket Я скопировал код ОБНОВЛЕНИЯ из вашего вопроса. Затем я изменил 45.0f, на glm::radians(45.0f), и у меня все работает нормально. - person Rabbid76; 28.11.2020
comment
Это не работает, не могли бы вы добавить свой рабочий код, а я сделаю все остальное - person Serket; 28.11.2020
comment
@Serket Какой рабочий код? Я поместил вашу матрицу в произвольный пример на свой локальный диск. В любом случае pastebin.com/MNp0TQZS. Необходимые файлы можно найти по адресу github.com/ Rabbid76/graphics-snippets/tree/master/example/cpp/ - person Rabbid76; 28.11.2020
comment
спасибо сообщу когда разберусь с проблемой - person Serket; 28.11.2020