Начало работы с Three.js

Введение

Для некоторых своих экспериментов я использовал Three.js , и он действительно отлично справляется с задачей абстрагирования головной боли, связанной с работой с 3D в браузере. С его помощью вы можете создавать камеры, объекты, источники света, материалы и многое другое, а также у вас есть выбор средства рендеринга, что означает, что вы можете решить, хотите ли вы, чтобы ваша сцена была нарисована с использованием холста HTML 5, WebGL или SVG. А поскольку исходный код открыт, вы даже можете принять участие в проекте. Но сейчас я сосредоточусь на том, чему научился, играя с ним в качестве движка, и расскажу вам о некоторых основах.

Несмотря на все великолепие Three.js, бывают моменты, когда у вас могут возникнуть трудности. Обычно вам придется потратить довольно много времени на примеры, реверс-инжиниринг и (в моем случае, конечно) поиск конкретной функциональности и время от времени задавать вопросы через GitHub . Кстати, если у вас возникнут вопросы, я обнаружил, что Mr. Doob и AlteredQualia чрезвычайно полезны!

1. Основы

Я предполагаю, что у вас есть хотя бы поверхностные знания 3D и достаточное знание JavaScript. Если вы этого не сделаете, возможно, стоит немного поучиться, прежде чем пытаться поиграть с этим материалом, поскольку это может немного сбить с толку.

В нашем 3D-мире у нас будет следующее, и я проведу вас через процесс создания:

  1. Сцена
  2. Рендерер
  3. Камера
  4. Один или два объекта (с материалами)

Вы, конечно, можете сделать несколько интересных вещей, и я надеюсь, что вы продолжите это делать и начнете экспериментировать с 3D в своем браузере.

2. Поддержка

Просто небольшое замечание о поддержке в браузерах. По моему опыту, браузер Chrome от Google — лучший браузер для работы с точки зрения поддерживаемых средств визуализации и скорости базового движка JavaScript. Chrome поддерживает Canvas, WebGL и SVG и работает невероятно быстро. Firefox занимает второе место с появлением версии 4. Его движок JavaScript кажется немного медленнее, чем у Chrome, но опять же, поддержка технологий рендеринга у него великолепна. Opera и Safari находятся в процессе добавления поддержки WebGL, но их текущие версии поддерживают только холст. Internet Explorer (версия 9+) поддерживает только рендеринг холста, и я ничего не слышал о планах Microsoft добавить возможности WebGL.

3. Установите сцену

Я предполагаю, что вы выбрали браузер, который поддерживает все технологии рендеринга, и хотите выполнять рендеринг с помощью Canvas или WebGL, поскольку они являются более стандартными вариантами. Canvas поддерживается более широко, чем WebGL, но стоит отметить, что WebGL работает на графическом процессоре вашей видеокарты, а это означает, что ваш процессор может сосредоточиться на других задачах, не связанных с рендерингом, таких как любая физика или взаимодействие с пользователем, которые вы пытаетесь выполнить.

Независимо от выбранного вами средства визуализации, вы должны иметь в виду, что JavaScript необходимо оптимизировать для повышения производительности. 3D — непростая задача для браузера (и здорово, что это вообще возможно), поэтому будьте осторожны, чтобы понять, где в вашем коде есть узкие места, и устраните их, если сможете!

Итак, с учетом вышесказанного, и если предположить , что вы загрузили и включили Three.js в свой HTML-файл, как вы настроите сцену? Так:

// set the scene size
var WIDTH = 400,
HEIGHT = 300;

// set some camera attributes
var VIEW_ANGLE = 45,
ASPECT = WIDTH / HEIGHT,
NEAR = 0.1,
FAR = 10000;

// get the DOM element to attach to
// - assume we've got jQuery to hand
var $container = $('#container');

// create a WebGL renderer, camera
// and a scene
var renderer = new THREE.WebGLRenderer();
var camera = new THREE.PerspectiveCamera(
                VIEW_ANGLE,
                ASPECT,
                NEAR,
                FAR );

var scene = new THREE.Scene();

// the camera starts at 0,0,0 so pull it back
camera.position.z = 300;

// start the renderer
renderer.setSize(WIDTH, HEIGHT);

// attach the render-supplied DOM element
$container.append(renderer.domElement);

Не так уж и сложно, правда!

4. Создание сетки

Итак, у нас есть сцена, камера и средство рендеринга (в примере кода я выбрал WebGL), но на самом деле нам нечего рисовать. Three.js на самом деле поддерживает загрузку нескольких различных стандартных типов файлов, что отлично подходит, если вы выводите модели из Blender, Maya, Cinema4D или чего-либо еще. Для простоты (в конце концов, речь идет о начале работы!) Я расскажу о примитивах. Примитивы — это геометрические сетки, относительно простые, такие как сферы, плоскости, кубы и цилиндры. Three.js позволяет легко создавать примитивы следующих типов:

// set up the sphere vars
var radius = 50, segments = 16, rings = 16;

// create a new mesh with sphere geometry -
// we will cover the sphereMaterial next!
var sphere = new THREE.Mesh(
new THREE.SphereGeometry(radius,
segments,
rings),

sphereMaterial);

// add the sphere to the scene
scene.add(sphere);

Все хорошо, а как насчет материала для сферы? В коде мы использовали переменнуюSphereMaterial , но еще не определили ее. Сначала нужно поговорить о материалах немного подробнее.

5. Материалы

Без сомнения, это одна из самых полезных частей Three.js. Он предоставляет вам ряд распространенных (и очень удобных) материалов для применения к вашим сеткам:

  1. «Базовый» — это просто означает, что он отображается «неосвещенным».
  2. Ламберт
  3. Фонг

Есть и другие, но опять же для простоты я позволю вам открыть их для себя. В случае с WebGL именно эти материалы могут спасти жизнь. Почему? Ну, потому что в WebGL вам нужно писать шейдеры для всего, что визуализируется. Шейдеры сами по себе являются огромной темой, но вкратце они написаны на GLSL (языке шейдеров OpenGL), который сообщает графическому процессору, как что-то должно выглядеть. Это означает, что вам нужно имитировать математику освещения, отражения и так далее. Это может очень быстро стать очень сложным. Благодаря Three.js вам не придется этого делать, если вы этого не хотите, потому что он абстрагирует это за вас. Однако если вы хотите писать шейдеры, вы также можете сделать это с помощью MeshShaderMaterial, так что это гибкая настройка.

Однако сейчас давайте применим к сфере материал Ламберта:

// create the sphere's material
var sphereMaterial = new THREE.MeshLambertMaterial(
{
// a gorgeous red.
color: 0xCC0000
});

Стоит также отметить, что помимо цвета вы можете указать и другие свойства при создании материала, такие как сглаживание или карты окружения. Вам следует посетить страницу Wiki, чтобы узнать о различных свойствах, которые вы можете установить для материалов и, по сути, для любого объекта, который предоставляет вам движок. Также недавно появился сайт Threejs.org , который предлагает более привлекательный вид API.

6. Свет!

Если бы вы визуализировали сцену прямо сейчас, вы бы увидели красный кружок. Несмотря на то, что у нас применен материал Ламберта, в сцене нет света, поэтому по умолчанию Three.js вернется к полному окружающему освещению, что аналогично плоскому окрашиванию. Давайте исправим это с помощью простой точки света:

// create a point light
var pointLight = new THREE.PointLight( 0xFFFFFF );

// set its position
pointLight.position.x = 10;
pointLight.position.y = 50;
pointLight.position.z = 130;

// add to the scene
scene.add(pointLight);

7. Рендеринг

Теперь у нас действительно все настроено для рендеринга, что примечательно. Но на самом деле нам нужно пойти дальше и сделать именно это:

// draw!
renderer.render(scene, camera);

Однако вам, вероятно, понадобится выполнить рендеринг более одного раза, поэтому, если вы собираетесь выполнить цикл, вам действительно следует использовать requestAnimationFrame; это, безусловно, самый разумный способ обработки анимации в браузере. Он еще не полностью поддерживается, поэтому я настоятельно рекомендую вам взглянуть на прокладку Пола Айриша .

8. Общие свойства объекта

Если вы потратите время на просмотр кода Three.js, вы увидите множество объектов, «наследованных» от Object3D. Это базовый объект, который содержит некоторые очень полезные свойства, такие как информация о положении , вращении и масштабе . В частности, наша Сфера — это меш, который наследуется от Object3D, к которому он добавляет свои собственные свойства: геометрию и материалы . Почему я упоминаю об этом? Что ж, маловероятно, что вам захочется иметь на экране просто сферу, которая ничего не делает, и эти свойства заслуживают изучения, поскольку они позволяют вам на лету манипулировать основными деталями сеток и материалов.

// sphere geometry
sphere.geometry

// which contains the vertices and faces
sphere.geometry.vertices // an array
sphere.geometry.faces // also an array

// its position
sphere.position // has x, y and z properties
sphere.rotation // same
sphere.scale // ... same

9. Маленькие грязные секреты

Я просто хотел быстро указать на одну ошибку в Three.js: если вы измените, например, вершины сетки, вы заметите в цикле рендеринга, что ничего не меняется. Почему? Ну, потому что Three.js (насколько я могу судить) кэширует данные сетки в целях оптимизации. На самом деле вам нужно сообщить Three.js, что что-то изменилось, чтобы он мог пересчитать все, что ему нужно. Вы делаете это с помощью следующего:

// changes to the vertices
sphere.geometry.__dirtyVertices = true;

// changes to the normals
sphere.geometry.__dirtyNormals = true;

Опять же, их больше, но те два, которые я нашел, являются наиболее полезными. Очевидно, вам следует отмечать только те вещи, которые изменились, чтобы избежать ненужных вычислений.

Заключение

Надеюсь, это краткое введение в Three.js оказалось для вас полезным. Нет ничего лучше, чем запачкать руки и попробовать что-то, и я не могу не рекомендовать это достаточно высоко. Работа с 3D-изображениями в браузере доставляет массу удовольствия, а использование такого движка, как Three.js, избавляет вас от многих головных болей и позволяет создавать действительно крутые вещи. Чтобы немного помочь вам, я включил исходный код в эту лабораторную статью, чтобы вы могли использовать его в качестве справочного материала. Если вам понравилось, дайте мне знать через Twitter , всегда приятно поздороваться!