Вы уже знаете, что вам нужно возвращать координаты пространства клипа (технически не нормализованные координаты устройства ) из вашего вершинного шейдера. Вопрос в том, как и где перейти от координат UIKit к координатам пространства клипа Metal.
Давайте начнем с определения этих различных пространств. Обратите внимание, что ниже я на самом деле am для простоты использую координаты NDC, поскольку в данном конкретном случае мы не представляем перспективу, возвращая позиции вершин с w != 1
. (Здесь я имею в виду w
координату позиции пространства клипа; в следующем обсуждении w
всегда относится к ширине вида).
Мы передаем вершины в наш вершинный шейдер в любом удобном для вас пространстве (это часто называют модельным пространством ). Поскольку мы работаем в 2D, нам не нужны обычные серии преобразований в мировое пространство, а затем в пространство глаз. По сути, координаты вида UIKit - это наше модельное пространство, мировое пространство и пространство глаз все в одном.
Нам нужна какая-то матрица ортографической проекции для перемещения из этого пространства в пространство клипа. Если мы уберем ненужные части, связанные с осью z, и предположим, что источником границ нашего вида является (0, 0), мы получим следующее преобразование:
Мы могли бы передать эту матрицу в наш вершинный шейдер или выполнить преобразование перед отправкой вершин в графический процессор. Учитывая, как мало данных, на самом деле это не имеет значения в данный момент. На самом деле, использование матрицы вообще немного расточительно, поскольку мы можем просто преобразовать каждую координату с помощью пары умножений и сложения. Вот как это может выглядеть в вершинной функции Metal:
float2 inverseViewSize(1.0f / width, 1.0f / height); // passed in a buffer
float clipX = (2.0f * in.position.x * inverseViewSize.x) - 1.0f;
float clipY = (2.0f * -in.position.y * inverseViewSize.y) + 1.0f;
float4 clipPosition(clipX, clipY, 0.0f, 1.0f);
Просто чтобы убедиться, что мы получили правильные результаты этого преобразования, давайте подключим верхнюю левую и нижнюю правую точки нашего представления, чтобыони оказываются на концах пространства отсечения (по линейности, если эти точки преобразуются правильно, как и все остальные):
Эти точки выглядят правильнымиИтак, мы закончили. Если вас беспокоит очевидное искажение, вызванное этим преобразованием, обратите внимание, что оно точно отменяется преобразованием области просмотра , которое происходит до растеризации.