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);
col = 1 - col;
// Инверсия цвета, цвет в шейдере представлен 4-мя компонентами
// RedGreenBlueAlpha - КрасныйЗелёныйСинийНепрозрачность,
// причём значение каждого компонента в диапазоне от 0 до 1
return col;
}
ENDCG
}
}
}
col = 1 - col;
В записанной выше строке есть скрытая работа, как уже было сказано ранее, fixed4 это структура состоящая из 4х элементов типа fixed, более того мы можем обратиться к каждому элементу по отдельности, вот так: col.r, или col.g, или col.b, или col.a, более того, можно обращаться к паре или тройке элементов: col.rgb или col.ba.
У цветового rgba есть синоним из мира геометрии xyzw, они абсолютно эквивалентны и, даже если вы работаете с цветами, к ним можно обращаться через xyzw, но чтобы не создавать двусмысленности xyzw лучше использовать с координатами. Вернёмся к вопросу о скрытой работе.
col = 1 - col;
На самом деле означает, что будет сделано следующее:
Следующий шейдер берёт соответствующие пиксели двух картинок и интерполирует цвет этих пикселей между собой формируя таким образом результирующую картинку.
Shader "Tutorial/ImageMerger"
{
Properties
{
// В этом шейдере нам понадобится две текстуры и одна
// переменная для указания степени смешивания
_FirstTex("First Texture", 2D) = "white" {}
_SecondTex("Second Texture", 2D) = "white" {}
_LerpFactor("Lerp Factor", Range(0, 1)) = 0.5
// Это свойство можно было объявить иначе
// _LerpFactor("Lerp Factor", Float) = 0.5
// но слайдер удобнее для пользователя, чем поле ввода
}
SubShader
{
Cull Off
ZWrite Off
ZTest Always
Pass
{
CGPROGRAM
#pragma vertex vert_img
#pragma fragment frag
#include "UnityCG.cginc"
sampler2D _FirstTex;
sampler2D _SecondTex;
float _LerpFactor;
fixed4 frag(v2f_img i) : COLOR
{
fixed4 firstColor = tex2D(_FirstTex, i.uv);
fixed4 secondColor = tex2D(_SecondTex, i.uv);
firstColor = lerp(firstColor, secondColor, _LerpFactor);
return firstColor;
}
ENDCG
}
}
}
lerp - это готовая функция, которая принимает две переменные, которые надо между собой интерполировать и одну переменную, которая укажет степень их интерполяции. Чтобы понять работу этой функции, представьте себе две точки на бумаге и проведите отрезок от первой точки ко второй, а _LerpFactor скажет где на этом отрезке поставить третью точку, которая и будет результатом функции, если _LerpFactor = 0, то результат будет совпадать с первой точкой _LerpFactor = 1, результат совпадёт со второй, а _LerpFactor = 0.5 укажет точно на середину отрезка.
Наложение одной текстуры поверх другой
Ещё один шейдер исключительно для примера того, что можно сделать. Он берёт одну картинку, а поверх неё накладывает другую так, чтобы были едва видны очертания накладываемой картинки. По схожему принципу работает фильтр Overlay в фотошопе.