формы повернуты при повороте с использованием openGL, glm math, ортогональной проекции - PullRequest
0 голосов
/ 03 мая 2018

Для практики я устанавливаю конвейер 2d / орфографического рендеринга в openGL для использования в простой игре, но у меня возникают проблемы, связанные с системой координат.

Короче говоря, повороты искажают 2D-формы, и я не могу понять, почему Я также не совсем уверен, что моя система координат надежна.

Сначала я искал предыдущие ответы, но следующее (наиболее релевантное 2D вращение opengl вызывает искажение спрайта ) указывает, что проблема заключалась в неправильном упорядочении преобразований, но сейчас я использую только представление матрица и матрица проекции, умноженные в правильном порядке в вершинном шейдере:

gl_Position = projection * view * model vec4(1.0); //(The model is just the identity matrix.)

Подведем итог моей установки: - Я успешно загружаю квад, который должен растягиваться по всему экрану:

GLfloat vertices[] = {
   -wf,  hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // top left
   -wf, -hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // bottom left
    wf, -hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // bottom right
    wf,  hf,  0.0f, 0.0, 0.0, 1.0, 1.0,  // top right
};
GLuint indices[] = {
    0, 1, 2,  // first Triangle
    2, 3, 0,   // second Triangle
};

wf и hf равны 1, и я пытаюсь использовать систему координат от -1 до 1, поэтому мне не нужно масштабировать по разрешению в шейдерах (хотя я не уверен, что это правильно.)

Моя область просмотра и орфографическая матрица:

glViewport(0, 0, SCREEN_WIDTH, SCREEN_HEIGHT);
...
glm::mat4 mat_ident(1.0f);
glm::mat4 mat_projection = glm::ortho(-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, 1.0f);

... хотя это явно не учитывает ширину и высоту экрана. Я видел, как другие использовали ширину и высоту вместо 1 с, но, похоже, это сломало систему или ничего не показало.

Я вращаюсь статическим методом, который изменяет структуру, содержащую glm::quaternion (время / 1000), чтобы получить секунды:

    main_cam.rotate((GLfloat)curr_time / TIME_UNIT_TO_SECONDS, 0.0f, 0.0f, 1.0f);
// which does: glm::angleAxis(angle, glm::vec3(x, y, z) * orientation)

Наконец, я передаю матрицу как униформу:

glUniformMatrix4fv(MAT_LOC, 1, GL_FALSE, glm::value_ptr(mat_projection * FreeCamera_calc_view_matrix(&main_cam) * mat_ident));

... и умножить в вершинном шейдере

   gl_Position = u_matrix * vec4(a_position, 1.0);
   v_position = a_position.xyz;

Полноэкранный четырехугольник вращается по центру (0, 0, как я хотел), но его длина и ширина искажаются, а это значит, что я что-то неправильно установил.

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

Вторичный вопрос - не следует ли мне устанавливать мои координаты на 1 / -1 в контексте 2d игры? Я сделал это для того, чтобы облегчить написание шейдеров. Я также обеспокоен движением персонажа / объекта, когда добавляю матрицы моделей.

Что может быть причиной проблемы? Если мне нужно умножить аргументы для gl :: ortho на ширину и высоту, то как мне преобразовать координаты, чтобы v_position (моя интерполированная версия «in» / «меняющаяся» версия атрибута позиции) работала от -1 до 1, как должно в шейдере? Каковы последствия выбора конкретной системы координат, когда дело доходит до простоты размещения объектов? В игре будут использоваться спрайты и текстуры, поэтому я рассматривал систему координат пикселей, но это быстро стало очень сложным для размышления на стороне шейдера. Я бы предпочел, чтобы ЭТО работало.

Спасибо за вашу помощь.

РЕДАКТИРОВАТЬ: Возможно ли, что мое переменное / интерполированное v_position должно быть установлено в вычисленное значение gl_Position вместо позиции атрибута?

1 Ответ

0 голосов
/ 03 мая 2018

Попробуйте учесть соотношение сторон окна, которое вы отображаете, в первых двух параметрах glm :: ortho, чтобы отразить соотношение сторон вашего дисплея.

GLfloat aspectRatio = SCREEN_WIDTH / SCREEN_HEIGHT;
glm::mat4 mat_projection = glm::ortho(-aspectRatio, aspectRatio, -1.0f, 1.0f, -1.0f, 1.0f);
...