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, шумови измествания на базата на Перлинов шум и ефекти на вълни във вода — всички тези ефекти се реализират във вертекс шейдъра без презареждане на геометрията от RAM.
Въпреки че и двата типа шейдъри са програмируеми етапи на графичния конвейер, 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 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също