Браузер в компьютере, браузер в телефоне или умных часах, а может даже у кого-то в чайнике? Веб-технологии окружают нас со всех сторон и по мере развития железной начинки, становятся все более зрелищными и совершенными. Всего несколько лет назад о WebGL говорили, как о забавной игрушке с туманными перспективами. Но многое изменилось и на смену ранее популярному flash приходят более продвинутые технологии HTML5/WebGL.

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

Указанный сайт ничто иное, как отличная замануха на просмотр фильма “Терминатор: Генезис”. Помимо стандартных постеров, трейлеров, тизеров - создатели фильма придумали вот такое великолепное интерактивное шоу.

Изюминка задумки заключается в привязке трехмерной графики к реальным кадрам из фильма. Посетитель SkyNet может узнать интересные подробности о главных персонажах, как роботов, так и живых актерах. Например, SpIder Tank. Что за монстр, непонятно? А так, покрутил модельку (кстати, качественно сделанную), почитал информацию о ключевых узлах, да еще и посмотрел видео, относящееся к возможностям монстра.

Честно, такая подача информации о фильме выглядит новаторски и очень завлекающе. WebGL/HTML5 поднимают планку на совсем другой уровень восприятия.

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

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

И здесь дело даже не в качестве моделей, а в точности реализации. Например, при демонстрации работы коленного сустава, вы никак не сможете выгнуть его больше положенного.

Кроме того, есть очень интересный режим “рентгена”, включаемый специальной кнопкой в плеере. В этом случае, модель становится полупрозрачной с возможностью рассмотрения некоторых внутренних особенностей. Причем, при необходимости можно выделить часть объекта на фоне “рентгеновского снимка”. Так, на скриншоте ниже можно отчетливо рассмотреть разрыв связки.

Как уверяют разработчики, всего создано около 5000 объектов, а также сделано несколько полноценных уроков по анатомии человека. Думается, такой подход к обучению будет гораздо результативнее, нежели по обычным бумажным атласам.

Идея проста до безобразия, но именно благодаря WebGL удалось совместить необычную визуальную картинку (нужно смотреть в “живую”, так как скриншот эффект не передает) с некой массовой доской сообщений.

В действительности, частички образующие форму шлема из знаменитой игры - это пожелания пользователей. Сотни и сотни сообщений, оставленных на странице сайта, постепенно образуют цельную модель. Первоначально шлем представлял собой простую, примитивную сетку. В этом можно убедиться, если передвинуть слайдер на шкале времени внизу экрана. Интересно, как будет выглядеть шлем, после достижения некоторого порога. А пока, вы можете также присоединиться к ожидающим игру и черкануть несколько строк на этой необычной “доске объявлений”.

Постскриптум Как, видите, все выбранные презентации показывают нужность и простоту использования технологии WebGL. Всё ближе и ближе смыкаются персональные компьютеры с мобильными системами. Настанет момент, когда браузерные приложения станут по-настоящему кроссплатформенными.

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

WebGL, в отличие от Javascript, имеет высокий порог вхождения, его до сих пор мало кто использует, а ещё меньше тех, кто об этом пишет. Большинство руководств или статей перепрыгивают сразу на использование какой-нибудь библиотеки. Но мы-то с вами знаем, что большие универсальные инструменты не всегда пригодны для наших задач или, возможно, делают это на неприемлемом уровне: проигрывают в скорости, поставляются с ненужным багажом и т.д.

Этой статьёй хочется облегчить порог вхождения в чистый WebGL, дать начальное представление и подсказать, куда двигаться дальше.

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

WebGL основан на OpenGL ES 2.0, который, в свою очередь, является специальной версией для работы на мобильных устройствах. Спецификация WebGL была выпущена в 2011 году, разрабатывается и поддерживается некоммерческой организацией Kronos Group, сайт которой частенько лежит, что ещё более усложняет изучение. Известно, что в настоящее время идёт разработка спецификации версии 2.0.


Статистика поддержки WebGL разными браузерами с сайта caniuse.com

WebGL доступен в большинстве современных браузеров и поддерживается у 83% пользователей. Приятным бонусом разработки на WebGL является то, что вы будете поддерживать только современные браузеры и забудете о кошмарах ECMAScript 3.

Если вы думаете, что WebGL рисует 3D, вы ошибаетесь. WebGL ничего не знает о 3D, это скорее низкоуровневый 2D API, и всё что он умеет делать, это рисовать треугольники. Но он умеет рисовать их очень много и очень быстро.

Хотите нарисовать квадрат? Пожалуйста, соедините два треугольника. Нужна линия? Без проблем, всего лишь несколько последовательно соединенных треугольников.

Как нарисовать треугольник Поскольку все фигуры в WebGL состоят из треугольников, поэтапно разберём, как отобразить один треугольник.

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

Шейдер - это программа, выполняемая на видеокарте и использующая язык GLSL. Этот язык достаточно простой, и его изучение не представляет проблемы.

Всего есть два вида шейдеров: вершинный и фрагментый, и для отрисовки абсолютно любой фигуры всегда используются оба. Разберёмся с каждым по очереди.

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

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

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

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


Если вершинный шейдер определяет геометрию фигуры, то фрагментный - её цвет

Как уже было сказано выше, код шейдеров пишется на языке GLSL. Рассмотрим код шейдеров для треугольника:

Пример вершинного шейдера:
attribute vec3 a_position; attribute vec3 a_color; uniform vec3 u_position; varying vec3 v_color; void main(void) { v_color = a_color; gl_Position = vec4(u_position + a_position, 1.0); }
Пример фрагментного шейдера:
precision mediump float; varying vec3 v_сolor; void main(void) { gl_FragColor = vec4(v_color.rgb, 1.0); }
Код состоит из переменных и главной функции, возвращающей основной результат работы шейдера: gl_Position передаёт координаты, а gl_FragColor устанавливает цвет.

Шейдеры имеют три типа переменных, которые передаются из основной программы:

  • attributes - доступны только в вершинном шейдере, разные для каждой из вершин;
  • uniforms - доступны в обоих шейдерах и одинаковы для всех вызовов шейдера;
  • varying - служат для передачи информации от вершинного шейдера к фрагментному.
  • При вызове фрагментого шейдера для конкретной точки, значения varying переменных линейно интерполируются между вершинами треугольника, которому принадлежит данная точка.


    Значения varying переменных внутри треугольника вычисляются
    на основе значений этих переменных в вершинах

    Попробуем инициализировать данные шейдеры. Для начала получим контекст WebGL:
    var gl = canvas.getContext(‘webgl’);
    Код шейдеров представляется обычной строкой и для использования его нужно скомпилировать:
    var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, document.getElementById("vertexShader").text); gl.compileShader(vertexShader); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, document.getElementById("fragmentShader").text); gl.compileShader(fragmentShader);
    Для связывания двух типов шейдеров вместе используется шейдерная программа:
    var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program);
    Если uniform-переменные связываются напрямую с переменными из js, то для атрибутов нужно использовать ещё одну сущность - буферы. Данные буферов хранятся в памяти видеокарты, что даёт значительный прирост в скорости рендеринга.

    В нашем случае нам понадобятся:

  • буфер вершин, который хранит всю информацию о расположению вершин геометрии;
  • буфер цветов с информацией о цвете вершин.
  • Зададим буфер вершин:

    Геометрия нашего треугольника

    Вершины имеют координаты:

    • (0, 0, 0);
    • (0.5, 1, 0);
    • (1, 0, 0).
    Стоит отметить, что при работе с буферами следует учитывать несколько особенностей:
  • данные в буфер передаются одним массивом без вложенности, в случае нашего треугольника данные будут выглядеть следующим образом: ;
  • передаваться должны только типизированные массивы ;
  • прежде чем передать данные, вы должны точно указать, какой буфер будет использоваться, методом gl.bindBuffer.
  • Как это будет выглядеть в программе:
    var vertexBuffer = gl.createBuffer(); var vertices = ; gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
    Создадим аналогичным образом буфер цветов. Цвет указываем для каждой из вершин в формате RGB, где каждая компонента цвета от 0 до 1:
    var colorBuffer = gl.createBuffer(); var colors = ; gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);
    Всё, что нам осталось, чтобы нарисовать треугольник, - это связать данные с переменными шейдерной программы и вызвать методы отрисовки. Для этого:
    // Получим местоположение переменных в программе шейдеров var uPosition = gl.getUniformLocation(program, "u_position"); var aPosition = gl.getAttribLocation(program, "a_position"); var aColor = gl.getAttribLocation(program, "a_color"); // Укажем какую шейдерную программу мы намерены далее использовать gl.useProgram(program); // Передаем в uniform-переменную положение треугольника gl.uniform3fv(uPosition, ); // Связываем данные цветов gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.enableVertexAttribArray(aColor); // Вторым аргументом передаём размерность, RGB имеет 3 компоненты gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0); // И вершин gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.enableVertexAttribArray(aPosition); gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0); // Очищаем сцену, закрашивая её в белый цвет gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT); // Рисуем треугольник // Третьим аргументом передаём количество вершин геометрии gl.drawArrays(gl.TRIANGLES, 0, 3);
    Наш треугольник готов:

    Полный код примера можно
    посмотреть

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

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

    Нам придётся прописать каждую вершину каждого треугольника. Есть способы использовать более короткую запись, но для начала сделаем по-простому:

    Это - просто

    var vertexBuffer = gl.createBuffer(); var vertices = [ // Передняя грань -1, -1, -1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, -1, // Задняя грань -1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, // Нижняя грань -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, -1, // Верхняя грань -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1, 1, // Левая грань -1, -1, -1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, -1, 1, // Правая грань 1, -1, -1, 1, 1, -1, 1, -1, 1, 1, 1, 1, 1, -1, 1, 1, 1, -1 ]; gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);


    Аналогично запишем буфер цветов, раскрасив грани куба в три цвета:
  • (1, 0.5, 0.5)
  • (0.5, 0.7, 1)
  • (0.3, 1, 0.3)
  • Тоже простой пример

    var colorBuffer = gl.createBuffer(); var colors = [ // Передняя грань 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, // Задняя грань 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, 1, 0.5, 0.5, // Нижняя грань 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, // Верхняя грань 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, 0.5, 0.7, 1, // Левая грань 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, // Правая грань 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3, 0.3, 1, 0.3 ]; gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(colors), gl.STATIC_DRAW);


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

    Известно, что матрица поворота в трёхмерном пространстве задаётся с помощью матрицы размером 3?3. К этой матрице добавляется вектор положения, таким образом, в итоге используется матрица 4?4.

    WebGL никак не помогает нам работать с матрицами, поэтому, чтобы не тратить на них много времени, будем использовать довольно известную библиотеку glMatrix . Создадим с помощью неё единичную матрицу положения:
    var cubeMatrix = mat4.create();
    Чтобы отрисовать трёхмерный объект, нам нужно ввести понятие камеры. Камера, как и любой объект, имеет своё положение в пространстве. Она также определяет, какие объекты будут видны на экране, и отвечает за преобразование фигур так, чтобы на экране у нас создалась иллюзия 3D.


    Перспектива куба на экране

    За это преобразование отвечает матрица перспективы. C glMatrix она создаётся в две строчки:
    var cameraMatrix = mat4.create(); mat4.perspective(cameraMatrix, 0.785, window.innerWidth / window.innerHeight, 0.1, 1000);
    Метод mat4.perspective(matrix, fov, aspect, near, far) принимает пять параметров:

  • matrix - матрица, которую необходимо изменить;
  • fov - угл обзора в радианах;
  • aspect - cоотношение сторон экрана;
  • near - минимальное расстояние до объектов, которые будут видны;
  • far - максимальное расстояние до объектов, которые будут видны.
  • Чтобы изображение куба попало в камеру, сдвинем камеру по оси Z:
    mat4.translate(cameraMatrix, cameraMatrix, );
    В отличие от треугольника, в шейдерах для куба дополнительно используется матрица положения и матрица камеры:

    Вершинный шейдер:
    attribute vec3 a_position; attribute vec3 a_color; uniform mat4 u_cube; uniform mat4 u_camera; varying vec3 v_color; void main(void) { v_color = a_color; gl_Position = u_camera * u_cube * vec4(a_position, 1.0); }
    Фрагментый шейдер:
    precision mediump float; varying vec3 v_color; void main(void) { gl_FragColor = vec4(v_color.rgb, 1.0); }
    Инициализация шейдеров происходит точно так же, как и в случае треугольника:
    var vertexShader = gl.createShader(gl.VERTEX_SHADER); gl.shaderSource(vertexShader, document.getElementById("vertexShader").text); gl.compileShader(vertexShader); var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER); gl.shaderSource(fragmentShader, document.getElementById("fragmentShader").text); gl.compileShader(fragmentShader); var program = gl.createProgram(); gl.attachShader(program, vertexShader); gl.attachShader(program, fragmentShader); gl.linkProgram(program); var uCube = gl.getUniformLocation(program, "u_cube"); var uCamera = gl.getUniformLocation(program, "u_camera"); var aPosition = gl.getAttribLocation(program, "a_position"); var aColor = gl.getAttribLocation(program, "a_color");
    Чтобы куб не стоял на месте, а вращался, необходимо постоянно менять его положение и обновлять кадр. Обновление происходит по средствам вызова встроенной функции requestAnimationFrame.

    В отличие от других подобных методов, requestAnimationFrame вызывает переданную функцию только когда видеокарта свободна и готова к отрисовке следующего кадра.
    // Создадим единичную матрицу положения куба var cubeMatrix = mat4.create(); // Запомним время последней отрисовки кадра var lastRenderTime = Date.now(); function render() { // Запрашиваем рендеринг на следующий кадр requestAnimationFrame(render); // Получаем время прошедшее с прошлого кадра var time = Date.now(); var dt = lastRenderTime - time; // Вращаем куб относительно оси Y mat4.rotateY(cubeMatrix, cubeMatrix, dt / 1000); // Вращаем куб относительно оси Z mat4.rotateZ(cubeMatrix, cubeMatrix, dt / 1000); // Очищаем сцену, закрашивая её в белый цвет gl.clearColor(1.0, 1.0, 1.0, 1.0); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // Включаем фильтр глубины gl.enable(gl.DEPTH_TEST); gl.useProgram(program); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); gl.enableVertexAttribArray(aPosition); gl.vertexAttribPointer(aPosition, 3, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); gl.enableVertexAttribArray(aColor); gl.vertexAttribPointer(aColor, 3, gl.FLOAT, false, 0, 0); gl.uniformMatrix4fv(uCube, false, cubeMatrix); gl.uniformMatrix4fv(uCamera, false, cameraMatrix); gl.drawArrays(gl.TRIANGLES, 0, 36); lastRenderTime = time; } render();
    Получаем вращающийся куб:

    Полный код примера можно
    посмотреть

    Мы научились рисовать простой куб, поняли, как заставить его вращаться, и познакомились с понятиями матрицы положения и камеры.

    Как отлаживать Поскольку при работе с WebGL часть программы исполняется на стороне видеокарты, процесс отладки значительно усложняется. Нет привычных инструментов в виде DevTools и даже console.log. В интернете есть множество статей и докладов на эту тему, здесь же приведу лишь основные способы.

    Чтобы понять, что код шейдеров был написан с ошибкой, после компиляции шейдеров можно использовать следующий метод:
    if (!gl.getShaderParameter(vertexShader, gl.COMPILE_STATUS)) { console.log(gl.getShaderInfoLog(vertexShader)); } if (!gl.getShaderParameter(fragmentShader, gl.COMPILE_STATUS)) { console.log(gl.getShaderInfoLog(fragmentShader)); } if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { console.log("Could not initialize shaders"); }
    Также есть специальное расширение для браузеров WebGL-Inspector . Оно позволяет отследить загруженные шейдеры, буферы, текстуры в видеокарту, и вызовы методов WebGL.

    Ещё есть Shader Editor, в Firefox DevTools этот функционал уже встроен, а для Chrome есть расширение , которое позволяет редактировать код шейдеров прямо в процессе работы приложения.

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

    Напоследок - список полезных ресурсов, где можно продолжить изучение WebGL.

    • Полный код примеров с треугольником  

    Материал в оригинале можно найти

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

    Простой путь
    • При использовании Windows убедитесь, что установлена Исполняемая библиотека Microsoft DirectX — ее можно бесплатно скачать с сайта Microsoft.
    • После этого установите самую последнюю версию драйверов видеокарты.
    • Теперь выбирайте браузер:
      • Firefox: достаточно версии 4 и выше.
      • Chrome: вам нужно просто установить его . Если вы его уже используете, просто проверьте, что он обновлен до версии 10 — почти наверняка это произошло автоматически (версия выпущена в марте 2011), но вы можете убедиться в этом в пункте меню «О браузере Google Chrome».
      • Safari: на Mac, OS X 10.7 имеет поддержку WebGL, но она отключена по умолчанию. Для ее включения зайдите в меню разработчика и отметьте флажок «Включить WebGL».
    Сложный путь

    Если вы сами разрабатываете на WebGL или вам нужны новейшие возможности, тогда вам просто необходимо иметь самую последнюю версию браузера. WebGL поддерживается в версиях для разработчиков всех браузеров, кроме Internet Explorer, поэтому вам остается просто выбрать подходящую версию для вашего компьютера. Насколько это легко — зависит от того, какой у вас компьютер:

    Firefox

    «Нестабильная» версия Firefox для разработчиков называется Minefield. Она обновляется каждую ночь и уже довольно надежная: я не замечал падений в последнее время (а я использую ее постоянно). Она может работать наряду с обычной версией Firefox, поэтому не нужно волноваться, что придется удалять ее, если вы прекратите ей пользоваться или просто на время переключитесь в обычную версию Firefox.

    Для получения Minefield:

    • Открывайте страницу ночных сборок и выбирайте подходящую версию для вашего компьютера. Будьте внимательны! Там может быть множество версий, с именами типа «firefox-10.0a1что-то там» или «firefox-10.0a2что-то там». Вам нужна самая последняя, где будет самое большое число после ‘a’ (альфа) или ‘b’ (бета).
    • Запускайте Minefield.

    Полезная подсказка — если вы хотите работать с Minefield вместе с обычным Firefox, вы можете сделать это добавлением аргументов командной строки: -P Minefield -no-remote. Первый аргумент запускает его с отдельным профилем (чтобы у вас были раздельные истории и наборы открытых вкладок в каждом браузере), а второй параметр обозначает, что при запуске Minefield, когда Firefox уже открыт, Minefield не будет открыт новой вкладкой в уже запущенном Firefox. Возможно, вы также захотите добавить -P default -no-remote к аргументам запуска обычного Firefox для аналогичного эффекта. Пользователям Windows: вы можете установить аргументы командной строки для любого приложения, кликнув правой кнопкой мыши на иконке приложения, затем выбрав «Свойства» и добавив параметры в конец поля «Объект». Пользователям Mac и Linux — я не знаю, как вы это делаете, но вероятно, что вы и сами в курсе:).

    Запуск Minefield с программным рендерингом на Linux

    Если ваша видеокарта — или драйвер, что более вероятно — не поддерживают OpenGL 2.0, то единственный способ добиться работы WebGL на Linux — использовать библиотеку под названием Mesa. По существу, Mesa эмулирует видеокарту на программном уровне, поэтому работает она медленнее — но это лучше, чем ничего. Mesa интегрируется с Minefield, «нестабильной» версией Firefox для разработчиков, обычно это часть вашего дистрибутива Linux. И вот как все это можно сделать:

    • Скачайте последнюю версию Minefield
    • Установите ее (на это время вам нужно будет закрыть все открытые экземпляры Firefox).
    • Через менеджер пакетов Linux убедитесь, что Mesa установлена и обновлена до последней версии
    • Запускайте Minefield.
    • Перейдите на страницу «about:config»
    • Отфильтруйте по «webgl»
    • Установите значение настройки «webgl.enabled_for_all_sites» в значение «true».
    • Установите значение настройки «webgl.software_rendering» в значение «true».
    • Пропишите в «webgl.osmesalib» путь к библиотеке OSMesa (обычно это /usr/lib/libOSMesa.so).
    Safari

    Запомните, что Safari поддерживает WebGL на Mac с системой Snow Leopard (OS X 10.6). Если у вас Leopard (10.5), Windows или Linux, то вам нужно использовать или (при более старой версии OS/X я не знаю браузера, который вы могли бы использовать 🙁).

    Итак, если у вас Snow Leopard, вам необходимо:

    • Убедитесь, что у вас по крайней мере четвертая версия Safari.
    • Загрузите и установите ночную сборку WebKit
    • Откройте терминал и выполните в нем команду: defaults write com.apple.Safari WebKitWebGLEnabled -bool YES
    • Запустите установленный WebKit
    Chromium

    Если вы хотите создаете страницы с использованием WebGL, разработчики Chrome рекомендуют использовать ночные сборки Chromium — браузера с открытым исходным кодом, на котором основан Chrome. Схема немного отличается для каждой операционной системы. Здесь инструкции для , и . (Предупреждение: я пробовал только на Windows, но мне сказали, что настройки остальных ОС тоже в порядке. Оставляйте комментарии, если это не так 🙂).

    Windows
    • Открывайте , прокрутите вниз до самой последней сборки и нажмите на ссылку для получения chrome-win32.zip
    • В распакованном каталоге запустите chrome.exe
    Macintosh
    • Открывайте страницу непрерывной интеграции , прокрутите вниз до самой последней сборки и нажмите на ссылку для получения chrome-mac.zip
    • Распакуйте файл в удобном для себя месте
    • Откройте терминал и перейдите в распакованный каталог chrome-mac
    • Выполните следующую команду: ./Chromium.app/Contents/MacOS/Chromium
    • После того как убедитесь, что все работает, вы, возможно, захотите немного автоматизировать вещи, чтобы не набирать команду каждый раз. Julien Limoges подсказал для этого полезный shell-скрипт .
    Linux
    • Открывайте 32-разрядную или 64-разрядную страницу непрерывной интеграции, прокрутите вниз до самой последней сборки и нажмите на ссылку для получения chrome-linux.zip
    • Распакуйте файл в удобном для себя месте
    • Убедитесь, что Chrome не запущен
    • Выполните следующую команду: ./chrome
    Несколько примеров

    Если же WebGL работает, то все настроено правильно! К сожалению, последние изменения в WebGL поломали многие примеры, но есть несколько обновленных:

    • Один из моих собственных примеров — Отскакивающие кубы Мандельброта
    • Реальный пример использования WebGL: ChemDoodle 3D отображает молекулы на веб-страницах
    • Много примеров есть в репозитории Khronos и в разделе Wiki Добавленные пользователями . «Эксперименты Chrome» также содержат раздел WebGL . Большая часть примеров работает и в других браузерах.
    • И, наконец, если вы хотите видеть лучшие примеры WebGL каждую неделю, подпишитесь на мой блог ! Каждый четверг я публикую сводку новостей WebGL, которые мне удалось найти за прошедшие семь дней и обычно в них входит несколько новых примеров.

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

    Устранение неполадок Mac

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

    Windows

    Самая распространенная проблема на Windows — не установлена исполняемая библиотека DirectX — ее можно бесплатно скачать с сайта Microsoft , поэтому стоит попробовать это сделать. Также стоит проверить, не появилось ли новых драйверов для видеокарты — проверьте в обновлениях Windows или на веб-сайте производителя видеокарты. Если это не сработало, возможно драйвер видеокарты находится в «черном списке». На Windows это случается реже, чем на Linux, но все-таки бывает. Посмотрите для подробностей.

    Linux

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

    Если у вас видеокарта ATI или Nvidia, первым делом проверьте свою версию OpenGL. Для этого запустите glxinfo и посмотрите на строку с заголовком «OpenGL version string». Если версия, которую вы видите, меньше 2.0, вам необходимо обновить ваши драйвера. Проверьте веб-сайт производителя видеокарты/компьютера и загляните в менеджер пакетов.

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

    По состоянию на 6 октября 2011 года, как выяснил пользователь Nardon , «Google занес в черный список все драйвера Linux, кроме официальных драйверов nVidia … Firefox 6 и выше разрешил большинство последних драйверов ATI, поэтому WebGL должно работать в этом браузере».

    Если вы не боитесь аварийных завершений работы и используете драйвер из черного списка, вы можете запустить Chrome с параметром командной строки –ignore-gpu-blacklist и посмотреть, что случится (спасибо Jonas Antunes da Silva за подсказку). Если это не исправит положение вещей, возможно для вашей видеокарты просто нет приличных драйверов для работы OpenGL. Возможно, лучшим выбором для вас будет использование программного рендеринга. Снова оставлю .

    Последнее обновление: 1.11.2015

    Сейчас мы напишем первую программу с использованием технологии WebGL. Фактически это будет не одна программа, а два примера, которые покажут в действии механизм WebGL.

    Первый пример

    Создадим какую-нибудь веб-страничку со следующим содержимым:

    Привет WebGL! Ваш браузер не поддерживает элемент canvas void main(void) { gl_FragColor = vec4(1.0, 1.0, 1.0, 1.0); } attribute vec3 aVertexPosition; void main(void) { gl_Position = vec4(aVertexPosition, 1.0); } var gl; var shaderProgram; var vertexBuffer; // установка шейдеров function initShaders() { // получаем шейдеры var fragmentShader = getShader(gl.FRAGMENT_SHADER, "shader-fs"); var vertexShader = getShader(gl.VERTEX_SHADER, "shader-vs"); //создаем объект программы шейдеров shaderProgram = gl.createProgram(); // прикрепляем к ней шейдеры gl.attachShader(shaderProgram, vertexShader); gl.attachShader(shaderProgram, fragmentShader); // связываем программу с контекстом webgl gl.linkProgram(shaderProgram); if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { alert("Не удалсь установить шейдеры"); } gl.useProgram(shaderProgram); // установка атрибута программы shaderProgram.vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); // делаем доступным атрибут для использования gl.enableVertexAttribArray(shaderProgram.vertexPositionAttribute); } // Функция создания шейдера по типу и id источника в структуре DOM function getShader(type,id) { var source = document.getElementById(id).innerHTML; // создаем шейдер по типу var shader = gl.createShader(type); // установка источника шейдера gl.shaderSource(shader, source); // компилируем шейдер gl.compileShader(shader); if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { alert("Ошибка компиляции шейдера: " + gl.getShaderInfoLog(shader)); gl.deleteShader(shader); return null; } return shader; } // установка буфера вершин function initBuffers() { // установка буфера вершин vertexBuffer = gl.createBuffer(); gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); // массив координат вершин объекта var triangleVertices = [ 0.0, 0.5, 0.0, -0.5, -0.5, 0.0, 0.5, -0.5, 0.0 ]; gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(triangleVertices), gl.STATIC_DRAW); // указываем кол-во точек vertexBuffer.itemSize = 3; vertexBuffer.numberOfItems = 3; } // отрисовка function draw() { // установка области отрисовки gl.viewport(0, 0, gl.viewportWidth, gl.viewportHeight); gl.clear(gl.COLOR_BUFFER_BIT); // указываем, что каждая вершина имеет по три координаты (x, y, z) gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, vertexBuffer.itemSize, gl.FLOAT, false, 0, 0); // отрисовка примитивов - треугольников gl.drawArrays(gl.TRIANGLES, 0, vertexBuffer.numberOfItems); } window.onload=function(){ // получаем элемент canvas var canvas = document.getElementById("canvas3D"); try { // Сначала пытаемся получить стандартный контекст WegGL // Если не получится, обращаемся к экспериментальному контексту gl = canvas.getContext("webgl") || canvas.getContext("experimental-webgl"); } catch(e) {} // Если контекст не удалось получить, выводим сообщение if (!gl) { alert("Ваш браузер не поддерживает WebGL"); } if(gl){ // установка размеров области рисования gl.viewportWidth = canvas.width; gl.viewportHeight = canvas.height; // установка шейдеров initShaders(); // установка буфера вершин initBuffers(); // покрасим фон в бледно-розовый цвет gl.clearColor(1.0, 0.0, 0.0, 0.5); // отрисовка сцены draw(); } }

    Я не буду останавливаться на этом коде - основные моменты подробнее мы рассмотрим детально позднее, но, я думаю, комментарии помогут разобраться. Но если вкратце: у нас есть элемент canvas , который представляет полотно для отрисовки сцены WebGL. Далее в виде скриптов javascript объявляются две мини-программы - фрагментный и вершинный шейдер.

    Весь код программы находится в обработчике функции window.onload . Вначале нам надо получить контекст gl , через который и буду вестись все основные действия. Далее программа содержит три основные части: установка шейдеров, установка буфера вершин и сама отрисовка.

    А пока можно запустить веб-страничку в браузере. И браузер явит нам белый треугольник на красном фоне.

    Всего лишь? Это только начало. Позже мы подробнее поговорим о шейдерах, вершинах, геометрических примитивах и т.д. А теперь перейдем ко второму примеру.

    Пример 2

    Второй пример представляет собой хрестоматийный пример вращающегося куба. Вначале загрузим специальную библиотеку Three.js . Ее минимизированную версию можно найти по адресу Three.js . Перейдем по этому адресу и сохраним весь код на жесткий диск в файл под названием three.min.js . Эта библиотека не является необходимой для работы с WebGL, однако она упрощает работу.

    В одном каталоге с загруженной библиотекой создадим файл index.html со следующим содержанием:

    Привет WebGL! window.onload=function(){ var camera, scene, renderer; var geometry, material, mesh; init(); animate(); // инициализация начальных значений function init() { // создаем камеру - перспективная проекция camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 1, 1000); // установка z-координаты камеры camera.position.z = 600; // настройка сцены scene = new THREE.Scene(); // настройка геометрии - в качестве геометрии будет куб // настроим его ширину, высоту и длину по оси z geometry = new THREE.CubeGeometry(200, 200, 200); // настройка материала - установка цвета material = new THREE.MeshBasicMaterial({ color: 0xff0000, wireframe: true}); // настраиваем меш, который будет отображать куб mesh = new THREE.Mesh(geometry, material); scene.add(mesh); // создаем объект для рендеринга сцены renderer = new THREE.WebGLRenderer(); // установка размеров renderer.setSize(window.innerWidth, window.innerHeight); // встраиваем в DOM-структуру страницы document.body.appendChild(renderer.domElement); } // функция анимации function animate() { requestAnimationFrame(animate); // вращение меша вокруг осей mesh.rotation.x += 0.01; mesh.rotation.y += 0.02; // рендеринг сцены - метод, производящий по сути отрисовку renderer.render(scene, camera); } }

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

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

    Но все изменилось с выходом WebGL в последних версиях Firefox и Chrome . API основан на хорошо известном графическом стандарте , дающим доступ через JavaScript плагины к графическому аппаратному обеспечению. Сама 3D графика выводится с помощью элемента canvas из HTML5 .

    Так как в Apple следят за стандартами, то ожидаем выхода Safari с поддержкой WebGL . В компании Opera уже тестируют свою собственную версию, ну и как всегда тормозит Microsoft .

    И так, если у вас есть последний браузер (Chrome или Firefox ), вы можете посмотреть подборку лучших WebGL сайтов.

    1. ROME: "3 Dreams of Black"

    — это тот же самый YouTube , только для 3D видео. По умолчанию сервис показывает видео в 2D , но если нажать кнопку Current 3D mode , то можно попробовать различные режимы 3D , в том числе и красно-синий «анаглиф».


    18. three.js

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

    Большое количество времени было потрачено на создание фреймворков, которые бы облегчили жизнь программистам сайтов, и самый известный из них — это three.js, созданный человеком Mr.doob .

    Этот фреймворк использовался при создании "3 Dreams of Black" (в котором Mr.doob был техническим директором), и сейчас это самый популярный выбор веб-программистов, изучающих 3D