Vertex Shader — это программируемый этап графического конвейера (graphics pipeline), который обрабатывает каждую вершину трёхмерной модели. По данным Khronos Group, 2025, вершинный шейдер принимает на вход атрибуты вершин — координаты, нормали, цвет и текстурные координаты — и преобразует их согласно заданной логике. Vertex Shader выполняется для каждой вершины независимо, что позволяет эффективно распараллеливать вычисления на тысячах ядер GPU.
Главное
Vertex Shader — это программируемый этап графического конвейера (graphics pipeline), который обрабатывает каждую вершину трёхмерной модели по отдельности. Вершина (vertex) — это точка в трёхмерном пространстве, содержащая атрибуты: координаты xyz, нормали, цвет и текстурные координаты UV.
В отличие от фиксированного конвейера (fixed-function pipeline), где преобразования выполнялись по жёстко заданному алгоритму, Vertex Shader даёт разработчику полный контроль над трансформацией вершин. Это позволяет реализовывать процедурную анимацию, деформацию моделей, скелетный скининг и любые математические преобразования на стороне GPU.
Графический конвейер OpenGL ES включает последовательность этапов от входных данных до финального изображения. Vertex Shader располагается после этапа сборки вершин (vertex assembly) и перед этапом растеризации. Каждая вершина, переданная из CPU через вершинный буфер, проходит через Vertex Shader ровно один раз, а результат передаётся на следующий этап для сборки примитивов.
| Этап конвейера | Назначение |
|---|---|
| Vertex Specification | Передача вершинных данных и атрибутов из VBO |
| Vertex Shader | Обработка каждой вершины, трансформация координат |
| Tessellation | Опциональное подразделение геометрии на подпримитивы |
| Geometry Shader | Опциональная генерация или удаление примитивов |
| Rasterization | Преобразование примитивов в фрагменты для заливки |
Vertex Shader получает на вход атрибуты вершины из вершинного буфера (VBO) через указатели атрибутов (vertex attribute pointers), настроенные в CPU-коде. Разработчик пишет шейдерный код на GLSL (OpenGL Shading Language) или аналогичном языке, который компилируется драйвером GPU в машинные инструкции для конкретного чипа.
Для каждой вершины Vertex Shader последовательно выполняет три операции: чтение входных атрибутов — применение трансформаций, определённых разработчиком — запись результатов в выходные переменные. Минимальный обязательный выход — позиция вершины в пространстве отсечения (gl_Position). Все остальные выходные данные (цвет, нормали, текстурные координаты) интерполируются и передаются на следующий этап — Fragment Shader.
#version 300 es
in vec3 aPosition;
in vec2 aTexCoord;
uniform mat4 uMVP;
out vec2 vTexCoord;
void main() {
gl_Position = uMVP * vec4(aPosition, 1.0);
vTexCoord = aTexCoord;
}
Vertex Shader решает широкий спектр задач графического конвейера, связанных с трансформацией геометрии. Каждая задача реализуется через математические операции над векторами и матрицами, выполняемые параллельно для тысяч вершин одновременно.
Базовая и самая распространённая задача — умножение вершинных координат на матрицы model, view и projection (MVP). Матрица MVP преобразует вершину из локального пространства модели в пространство отсечения (clip space), которое затем нормализуется и преобразуется в экранные координаты в автоматических этапах конвейера.
Для анимированных персонажей Vertex Shader реализует скелетную анимацию (skinning). Каждая вершина привязана к нескольким костям с определёнными весами. Vertex blending — взвешенная сумма трансформаций от привязанных костей — позволяет плавно деформировать кожу персонажа при движении скелета.
Vertex Shader может модифицировать геометрию на основе времени или других uniform-параметров без участия CPU. Wave deformation, шумовые смещения по перлиновому шуму и эффекты ряби на воде — все эти эффекты реализуются в вершинном шейдере без перезагрузки геометрии из оперативной памяти.
Хотя оба типа шейдеров являются программируемыми этапами графического конвейера, Vertex Shader и Fragment Shader решают принципиально разные задачи и работают на различных стадиях обработки изображения.
| Характеристика | Vertex Shader | Fragment Shader |
|---|---|---|
| Входные данные | Атрибуты вершин из VBO | Интерполированные данные из VS |
| Количество вызовов | Количество вершин | Количество фрагментов |
| Основная задача | Трансформация геометрии | Расчёт цвета пикселя |
| Вычислительная нагрузка | Сложность геометрии | Разрешение экрана |
| Доступ к текстурам | Ограничен (через texture lookup) | Полный доступ |
Ключевое отличие — частота вызовов. Vertex Shader вызывается один раз на вершину, тогда как Fragment Shader — для каждого фрагмента (пикселя). В сцене с высоким разрешением количество вызовов Fragment Shader превышает количество вызовов Vertex Shader в тысячи раз, что делает оптимизацию пиксельных шейдеров ещё более критичной.
Производительность Vertex Shader критически важна для приложений реального времени, особенно в мобильной разработке с ограниченным энергопотреблением. Основные факторы производительности — количество вершин, сложность шейдерного кода и пропускная способность памяти GPU.
Для снижения нагрузки на Vertex Shader применяются следующие подходы. Level of Detail (LOD) — переключение на упрощённые версии моделей при удалении камеры от объекта. Instancing — многократная отрисовка одной геометрии с разными матрицами трансформации за один вызов отрисовки (draw call).
// Vertex Shader with instancing support
in vec3 aPosition;
in mat4 aInstanceMatrix;
uniform mat4 uViewProjection;
void main() {
vec4 worldPos = aInstanceMatrix * vec4(aPosition, 1.0);
gl_Position = uViewProjection * worldPos;
}
Vertex Shader на разных графических API имеет схожую логику, но различный синтаксис и соглашения о именовании. Рассмотрим реализацию базового вершинного шейдера на GLSL для OpenGL ES 3.0 и на Metal Shading Language для iOS и macOS.
#version 300 es
in vec4 position;
in vec3 normal;
in vec2 texcoord;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat3 normalMatrix;
out vec3 vNormal;
out vec2 vTexCoord;
out vec3 vPosition;
void main() {
vec4 mvPosition = modelViewMatrix * position;
vPosition = mvPosition.xyz;
vNormal = normalMatrix * normal;
vTexCoord = texcoord;
gl_Position = projectionMatrix * mvPosition;
}
#include <metal_stdlib>
using namespace metal;
struct VertexIn {
float3 position [[attribute(0)]];
float3 normal [[attribute(1)]];
};
struct VertexOut {
float4 position [[position]];
float3 worldNormal;
};
vertex VertexOut
vertexMain(VertexIn in [[stage_in]],
constant float4x4& mvp [[buffer(1)]]) {
VertexOut out;
out.position = mvp * float4(in.position, 1.0);
out.worldNormal = in.normal;
return out;
}
Часто задаваемые вопросы
Vertex Shader — это программа на GPU, обрабатывающая каждую вершину 3D-модели и преобразующая её координаты в экранные координаты. Представьте модель как сетку из точек; вершинный шейдер перемещает эти точки согласно заданным математическим правилам.
Vertex Shader обрабатывает вершины и отвечает за геометрию, а Fragment Shader определяет цвет каждого пикселя. Первый вызывается для каждой вершины (тысячи), второй — для каждого пикселя (миллионы).
Vertex Shader пишется на языке, соответствующем графическому API: GLSL для OpenGL ES, Metal Shading Language для Metal API на iOS/macOS, HLSL для Direct3D. Концептуально все они выполняют одинаковые операции над вершинами.
Сложность вершинного шейдера напрямую влияет на FPS: больше инструкций на вершину = дольше обработка. Оптимизация включает уменьшение числа вершин через LOD, использование инстансинга и минимизацию условных переходов в коде шейдера.
Основные игровые задачи: трансформация координат через MVP-матрицы, скининг анимированных персонажей, процедурная деформация одежды и волос, морфинг между выражениями лица и эффекты частиц с анимацией на GPU.
Итоги
Мы разработаем мобильное приложение под ключ
IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.
Читайте также