Шейдер с эффектом светящегося контура в 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 не тянут.