
Графы шейдеров это новый инструмент для создания шейдеров в юнити. Он позволяет создавать шейдеры людям не имеющим навыков написания кода. Результат каждой операции виден при редактировании. Идеальный инструмент для новичков и экспериментаторов.
Добавление Shader Graph в проект делается при помощи Package Manager.

Но на сегодня доступна версия только для Lightweight Render Pipeline, поэтому для экспериментов нужно создавать проект так:

Простейший шейдер
Shader Graph позволяет создать два вида шейдеров Unlit(без освещения) и PBR(фотореалистичный рендер), а так же sub(нода для шейдера). Последнее можно использовать внутри Unlit и PBR шейдеров.

Unlit не использует встроенных возможностей в юнити по освещнию и затенению модели, только отображает текстуру поверх модели и поэтому с ним намного проще ознакомиться.
Создаём материал и создаём Unlit Graph. Перетягиванием назначаем материалу шейдер.

Открыв шейдер двойным кликом мы увидим мастер-ноду

На выходе этого шейдера мы можем контролировать:
- Position — позицию вершины
- Color — цвет каждого пикселя поверхности
- Alpha — его прозрачность
- AlphaClipThreshold — порог прозрачности, если мы не используем полупрозрачность
Подавляющее большинство шейдеров не использует полупрозрачность из-за вычислительной сложности и ограничений, которые накладываются на такие шейдеры. И там, где можно обойтись без полупрозрачности, надо обходиться без неё.
Будет ваш шейдер использовать полупрозрачность или нет, можно настроить в мастер-ноде:

- Opaque — непрозрачный
- Transparent — полупрозрачный
Чтобы раскрасить модель мы можем подать на вход(color) мастер-ноды трёхмерный вектор или цвет, что для шейдера по сути одно и то же, только по разному отображается в графе.
Новые ноды создаются через контекстное меню

в данном случае мы можем использовать две ноды Color или Vector4

но чтобы их можно было настраивать из инспектора нам нужно создать свойство

а потом мышкой перетянуть его в граф тем самым создав ноду.

- Exposed — позволяет это свойство видеть в инспекторе при редактировании материала
- Default — задаёт значение цвета по умолчанию
- Mode — позволяет выбрать диапазон яркости(HDR позволяет выйти за рамки обычной яркости)
Чтобы созданное свойство влияло на цвет материала надо его выход соединить со входом Color у мастер-ноды.

Тот же шейдер, но кодом
Shader "Tutorial/Simpliest" // Shader - обязательное начало для любого шейдера,
// после этого ключевого слова в
// кавычках пишется url-подобное имя шейдера
{
Properties // блок свойств, которые будут отображаться во вкладке
// inspector в Unity
{
_Color ("Color", Color) = (0.5,0.6,0.7,1)
//Каждая строка связана с переменной и содержит следующие данные:
// _Color - имя переменной, оно должно совпадать по написанию с
// одной из переменных внутри CGPROGRAM
// "Color" - текст, который будет отображаться в окне
// Inspector перед значением переменной
// Color - тип данных, от него зависит как будет выглядеть
// блок выбора значения в Inspector, бывает
// 5 типов данных:
// Color - выглядит как выбор цвета,
// Vector - как 4 текстовых поля ввода,
// Float - поле ввода одного числа с плавающей запятой,
// 2D - текстура,
// CUBE - выбор кубической текстуры
// (0.5,0.6,0.7,1) - значение переменной по умолчанию
}
SubShader // в одном шейдере может быть несколько этих блоков,
// но одновременно работать может только один
{
// No culling or depth
// Это зарезервированные слова, в этом шейдере они указаны
// для упрощения работы GPU, благодаря им потребуется меньше
// вычислений для отображения шейдера, а ZTest Always говорит
// о том, что этот шейдер будет рисовать объект поверх всех остальных
Cull Off
ZWrite Off
ZTest Always
Pass // этих блоков может быть несколько внутри одного SubShader,
// каждый Pass это отдельный проход рендера по объекту с этим
// шейдером, результат следующего Pass рисуется поверх предыдущего
{
CGPROGRAM // Зарезервированное слово, оно лишь отмечает начало
// кода самого шейдера
#pragma vertex vert_img // использовать для вертексного шейдера
// vert_img, которая описана не нами
#pragma fragment frag // для фрагментного шейдера использовать
//функцию frag, описанную ниже
#include "UnityCG.cginc" // позволяет нам использовать готовые функции,
// написанные командой Unity
// в их числе и vert_img, код файла можно найти
// в файле:
// %UNITY%\Editor\Data\CGIncludes\UnityCG.cginc
fixed4 _Color; // fixed4 - тип переменной, именно этот тип представляет
// собой структуру из 4х переменных типа fixed
fixed4 frag (v2f_img i) : COLOR
{
fixed4 col = _Color;
return col;
}
ENDCG // Зарезервированное слово, оно отмечает конец кода самого шейдера
}
}
}
Самый простой шейдер с текстурой
Чтобы наложить нашу текстуру на меш, нам надо создать ноду, которую можно будет настроить извне Shader Graph. Для этого создадим свойство

и вытянем его, при этом создастся нода текстуры

После этого нужно создать ноду сэмплера текстуры, которая сможет на вход получать текстуру и uv-координату, а на выход давать цвет пикселя.

Выход сэмплера соединяем со входом color мастер-ноды

Простейший шейдер с текстурой кодом
Shader "Tutorial/Texture"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
// В предыдущей части в качестве свойства был цвет,
// а теперь текстура, в Inspector будет предложено
// выбрать одну. Здесь "white" это значение по умолчанию,
// означает, что будет создана текс��ура белого цвета.
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
// sampler2D - это тип переменной который надо ставить когда
// мы хотим работать с текстурой, заметьте, что имя переменной
// _MainTex совпадает с именем свойства в блоке Properties,
// это обязательно для корректной работы.
fixed4 frag(v2f_img i) : COLOR
{
// Следующая строка позволяет нам получить цвет пикселя в точке
// с которой мы работаем в этой итерации, если помните, то ранее
// было сказано, что фрагментный шейдер работает с каждым видимым
// пикселем объекта.
// tex2D - это готовая функция для получения значения цвета,
// первый параметр (_MainTex) это из какой текстуры мы хотим
// получить цвет, а второй (i.uv) это UV координаты в которых
// мы хотим узнать цвет.
fixed4 col = tex2D(_MainTex, i.uv);
return col;
}
ENDCG
}
}
}Негатив текстуры
Перед отображением текстуры на экране мы можем её изменить применив математические операции. Например создать негатив простым вычитанием.
Добавим ноду Substract уменьшаемое будет (1;1;1;1), а вычитаемое выходом текстуры.

Негатив текстуры кодом
Shader "Tutorial/Texture"
{
Properties
{
_MainTex("Texture", 2D) = "white" {}
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
fixed4 frag(v2f_img i) : COLOR
{
fixed4 col = tex2D(_MainTex, i.uv);
col = 1 - col;
// Инверсия цвета, цвет в шейдере представлен 4-мя компонентами
// RedGreenBlueAlpha - КрасныйЗелёныйСинийНепрозрачность,
// причём значение каждого компонента в диапазоне от 0 до 1
return col;
}
ENDCG
}
}
}Смешение двух текстур
Для того чтобы смешать две текстуры нам понадобится три свойства, два из которых будут текстурами, а третье числом, которое укажет в какой степени их смешивать.
А саму операцию смешивания произведёт нода Lerp.

Смешение двух текстур кодом
Shader "Tutorial/NoiseOverlay"
{
Properties
{
_MainTex("Main Texture", 2D) = "white" {}
_NoiseTex("Noise Texture", 2D) = "white" {}
_LerpValue("Lerp Value", Range(0, 1)) = 0.5
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _MainTex;
sampler2D _NoiseTex;
float _LerpValue;
fixed4 frag(v2f_img i) : COLOR
{
half4 base = tex2D(_MainTex, i.uv);
half4 overlay = tex2D(_NoiseTex, i.uv);
return lerp(base, overlay , _LerpValue);
}
ENDCG
}
}
}
Cutout маска
Чтобы сделать полностью прозрачной часть модели нужно подать на вход мастер-ноды значение Alpha канала, создать свойство-слайдер и подать его на вход AlphaClipThreshold

Слайдер нужен для исправления бага в Graph shader, который не позволяет сделать cutout и к тому же он позволит менять значение из настроек материала.
Инверсия UV
Для работы с UV нужно создать ноду UV и подключить её к сэмплеру текстуры

здесь же можно выбрать канал UV, у некоторых моделей этих каналов может быть несколько, на случай многослойных текстур. Этим шагом мы не изменили ровным счётом ничего, а чтобы инвертировать UV, нам нужно создать ноду которая инвертирует значения UV, нам подойдёт обычное умножение на -1 координаты по Y.

Отзеркаливание текстуры можно сделать настраиваемым из материала, для этого нам понадобится нода Branch, она на вход получает булево значение, а на выход одно из двух значений, в нашем случае 1 или -1

Впечатления
Создание шейдера при помощи Shader Graph сильно упрощает задачу хотя бы потому, что можно наблюдать за изменением результата после каждого этапа вычислений. Са�� принцип создания через редактор нод позволяет создать что-то новое даже тем, кто ничего не понимает в шейдерах. Инструмент ещё сырой, но уже очень полезный. Так как можно поэкспериментировать в редакторе, а потом воспроизвести созданное кодом, названия функций в большинстве случаев совпадает с названием нод, поэтому Shader Graph может оказаться полезным и программистам.
P.S. благодарю Darkirius за помощь в подготовке статьи
P.P.S. так же вы можете ознакомиться с уроками по написанию шейдеров в юнити по ссылке Гит-книга