Неправильный порядок значений матрицы в glm? - PullRequest
8 голосов
/ 24 февраля 2011

Я начал использовать библиотеку GLM для выполнения математических операций над OpenGL 3 и GLSL.Мне нужна ортографическая проекция для рисования 2D-графики, поэтому я написал такой простой код:

glm::mat4 projection(1.0);
projection = glm::ortho( 0.0f, 640.0f, 480.0f, 0.0f, 0.0f, 500.0f);

Печать на экране значений, созданных glm :: ortho, которые я получаю:

 0.00313   0.00000   0.00000   0.00000
 0.00000  -0.00417   0.00000   0.00000
 0.00000   0.00000  -0.00200   0.00000
-1.00000   1.00000  -1.00000   1.00000

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

Я протестировал эту матрицу с моим шейдером и некоторыми примитивами, и я получил толькоПустой экран.Но если я вручную изменю матрицу следующим образом, она будет работать нормально:

 0.00313   0.00000   0.00000  -1.00000
 0.00000  -0.00417   0.00000   1.00000
 0.00000   0.00000  -0.00200  -1.00000
 0.00000   0.00000   0.00000   1.00000

Более того, глядя на функцию "ortho" в файле "glm / gtc / matrix_transform.inl":

template <typename valType>
inline detail::tmat4x4<valType> ortho(
    valType const & left,
    valType const & right,
    valType const & bottom,
    valType const & top,
    valType const & zNear,
    valType const & zFar)
{
    detail::tmat4x4<valType> Result(1);
    Result[0][0] = valType(2) / (right - left);
    Result[1][1] = valType(2) / (top - bottom);
    Result[2][2] = - valType(2) / (zFar - zNear);
    Result[3][0] = - (right + left) / (right - left);
    Result[3][1] = - (top + bottom) / (top - bottom);
    Result[3][2] = - (zFar + zNear) / (zFar - zNear);
    return Result;
}

Я заменил последние 3 строки инициализации следующим кодом и также работал нормально:

    Result[0][3] = - (right + left) / (right - left);
    Result[1][3] = - (top + bottom) / (top - bottom);
    Result[2][3] = - (zFar + zNear) / (zFar - zNear);

Это минимальный вершинный шейдер, который я использую для теста (обратите внимание, что на данный моментuni_MVP - это только матрица проекций, описанная выше):

uniform mat4 uni_MVP;

in  vec2 in_Position;

void main(void)
{
  gl_Position = uni_MVP * vec4(in_Position.xy,0.0, 1.0);
}

Я думаю, что это не ошибка, потому что все функции работают одинаково.Может быть, проблема моего компилятора C ++, который инвертирует порядок многомерных массивов?Как я могу решить эту проблему без изменения всего исходного кода GLM?

Я использую последнюю версию библиотеки GLM (0.9.1) с Code :: Blocks и MinGW, работающими в Windows Vista.

1 Ответ

21 голосов
/ 24 февраля 2011

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

 0  4  8  12
 1  5  9  13
 2  6 10  14
 3  7 11  15

Однако ваши обычные многомерные массивы C / C ++ обычно нумеруются следующим образом:

 0  1  2  3
 4  5  6  7
 8  9 10 11
12 13 14 15

т.е. индексы строк и столбцов транспонируются. В старых версиях OpenGL использовалось некоторое расширение, позволяющее предоставлять матрицы в транспонированном виде, чтобы люди не переписывали свой код. Это называется GL_ARB_transpose_matrix http://www.opengl.org/registry/specs/ARB/transpose_matrix.txt

С шейдерами это даже проще, чем использование новых функций. У glUniformMatrix есть параметр GLboolean transpose, у вас есть 3 догадки, что он делает.

...