Типи та конструктори
| Тип | Опис | Приклад конструктора |
|---|---|---|
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 — у будь-якому порядку та
кількості:
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 біти | Світові координати, час, глибина, дані симуляції |
#version 300 es
precision highp float;
precision highp int;
precision highp sampler2D;
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) |
new THREE.ShaderMaterial({ uniforms: { uTime: { value: 0 } }
})
та оновлюйте їх у циклі анімації за допомогою
material.uniforms.uTime.value = t.
Вершинний шейдер
Отримує атрибути для кожної вершини, перетворює позицію у простір відсікання, обчислює варіанти (varyings) для фрагментного етапу.
#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, виконує вибірку з текстур, обчислює вихідний колір пікселя.
#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);
}
Патерни шейдерів
Хеш / Шум
// Простий 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)
// Примітиви 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 (обмін текстур симуляції)
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
// Пакуємо 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
// Перевідображення [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)); }