Этапы тесселяции

Среда выполнения Direct3D 11 поддерживает три новых этапа, реализующих тесселяции, которая преобразует поверхности деления с низким уровнем детализации в примитивы с более высокой детализацией на GPU. Тесселяции разбивает на плитки поверхности старшего порядка на структуры, подходящие для прорисовки.

Реализуя тесселяцию на аппаратном оборудовании, графический конвейер может оценить модели низкой детализации (с малым числом полигоном) и прорисовать их более детально. Хоть выполнение тесселяции возможно и программными методами, аппаратная тесселяция может дать огромное число визуальных деталей (включая поддержку карт смещения) без добавления визуальных деталей к размерам моделей и парализации частот обновления.

Преимущества тесселяции

Тесселяции:

  • Экономия большого объема памяти и пропускной способности, что позволяет приложению отрисовывать более подробные поверхности из моделей с низким разрешением. Метод тесселяции, реализованный в конвейере Direct3D 11, также поддерживает сопоставление смещения, которое может создавать потрясающие объемы деталей поверхности.
  • Поддерживает масштабируемые методы отрисовки, такие как непрерывные уровни детализации или зависимые от просмотра уровни детализации, которые можно вычислить на лету.
  • Повышение производительности за счет выполнения дорогостоящих вычислений с меньшей частотой (выполнение вычислений в модели с более низким уровнем детализации). Сюда могут входить расчеты смешения с применением форм наложения и морфинговые цели для реалистичной анимации или физических расчетов для обнаружения столкновений или эмуляции динамики мягких тел.

Конвейер Direct3D 11 реализует тесселяции в оборудовании, которое разгружает работу с ЦП на GPU. Это может дать очень существенный прирост производительности, если в приложение реализуется большое число морфинговых целей и/или более сложные модели деформации/скиннинга. Чтобы получить доступ к новым функциям тесселяции, необходимо изучить некоторые новые этапы конвейера.

Новые этапы конвейера

В ходе тесселяции задействуется GPU для расчета более подробной поверхности из поверхности, составленной из преобразований четырехугольников, треугольников и изолиний. Для аппроксимации поверхности высокого порядка, каждое преобразование подразделяется на треугольники, точки и линии согласно факторам тесселяции. Конвейер Direct3D 11 реализует тесселяции с помощью трех новых этапов конвейера:

  • Этап шейдера корпуса — программируемый этап шейдера, который создает исправление геометрии (и константы исправления), соответствующее каждому входному исправлению (четырехугольник, треугольник или линия).
  • Этап Tessellator — этап конвейера фиксированной функции, который создает шаблон выборки предметной области, представляющей геометрическое исправление, и создает набор небольших объектов (треугольников, точек или линий), соединяющих эти образцы.
  • Этап шейдера домена — программируемый этап шейдера, который вычисляет положение вершины, соответствующее каждому образцу предметной области.

На следующей схеме показаны новые этапы конвейера Direct3D 11.

схема конвейера direct3d 11, с выделенными этапами шейдера поверхности, тесселятора и шейдера доменов

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

схема выполнения тесселяции

Этап Hull-Shader

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

схема этапа шейдера поверхностей

Шейдер оболочки реализуется с помощью функции HLSL и имеет следующие свойства:

  • Входные данные шейдера — от 1 до 32 контрольных точек.
  • Шейдер выводит от 1 до 32 контрольных точек независимо от количества факторов тесселяции. Выходные контрольные точки шейдера поверхностей могут использоваться на этапе шейдера доменов. Константные данные исправления могут использоваться шейдером предметной области; Факторы тесселяции могут использоваться шейдером предметной области и этапом тесселяции.
  • Факторы тесселяции определяют, на сколько частей делить каждый участок.
  • Шейдер объявляет состояние, необходимое для этапа tessellator. Сюда входят такие сведения, как число контрольных точек, тип поверхности участка и тип секционирования при тесселяции. Эти сведения появляются в виде объявлений, как правило, в начале кода шейдера.
  • Если на этапе шейдера корпуса для любого коэффициента тесселяции края задано значение = 0 или NaN, исправление будет отбираться. В результате, этап тесселяции может выполняться или не выполняться, шейдер доменов не будет выполняться, а для указанного участка не будет выдано видимых выходных данных.

На более глубоком уровне шейдер корпуса фактически работает в два этапа: этап точки управления и этап с константой исправлений, которые выполняются оборудованием параллельно. Компилятор HLSL извлекает параллелизм в шейдере поверхностей и кодирует его в байт-код, управляющий оборудованием.

  • Этап контрольных точек выполняется единожды для каждой контрольной точки. При этом считываются контрольные точки для участка и создается одна выходная контрольная точка (определенная ControlPointID).
  • Этап констант участков выполняется единожды для каждого участка. При этом создаются факторы тесселяции ребер и другие константы отдельных участков. Внутри системы может одновременно выполняться множество этапов констант участков. Этап констант участков есть доступ только для чтения ко всем входным и выходным контрольным точкам.

Ниже приведен пример шейдера корпуса:

[patchsize(12)]
[patchconstantfunc(MyPatchConstantFunc)]
MyOutPoint main(uint Id : SV_ControlPointID,
     InputPatch<MyInPoint, 12> InPts)
{
     MyOutPoint result;
     
     ...
     
     result = TransformControlPoint( InPts[Id] );

     return result;
}

Пример создания шейдера корпуса см. в разделе Практическое руководство. Создание шейдера корпуса.

Этап тесселлатора

Tessellator — это этап фиксированной функции, инициализируемый путем привязки шейдера корпуса к конвейеру (см. раздел Практическое руководство. Инициализация этапа тесселлатора). Назначение этапа тесселятора подразделить домен (четырехугольник, треугольник или линию ) на большое число меньших объектов (треугольников, точек или линий). Тесселятор разбивает канонический домен в нормализованной (ноль к единице) системе координат. Например, домен четырехугольника тесселируется в единичный квадрат.

Тесселяция выполняется единожды для каждого участка с использованием факторов тесселяции (указывают тщательность тесселяции домена) и типа секционирования (указывает алгоритм разделения участка на части), переданных с предыдущего этапа шейдера поверхностей. Тесселяция выводит координаты uv (дополнительно — w) и топологию поверхности для этапа шейдера доменов.

На внутреннем этапе тесселлатор работает в два этапа:

  • В ходе первой фазы обрабатываются факторы тесселяции, устраняются ошибки округления, обрабатываются очень маленькие факторы, уменьшаются и объединяются факторы, при этом применяется 32-разрядная арифметика с плавающей запятой.
  • На второй фазе формируются списки точек или топологи на основе выбранного типа секционирования. Это основная задача этапа тесселятора, где применяются 16-разрядные дроби с арифметикой фиксированной точки. Арифметику фиксированной точки можно ускорить аппаратно с сохранением допустимый точности. Например, для преобразования шириной 64 метра такая точность позволяет размещать точки с разрешением в 2 мм.
Тип секционирования Диапазон
fractional_odd [1...63]
fractional_even Диапазон TessFactor: [2..64]
Целое число Диапазон TessFactor: [1..64]
pow2 Диапазон TessFactor: [1..64]

Этап Domain-Shader

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

схема этапа шейдера доменов

Свойства шейдера предметной области:

  • Шейдер предметной области вызывается один раз для каждой выходной координаты из этапа tessellator.
  • Шейдер домена использует контрольные точки вывода из этапа шейдера корпуса.
  • Шейдер предметной области выводит положение вершины.
  • Входные данные — это выходные данные шейдера корпуса, включая контрольные точки, константы исправлений и факторы тесселяции. Факторы тесселяции могут включать значения, используемые тесселлятором фиксированной функции, а также необработанные значения (например, перед округлением целочисленной тесселяции), что упрощает геоморфирование, например.

После завершения работы шейдера предметной области выполняется тесселяция и данные конвейера переходит к следующему этапу конвейера (геометрический шейдер, пиксельный шейдер и т. д.). Шейдер геометрии, ожидающий примитивы со смежностью (например, 6 вершин на треугольник), недействителен при активной тесселяции (это приводит к неопределенному поведению, о чем будет сообщать уровень отладки).

Ниже приведен пример шейдера предметной области:

void main( out    MyDSOutput result, 
           float2 myInputUV : SV_DomainPoint, 
           MyDSInput DSInputs,
           OutputPatch<MyOutPoint, 12> ControlPts, 
           MyTessFactors tessFactors)
{
     ...

     result.Position = EvaluateSurfaceUV(ControlPoints, myInputUV);
}

API для инициализации этапов тесселяции

Тесселяции реализованы с помощью двух новых программируемых этапов шейдера: шейдер корпуса и шейдер предметной области. Эти новые этапы шейдера программируются с помощью кода HLSL, определенного в модели шейдера 5. Новые целевые объекты шейдера: hs_5_0 и ds_5_0. Как и все программируемые этапы шейдера, код для оборудования извлекается из скомпилированных шейдеров, передаваемых в среду выполнения, когда шейдеры привязаны к конвейеру с помощью таких API, как DSSetShader и HSSetShader. Но сначала необходимо создать шейдер с помощью таких API, как CreateHullShader и CreateDomainShader.

Включите тесселяцию, создав шейдер поверхности и привязав его к этапу шейдера поверхности (это автоматически настраивает этап тесселятора). Для формирования финальных позиций вершин из тесселированных преобразований также понадобится создать шейдер доменов и привязать его к этапу шейдера доменов. После включения тесселяции входные данные на этапе входных данных ассемблера должны быть данными исправлений. То есть топология сборщика входных данных должна быть топологией константы исправлений из D3D11_PRIMITIVE_TOPOLOGY задана с помощью IASetPrimitiveTopology.

Чтобы отключить тесселяцию, установите для шейдера поверхности и шейдера доменов значение NULL. Ни этап геометрического шейдера, ни этап потокового вывода не могут считывать контрольные точки вывода шейдера корпуса или данные исправлений.

Практическое руководство.

В документации также приведены примеры инициализации этапов тесселяции.

Элемент Описание
Практическое руководство. Создание шейдера корпуса
Создайте шейдер корпуса.
Практическое руководство. Проектирование шейдера корпуса
Проектирование шейдера корпуса.
Практическое руководство. Инициализация этапа тесселлатора
Инициализация этапа тесселяции.
Практическое руководство. Создание шейдера домена
Создайте шейдер домена.
Практическое руководство. Проектирование шейдера предметной области
Создайте шейдер домена.

Графический конвейер