Frontender Magazine

Подготовка к использованию WebGL

WebGL позволяет использовать API на основе OpenGL ES 2.0 для выполнения 3D-визуализации в HTML-элементе canvas в браузерах, которые его поддерживают без помощи плагинов. Программы на WebGL состоят из кода последовательности операций, написанного на JavaScript, и кода для создания специальных эффектов (кода шейдеров), который выполняется графическим процессором компьютера. Элементы WebGL можно использовать вперемешку с другими элементами HTML и сочетать с другими частями страницы или её фона.

В этой статье предложено введение в основы применения WebGL. Она рассчитана на то, что вы уже имеете представление о математической составляющей создания 3D-графики и не ставит перед собой цель попытаться научить вас работать с OpenGL.

Подготовка к визуализации в 3D

Для 3D-визуализации с помощью WebGL вам в первую очередь потребуется холст canvas. Во фрагменте HTML-кода, представленном ниже, создаётся такой холст и добавляется обработчик события onload, инициализирующий WebGL контекст.

<body onload="start()">
  <canvas id="glcanvas" width="640" height="480">
    Ваш браузер не поддерживает элемент HTML5 <code>&lt;canvas&gt;</code>.
  </canvas>
</body>

Подготовка контекста WebGL

После загрузки документа вызывается JavaScript-функция start(). Её миссия состоит в определении WebGL контекста и начале визуализации контента.

var gl; // Глобальная переменная для WebGL контекста

function start() {
  var canvas = document.getElementById("glcanvas");

  gl = initWebGL(canvas);      // Инициализация контекста GL

  // Следующий код выполняется только если WebGL поддерживается и работает

  if (gl) {
    gl.clearColor(0.0, 0.0, 0.0, 1.0);                      // Прописываем чёрный непрозрачный цвет в качестве цвета для очистки холста 
    gl.enable(gl.DEPTH_TEST);                               // Активация тестирования глубины
    gl.depthFunc(gl.LEQUAL);                                // Ближние элементы перекрывают дальние
    gl.clear(gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT);      // Сброс цвета и буфера глубины
  }
}

Первым делом мы создаём привязку к холсту, помещая его в переменную с именем canvas. Безусловно, если нет необходимости постоянно обращаться к холсту, следует избегать глобальных переменных и хранить его в локальной переменной или поле объекта.

Когда уже создан холст, вызываем функцию с именем initWebGL();, её мы создаём тут же. Задача этой функции состоит в инициализации WebGL контекста.

Если контекст инициализирован успешно, gl служит привязкой к нему. В этом случае мы изменяем цвет для очистки холста на чёрный и очищаем с его помощью контекст. После этого производим настройку контекста путем установки параметров. В этом случае мы активируем тестирование глубины и указываем, что ближние объекты должны перекрывать дальние.

Для поверхностного ознакомления этого достаточно. Более подробно о том, как начать что-то делать, мы разберём чуть позже.

Создание WebGL контекста

Функция initWebGL() выглядит так:

function initWebGL(canvas) {
  gl = null;

  try {
    // Попытка захвата стандартного контекста. При её неудаче используется резервный контекст.
    gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl");
  }
  catch(e) {}

  // Если контекста GL нет, прекращение работы с WebGL
  if (!gl) {
    alert("Невозможно инициализировать WebGL. Ваш браузер её не поддерживает.");
    gl = null;
  }

  return gl;
}

Чтобы получить доступ к WebGL контексту для холста, мы запрашиваем у canvas контекст с именем webgl. Если такая попытка заканчивается неудачей, пробуем имя experimental-webgl. Если и это не приводит к удовлетворительному результату, выводим уведомление пользователю о том, что у него не поддерживается WebGL. Вот и всё. На этом этапе gl либо имеет значение null (что подразумевает отсутствие WebGL контекста), либо является ссылкой на WebGL контекст, в котором будет происходить визуализация.

Примечание: имя контекста experimental-webgl используется временно, пока идёт процесс подготовки спецификации; когда он будет завершён, будет использоваться имя webgl.

На этом этапе у нас есть код, которого достаточно для успешной инициализации WebGL контекста, и должно получиться большое и пустое чёрное поле, готовое к принятию контента.

Кликните здесь, чтобы увидеть живой пример, если вы используете совместимый с WebGL браузер.

Изменение размера WebGL контекста

Разрешение области просмотра нового WebGL контекста будет подогнано под высоту и ширину его элемента canvas, без CSS, в момент получения контекста. Отредактировав стиль элемента canvas, можно изменить его отображаемый размер, но нельзя изменить разрешение визуализации. Изменение атрибутов ширины и высоты элемента canvas после создания контекста также не повлияет на количество пикселей, которое будет отрисовано. Чтобы можно было изменять разрешение визуализации WebGL, например, когда пользователь меняет размер окна, или же если вы хотите сделать возможной встроенную настройку параметров графики, нужно вызвать функцию viewport() контекста WebGL для подтверждения изменений.

Чтобы изменить разрешение визуализации контекста WebGL с переменными gl и canvas, как в примере выше, следует использовать:

gl.viewport(0, 0, canvas.width, canvas.height);

Размер холста, для которого визуализация выполняется с разрешением, не соответствующим прописанному в CSS, будет принудительно изменён. Изменение размера через CSS пригодится, если нужно сэкономить ресурсы путём визуализации в низком разрешении и масштабировании в браузере; также возможно уменьшение масштаба, которое бы представило прекрасный пример эффекта сглаживания пусть даже и с примитивными результатами и высокой стоимостью производительности. Но чаще всего лучше полагаться на множественную выборку сглаживания (MSAA) и реализацию фильтрации текстур в браузере пользователя, если они предусмотрены и соответствуют вашим требованиям.

Читайте также

Если вы заметили ошибку, вы всегда можете отредактировать статью, создать issue или просто написать об этом Антону Немцеву в skype ravencry.

Mozilla
Автор:
Mozilla
Сaйт:
https://hacks.mozilla.org/
Twitter:
@mozilla
Наталья Фадеева
Переводчик:
Наталья Фадеева
вКонтакте:
natatik_l
Twitter:
@very_busy_girl
GitHub:
NatalieF