Довідник · GLSL ES 3.0 · WebGL 2

Шпаргалка з шейдерів GLSL

Типи, вбудовані функції, уніформи, кваліфікатори точності та поширені патерни шейдерів для шейдерів WebGL 2 / Three.js.

Типи та конструктори

Тип Опис Приклад конструктора
bool Булеве значення bool b = true;
int 32-бітне знакове ціле int n = 42;
uint ES 3.0 32-бітне беззнакове ціле uint u = 0xFFu;
float 32-бітне число з рухомою комою float f = 1.0;
vec2 / vec3 / vec4 Вектор float (2/3/4 компоненти) vec3 v = vec3(1.0, 0.5, 0.0);
ivec2 / ivec3 / ivec4 Цілочисловий вектор ivec2 uv = ivec2(x, y);
uvec2 / uvec3 / uvec4 ES 3.0 Беззнаковий цілочисловий вектор uvec4 c = uvec4(255u);
mat2 / mat3 / mat4 Матриця float (по стовпцях) mat4 m = mat4(1.0); // одинична
sampler2D Семплер 2D-текстури uniform sampler2D uTex;
sampler3D ES 3.0 Семплер 3D-текстури uniform sampler3D uVol;
samplerCube Семплер кубічної карти uniform samplerCube uEnv;

Свізлінг

До компонентів можна звертатися через .xyzw, .rgba або .stpq — у будь-якому порядку та кількості:

GLSL
vec4 col = vec4(1.0, 0.5, 0.2, 1.0);
vec3 rgb = col.rgb;      // (1.0, 0.5, 0.2)
vec2 br  = col.bra.xy;   // (0.2, 1.0)
col.yz   = vec2(0.0);    // встановити g і b у 0

Кваліфікатори точності

Кваліфікатор Діапазон float (приблизно) Коли використовувати
lowp −2 … 2, ~8 біт Кольори, нормалізовані кольори, сильно оптимізовані мобільні
mediump −2¹⁴ … 2¹⁴, ~10 біт Більшість UV текстур, просте освітлення
highp −2⁶² … 2⁶², ~24 біти Світові координати, час, глибина, дані симуляції
GLSLТипова преамбула
#version 300 es
precision highp float;
precision highp int;
precision highp sampler2D;
Примітка: Фрагментні шейдери не мають типової точності float у GLSL ES — завжди оголошуйте precision mediump float; (або highp) на початку.

Вбудовані функції

Тригонометричні

Функція Повертає
sin(x), cos(x), tan(x) Покомпонентна тригонометрія
asin(x), acos(x), atan(y,x) Обернена тригонометрія; atan(y,x) повертає кут у (−π, π]
radians(deg), degrees(rad) Перетворення одиниць

Математика та інтерполяція

Функція Повертає
abs(x) Абсолютне значення покомпонентно
floor(x), ceil(x), round(x) Підлога / стеля / округлення
fract(x) x − floor(x) — дробова частина
mod(x, y) Залишок від ділення float; x − y·floor(x/y)
min(x,y), max(x,y) Покомпонентні мінімум/максимум
clamp(x, lo, hi) Обмеження x до [lo, hi]
mix(a, b, t) Лінійна інтерполяція: a·(1−t) + b·t
step(edge, x) 0, якщо x < edge, інакше 1
smoothstep(lo, hi, x) Кубіка Ерміта: 3t²−2t³ в [lo,hi]
pow(x, y), exp(x), log(x) Експоненційні
sqrt(x), inversesqrt(x) Квадратний корінь; 1/√x швидке обернене
sign(x) −1, 0 або +1

Вектори та геометрія

Функція Повертає
length(v) Евклідова довжина √(x²+y²+…)
distance(a, b) length(a−b)
dot(a, b) Скаляр скалярного добутку
cross(a, b) Векторний добуток vec3
normalize(v) Одиничний вектор: v / length(v)
reflect(I, N) Відбиття падаючого I відносно нормалі N
refract(I, N, eta) Заломлення за законом Снеліуса; eta = n₁/n₂
faceforward(N, I, Nref) Повертає N, орієнтований у бік від I

Семплінг текстур

Функція Повертає
texture(sampler, uv) Уніфікований виклик семплера GLSL ES 3.0 (замінює texture2D)
textureLod(sampler, uv, lod) Вибірка на явному рівні мипу
textureOffset(s, uv, off) Вибірка зі сталим зсувом текселя
texelFetch(s, iuv, lod) ES 3.0 Отримання точного текселя за цілими координатами — без фільтрації
textureSize(s, lod) ES 3.0 Повертає розміри текстури як ivec2 на рівні мипу

Поширені уніформи (Three.js)

Назва уніформи Тип Значення
uTime float Минулі секунди від старту — передавайте clock.getElapsedTime()
uResolution vec2 Розмір в’юпорта у фізичних пікселях: new THREE.Vector2(w * dpr, h * dpr)
uMouse vec2 Нормалізована позиція миші (0–1)²
projectionMatrix mat4 Автоматично надається Three.js
modelViewMatrix mat4 Автоматично надається Three.js
normalMatrix mat3 Автоматично надається Three.js (обернена транспонована MV)
Уніформи ShaderMaterial: Передавайте власні уніформи через new THREE.ShaderMaterial({ uniforms: { uTime: { value: 0 } } }) та оновлюйте їх у циклі анімації за допомогою material.uniforms.uTime.value = t.

Вершинний шейдер

Отримує атрибути для кожної вершини, перетворює позицію у простір відсікання, обчислює варіанти (varyings) для фрагментного етапу.

GLSLВершинний шейдер (ES 3.0)
#version 300 es
precision highp float;

// Вбудовані атрибути Three.js
in vec3 position;    // позиція в просторі моделі
in vec3 normal;      // нормаль у просторі моделі
in vec2 uv;          // UV-координата

// Вбудовані уніформи Three.js (надаються автоматично)
uniform mat4 projectionMatrix;
uniform mat4 modelViewMatrix;
uniform mat3 normalMatrix;

// Власні уніформи
uniform float uTime;

// Varyings — передаються у фрагментний шейдер
out vec2 vUv;
out vec3 vNormal;
out vec3 vWorldPos;

void main() {
  vUv = uv;
  vNormal = normalize(normalMatrix * normal);

  vec3 pos = position;
  // Анімація: зміщуємо y синусоїдою
  pos.y += sin(pos.x * 3.0 + uTime) * 0.1;

  vec4 worldPos = modelViewMatrix * vec4(pos, 1.0);
  vWorldPos = worldPos.xyz;

  gl_Position = projectionMatrix * worldPos;
}

Фрагментний шейдер

Отримує інтерпольовані varyings, виконує вибірку з текстур, обчислює вихідний колір пікселя.

GLSLФрагментний шейдер (ES 3.0)
#version 300 es
precision highp float;

uniform sampler2D uTexture;
uniform float uTime;

in vec2  vUv;
in vec3  vNormal;
in vec3  vWorldPos;

out vec4 fragColor;   // замінює gl_FragColor в ES 3.0

void main() {
  // Базовий колір із текстури
  vec4 albedo = texture(uTexture, vUv);

  // Просте дифузне освітлення
  vec3  lightDir = normalize(vec3(1.0, 2.0, 1.5));
  float diff     = max(dot(vNormal, lightDir), 0.0);
  vec3  lit      = albedo.rgb * (0.2 + 0.8 * diff);

  // Френелівське крайове сяйво
  vec3  viewDir  = normalize(-vWorldPos);
  float fresnel  = pow(1.0 - dot(viewDir, vNormal), 3.0);
  vec3  rim      = mix(vec3(0.0), vec3(0.4, 0.6, 1.0), fresnel);

  fragColor = vec4(lit + rim, albedo.a);
}

Патерни шейдерів

Хеш / Шум

GLSL
// Простий 2D-хеш → псевдовипадковий float у [0,1]
float hash21(vec2 p) {
  p = fract(p * vec2(127.1, 311.7));
  p += dot(p, p + 19.19);
  return fract(p.x * p.y);
}

// Value noise: плавний, один виклик без текстур
float noise(vec2 p) {
  vec2 i = floor(p), f = fract(p);
  vec2 u = f * f * (3.0 - 2.0 * f); // smoothstep
  return mix(
    mix(hash21(i),           hash21(i + vec2(1,0)), u.x),
    mix(hash21(i + vec2(0,1)), hash21(i + vec2(1,1)), u.x), u.y
  );
}

Поле знакових відстаней (SDF)

GLSL
// Примітиви SDF (2D)
float sdCircle(vec2 p, float r)       { return length(p) - r; }
float sdBox(vec2 p, vec2 b)           { vec2 d = abs(p)-b; return length(max(d,0.))+min(max(d.x,d.y),0.); }
float sdSegment(vec2 p,vec2 a,vec2 b) { vec2 pa = p-a, ba = b-a; float h = clamp(dot(pa,ba)/dot(ba,ba),0.,1.); return length(pa-ba*h); }

// Плавне булеве об’єднання (k керує радіусом злиття)
float smin(float a, float b, float k) {
  float h = clamp(0.5 + 0.5*(b-a)/k, 0., 1.);
  return mix(b, a, h) - k*h*(1.-h);
}

Ping-pong (обмін текстур симуляції)

JavaScript (Three.js)
const opts = { width: N, height: N, type: THREE.FloatType };
const rtA  = new THREE.WebGLRenderTarget(N, N, opts);
const rtB  = new THREE.WebGLRenderTarget(N, N, opts);
let ping = rtA, pong = rtB;

// Кожен кадр: рендеримо в pong, читаючи з ping
simMaterial.uniforms.uState.value = ping.texture;
renderer.setRenderTarget(pong);
renderer.render(simScene, simCamera);
renderer.setRenderTarget(null);
[ping, pong] = [pong, ping]; // обмін

Пакування Float ↔ RGBA

GLSL
// Пакуємо float [0,1] у 4 байти (RGBA8) — корисно для
// зберігання стану симуляції у 8-бітних текстурах без OES_texture_float
vec4 packFloat(float v) {
  vec4 enc = vec4(1.0, 255.0, 65025.0, 16581375.0) * v;
  enc = fract(enc);
  enc -= enc.yzww * vec4(1.0/255.0, 1.0/255.0, 1.0/255.0, 0.0);
  return enc;
}

// Розпаковуємо RGBA8 назад у float [0,1]
float unpackFloat(vec4 rgba) {
  return dot(rgba, vec4(1.0, 1.0/255.0, 1.0/65025.0, 1.0/16581375.0));
}

Поширені допоміжні сніпети GLSL

GLSL
// Перевідображення [a,b] → [c,d]
float remap(float x, float a, float b, float c, float d) {
  return c + (d - c) * ((x - a) / (b - a));
}

// Матриця обертання 2D
mat2 rot2(float a) { float c = cos(a), s = sin(a); return mat2(c,-s,s,c); }

// Яскравість (сприйнята світність)
float luma(vec3 rgb) { return dot(rgb, vec3(0.2126, 0.7152, 0.0722)); }

// sRGB ↔ лінійний
vec3 toLinear(vec3 c)  { return pow(c, vec3(2.2)); }
vec3 toSRGB(vec3 c)    { return pow(c, vec3(1.0/2.2)); }