Введение
Визуальные эффекты, основанные на гексагональной сетке, придают уникальный стиль играм и приложениям.
В этом материале мы рассмотрим реализацию гексагонального фрагментного шейдера для движка Godot Engine.
Он позволяет разбивать экран на гексагональные ячейки и окрашивать их в зависимости от положения UV-координат, создавая эффект «расплывающегося выбора» или «плавного выделения» внутри гекса.
Принцип работы
Шейдер делит экранное пространство на гексагональную сетку с помощью преобразования координат. Каждый пиксель определяет свою принадлежность к определённой ячейке, а затем вычисляет вклад (вес) в цвета соседних трёх гексагона. Это делает границы между ячейками мягкими и визуально привлекательными.
Основные шаги, выполняемые шейдером:
- Подготовка координат — UV-информация инвертируется по вертикали, масштабируется под заданную плотность сетки и трансформируется в осевые координаты гексагональной решётки.
- Округление и индексация — вычисляются ближайшие три гексагона, к которым пиксель может принадлежать.
- Локальные координаты — определяются координаты внутри текущей гекс-клетки и проверяется, нужно ли перевернуть направление.
- Вычисление влияния (весов) — пиксель «голосует» за три ближайших гексагона, и каждый получает свою долю в итоговом цвете.
- Фокусировка — веса поднимаются в степень, регулируемую параметром
HexFocus
, чтобы усилить влияние центра клетки и уменьшить вклад краёв. - Нормализация и окрашивание — итоговые значения нормализуются и устанавливаются в качестве
ALBEDO
.
Пример кода
shader_type spatial;
render_mode blend_mix, depth_draw_opaque, cull_back, diffuse_lambert, specular_schlick_ggx;
uniform vec2 hex_grid_density = vec2(6.0, 6.0); // количество ячеек
uniform float hex_cell_size = 1.0; // размер гекса
uniform float hex_focus = 6.0; // фокусировка цвета внутри гекса
void fragment() {
vec2 uv = UV;
// Переворот Y-координаты UV
vec2 flipped_uv = vec2(uv.x, 1.0 - uv.y);
// Масштабирование под hex-сетку
vec2 grid_uv = flipped_uv * hex_grid_density;
// Коэффициенты преобразования
float sqrt3_div2 = 1.732 / 2.0;
float inv_sqrt3 = 1.0 / (1.732);
float axial_x = grid_uv.x - grid_uv.y * (sqrt3_div2 / 1.5);
float axial_y = grid_uv.y * inv_sqrt3;
vec2 axial_coords = vec2(axial_x, axial_y);
// Нормализация относительно размера клетки
vec2 cell_coords = axial_coords / vec2(hex_cell_size);
vec2 floored_coords = floor(cell_coords);
float cell_diff = floored_coords.x - floored_coords.y;
// Вспомогательный вектор
vec3 offsets = vec3(0.0, 1.0, 2.0);
vec3 temp = vec3(cell_diff) + offsets;
// Нормализация
vec3 normalized = temp * vec3(1.0 / 3.0);
normalized += vec3(2.0 / 3.0);
// Получаем индексы вершин гексагона
vec3 hex_index = round(fract(normalized));
float i0 = hex_index.x;
float i1 = hex_index.y;
float i2 = hex_index.z;
// Подготовка векторов для dot product'ов
vec3 axis0 = vec3(i2, i0, i1);
vec3 axis1 = vec3(i1, i2, i0);
vec3 axis2 = vec3(i0, i1, i2);
// Получаем локальные координаты внутри клетки
vec2 local_coords = fract(cell_coords);
float sum_coords = local_coords.x + local_coords.y;
float abs_dist = abs(sum_coords - 1.0);
bool flip_needed = (sum_coords - 1.0) > 0.0;
vec2 flipped_coords = vec2(1.0) - vec2(local_coords.y, local_coords.x);
vec2 chosen_coords = mix(local_coords, flipped_coords, float(flip_needed));
vec3 influence = vec3(abs_dist, chosen_coords.x, chosen_coords.y);
// Вычисляем веса влияния
float w0 = dot(axis0, influence);
float w1 = dot(axis1, influence);
float w2 = dot(axis2, influence);
vec3 weights = vec3(w0, w1, w2);
// Усиление акцента с помощью степени
vec3 focused_weights = pow(weights, vec3(hex_focus));
// Нормализация
float total = dot(focused_weights, vec3(1.0));
vec3 final_color = focused_weights / vec3(total);
ALBEDO = final_color;
}
Параметры
Параметр | Описание |
---|---|
hex_grid_density | Количество гексагонов по X и Y. Изменяет плотность сетки. |
hex_cell_size | Размер одной гекса-клетки. Можно использовать для масштабирования. |
hex_focus | Степень фокусировки внутри ячейки. Чем выше, тем ярче центр ячейки. |
Применение
Этот шейдер идеально подходит для:
- процедурной генерации мозаичных материалов.
- визуализации сеток и структур;
- эффектов выбора или фокусировки в UI;
- стилизованных экранных фильтров;


Вы можете скачать этот алгоритм, перейдя по ссылке, или воспользовавшись сайтом:
- GodotShader: Procedural Hexagonal Pattern | Shader Algorithm — Godot Shaders
- Google Drive: Hexagonal Algorithm