OpenGL растянутые формы - соотношение сторон

Я получил мое представление openGL в размере (допустим..) 800(ширина)x600(высота). Затем я получил 2D объект координат:

0.0 , 0.0
0.1 , 0.0
0.1 , 0.1
0.0 , 0.1

это, как вы понимаете, должно быть квадратом (по аналогии). Но на моем принте openGL это растягивается. Теперь я понимаю, почему это происходит. Это в основном потому, что я работаю с матрицей по умолчанию -1,1. И так как мое разрешение 800x600 не имеет соотношения сторон 1, моя форма растягивается.

Теперь меня больше интересует, как это исправить. Я читал о таких функциях, как glFrustum, glOrtho, glViewPort, которые выполняются в матрице проекции и могут решать такие проблемы. Дело в том, что я не уверен в их использовании. То, что я в основном хочу, это сохранить вышеуказанные координаты при создании квадрата и на самом деле выглядеть как квадрат на моем Виде.

Как правильно решить эту проблему?

1 ответ

Решение
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
float aspect = (float)width / (float)height;
glOrtho(-aspect, aspect, -1, 1, -1, 1);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

Обновление: объяснение того, что происходит

OpenGL является конечным автоматом и в случае OpenGL-2.1 и ниже поддерживает набор матриц преобразования. Вершина ↑v сначала умножается на матрицу вида модели для получения вершины координаты глаза ↑v ', которая используется для расчетов освещения. Затем ↑v умножается на матрицу проекции, чтобы достичь так называемого пространства клипа ↑v ', где (как следует из названия) выполняются операции отсечения (или, по крайней мере, определяется их результат). Из пространства клипа так называемые нормализованные координаты устройства (NDC) достигаются путем вычисления ↑v #{x, y, z, w} = ↑v{x, y, z, w} /↑v_w

# V # определяется как находящийся в диапазоне [-1 … 1], который отображается для заполнения выбранного прямоугольника области просмотра. Окно просмотра не влияет на матрицы преобразования! Это только преобразование из NDC в оконные координаты, которые оно определяет.

В приведенном выше коде я установил матрицу вида модели на тождество, то есть вершины переходят в проекцию как есть. Сама проекция является орто-проекцией, которая отображает диапазон значений x [-aspect … аспект] → [-1 … 1] и диапазон значений y [-1 … 1] → [-1 … 1] (т.е. без изменений для y). Таким образом, вершины преобразуются аспектом окна, чтобы вписаться в диапазон значений NDC для области просмотра.

И почему я сказал вам, что OpenGL является конечным автоматом? Потому что это означает, что вы можете переключать проекции и преобразования в любое время. Поэтому, если вам нужно визуализировать миникарту, не пытайтесь поместить ее в 3D-сцену. Просто переключите окно просмотра и проекцию для него. В общем, вы должны установить все состояние рендеринга (то есть все матрицы) в функции рисования. Обработчики событий окна (кроме обработчика перерисовки) вообще не должны выполнять никаких операций OpenGL.

Другие вопросы по тегам