«WebGL Beginner’s Guide» Глава 1: Начиная работать с WebGL

Содержание

Хочу начать вольный перевод отличной книги «WebGL Beginner’s Guide», которая, на мой взгляд, будет интересна не только новичкам, но и более продвинутым разработчикам.

7963f07ca510a7a23645c3a9527346de

Содержание:

  • Глава 1: Начиная работать с WebGL
  • Глава 2: Рендеринг геометрии
  • Глава 3: Освещение
  • Глава 4: Камера
  • Глава 5: Движение
  • Глава 6: Цвет, глубина и альфа-смешение
  • Глава 7: Текстуры
  • Глава 8: Выбор
  • Глава 9: Собираем все вместе
  • Глава 10: Дополнительные методы

WebGL первоначально была основана на OpenGL ES 2.0 (ES означает Embedded Systems), версии спецификации OpenGL для таких устройств как iPhone от Apple и iPad. Но спецификация развивалась, стала независимой, ее основная цель это обеспечение переносимости между различными операционными системами и устройствами. Идея веб-интерфейса, рендеринг в реальном времени открыли новую вселенную возможностей для веб-3D сред, таких как видеоигры, научная и медицинская визуализация. Кроме того, из-за широкого распространения веб-браузеров, эти и другие виды 3D-приложений могут быть запущены на мобильных устройствах, таких как смартфоны и планшеты. Если вы хотите создать свою первую веб-видеоигру, 3D арт-проект для виртуальной галереи, визуализацию данных ваших экспериментов или любое другое 3D-приложение, вы должны иметь ввиду, что первым шагом должно быть то, что вы должны убедиться, что у вас есть подходящая среда.
В этой главе вы сможете:

  • Понять структуру WebGL-приложения
  • Создавать свои области рисования (canvas)
  • Проверить WebGL-возможности вашего браузера
  • Понять, как устроена машина состояний WebGL
  • Изменять переменные WebGL, которые влияют на вашу сцену
  • Загружать и исследовать полнофункциональные сцены

Системные требования

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

  • Firefox 4.0 или более поздней версии
  • Google Chrome 11 или более поздней версии
  • Safari (OSX 10.6 или более поздней версии). По умолчанию WebGL отключена, но вы можете включить ее, установив опцию Enable WebGL в меню Developer
  • Opera 12 или более поздней версии

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

Что представляет собой WebGL

WebGL является 3D графической библиотекой, которая позволяет современным интернет-браузерам отрисовывать 3D-сцены стандартным и эффективным способом. Согласно Википедии, рендеринг это визуализация процесса создания изображения из модели с помощью компьютерной программы. Поскольку этот процесс выполняется на компьютере, существуют различные способы получения таких изображений.
Первое различие, которое мы должны сделать, используем ли мы какие-либо специальные графические аппаратные средства или нет. Мы можем говорить о программном рендеринге, в тех случаях, когда все расчеты, необходимые для отрисовки 3D-сцен выполняются с использованием основного процессора компьютера; с другой стороны, мы используем термин аппаратного рендеринга, в тех случаях, когда есть графический процессор (GPU) для вычисления 3D-графики в реальном времени. С технической точки зрения, аппаратный рендеринг является гораздо более эффективным по сравнению с программным, потому что есть специализированные аппаратные составляющие, которые обрабатывают операции. Но, с другой стороны, программный рендеринг обычно более распространен из-за нехватки аппаратных зависимостей.
Второе различие, которое мы можем сделать, это происходит ли процесс рендеринга локально или удаленно. Когда изображение, которое должно быть отображено сложное, то рендеринг, скорее всего, будет происходить удаленно. Это случай 3D-анимационных фильмов, когда выделенные серверы с большим количеством аппаратных ресурсов позволяют рендерить сложные сцены. Мы будем называть это серверным рендерингом. Противоположностью этому является рендеринг, выполняющийся локально. Мы будем называть это клиентским рендерингом.
WebGL имеет клиенто-ориентированный подход; элементы, которые составляют части 3D-сцены, обычно загружаются с сервера. Однако, вся дальнейшая обработка, необходимая для получения изображения выполняется локально, с помощью графического оборудования клиента.
По сравнению с другими технологиями (например, Java 3D, Flash и Unity Web Player Plugin) WebGL имеет ряд преимуществ:

  • JavaScript программирование: JavaScript это «родной» язык для веб-разработчиков и веб-браузеров. Работа с JavaScript позволяет получить доступ ко всем DOM-элементам, а также легко с ними обращаться, в отличие от общения с апплетами. Так как WebGL программируется в JavaScript, то это облегчает интеграцию WebGL-приложений с другими JavaScript – библиотеками, такими как JQuery и другими технологиями HTML5.
  • Автоматическое управление памятью: в отличие от своего собрата OpenGL и других технологий, где есть конкретные операции выделения и освобождения памяти вручную, в WebGL нет такой необходимости. Из этого следует, что при выходе JavaScript переменной из области видимости, память, занимаемая ей, автоматически освобождается. Это чрезвычайно облегчает программирование, уменьшает объем кода, делает его более ясным и понятным.
  • Проницаемость: благодаря современным технологическим достижениям, веб-браузеры с поддержкой JavaScript устанавливаются на смартфоны и планшетные устройства. На момент написания, Mozilla Foundation является программой для тестирования возможностей WebGL в телефонах Motorola и Samsung. Существуют подобные разработки поддержки WebGL для платформы Android.
  • Производительность: производительность приложений WebGL сопоставима с эквивалентными автономными приложениями (с некоторыми исключениями). Это происходит благодаря способности WebGL иметь доступ к локальным аппаратным ускорителям графики. До сих пор, многие веб-технологии для 3D рендеринга используют программный рендеринг.
  • Нулевая компиляция: учитывая, что WebGL написана на JavaScript, то нет необходимости в предварительной компиляции кода перед выполнением в веб-браузере. Это позволяет вносить изменения на лету и смотреть, как эти изменения влияют на 3D веб-приложение. Тем не менее, когда мы затронем тему шейдеров, то мы поймем, что нуждаемся в некоторой компиляции. Однако, это происходит с помощью наших графических аппаратных средств, а не в нашем браузере.

Структура WebGL приложения

Как и в любой библиотеке 3D-графики, в WebGL необходимо присутствие определенных компонентов для создания 3D-сцен. Эти основные элементы будут рассмотрены в первых четырех главах книги. Начиная с 5 главы, мы будем рассматривать элементы, которые не имеют отношения к работе с 3D-сценой, такие как цвета и текстуры, а затем, позже, мы перейдем к более сложным темам.
Элементы, к которым мы обращаемся, следующие:

  • Canvas: это заполнитель, где будет отображаться сцена. Это стандартный HTML5-элемент, который может быть доступен с помощью объектной модели документа (DOM) через JavaScript.
  • Объекты: это 3D сущности, которые составляют часть сцены. Эти сущности состоят из треугольников. Во второй главе мы увидим, как WebGL обрабатывает геометрию. Мы будем использовать WebGL-буферы для хранения многоугольников и увидим, как WebGL использует буферы для визуализации объектов на сцене.
  • Свет: ничего в 3D мире нельзя увидеть, если нет никаких источников света. Этот элемент любого WebGL-приложения будет рассмотрен в 3 главе. Мы узнаем, что WebGL использует шейдеры для моделирования света на сцене. Так же мы посмотрим, как 3D-объекты отражают и поглощают свет в соответствии с законами физики, а также обсудим иные модели света, которые мы можем создать в WebGL для визуализации наших объектов.
  • Камера: выступает в качестве холста для просмотра 3D-мира. Посмотрим, как с ее помощью можно исследовать 3D-сцену. В 4 главе, будут рассмотрены различные матричные операции, которые необходимы для получения перспективного вида. Также мы поймем, как эти операции могут моделировать поведение камеры.

Эта глава посвящена первому элементу нашего списка – canvas. В ближайших разделах мы увидим, как создать canvas (холст) и как настроить WebGL-контекст.

Создание HTML5 canvas

Давайте создадим веб-страницу и добавим HTML5 canvas. Canvas представляет собой прямоугольный элемент на веб-странице, где будет отображаться 3D-сцена.

  1. Используя ваш любимый редактор, создайте веб-страницу со следующим содержимым:
        <!DOCTYPE html>
        <html>
            <head>
                <title> WebGL Beginner's Guide - Setting up the canvas </title>
                <style type="text/css">
                    canvas {border: 2px dotted blue;}
                </style>
            </head>
            <body>
                <canvas id="canvas-element-id" width="800" height="600">
                    Your browser does not support HTML5
                </canvas>
            </body>
        </html>
        
  2. Сохраните файл как ch1_Canvas.html.
  3. Откройте этот файл через поддерживаемый браузер.
  4. Вы должны увидеть что-то похожее на это:

    d59f8939ed16c0d146c1bf49b6f87445

Что только что произошло?
Мы только что создали простую веб-страницу с содержащимся в ней холстом. Этот холст будет содержать наши 3D-приложения. Давайте разберем некоторые важные элементы, представленные в этом примере.
Определение CSS-стиля для границы
Это кусок кода, который определяет стиль холста:

<style type="text/css">
    canvas {border: 2px dotted blue;}
</style>

Как вы можете себе представить, этот код не является фундаментальным для создания WebGL-приложений. Тем не менее, синяя пунктирная линия является хорошим способом проверки, где находится холст, учитывая, что полотно будет изначально пусто.
Понимание атрибутов холста
В предыдущем примере есть 3 атрибута:

  • Id: это идентификатор холста в объектной модели документа (DOM)
  • Ширина и высота: эти два атрибута определяют размер нашего холста. Когда эти два атрибута отсутствуют Firefox, Chrome, и WebKit по умолчанию будут использовать холст 300×150.

Что делать, если canvas не поддерживается?
Если вы видите, что на экране появилось сообщение: Your browser does not support HTML5 (которое было записано между тегами и ), то вы должны убедиться, что используете браузер, который поддерживает WebGL.
Если вы используете Firefox и все еще видите сообщение HTML5 not supported, то проверьте, что включена поддержка WebGL. Для этого введите в адресной строкеabout:config, а затем посмотрите на свойство webgl.disabled. Если установлено вtrue то перейдите и поменяйте. При повторном запуске Firefox и загрузке ch1_Canvas.html вы должны увидеть пунктирные линии холста, то есть все в порядке.
При удаленном подключении, если вы не видите холст, то это может быть связано с тем, что Firefox внес в черный список некоторые драйверы графической карты. В этом случае ничего не остается, как использовать другой компьютер.

Доступ к контексту WebGL

Контекст WebGL это дескриптор (точнее, объект JavaScript), через который мы можем получить доступ ко всем функциям и атрибутам WebGL. Они составляют Application Program Interface WebGL (API).
Мы собираемся создать функцию JavaScript, которая будет проверять можно ли на холсте получить контекст WebGL. В отличие от других библиотек JavaScript, которые должны быть загружены и подключены в рабочий проект, WebGL уже находится в вашем браузере. Другими словами если вы используете один из поддерживаемых браузеров, то вам не нужно устанавливать и включать какую-либо библиотеку.
Мы собираемся изменить предыдущий пример, добавив JavaScript-функцию, которая будет проверять наличие поддержки WebGL в вашем браузере (пытаться получить дескриптор). Эта функция будет вызываться при загрузке страницы. Для этого мы будем использовать стандартное DOM-событие onLoad.

  1. Открываем файл ch1_Canvas.html в вашем любимом текстовом редакторе (в идеале можно выбрать синтаксис для HTML/JavaScript).
  2. Добавьте следующий код прямо под тегом </style>:
    <script>
            var gl = null;
            function getGLContext()
            {
                var canvas = document.getElementById("canvas-element-id");
                if (canvas == null)
                {
                    alert("there is no canvas on this page");
                    return;
                }
                var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
                for (var i = 0; i < names.length; ++i) 
                {
                    try 
                    {
                        gl = canvas.getContext(names[i]);
                    } 
                    catch(e) {}
                    if (gl) 
                        break;
                }
                if (gl == null)
                {
                    alert("WebGL is not available");
                }
                else
                {
                    alert("Hooray! You got a WebGL context");
                }
            }
    </script>
    
  3. Мы должны вызвать эту функцию на событие onLoad. Измените содержимое тегаbody на следующее:
        <body onLoad ="getGLContext()">
    
  4. Сохраните файл ch1_GL_Context.html.
  5. Откройте файл ch1_GL_Context.html, используя один из браузеров, поддерживающих WebGL.
  6. Если вы не сможете запустить WebGL, то увидите примерно следующее диалоговое окно:

    91646099b734d991d50c2607b6a78a6b

Что же только что произошло?
Используя переменную JavaScript (gl), мы получили ссылку на контекст WebGL. Давайте вернемся и проверим код, который позволяет получить доступ к WebGL:

    var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
    for (var i = 0; i < names.length; ++i) 
    {
        try 
        {
            gl = canvas.getContext(names[i]);
        } 
        catch(e) {}
        if (gl) 
            break;
    }

Метод холста getContext дает нам доступ к WebGL. Все, что нам нужно, это указать имя контекста, которое может быть разным у разных производителей. Поэтому мы сгруппировали все возможные имена контекста в массив names. Крайне важно проверить спецификацию WebGL (вы можете найти ее в интернете) на любые изменения, касающиеся соглашения об именовании.
getContext так же может обеспечить доступ к 2D-графике HTML5 при использовании 2D –библиотеки, в зависимости от имени контекста. В отличие от WebGL это соглашение об именах является стандартным. API 2D-графики HTML5 является полностью независимым от WebGL и выходит за рамки этой книги.

Машина состояний WebGL

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

  1. Используя ваш любимый текстовый редактор, откройте файлch1_GL_Attributes.html:
        <html>
            <head>
                <title> 
                    WebGL Beginner's Guide - Setting WebGL context attributes 
                </title>
                <style type="text/css">
                    canvas {border: 2px dotted blue;}
                </style>
                <script>
                    var gl = null;
                    var c_width = 0;
                    var c_height = 0;
                    window.onkeydown = checkKey;
                    function checkKey(ev)
                    {
                        switch(ev.keyCode)
                        {
                            case 49:
                            { 
                                // 1
                                gl.clearColor(0.3,0.7,0.2,1.0);
                                clear(gl);
                                break;
                            }
                            case 50:
                            {
                                 // 2
                                gl.clearColor(0.3,0.2,0.7,1.0);
                                clear(gl);
                                break;
                            }
                            case 51:
                            { 
                                // 3
                                var color = gl.getParameter(gl.COLOR_CLEAR_VALUE);
                                // Don't get confused with the following line. It 
                                // basically rounds up the numbers to one decimal cipher 
                                //just for visualization purposes
                                alert('clearColor = (' + 
                                    Math.round(color[0]*10)/10 + 
                                    ',' + Math.round(color[1]*10)/10+
                                    ',' + Math.round(color[2]*10)/10+')');
                                window.focus();
                                break;
                            }
                        }
                    }
                    function getGLContext()
                    {
                        var canvas = document.getElementById("canvas-element-id");
                        if (canvas == null)
                        {
                            alert("there is no canvas on this page");
                            return;
                        }
                        var names = ["webgl", "experimental-webgl", "webkit-3d", "moz-webgl"];
                        var ctx = null;
                        for (var i = 0; i < names.length; ++i) 
                        {
                            try 
                            {
                                ctx = canvas.getContext(names[i]);
                            } 
                            catch(e) {}
                            if (ctx) 
                                break;
                        }
                        if (ctx == null)
                        {
                            alert("WebGL is not available");
                        }
                        else
                        {
                            return ctx;
                        }
                    }
                    function clear(ctx)
                    {
                        ctx.clear(ctx.COLOR_BUFFER_BIT); 
                        ctx.viewport(0, 0, c_width, c_height);
                    }
                    function initWebGL()
                    {
                        gl = getGLContext();
                    }
                </script>
            </head>
            <body onLoad="initWebGL()">
                <canvas id="canvas-element-id" width="800" height="600">
                    Your browser does not support the HTML5 canvas element.
                </canvas>
            </body>
        </html>
        
  2. Вы видите, что этот файл очень похож на наш предыдущий пример. Тем не менее, появляются новые конструкции, которые мы кратко объясним. Этот файл содержит 4 JavaScript-функции:
    • checkKey: это вспомогательная функция. Она захватывает ввод с клавиатуры и выполняет код в зависимости от введенной команды
    • getGLContext: подобна той, которую мы уже рассмотрели
    • clear: очищает холст текущим цветом, который является одним из атрибутов WebGL-контекста. Как упоминалось ранее, WebGL работает как конечный автомат, поэтому он будет поддерживать выбранный цвет, чтобы очистить холст до того, как этот цвет будет изменен с помощью функцииgl.clearColor.
    • initWebGL: эта функция может заменить функцию getGLContext, как функция, вызываемая на событие onLoad документа. Эта функция вызывает улучшенную версию getGLContext, которая возвращает контекст в переменную ctx. Затем этот контекст присваивается глобальной переменноgl.
  3. Откройте файл test_gl_attributes.html, используя поддерживаемый браузер.
  4. Нажмите 1. Вы увидите, как холст меняет свой цвет на зеленый. Если вы захотите узнать используемый цвет, то нажмите 3.
  5. Холст окрашен в зеленый цвет, пока мы не решим изменить цвет очистки, вызвав функцию gl.clearColor. Давайте изменим его, нажав 2. Если посмотреть на код, то можно увидеть, что цвет изменится на синий. Если вы хотите узнать какой это точно цвет, нажмите 3.

Что же только что произошло?
В этом примере мы увидели как мы можем изменять и задавать цвет, который WebGL использует для очистки холста с помощью вызова функции clearColor. Соответственно, мы использовали функцию getParameter (gl.COLOR_CLEAR_VALUE), чтобы получить текущее значение цвета заливки холста.
На протяжении всей книги мы будем видеть аналогичные конструкции, когда конкретные функции устанавливают атрибуты контекста, а WebGL-функция getParameter извлекает текущее значение атрибутов в зависимости от переданного аргумента (в нашем примере это COLOR_CLEAR_VALUE).
Получить доступ к WebGL API, используя контекст
Также важно отметить, что все функции WebGL доступны через контекст WebGL. В наших примерах контекст находится в переменной gl. Таким образом, любой вызов WebGL API будет производится с помощью этой переменной.

Загружаем 3D-сцену

До сих пор мы видели как можно получить и настроить контекст WebGL; следующим шагом является обсуждение объектов, освещения и камеры. Однако, почему мы должны ждать, чтобы посмотреть на возможности WebGL? В этом разделе мы посмотрим как выглядит WebGL-сцена.

Виртуальный автосалон

Благодаря книге, мы будем развивать виртуальное приложение автосалона с помощью WebGL. На данный момент, мы будем загружать одну простую сцену на холст. Эта сцена будет содержать автомобиль, несколько источников света и камеру.
После прочтения книги, вы сможете создавать сцены, подобные той, которую мы будем создавать.

  1. Откройте файл ch1_Car.html в любом из поддерживаемых браузеров
  2. Вы увидите WebGL-сцену с автомобилем, как показано ниже:

    f5a0bd6c32fcbbd44ffc10a5bdbec55a

  3. С помощью ползунка можно интерактивно обновлять четыре источника света, которые определены для этой сцены. Каждый источник света состоит из трех элементов: окружение, диффузные и зеркальные элементы. Более подробно мы рассмотрим тему освещения в 3 главе.
  4. Нажмите и потащите на холсте, чтобы повернуть автомобиль и визуализировать его с разных сторон. Вы можете увеличить его, нажав клавишу Alt при перетаскивании мышью на холсте. Также вы можете использовать клавиши со стрелками, чтобы поворачивать камеру вокруг автомобиля. Убедитесь в том, что холст находится в фокусе, нажав на него, прежде чем использовать клавиши со стрелками. В 4 главе мы посмотрим, как создать и работать с камерой в WebGL.
  5. Для достижения эффекта, который возникает при нажатии на клавиши со стрелками, мы используем JavaScript-таймеры. Мы поговорим об анимации в 5 главе.
  6. Используйте виджет выбора цвета, как показано на предыдущем скриншоте, чтобы изменить цвет автомобиля. Использование цветов будет рассмотрено в 6 главе. Главы 7-10 будет описано использование текстур, выбор объектов на сцене, как построить виртуальный автосалон и передовые WebGL-методы соответственно.

Что же только что произошло?
Мы загрузили простую сцену в интернет-браузер с помощью WebGL.
Эта сцена состоит из:

  • Холста, с помощью которого мы видим сцену
  • Несколько полигонов (объектов), которые представляют собой части автомобиля: крыша, окна, фары, крылья, двери, колеса, спойлер бамперы и так далее.
  • Источники света, в противном случае все было бы черным
  • Камера, которая определяет наше положение в 3D-мире. Камера, может быть интерактивной, то есть положение наблюдателя может меняться, в зависимости от пользовательского ввода. В этом примере мы использовали левую и правую клавиши со стрелками и мышь, чтобы перемещать камеру вокруг автомобиля.

Существуют и другие элементы, которые не охвачены в данном примере, такие как текстуры, цвета и специальные световые эффекты (зеркальность). Не паникуйте! Позже будут рассмотрены все элементы более подробно.

Резюме

В этой главе мы рассмотрели четыре основных элемента, которые всегда присутствуют в любом WebGL-приложении: холст, объект, свет и камера.
Мы узнали, как добавить на веб-страницу HTML5 canvas, как установить его ID, ширину и высоту. После этого мы написали код, который создавал контекст WebGL. Мы увидели, что WebGL работает как машина состояний, как таковая, мы можем запросить любую из своих переменных, использую функцию getParameter.
В следующей главе мы узнаем, как определить, загрузить и отрисовать 3D-модель в WebGL-сцене.

Ресурсы к этой статье вы можете скачать по ссылке

Всем большое спасибо за внимание!