A-Frame предоставляет возможность создавать кастомные шейдеры с
использованием GLSL (OpenGL Shading Language), что позволяет управлять
визуальными эффектами на уровне вершин и фрагментов. Шейдеры в A-Frame
реализуются через компонент shader и систему
registerShader, которая связывает GLSL-код с сущностью.
Каждый шейдер состоит из двух частей: вершинного
шейдера (vertex shader) и фрагментного
шейдера (fragment shader). Вершинный шейдер
отвечает за позиционирование вершин объекта, а фрагментный — за цвет и
текстуру пикселей. В A-Frame доступны стандартные атрибуты, такие как
position, normal, uv, а также
uniform-переменные для передачи данных из JavaScript.
AFRAME.registerShader('custom-shader', {
schema: {
color: {type: 'color', default: '#FFF'},
time: {type: 'time', is: 'uniform'}
},
vertexShader: `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
}
`,
fragmentShader: `
uniform vec3 color;
uniform float time;
varying vec2 vUv;
void main() {
gl_FragColor = vec4(abs(sin(time + vUv.x)), 0.0, 0.0, 1.0);
}
`
});
schema и uniform-переменныеСвойство schema описывает все данные, которые можно
передавать шейдеру извне. Каждый параметр автоматически становится
uniform-переменной в GLSL. Типы данных могут быть
простыми (color, number, vec3)
или специализированными (map для текстур,
texture). Uniform-переменные обновляются каждый кадр, что
позволяет создавать анимации и интерактивные эффекты.
schema: {
color: {type: 'color', default: '#FF0000'},
intensity: {type: 'number', default: 1.0}
}
В GLSL они доступны как обычные переменные:
uniform vec3 color;
uniform float intensity;
Вершинные атрибуты — это данные, связанные с геометрией модели. Наиболее часто используются:
position — координаты вершиныnormal — нормаль вершиныuv — координаты текстурыЭти атрибуты передаются в vertex shader автоматически. Для создания анимаций можно модифицировать позицию вершин с помощью тригонометрических функций или шума:
void main() {
vec3 newPosition = position + normal * sin(time + position.x);
gl_Position = projectionMatrix * modelViewMatrix * vec4(newPosition, 1.0);
}
Для работы с изображениями используется тип map.
Текстура передаётся в шейдер как uniform-переменная типа
sampler2D. Координаты uv позволяют правильно
наложить текстуру на геометрию. В фрагментном шейдере текстуру можно
смешивать с цветом:
uniform sampler2D map;
varying vec2 vUv;
uniform vec3 color;
void main() {
vec4 texColor = texture2D(map, vUv);
gl_FragColor = vec4(texColor.rgb * color, texColor.a);
}
A-Frame автоматически передает uniform-переменную time в
миллисекундах. Она удобна для создания динамических эффектов, таких как
пульсация, волны или вращение:
float wave = sin(vUv.x * 10.0 + time * 0.001);
gl_FragColor = vec4(vec3(wave), 1.0);
Для интерактивности можно передавать значения через компоненты A-Frame, например, позицию контроллера, расстояние до камеры или события клика.
Vertex Shader: отвечает за преобразование вершин и геометрию. Здесь можно добавлять эффекты деформации, анимации поверхности, сдвиги текстуры и вращение.
Fragment Shader: работает на уровне пикселя. Здесь создаются эффекты освещения, смешивания цветов, наложения текстур, прозрачность и другие визуальные детали.
Пример комбинированного эффекта:
// Vertex Shader
varying vec2 vUv;
varying vec3 vNormal;
void main() {
vUv = uv;
vNormal = normal;
vec3 pos = position + normal * sin(time + position.x);
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
}
// Fragment Shader
uniform vec3 color;
varying vec2 vUv;
varying vec3 vNormal;
void main() {
float light = dot(normalize(vNormal), vec3(0.0, 1.0, 0.0));
gl_FragColor = vec4(color * light * abs(sin(time)), 1.0);
}
varying вместо повторного
вычисления: передача данных из vertex shader в fragment shader
экономит ресурсы..jpg или .png с
power-of-two размером) для уменьшения памяти GPU.uv с математическими функциями.После регистрации шейдера его можно применять к любой сущности с
компонентом material:
<a-box shader="custom-shader" color="#00FF00" position="0 1 -3"></a-box>
<a-sphere shader="custom-shader" color="#FF0000" position="2 1 -3"></a-sphere>
В этом случае все uniform-переменные шейдера будут доступны для динамического изменения через Jav * aScript:
document.querySelector('a-box').setAttribute('material', 'color', '#0000FF');
Использование кастомных GLSL-шейдеров в A-Frame открывает полное управление визуальной частью сцены, позволяет создавать уникальные эффекты и расширяет стандартные возможности движка WebVR.