Для практики я устанавливаю конвейер 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 вместо позиции атрибута?