С момента своего появления 3D-графика в браузере стала популярной темой. Но если бы вы создавали свои приложения с использованием простого старого WebGL, это заняло бы очень много времени. Но теперь у нас есть несколько довольно полезных библиотек, которыми мы можем воспользоваться, например Three.js . Итак, в этой серии я покажу вам, как создавать потрясающие трехмерные эффекты для браузера.
Я ожидаю, что у вас будет общее представление о трехмерном пространстве, прежде чем вы начнете читать этот учебник, так как я не буду объяснять такие вещи, как координаты, векторы и т. Д.
подготовка
Мы начнем с кода из предыдущей части этой серии. Также возьмите предоставленные мною ресурсы и поместите их в ту же папку, что и ваше приложение. Теперь, поскольку здесь мы будем использовать изображения, вам придется поместить ваше приложение на некоторый статический сервер (может быть локальный), потому что, если вы не запустите браузер с включенным доступом к файлам из файлов (например, с помощью --allow-file-access-from-files
флаг --allow-file-access-from-files
в Chrome) CORS не позволит вам загрузить их из файла. Это все, что вам нужно сделать, прежде чем продолжить.
Шаг 1: Загрузка текстуры
Если вам когда-нибудь стало так скучно, что вы пошли на создание чего-либо с использованием чистого OpenGL, вы, вероятно, помните, как тяжело загрузить текстуру. К счастью, Three.js поставляется с хорошей функцией, которая будет загружать и настраивать текстуру для нас. Добавьте эту строку перед определением материала нашего куба:
1
|
var cubeTexture = THREE.ImageUtils.loadTexture(‘./box.png’);
|
Это действительно все, что вам нужно сделать, чтобы загрузить текстуру.
В реальном приложении вам нужно будет предварительно загрузить текстуру, как любое обычное изображение, и показать пользователям какую-нибудь необычную полосу загрузки, чтобы сообщить им, что вы загружаете (Three.js будет использовать кэшированное изображение).
Шаг 2: Рисуем куб
Теперь мы применим текстуру к нашему кубу. Это также легко, вам просто нужно заменить определение цвета в материале куба так:
1
|
var cubeMaterial = new THREE.MeshLambertMaterial({ map: cubeTexture });
|
Атрибут map
устанавливает текстуру. Теперь вы можете открыть браузер и увидеть вращающийся текстурированный куб:
Вы также можете раскрасить текстуру, просто добавьте определение color
в настройках материала, например:
1
|
var cubeMaterial = new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0x28c0ec });
|
И теперь куб становится синим:
Таким образом, вы можете иметь несколько разных объектов с одинаковой текстурой, если меняется только цвет.
Шаг 3: несколько материалов
Вы можете установить различные материалы для каждого лица куба. Чтобы достичь этого, вы должны изменить определение всего материала. Сначала определите массив materials
. Каждый элемент в массиве будет соответствовать материалу одного лица. Они идут в следующем порядке: справа, слева, сверху, снизу, спереди и сзади:
1
2
3
4
5
6
7
|
var materials = [];
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0xff0000 }));
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0xffff00 }));
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0xffffff }));
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0x00ffff }));
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0x0000ff }));
materials.push(new THREE.MeshLambertMaterial({ map: cubeTexture, color: 0xff00ff }));
|
Как вы видите, у каждого лица есть свой материал, поэтому вы можете устанавливать различные текстуры, цвета и другие атрибуты для каждого. Затем измените тип материала куба на THREE.MeshFaceMaterial
:
1
|
var cubeMaterial = new THREE.MeshFaceMaterial(materials);
|
Вам нужно только передать массив materials
в качестве параметра. В браузере вы должны увидеть, что каждая сторона куба имеет разный цвет:
Шаг 4: Частицы!
Допустим, вы хотите создать эффект вращающихся снежинок в своем приложении. Если вы будете рендерить каждую снежинку в виде меша, вы получите очень низкий fps. Вот где частицы вступают в игру. Они намного менее сложны, и рисование их как целой системы частиц делает их действительно эффективными.
Начнем с создания геометрии для наших частиц:
1
|
var particles = new THREE.Geometry;
|
THREE.Geometry
— это объект базовой геометрии, без какой-либо формы. Теперь мы должны определить положение каждой частицы в системе. Пусть это будет совершенно случайно:
1
2
3
4
|
for (var p = 0; p < 2000; p++) {
var particle = new THREE.Vector3(Math.random() * 500 — 250, Math.random() * 500 — 250, Math.random() * 500 — 250);
particles.vertices.push(particle);
}
|
Этот цикл создаст 2000 случайно расположенных частиц и поместит их все в геометрию. Далее вы должны определить материал частиц:
1
|
var particleMaterial = new THREE.ParticleBasicMaterial({ color: 0xeeeeee, size: 2 });
|
Обратите внимание, что мы используем THREE.ParticleBasicMaterial
, который предназначен только для частиц. В опциях мы определяем только цвет и размер каждой частицы. Наконец, вы можете создать систему частиц и добавить ее в сцену:
1
2
3
|
var particleSystem = new THREE.ParticleSystem(particles, particleMaterial);
scene.add(particleSystem);
|
Теперь, чтобы сделать сцену лучше, давайте повернем частицы в направлении, противоположном тому, в котором вращается куб (измените функцию render
чтобы она выглядела так):
1
2
3
4
5
6
7
8
9
|
function render() {
requestAnimationFrame(render);
var delta = clock.getDelta();
cube.rotation.y -= delta;
particleSystem.rotation.y += delta;
renderer.render(scene, camera);
}
|
Мы переместили clock.getDelta
в переменную, потому что, если вы будете использовать это так:
1
2
|
cube.rotation.y -= clock.getDelta();
particleSystem.rotation.y += clock.getDelta();
|
Система частиц не будет вращаться, потому что второй вызов вернет число, близкое к нулю (помните, что он получает время от последнего вызова).
Теперь откройте браузер, и вы увидите вращающиеся куб и частицы:
Давайте объединим обе вещи, которые вы изучили в этом уроке, и превратим эти уродливые белые квадраты в настоящие снежинки. Сначала загрузите текстуру снежинки:
1
|
var particleTexture = THREE.ImageUtils.loadTexture(‘./snowflake.png’);
|
Теперь измените материал частиц, чтобы использовать текстуру. Также включите прозрачность и увеличьте размер частиц, чтобы мы могли видеть форму:
1
|
var particleMaterial = new THREE.ParticleBasicMaterial({ map: particleTexture, transparent: true, size: 5 });
|
Если вы откроете браузер, то увидите, что вокруг куба текут красивые снежинки:
Шаг 5: дым
Эффект дыма довольно легко достичь, и он выглядит красиво. Начните с создания геометрии, как со снежинками:
1
2
3
4
5
|
var smokeParticles = new THREE.Geometry;
for (var i = 0; i < 300; i++) {
var particle = new THREE.Vector3(Math.random() * 32 — 16, Math.random() * 230, Math.random() * 32 — 16);
smokeParticles.vertices.push(particle);
}
|
Единственная разница здесь в том, что мы выбираем позицию из прямоугольной призмы с размерами 32x32x230. Теперь давайте загрузим текстуру и определим материал:
1
2
|
var smokeTexture = THREE.ImageUtils.loadTexture(‘./smoke.png’);
var smokeMaterial = new THREE.ParticleBasicMaterial({ map: smokeTexture, transparent: true, blending: THREE.AdditiveBlending, size: 50, color: 0x111111 });
|
В определении материала есть вариант blending
. Он сообщает визуализатору, как он должен отображать один объект на другом. С THREE.AdditiveBlending
перекрывающиеся значения цвета будут добавляться друг к другу, что приведет к более яркому дыму в областях с более высокой плотностью частиц. Мы также установили цвет почти черный, чтобы дым выглядел более естественно.
Наконец, создайте систему частиц, переместите ее немного влево и добавьте к сцене:
1
2
3
4
5
|
var smoke = new THREE.ParticleSystem(smokeParticles, smokeMaterial);
smoke.sortParticles = true;
smoke.position.x = -150;
scene.add(smoke);
|
Вы также должны установить smoke.sortParticles
в true. Когда оно ложно, фон спрайта может быть нарисован черным. Если вы откроете браузер, вы увидите неподвижный столб дыма рядом с кубом:
Чтобы оживить дым, нам нужно пройти через все частицы и немного их поднять. Добавьте этот код в функцию render
:
01
02
03
04
05
06
07
08
09
10
11
12
|
var particleCount = smokeParticles.vertices.length;
while (particleCount—) {
var particle = smokeParticles.vertices[particleCount];
particle.y += delta * 50;
if (particle.y >= 230) {
particle.y = Math.random() * 16;
particle.x = Math.random() * 32 — 16;
particle.z = Math.random() * 32 — 16;
}
}
smokeParticles.__dirtyVertices = true;
|
В цикле мы добавляем delta * 50
к позиции y частицы. Затем мы проверяем, является ли частица выше 230, если это так, мы случайным образом выбираем ее новую позицию где-то в нижней части столба дыма. Наконец, самое важное: установить для флага __dirtyVertices
геометрии __dirtyVertices
true.
Чтобы повысить производительность, Three.js кэширует объекты, чтобы избежать повторного построения всех вызовов WebGL в каждом кадре, поэтому, если мы что-то изменим в геометрии объекта, мы должны сообщить рендереру, что он изменился. По
__dirtyVertices
флаг__dirtyVertices
просто достигнет элемента.
Если вы откроете браузер сейчас, вы должны увидеть плавно анимированный дым рядом с кубом.
Вывод
В этом уроке вы узнали, как использовать текстуры и частицы. Как и раньше, не бойтесь немного поэкспериментировать с вашим приложением. Если у вас есть проблемы, взгляните на документацию . В следующей статье я научу вас, как загружать модели и анимировать их.