Давайте начнем с основ.
Обычно вы хотите преобразовать свои локальные вершины треугольника с помощью следующих шагов:
local-space coords-> world-space coords -> view-space coords -> clip-space coords
В стандартном GL первые 2 преобразования выполняются через GL_MODELVIEW_MATRIX
, третье - через GL_PROJECTION_MATRIX
Эти преобразования вида модели для многих интересных преобразований, которые мы обычно хотим применить (например, преобразовать, масштабировать и повернуть), оказываются выразимыми как векторно-матричное умножение, когда мы представляем вершины в однородные координаты . Как правило, вершина V = (x, y, z)
представлена в этой системе как (x, y, z, 1)
.
Ok. Скажем, мы хотим преобразовать вершину V_local посредством перевода, затем вращения, а затем перевода. Каждое преобразование может быть представлено в виде матрицы *, назовем их T1, R1, T2.
Мы хотим применить преобразование к каждой вершине: V_view = V_local * T1 * R1 * T2
. Матричное умножение, будучи ассоциативным, мы можем вычислить раз и навсегда M = T1 * R1 * T2
.
Таким образом, нам нужно только передать M вершинной программе и вычислить V_view = V_local * M
. В конце типичный вершинный шейдер умножает положение вершины на одну матрицу. Вся работа по вычислению этой матрицы состоит в том, как вы перемещаете свой объект из локального пространства в пространство клипа.
Хорошо ... Я просмотрел ряд важных деталей.
Во-первых, то, что я до сих пор описывал, действительно охватывает только те преобразования, которые мы обычно хотим выполнять, до пространства просмотра, а не пространства клипа. Однако аппаратное обеспечение ожидает, что выходная позиция вершинного шейдера будет представлена в этом специальном пространстве клипа. Трудно объяснить координаты пространства клипа без значительной математики, поэтому я опущу это, но важный момент заключается в том, что преобразование, которое приводит вершины в это пространство клипа, обычно может быть выражено как тот же тип умножения матриц. Это то, что вычисляют старые gluPerspective, glFrustum и glOrtho.
Во-вторых, это то, что вы применяете к позициям вершин. Математика для преобразования норм несколько иная. Это потому, что вы хотите, чтобы нормаль оставалась перпендикулярной поверхности после преобразования (для справки, она требует умножения на обратное транспонирование модельного представления в общем случае, но это может быть упрощено во многих случаях)
В-третьих, вы никогда не отправляете 4-D координаты в вершинный шейдер. В общем, вы проходите 3-D. OpenGL преобразует эти 3-D координаты (или 2-D, кстати) в 4-D, так что вершинному шейдеру не нужно добавлять дополнительную координату. он расширяет каждую вершину, чтобы добавить 1 в качестве w
координаты.
Итак ... чтобы собрать все это вместе, для каждого объекта вам нужно вычислить эти магические М-матрицы на основе всех преобразований, которые вы хотите применить к объекту. Внутри шейдера вы должны затем умножить каждую позицию вершины на эту матрицу и передать ее в выходной сигнал положения вершинного шейдера. Типичный код более или менее (используется старая номенклатура):
mat4 MVP;
gl_Position=MVP * gl_Vertex;
* фактические матрицы можно найти в Интернете, особенно на страницах руководства для каждой из этих функций: поворот , перевод , масштаб , перспектива , орто