Vertex Shader — це програмований етап графічного конвеєра (graphics pipeline), який обробляє кожну вершину тривимірної моделі незалежно. За даними Khronos Group, 2025, вершинний шейдер приймає на вхід атрибути вершин — координати, нормалі, колір і текстурні координати — і перетворює їх згідно із заданою логікою. Vertex Shader виконується для кожної вершини незалежно, що дозволяє ефективно розпаралелювати обчислення на тисячах ядер GPU.
Головне
Vertex Shader — це програмований етап графічного конвеєра, який обробляє кожну вершину 3D-моделі окремо. Вершина (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 з підтримкою інстансингу
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 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також