ShaderMaterial дає повний контроль над вершинними та
фрагментними шейдерами GLSL, зберігаючи при цьому граф сцени, матриці та
обробку геометрії Three.js. Цей урок охоплює весь робочий процес:
uniform-змінні, varying-змінні, семплювання текстур, процедурні візерунки
та анімовані ефекти.
1Мінімальний каркас ShaderMaterial
import * as THREE from
'https://cdn.jsdelivr.net/npm/three@0.160/build/three.module.js';
const mat = new THREE.ShaderMaterial({ vertexShader: /* glsl */ ` void
main() { // modelViewMatrix, projectionMatrix, position вставляє
Three.js gl_Position = projectionMatrix * modelViewMatrix *
vec4(position, 1.0); } `, fragmentShader: /* glsl */ ` void main() {
gl_FragColor = vec4(0.13, 0.77, 0.37, 1.0); // суцільний зелений } `, });
const mesh = new THREE.Mesh(new THREE.SphereGeometry(1, 64, 32), mat);
scene.add(mesh);
Three.js автоматично додає на початок шейдерів
ShaderMaterial оголошення projectionMatrix,
modelViewMatrix, normalMatrix,
position, normal, uv та
uv2. RawShaderMaterial цього не робить (усе
оголошуєте ви самі).
// Підключаємо допоміжні функції GLSL hash + value noise; зовнішня
текстура не потрібна const noiseFrag = /* glsl */ ` precision highp float; varying
vec2 vUv; uniform float u_time; float hash(vec2 p) { p = fract(p *
vec2(234.34, 435.345)); p += dot(p, p + 34.23); return fract(p.x *
p.y); } float noise(vec2 p) { vec2 i = floor(p), f = fract(p); vec2 u
= f * f * (3.0 - 2.0 * f); return mix(mix(hash(i + vec2(0,0)), hash(i
+ vec2(1,0)), u.x), mix(hash(i + vec2(0,1)), hash(i + vec2(1,1)),
u.x), u.y); } float fbm(vec2 p) { float v = 0.0, a = 0.5; for (int i =
0; i < 5; i++) { v += noise(p) * a; p *= 2.1; a *= 0.5; } return v;
} void main() { float n = fbm(vUv * 4.0 + u_time * 0.3); vec3 col =
mix(vec3(0.05, 0.1, 0.2), vec3(0.1, 0.8, 0.5), n); gl_FragColor =
vec4(col, 1.0); } `;
6ShaderMaterial проти RawShaderMaterial
// ShaderMaterial автоматично вставляє: // - Вбудовані uniform-змінні:
modelMatrix, viewMatrix, projectionMatrix, // modelViewMatrix,
normalMatrix, cameraPosition // - Вбудовані атрибути: position,
normal, uv, tangent, color // - директиви #define для світла, якщо
lights:true const mat = new THREE.ShaderMaterial({ lights: true, //
вставляє define THREE_MAX_LIGHTS та uniform-змінні світла fog: true, //
вставляє uniform-змінні туману u_fogColor, u_fogNear, u_fogFar depthWrite: true,
transparent: false, // ShaderMaterial може поєднувати фрагменти Three.js через
#include <common> тощо }); // RawShaderMaterial: БЕЗ автоматичних
вставок // Ви маєте самі оголосити precision, усі uniform-змінні та всі
атрибути. // Використовуйте, коли потрібен найменший можливий шейдер
без накладних витрат. const rawMat = new THREE.RawShaderMaterial({
vertexShader: ` precision highp float; attribute vec3 position;
uniform mat4 projectionMatrix; uniform mat4 modelViewMatrix; void
main() { gl_Position = projectionMatrix * modelViewMatrix *
vec4(position, 1.0); } `, fragmentShader: ` precision highp float;
void main() { gl_FragColor = vec4(1.0, 0.5, 0.0, 1.0); } `, });
Налагоджуючи шейдер, додайте
console.log(mat.vertexShader) — Three.js покаже кінцевий
вихідний код шейдера, зокрема весь вставлений код, що полегшує
розуміння того, що саме компілюється.
Часті запитання
Чого я навчуся в цьому уроці?
Напишіть повністю власний вершинний і фрагментний шейдер GLSL у Three.js за допомогою ShaderMaterial — uniform-змінні, varying-змінні, семплювання текстур та ефекти на основі шуму.
Які теми розглядаються в цьому уроці?
Цей урок охоплює такі теми: Мінімальний каркас ShaderMaterial, Uniform-змінні та їх оновлення, Varying-змінні: передача даних вершина → фрагмент, Семплювання текстур, Процедурний візерунок із шуму, Розширення ShaderMaterial проти RawShaderMaterial.
Які інструменти й технології використовуються?
Цей урок використовує: Three.js, GLSL, ShaderMaterial, Uniform-змінні.