Язык GLSL: типы и функции
GLSL — язык шейдеров, похожий на C, но со встроенными векторами, матрицами и быстрыми графическими функциями.
GLSL (OpenGL Shading Language) — язык, на котором пишут вершинные и фрагментные шейдеры; в нём векторы и матрицы — встроенные типы.
Зачем это знать
В графике вектор из 3–4 чисел — повсюду: позиция, цвет, нормаль. GLSL делает работу с ними естественной: сложение векторов, скалярное и векторное произведение, нормализация — встроены и считаются аппаратно. Знание типов и квалификаторов — это азбука написания шейдеров.
Векторные и матричные типы
| Тип | Что это |
float | число с плавающей точкой |
vec2/vec3/vec4 | вектор из 2/3/4 float |
mat3/mat4 | матрица 3×3 / 4×4 |
sampler2D | дескриптор текстуры |
У вектора компоненты доступны как .x .y .z .w или как цвет .r .g .b .a. Можно «тасовать» их — это swizzling: color.rgb, pos.xy, v.xxy.
Квалификаторы каналов данных
| Квалификатор | Назначение |
attribute (in) | данные на вершину: позиция, нормаль, UV |
uniform | одинаков для всех вершин/пикселей вызова: матрицы, время, текстуры |
varying (out/in) | из вершинного во фрагментный, интерполируется |
Встроенные функции — на Python-аналогах
Чтобы прочувствовать встроенные функции GLSL, воспроизведём три из них на stdlib Python: clamp, mix, step.
def clamp(x, lo, hi):
return max(lo, min(x, hi))
def mix(a, b, t):
return a + (b - a) * t
def step(edge, x):
return 0.0 if x < edge else 1.0
print("clamp(1.5, 0, 1):", clamp(1.5, 0, 1))
print("clamp(-0.2, 0, 1):", clamp(-0.2, 0, 1))
print("mix(0, 10, 0.3):", mix(0, 10, 0.3))
print("step(0.5, 0.4):", step(0.5, 0.4))
print("step(0.5, 0.6):", step(0.5, 0.6))
Вывод:
clamp(1.5, 0, 1): 1 clamp(-0.2, 0, 1): 0 mix(0, 10, 0.3): 3.0 step(0.5, 0.4): 0.0 step(0.5, 0.6): 1.0
clamp зажимает значение в диапазон, mix смешивает, step даёт резкую границу 0/1 — это рабочие лошадки шейдеров для эффектов и масок.
Маленький осмысленный GLSL
precision mediump float;
uniform float uTime; // время, обновляется каждый кадр
varying vec2 vUV;
void main() {
float pulse = 0.5 + 0.5 * sin(uTime); // 0..1, пульсирует
vec3 base = vec3(vUV, 0.5); // цвет из координат
vec3 col = mix(base, vec3(1.0), pulse); // мигание к белому
gl_FragColor = vec4(col, 1.0);
}
Как работает под капотом
Векторные операции GLSL покомпонентны: a + b для vec3 складывает по координатам, a * b — тоже покомпонентно (а не скалярное произведение — для него есть dot). GPU исполняет такие операции над всеми компонентами параллельно одной инструкцией. Swizzling бесплатен — это просто переадресация компонент.
Частые ошибки
- Думать, что
vec3 * vec3— скалярное произведение; это покомпонентное умножение, dot — отдельно. - Менять uniform «на каждый пиксель» — uniform постоянен в пределах вызова отрисовки.
- Забывать
precisionво фрагментном шейдере на мобильных GPU (WebGL) — ошибка компиляции.
Итоги
- GLSL: встроенные vec2/3/4, mat3/4, swizzling (.rgb, .xy).
- attribute — на вершину, uniform — на вызов, varying — интерполируется.
- clamp, mix, step, dot, normalize — базовые встроенные функции.
- Операции над векторами покомпонентны; dot — отдельная функция.