Shader — це не магія. Написання шейдерів у Unity. Введення

Всім привіт! Сьогодні хочеться поговорити про шейдери. Вміння писати шейдери (і в цілому працювати з рендером) дуже важливо при розробці під мобільні платформи або AR/VR, якщо хочеться досягти крутої графіки. Багато розробники вважають, що шейдери — це магія. Що з ним мало хорошої інформації, і щоб їх писати потрібно мати, як мимимум, звання кандидата наук. Так, розробка шейдерів по своїм принципам сильно відрізняється від клієнтської розробки. Але основне розуміти базові принципи роботи шейдерів, а так само знати їх суть, щоб у цьому не було нічого магічного і пошук інформації по цій темі був простим завданням. Дана серія статей розрахована на новачків, так що якщо ви розбираєтеся в програмуванні шейдерів, дана серія вам не буде цікава. Всім, хто хоче розібратися в цій темі — ласкаво просимо під кат!

Це вступна стаття в якій я розповім загальні принципи написання шейдерів. Якщо тема буде цікава, то ми розберемо вже докладніше в окремих статтях: вершинні шейдери, геометричні шейдери, фрагментные/піксельні шейдери, трипланарные шейдери, скринспейс ефекти і комп’ютерна шейдери (OpenCL, СUDA тощо). І в цілому всю ту магію, яку можна робити на GPU. Розбиратися це буде в контексті стандартного рендер пайплайна Unity. Так LWRP і HDRP мені поки здаються трохи сыроватыми.

Що таке шейдер?

Your browser does not support HTML5 video.
Джерело: www.shadertoy.com/view/MsGSRd

По суті це програма виконується на гпу, вихідними даними для яких є різна інформація. У вершинні шейдери — це параметри вершин меша. Піксельні шейдери виконуються попіксельно.

Для розуміння того, як працюють шейдери потрібно розповісти, що таке графічний конвеєр (graphic pipeline). Дуже часто про цю тему говорять досить складними словами, але ми це трохи спростимо для розуміння. Візьмемо на прикладі OpenGL. В цьому плані мені дуже подобається ця картинка.

Якщо опустити деталі пов’язані з освітленням і т. п. То в цілому з точки написання тих же Unlit шейдерів на hlsl суть така. У нас є в шейдере

#pragma vertex vert
#pragma fragment frag

де ми визначаємо, що вертексная частина шейдера буде писатися в функції vert, а фрагментная — в функції frag.

Структури які ми описуємо в шейдере визначають, які дані ми будемо забирати з меша і після обробки вертексным шейдером, які висять на нашому MeshRenderer і MeshFilter об’єкті.

 struct appdata
{
 float4 vertex : POSITION;
 float2 uv : TEXCOORD0;
};

 struct v2f
{
 float2 uv : TEXCOORD0;
UNITY_FOG_COORDS(1)
 float4 vertex : SV_POSITION;
};

Далі вертексный шейдер обчислює отримавши на вхід дані appdata і віддає результат у вигляді структури v2f, яка надалі піде в фрагментний шейдер. Який в свою чергу вже розрахує колір пікселя. Так як інформація v2f пишеться тільки у вершини (яких менше, ніж пікселів), дані в фрагментной частини інтерполюються. Все це можна представити як те, що vert вважається в кожному вертексе незалежно. Потім результат передається в фрагментную частина, де frag для кожного пікселя вважається так само незалежно. Так як обчислення проводяться паралельно, в даних частинах немає ніякої інформації про сусідів (якщо не передавати її якось хитро).

Більш детально всі нюанси, а так само безліч прикладів описані в документації Unity docs.unity3d.com/Manual/SL-Reference.html

Мови програмування шейдерів

Your browser does not support HTML5 video.
Джерело: www.shadertoy.com/view/WsS3Dc

Про що ще важливо не забувати. Про те, що шейдери зараз пишуться на трьох мовах програмування, які не мають ніякого відношення до юніті. CG, GLSL і HLSL. Найпростіший спосіб писати шейдери в юніті — це HLSL, так як саме на ньому пишуться файли шейдерів з дозволом .shader. І якщо за шейдерам в контексті юніті інформації порівняно мало, то інформації окремо по HLSL, GLSL і CG — просто тонни. У документації до шейдерам описано, яким чином написане на цих мовах перенести в Unity. Тому виходить, що майже вся інформація в загальному про ці мови програмування валидна. Всі три мови дуже сильно схожі на мову С, але у кожного свої особливості.

Далі з точки зору вивчення шейдерів, коли ці мови вже не викликають питань можна подивитися які можливості надає сам по собі«UnityCG.cginc» та інші бібліотеки написані юнити, щоб спростити собі роботу.

Чому if в шейдери — це погано?

Your browser does not support HTML5 video.
Джерело: www.shadertoy.com/view/Md3cWr

Тут важливо розуміти, як шейдери виконуються на рівні заліза і чому вони такі швидкі, що можуть виконувати мільйони операцій не напружуючись.

Основна ідея графічних процесорів — це максимальна паралельність обчислень. Тут потрібно ввести таке поняття, як “хвильовий фронт”. По суті воно досить просте, хвильовий фронт — це група шейдерів виконує одну і ту саму послідовність операції. Тобто з точки зору гпу найкращий варіант, коли в одне і теж час виконуються одні і ті ж інструкції. Єдина відмінність у виконанні — це вхідні дані. Проблема розгалуження в тому, що може статися ситуація, коли в одній групі шейдерів, шейдери повинні викликати різні операції. Що в свою чергу призводить до створення нового хвильового фронту, копіювання в нього даних і т. п. А це дуже дорого.

Там є нюанси і виключення, але для того, щоб спокійно писати if, ви повинні розуміти, як він себе поведе на цільовий версії графічного апі. Так як той же самий OpenGL ES 2 або DX11 в цьому плані сильно відрізняються.

Навіщо мені це знати, адже є нодовые редактори?

Важливо розуміти, що нодові редактори — це в першу чергу інструмент для техникал артистів. Це фахівці, які мають експертизу в математиці, але в більшій мірі є дизайнерами. Шейдери типу wireframe (де потрібне розуміння барицентрических координат) або ж перетворення до картезианским координатами, яке використовується для хитрих проекцій, в рази простіше робити кодом, так само як і багато математичні моделі фізичних матеріалів. При цьому з точки зору шейдерного програміста ви по суті робите кастомні ноди і інструменти для техникал артистів, щоб творити реальну магію. Нодовые редактори мають обмежений функціонал з цієї точки зору. Тому важливо вміти писати шейдери на мовах типу hlsl. Розуміти те, як працює рендер і т. п.

Корисні ресурси для вивчення

Your browser does not support HTML5 video.
Джерело: www.shadertoy.com/view/4tlcWj

З точки зору вивчення шейдерного програмування хорошим вправою є переписування шейдерів з www.shadertoy.com або glslsandbox.com. Крім того існує крутий профіль спеціаліста з Unity, де можна побачити багато цікавого github.com/keijiro

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

Якщо тема шейдерів буде цікава, то постараюся випустити на серію статей на цю тему, вже з конкретними прикладами та туторіалами на тему створення різних ефектів. Пропонуйте в коментарях про що вам було б цікаво прочитати і які теми вивчити. Спасибі за увагу!

Всі ефекти в статті — це запис ефектів шейдерів з shadertoy.

Степан Лютий

Обожнюю технології в сучасному світі. Хоча частенько і замислююся над тим, як далеко вони нас заведуть. Не те, щоб я прям і знаюся на ядрах, пікселях, коллайдерах і інших парсеках. Просто приходжу в захват від того, що може в творчому пориві вигадати людський розум.

Вам також сподобається...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *