Зачем мне нужно конвертировать кватернион в матрицу 4x4 при загрузке в шейдеры?

Я прочитал несколько руководств по скелетной анимации в OpenGL, все они, похоже, сосредоточены на использовании кватернионов для вращения, трехмерного вектора для перевода, а не матриц.

Но когда они доходят до процесса скиннинга вершин, они объединяют все кватернионы и трехмерные векторы в матрицу 4x4 и загружают матрицы для выполнения остальных вычислений в шейдерах. Матрицы 4x4 имеют 16 элементов, а кватернион + 3d-вектор - только 7. Так почему же мы конвертируем их в матрицы 4x4 перед загрузкой?


person deniz    schedule 29.03.2013    source источник
comment
Потому что объединение всего в одну матрицу, а затем умножение на нее быстрее, чем умножение на несколько значений в разных формах? (не говоря уже о том, что математика не только проще, языки шейдеров имеют встроенные матричные мультиинструкции)   -  person ssube    schedule 29.03.2013


Ответы (2)


Поскольку при наличии только двух матриц 4 × 4, по одной для каждой кости, назначенной и взвешенной вершине, вам нужно выполнить только два умножения 4-векторных матриц 4 × 4 и взвешенную сумму.

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

Вполне возможно использовать 4-элементный вектор uniform в качестве кватерниона, но тогда вам придется объединить множество вычислений в вершинном шейдере: сначала поверните вершину на два кватерниона, затем переместите ее и затем умножьте его на матрицу просмотра модели. Просто загружая две матрицы преобразования, взвешенные в шейдере, вы экономите много вычислений на GPU. Выполнение умножения кватернионов на матрицу на ЦП выполняет вычисление только один раз для каждой кости, тогда как в шейдере оно выполняется для каждой отдельной вершины. Графические процессоры хороши, если вам нужно выполнять множество одинаковых вычислений с разной датой ввода. Но они отстой, если вам нужно вычислить только несколько значений, которые повторно используются для больших объемов данных. Однако процессоры любят такие задачи.

Преимущество однородных преобразований, представленных матрицами 4×4, заключается в том, что одна матрица может содержать целую цепочку преобразований. Если вы разделяете повороты и переводы, вам придется выполнять всю цепочку операций по порядку. Только с одним вращением и перемещением это меньше операций, чем одно матричное преобразование 4 × 4. Добавьте одно единственное преобразование, и вы достигли точки безубыточности.

Матрицы преобразования, даже в скелетной позе, примененной к сетке, одинаковы для всех вершин. Скажем, сетка имеет 100 вершин вокруг пары костей (это небольшое число, кстати), тогда вам придется выполнять описанные выше вычисления для каждой любой вершины, тратя впустую драгоценные вычислительные циклы графического процессора. А для чего? Для определения примерно 32 скалярных значений (или 8 4-векторов). А теперь сравните это: 100 4-векторов (если учитывать только положение вершин) и только 8. Это порядок величины накладных расходов, связанных с обработкой поз кватернионов в шейдере. Вычислите его один раз на ЦП и передайте предварительно рассчитанный ГП, чтобы разделить его между примитивами. Если вы запрограммируете его правильно, весь расчет одного столбца матрицы прекрасно впишется в конвейер ЦП, что значительно превзойдет каждую попытку его распараллеливания. Распараллеливание не приходит бесплатно!

person datenwolf    schedule 29.03.2013
comment
Неправильный. Это не медленнее. Даже на PS3 и 360. - person Axel Gneiting; 29.03.2013
comment
Производительность графического процессора очень зависит от архитектуры, поэтому я не думаю, что вы можете делать общие прогнозы, такие как ваш первый абзац. Скалярные архитектуры, скорее всего, потребуют больше инструкций для выполнения умножения 4×4, чем 3×3. Для векторных машин умножение 3 × 3, вероятно, может быть выполнено с использованием тех же инструкций 4-элементных векторных операций, но, например, для выполнения матричного умножения 3 × 3 потребуется всего три инструкции. Кроме того, сложения обычно выполняются быстрее, чем умножения. - person radical7; 29.03.2013
comment
@datenwolf Можете ли вы также отредактировать свой первый абзац? По-моему, пропущено несколько слов. - person radical7; 29.03.2013
comment
я также хочу спросить, зачем нам нужны инверсные позы связывания - person deniz; 29.03.2013
comment
@deniz: обратные позы необходимы для расчетов освещения; или, чтобы быть более конкретным, обратное транспонирование. - person datenwolf; 29.03.2013

В современных графических процессорах нет ограничений на формат данных, которые вы загружаете в буферы констант.

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

Обратите внимание, что старое аппаратное скиннинг с фиксированными функциями действительно работало только с матрицами, но это было давно.

person Axel Gneiting    schedule 29.03.2013