Шейдер с эффектом светящегося контура в Unity
Шейдеры в Unity всегда казались мне чем-то вроде тёмного искусства, пока я не решил добавить в свою игру эффект светящегося контура для объектов. Представьте: персонаж подсвечивается, как будто его окружает неоновая аура, — выглядит круто и сразу привлекает внимание. В этой статье расскажу, как я создал такой шейдер, с какими проблемами столкнулся и как вы можете повторить это без боли. Спойлер: это проще, чем кажется!
Зачем нужен светящийся контур?
Эффект glowing outline часто используется в играх, чтобы выделить интерактивные объекты, показать выбранного персонажа или просто добавить стиля. Когда я работал над небольшой 3D-игрой, заказчик попросил сделать так, чтобы ключевые предметы «светились» при наведении. Стандартные материалы Unity не давали нужного эффекта, и я полез изучать шейдеры.
Для этого проекта я выбрал подход с написанием шейдера вручную, хотя Unity предлагает Shader Graph для визуального создания эффектов. Код даёт больше контроля, и мне хотелось разобраться, как всё работает под капотом.
Шаг 1: Понимание идеи
Светящийся контур обычно создаётся с помощью двух проходов (passes) в шейдере:
- Первый проход рисует сам объект с обычной текстурой.
- Второй проход рисует «надутую» версию объекта, которая создаёт контур, с применением яркого цвета.
Я вдохновлялся туториалами, но многие из них были либо слишком сложными, либо устаревшими. После пары часов экспериментов я собрал рабочий шейдер.
Шаг 2: Пишем шейдер
Вот пример шейдера, который добавляет светящийся контур к объекту. Он написан на ShaderLab с использованием HLSL для логики рендеринга:
Shader "Custom/GlowOutline"
{
Properties
{
_MainTex ("Texture", 2D) = "white" {}
_OutlineColor ("Outline Color", Color) = (1, 1, 0, 1)
_OutlineWidth ("Outline Width", Float) = 0.01
}
SubShader
{
Tags { "RenderType"="Opaque" }
// Первый проход: рисуем контур
Pass
{
Cull Front // Игнорируем лицевые грани
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float3 normal : NORMAL;
};
struct v2f
{
float4 vertex : SV_POSITION;
};
float _OutlineWidth;
fixed4 _OutlineColor;
v2f vert (appdata v)
{
v2f o;
// "Надуваем" модель, смещая вершины вдоль нормалей
v.vertex += float4(v.normal * _OutlineWidth, 0);
o.vertex = UnityObjectToClipPos(v.vertex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return _OutlineColor;
}
ENDCG
}
// Второй проход: рисуем основной объект
Pass
{
CGPROGRAM
#pragma vertex vert
#pragma fragment frag
#include "UnityCG.cginc"
struct appdata
{
float4 vertex : POSITION;
float2 uv : TEXCOORD0;
};
struct v2f
{
float2 uv : TEXCOORD0;
float4 vertex : SV_POSITION;
};
sampler2D _MainTex;
float4 _MainTex_ST;
v2f vert (appdata v)
{
v2f o;
o.vertex = UnityObjectToClipPos(v.vertex);
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
return o;
}
fixed4 frag (v2f i) : SV_Target
{
return tex2D(_MainTex, i.uv);
}
ENDCG
}
}
}
Этот шейдер создаёт жёлтый контур вокруг объекта. Вы можете настроить цвет и ширину контура через инспектор Unity (параметры _OutlineColor и _OutlineWidth).
Шаг 3: Применяем шейдер
Чтобы использовать шейдер:
- Создайте новый материал в Unity.
- Выберите шейдер
Custom/GlowOutlineв выпадающем меню. - Назначьте материал на объект (например, куб или персонажа).
- Настройте текстуру, цвет и ширину контура в инспекторе.
Когда я впервые применил этот шейдер к модели, контур выглядел слишком толстым. Пришлось уменьшить _OutlineWidth до 0.005, чтобы получить аккуратный эффект. Это научило меня: всегда тестируйте шейдер на реальных моделях, а не на тестовых сферах!
Шаг 4: Оптимизация и проблемы
Мой первый шейдер работал, но на сложных моделях с большим числом полигонов контур выглядел неровно. Причина? Нормали модели были неравномерными. Я решил это, экспортировав модель из Blender с опцией «Smooth Normals».
Еще одна проблема — производительность. Контурный проход может быть тяжелым для мобильных устройств. Чтобы оптимизировать:
- Используйте шейдер только для ключевых объектов.
- Уменьшайте
_OutlineWidth, чтобы снизить нагрузку на рендеринг. - Тестируйте на целевой платформе (я проверял на старом iPhone, и пришлось упростить шейдер).
Советы для начинающих
Мой опыт с шейдерами научил меня нескольким вещам:
- Начните с простого: Попробуйте изменить цвет или прозрачность объекта, чтобы понять структуру шейдера.
- Изучайте примеры: Unity Asset Store и GitHub полны бесплатных шейдеров. Разберите их код, чтобы понять, как они работают.
- Не бойтесь ошибок: Мой первый шейдер выдавал чёрный экран, потому что я забыл включить текстуру. Дебаггинг — часть процесса.
Если хотите ускорить обучение, рекомендую книгу The Book of Shaders (есть бесплатная версия онлайн) и туториалы на канале Freya Holmér. Они помогли мне понять, как шейдеры обрабатывают свет и текстуры.
Итог
Создание шейдера с эффектом светящегося контура оказалось не таким уж сложным, а результат добавил моей игре вау-эффект. Теперь я использую этот шейдер для выделения объектов, и заказчик в восторге. Шейдеры — это не только про красивые картинки, но и про умение решать задачи, которые стандартные инструменты Unity не тянут.
