ShaderMaterial предоставляет полный контроль над
визуальным представлением объекта, позволяя использовать собственные
GLSL-шейдеры для вершин и фрагментов. В отличие от стандартных
материалов (MeshStandardMaterial,
MeshPhongMaterial и других), где визуальные свойства
ограничены предопределёнными параметрами, ShaderMaterial
открывает доступ к полной графической цепочке рендеринга.
Основные параметры ShaderMaterial:
vertexShader – GLSL-код вершинного шейдера.fragmentShader – GLSL-код фрагментного шейдера.uniforms – объект, содержащий данные, передаваемые
шейдерам.defines – предопределённые макросы для шейдеров.transparent, side, blending –
стандартные свойства материала для контроля прозрачности, сторон и
смешивания.Пример базовой структуры:
const material = new THREE.ShaderMaterial({
vertexShader: `
varying vec3 vPosition;
void main() {
vPosition = position;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
varying vec3 vPosition;
void main() {
gl_FragColor = vec4(vPosition * 0.5 + 0.5, 1.0);
}
`
});
Здесь vPosition передаёт координаты вершин из вершинного
шейдера во фрагментный, что позволяет управлять цветом на основе
положения.
uniforms позволяют передавать динамические данные из
JavaScript в GLSL. Это может быть время, текстуры, векторы, матрицы или
любые другие значения.
Пример:
const uniforms = {
time: { value: 0.0 },
color: { value: new THREE.Color(0xff0000) }
};
const material = new THREE.ShaderMaterial({
uniforms,
vertexShader: vertexShaderCode,
fragmentShader: fragmentShaderCode
});
function animate(deltaTime) {
uniforms.time.value += deltaTime;
}
Особенности uniforms:
float, vec2,
vec3, vec4, mat3,
mat4, sampler2D и другие.Взаимодействие между вершинным и фрагментным шейдерами осуществляется
через varying переменные. Они автоматически интерполируются
для каждого фрагмента. Пример передачи нормалей и UV-координат:
// Вершинный шейдер
varying vec3 vNormal;
varying vec2 vUv;
void main() {
vNormal = normalMatrix * normal;
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
// Фрагментный шейдер
varying vec3 vNormal;
varying vec2 vUv;
void main() {
float intensity = dot(normalize(vNormal), vec3(0.0, 0.0, 1.0));
gl_FragColor = vec4(vUv, intensity, 1.0);
}
Интерполяция varying позволяет создавать плавные
переходы цветов, освещения или эффектов по поверхности модели.
ShaderMaterial поддерживает любые текстуры через
uniforms типа sampler2D. Для этого создаётся uniform с
текстурой и передаётся в GLSL:
const texture = new THREE.TextureLoader().load('texture.jpg');
const material = new THREE.ShaderMaterial({
uniforms: {
uTexture: { value: texture }
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform sampler2D uTexture;
varying vec2 vUv;
void main() {
gl_FragColor = texture2D(uTexture, vUv);
}
`
});
Поддерживаются прозрачные текстуры и альфа-каналы при
transparent: true. Можно комбинировать несколько текстур с
помощью разных uniforms.
Для создания динамических эффектов часто используют uniform
time. Это позволяет реализовать пульсации, смещения, волны
и другие эффекты без изменения геометрии:
uniforms: {
time: { value: 0.0 }
},
fragmentShader: `
uniform float time;
varying vec2 vUv;
void main() {
float wave = sin(vUv.x * 10.0 + time) * 0.5 + 0.5;
gl_FragColor = vec4(vec3(wave), 1.0);
}
`
В JavaScript-анимации:
function animate(deltaTime) {
uniforms.time.value += deltaTime;
renderer.render(scene, camera);
requestAnimationFrame(animate);
}
ShaderMaterial поддерживает:
transparent: true и
управление альфа-каналом через gl_FragColor.a.side: THREE.DoubleSide.blending: THREE.AdditiveBlending или другие режимы для
эффектов свечения.Пример создания полупрозрачного материала с двойной стороной:
const material = new THREE.ShaderMaterial({
vertexShader: vertexShaderCode,
fragmentShader: fragmentShaderCode,
transparent: true,
side: THREE.DoubleSide
});
defines и макросовdefines позволяет внедрять макросы на этапе компиляции
GLSL, что упрощает условные конструкции и конфигурацию шейдера:
const material = new THREE.ShaderMaterial({
defines: {
USE_WAVE: true
},
vertexShader: `
#ifdef USE_WAVE
uniform float time;
#endif
void main() {
vec3 pos = position;
#ifdef USE_WAVE
pos.y += sin(position.x * 5.0 + time);
#endif
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
`,
fragmentShader: fragmentShaderCode
});
Макросы позволяют отключать или включать сложные эффекты без изменения основной логики шейдера.
Для больших сцен и сложных эффектов важно:
material.needsUpdate = true при изменении кода.precision и простые математические функции
для улучшения производительности.sampler2D и mix.ShaderMaterial является ключевым инструментом для
создания уникальных визуальных эффектов, полного контроля над
рендерингом и реализации GPU-вычислений в Three.js.