Webgl примеры 3d. Оживление объектов при помощи 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 устанавливает цвет.

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

  1. attributes - доступны только в вершинном шейдере, разные для каждой из вершин;
  2. uniforms - доступны в обоих шейдерах и одинаковы для всех вызовов шейдера;
  3. 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, то для атрибутов нужно использовать ещё одну сущность - буферы. Данные буферов хранятся в памяти видеокарты, что даёт значительный прирост в скорости рендеринга.

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

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

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

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

  • (0, 0, 0);
  • (0.5, 1, 0);
  • (1, 0, 0).
Стоит отметить, что при работе с буферами следует учитывать несколько особенностей:
  1. данные в буфер передаются одним массивом без вложенности, в случае нашего треугольника данные будут выглядеть следующим образом: ;
  2. передаваться должны только типизированные массивы ;
  3. прежде чем передать данные, вы должны точно указать, какой буфер будет использоваться, методом 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. (1, 0.5, 0.5)
  2. (0.5, 0.7, 1)
  3. (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) принимает пять параметров:

  1. matrix - матрица, которую необходимо изменить;
  2. fov - угл обзора в радианах;
  3. aspect - cоотношение сторон экрана;
  4. near - минимальное расстояние до объектов, которые будут видны;
  5. 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 технологии открывают для разработчиков целый мир возможностей, которые можно реализовать прямо в окне браузера. Сегодня я хочу представить Вам 9 крутых примеров, которые Вам точно понравятся и Вы их ни в коем случае не должны пропустить!

WebGL вода

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

Белые квадраты — Fizzy Cam

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

Листья

Реалистичные листья которые подхватывает и уносит вдаль ветер. Вроде бы просто всё смотрится, но узнавая, что это реализовано в веб браузере, становится довольно интересно и необычно.

Научи меня летать

Мини игра, которая сделан в веб браузере на WebGL технологиях. В прочем очень просто, и сделано для того чтобы показать, на что способны новейшие технологии. Очень круто.

Большой глаз

В этом демо показан большой глаз, который следит за курсором. А если у Вас ещё и играет музыка, он пульсирует и изменяет цвета. Немного приводит в шок:) но и впечатляет не меньше.

Частицы

Крутая анимация частиц в веб — браузере, смотрится очень красиво и необычно. Также Вы можете добавить количество частиц и покрутить анимацию.

Глобус

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

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

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

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

Заставим квадрат вращаться

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

Var squareRotation = 0.0;

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

MvPushMatrix(); mvRotate(squareRotation, );

Этот код сохраняет матрицу текущего положения, затем поворачивает матрицу на текущее значение переменной squareRotation вокруг осей X и Z.

После отрисовки мы восстанавливаем изначальное состояние матрицы положения:

MvPopMatrix();

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

Чтобы заставить квадрат крутиться нам нужно добавить в программу код, который будет изменять значение переменной squareRotation во времени. Для этого мы заведём ещё одну переменную в которую будем записывать время последней отрисовки (давайте назовём её lastSquareUpdateTime), затем добавим следующий код в конец нашей процедуры drawScene() :

Var currentTime = (new Date).getTime(); if (lastSquareUpdateTime) { var delta = currentTime - lastSquareUpdateTime; squareRotation += (30 * delta) / 1000.0; } lastSquareUpdateTime = currentTime;

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

Сделаем так, чтобы квадрат начал двигаться

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

Давайте отслеживать сдвиг положения квадрата по каждой оси в новых переменных:

Var squareXOffset = 0.0; var squareYOffset = 0.0; var squareZOffset = 0.0;

И расстояние на которое нужно сместить квадрат по каждой из осей в следующих переменных:

Var xIncValue = 0.2; var yIncValue = -0.4; var zIncValue = 0.3;

Теперь мы можем просто добавить следующий код к уже написанному, который обновляет положение угла поворота:

SquareXOffset += xIncValue * ((30 * delta) / 1000.0); squareYOffset += yIncValue * ((30 * delta) / 1000.0); squareZOffset += zIncValue * ((30 * delta) / 1000.0); if (Math.abs(squareYOffset) > 2.5) { xIncValue = -xIncValue; yIncValue = -yIncValue; zIncValue = -zIncValue; }

И, наконец, мы добавляем в процедуру drawScene() следующий код:

MvTranslate();

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

Если ваш браузер поддерживает работу с WebGL, в действии.

Больше операций с матрицами

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

Var mvMatrixStack = ; function mvPushMatrix(m) { if (m) { mvMatrixStack.push(m.dup()); mvMatrix = m.dup(); } else { mvMatrixStack.push(mvMatrix.dup()); } } function mvPopMatrix() { if (!mvMatrixStack.length) { throw("Can"t pop from an empty matrix stack."); } mvMatrix = mvMatrixStack.pop(); return mvMatrix; } function mvRotate(angle, v) { var inRadians = angle * Math.PI / 180.0; var m = Matrix.Rotation(inRadians, $V()).ensure4x4(); multMatrix(m); }

Эти утилиты были заимствованы из примера разработанного Владом Вукицевичем (Vlad Vukićević).

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

Первое, что вам нужно сделать при начале работы с 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. Возможно, лучшим выбором для вас будет использование программного рендеринга. Снова оставлю .



Есть вопросы?

Сообщить об опечатке

Текст, который будет отправлен нашим редакторам: