Ортогональная проекция с исходной точкой внизу слева на экране

Я использую привязки OpenGL python и пытаюсь использовать только современные вызовы opengl. У меня есть VBO с вершинами, и я пытаюсь выполнить рендеринг с ортогональной матрицей проекции, переданной в вершинный шейдер.

В настоящее время я рассчитываю свою матрицу проекции со следующими значениями:

from numpy import array

w = float(width)
h = float(height)
n = 0.5
f = 3.0

matrix = array([
                   [2/w,        0,        0,        0],
                   [  0,      2/h,        0,        0],
                   [  0,        0,  1/(f-n), -n/(f-n)],
                   [  0,        0,        0,        1],
               ], 'f')


#later
projectionUniform = glGetUniformLocation(shader, 'projectionMatrix')
glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, matrix)

Этот код, который я получил отсюда:

Формула для матрицы ортогональной проекции?

Кажется, это работает нормально, но я бы хотел, чтобы мой Origin был в нижнем левом углу экрана. Могу ли я применить эту функцию к моей матрице, чтобы все «просто работало», или я должен вручную переводить каждый объект на w / 2 h / 2?

примечание стороны: будут ли координаты совпадать с позициями пикселей, чтобы это работало правильно?

Поскольку я использую современные методы OpenGL, я не думаю, что мне следует использовать вызовы gluOrtho2d или GL_PROJECTION.


person Shootfast    schedule 16.11.2012    source источник


Ответы (3)


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

Матрица, которую я использовал для этого (каждая строка на самом деле является столбцом для OpenGL):

OrthoMat = mat4(
        vec4(2.0/(screenDim.s - left),  0.0,    0.0,    0.0),
        vec4(0.0,   2.0/(screenDim.t - bottom),     0.0,    0.0),
        vec4(0.0,   0.0,    -1 * (2.0/(zFar - zNear)),  0.0),
        vec4(-1.0 * (screenDim.s + left)/(screenDim.s - left), -1.0 * (screenDim.t + bottom)/(screenDim.t - bottom), -1.0 * (zFar + zNear)/(zFar - zNear), 1.0)
 );

Математика screenDim фактически представляет собой ширину или высоту, поскольку left и bottom установлены на 0. zFar и zNear равны 1 и -1 соответственно (поскольку это 2D, они не очень важны).

Эта матрица принимает значения в пикселях, и позиции вершин также должны быть в пикселях. Точка (0, 32) всегда будет в том же положении, когда вы изменяете размер экрана.

Надеюсь это поможет.

Редактировать №1: Для ясности, указанные мной значения left / bottom / zfar / znear - это те, которые я выбрал для их создания. Вы можете изменить их по своему усмотрению.

person Hydronium    schedule 19.11.2012
comment
Большое спасибо за пример, Алекс. Объединив это и мой перепутанный GL_FALSE, все работает, как ожидалось! - person Shootfast; 19.11.2012

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

См. Определение в Википедии.

person Dirk    schedule 16.11.2012

glUniformMatrix4fv(projectionUniform, 1, GL_FALSE, matrix)

Ваша матрица хранится в строчном порядке. Таким образом, вы должны передать GL_TRUE, или вы должны изменить матрицу на основной столбец.

person Nicol Bolas    schedule 18.11.2012
comment
Спасибо, что заметили этого Николя. Есть идеи, как переместить начало координат в нижний левый угол? - person Shootfast; 19.11.2012