Как в вершинном шейдере правильно преобразовывать нормали и другие вектора, "привязанные" к объекту

Пусть у нас есть некоторое преобразование, применяемое к вершинам объекта (грани). Не ограничивая общности можно считать, что это линейное преобразования (т.е. в нем нет переноса), так как перенос никак не влияет на вектора, "прикрепленные" к объекту.

Тогда это преобразование задается матрицей 3х3 (в вершинных шейдерах в качестве этой матрицы выступает верхняя левая 3х3 подматрица матрицы modelView) М.

Рассмотрим треугольник ABC. Пусть также задана нормаль n к нему. Тогда выполняются следующие два равенства (через круглые скобки обозначено скалярное произведение):

equations for normal to triangle

Матрица М переводит точки A,B и C в точки M*A, M*B и M*C, также образующие треугольник. Обозначим через n' нормаль к этому треугольнику.

Рис 1. Преобразование треугольника и нормали.

Тогда выполняются следующие равенства:

equations for normal for transformed triangle

Преобразуем их, воспользовавшись свойствами скалярного произведения.

tranformed equations for normal

Из этих равенств следует что вектор MT*n' параллелен n, т.е. отличается от него только длиной. Поскольку длина нас не интересует (направления все равно нормируются), то будем считать, что этот вектор просто совпадает с нормалью.

Тогда мы имеем:

equation for tranformed normal

Таким образом вектора, "прикрепленные" к объекту (нормаль, касательная, бинормаль и т.п.) преобразуются при помощи верхней левой 3х3 подматрицы матрицы modelView транспонированной и обращенной.

Порядок, т.е. что выполняется раньше - транспонирование или обращение - не играет никакой роли, т.к. для любой невырожденной матрицы M всегда справедливо

Для доказательства этого утверждения достаточно протранспонировать выражение M*M-1=I и воспользоваться следующим свойством операции транспонирования: (A*B)T=(BT)*(AT).

Обратите внимание, что если матрицы modelView задает только повороты и перенос, то верхняя левая 3х3 подматрица будет ортогональной, т.е. M-1 = MT.

Тогда имеет место следующее тождество:

Т.е. в этом случае можно для преобразования векторов использовать просто верхнюю левую 3х3 подматрицу матрицы modelView.

Используются технологии uCoz