Unity - керівництво поверхневі шейдери з використанням тесселяції dx11
У поверхневих шейдерах є деяка підтримка GPU тесселяции DirectX 11. Ідея така:
- Тесселяція визначається модифікатором tessellate: FunctionName. Ця функція розраховує фактори тесселяции на кордоні і всередині трикутника.
- При використанні тесселяции, після неї викликається "вершинний модифікатор" (vertex: FunctionName) для з кожної згенерованої вершини в доменному шейдера. Тут ви зазвичай зробили б накладення карт зсуву.
- Опціонально поверхневі шейдери можуть виробляти розрахунок phong тесселяции для згладжування поверхні моделі, навіть без накладення карт зсуву.
Поточні обмеження підтримки тесселяції:
- Тільки трикутний домен - немає квадов, немає isoline тесселяции.
- Коли використовується тесселяция, шейдер автоматично компілюється з використанням Shader Model 5.0, тому він буде працювати тільки під DX11.
Ні GPU тесселяции, зміщення в модификаторе вершин
Давайте почнемо з поверхневого шейдера, який здійснює накладення карт зсуву без тесселяції. Він просто рухає вершини уздовж їх нормалей, на основі значень, зчитувальних з карти зміщення:
Шейдер, наведений вище, вельми стандартний, цікаві місця:
- Верховий модифікатор disp здійснює вибірку з карти зсувів і зрушує вершини уздовж їх нормалей.
- Використовується для користувача структура "введення вершинних даних" (appdata) замість структури за замовчуванням appdata_full. Поки вона не потрібна, але для тесселяції ефективніше використовувати якомога меншу структуру.
- Так як наші вершинні координати не мають 2й UV координати, ми додаємо директиву nolightmap для виключення карт освітлення.
Ось як деякі прості об'єкти будуть виглядати при використанні цього шейдера:

Фіксована кількість тесселяции
Давайте додамо фіксовану кількість тесселяции, тобто однаковий рівень тесселяції для всього заважав. Цей підхід придатний в разі, якщо на екрані полігони вашої моделі приблизно однакового розміру. Тоді деякий код міг би змінювати рівень тесселяції на основі відстані від камери.
Функція тесселяции tessFixed в нашому шейдера повертає чотири чинника тесселяции у вигляді одного значення float4: три фактори для кожної сторони трикутника і один фактор для внутрішньо області трикутника. Тут ми просто повертаємо постійне значення, яке зазначено у властивостях матеріалу.

Тесселяція на основі відстані
Ми також можемо змінювати рівень тесселяції в залежності від відстані до камери. Наприклад, ми могли б оголосити два значення відстані; відстань, на якому тесселяция максимальна (скажімо, 10 метрів), і відстань, у міру наближення до якого рівень тесселяції плавно падає (скажімо, 20 метрів).
Тут функція тесселяции отримує три параметри; дані вершин трьох кутів трикутника до тесселяции. Це необхідно для розрахунку рівнів тесселяції, які залежать від поточного положення вершин. Ми включаємо вбудований допоміжний файл Tessellation.cginc і викликаємо з нього функцію UnityDistanceBasedTess для здійснення всієї роботи. Ця функція розраховує відстань до камери кожної вершини і витягує кінцеві фактори тесселяции.

Тесселяція на основі довжини сторони
Тесселяція, заснована тільки на відстані хороша тільки коли розміри трикутників досить схожі. На зображенні, представленому вище, ви можете помітити, що у об'єктів з маленькими трикутниками тесселяция занадто сильна, в той час як об'єкти з великими трикутниками недостатньо тесселіровани.
Замість цього, рівні тесселяции можуть бути розраховані на основі довжини сторони трикутника на екрані. - чим довше сторона, тим більший повинен застосовуватися фактор тесселяции.
Тут знову, ми просто викликаємо функцію UnityEdgeLengthBasedTess з Tessellation.cginc для здійснення всієї роботи.

Для збереження гарної продуктивності, замість наведеної вище функції рекомендується викликати функцію UnityEdgeLengthBasedTessCull. яка зробить відсікання острівців по піраміді видимості. Це робить шейдер трохи більше ресурсномістких, але зберігає велику кількість ресурсів GPU для частин заважав, які не потрапляють в зону видимості камери.
Phong тесселяция
Phong тесселяция змінює положення поділені полігонів так, щоб результуюча поверхню трохи слідувала нормалям заважав. Це досить ефективний спосіб згладжування нізкополігональних мешів.
Поверхневі шейдери Unity можуть автоматично розраховувати phong тесселяцию за допомогою директиви компіляції tessphong: VariableName. Ось приклад шейдера:
Ось порівняння між звичайним шейдером (верхній рядок) і тим, який використовує phong тесселяцию (нижня рядок). Ви можете помітити, що навіть без будь-якого накладення карт зсуву, поверхня стає більш округлої.

Приклади освітлення в поверхневих шейдерах
Програмування вершинних і фрагментних (піксельних) шейдеров