Каталоги Сервисы Блограйдеры Обратная связь Блогосфера
Какой рейтинг вас больше интересует?
|
Введение в WebGL2016-07-29 08:00:10В данном обзоре мы создадим простую 3d-программу, используя WebGL. Сначала мы ...
В данном обзоре мы создадим простую 3d-программу, используя WebGL. Сначала мы будем использовать
WebGL Api напрямую. Потом сделаем варианты на популярных WebGL-фреймворках Three.js и BabylonJS. Небольшое вступлениеWebGL позволяет использовать в браузере преимущества аппаратного ускорения трехмерной графики без установки плагинов. WebGL основана на OpenGL ES 2.0, которая в свою очередь базируется на спецификации OpenGL 2.0 и используется на мобильных устройствах. Название “WebGL” можно интерпретировать как “OpenGL для браузеров”. В состав рабочей группы WebGL, разрабатывающей стандарт, входит некоммерческая организация Khronos Group, а также разработчики ведущих браузеров. Первая версия WebGL была выпущена в 2011 году. На данный момент последней является версия 1.0.3, выпущенная в 2014, и ожидается выход версии 2.0. Версия 2.0 основана уже на OpenGL ES 3.0 API. Все популярные браузеры (Safari, Chrome, Firefox, IE, Edge) поддерживают WebGL, в том числе и на мобильных устройствах. Позже всех включили поддержку WebGL в своих браузерах Apple и Microsoft: Apple - начиная с Safari 8 в 2014 году, Microsoft - начиная с IE 11 в 2013 году. WebGL используется не только для создания 3d-программ. Многие 2d-фреймворки используют WebGL, получая все преимущества аппаратного ускорения. Используем WebGL Api напрямуюДаже если вы используете WebGL-фреймворк и не собираетесь участвовать в разработке оного, знания по WebGL необходимы для понимания того, что происходит в вашей программе, для решения возникающих задач, в том числе проблем производительности. И Three.js и BabylonJS предоставляют api низкого уровня, которое близко к использованию нативного api. Иногда возникает потребность переписать / дописать часть кода фреймворка специально для своего приложения. Долгое время на официальном сайте Three.js можно было прочитать, что для рисования куба, используя только нативные средства браузера, понадобилось бы написать сотни строк кода. На самом деле нам действительно понадобится больше чем сотня строк, но все не так сложно как то там звучит. Шаг первыйСначала создадим html. Нам нужен элемент canvas и его контекст “webgl”.
Для поддержки устаревших версий браузеров, в частности Internet Explorer 11, нужно проверить контекст “experimental-webgl”.
JavaScript:
Чтобы что-то нарисовать в WebGL, как и в любой программе OpenGL, необходимы шейдеры. По сути, шейдеры - это программы на C-подобном языке, которые выполняются графической картой. Язык, используемый в шейдерах (shading language), ограничен и специально разработан для решения типичных графических задач, например матричных/векторных операций. В WebGL используется язык шейдеров OpenGL ES SL. Есть два типа шейдеров: вершинный (vertex shader) и фрагментный (fragment shader). Вершинный используется в основном для описания геометрии. Он выполняется для каждой вершины, которую передали шейдеру. Фрагментный шейдер выполняется для каждого фрагмента изображения (своего рода “пикселя”). Часть данных фрагментный шейдер получает от вершинного шейдера и эти данные интерполируются. В основном он используется для применения освещения, текстур. Его задача - определить цвет каждого фрагмента. Как видно из кода ниже, цвет фрагмента определяется путем присвоения значения специальной переменной gl_FragColor. В вершинном шейдере нужно присвоить значение специальной переменной gl_Position для задания координаты вершины. При этом используются данные, которые передаются из javascript-части, т.е. в нашем случае - это переменная-атрибут aPosition. Переменные gl_FragColor и gl_Position имеют специальное предназначение и их не нужно объявлять самому. Вершинный шейдер, записанный в виде массива:
Фрагментный шейдер в виде массива:
Т.к. шейдеры мы задали массивом, получим код вершинного шейдера таким образом
Рассмотрим код функции createShader, которая создает и компилирует шейдер. Да, компилирует, а потом нас ждет и линкование.
Создание шейдера с указанием типа
Указание кода шейдера
Компиляция шейдера
После компиляции шейдера хорошо бы проверить статус компиляции и вывести информацию об ошибках, если таковые были.
Cозданный шейдер понадобится далее для создания объекта WebGLProgram в методе initProgram. Сначала метод initProgram вызывает createShader, чтобы создать оба шейдера.
Потом создается программа WebGLProgram
Указываем оба скомпилированных шейдера:
И, наконец, обещанное линкование:
Хорошей практикой является проверка статуса линкования и логирование возможных ошибок.
После линкования нужно “принять к использованию” созданную программу, вызвав метод контекста useProgram
На этом этапе программа успешно создана. Остается только передать в шейдеры все нужные данные. Выглядит несколько громоздко, но зато гибко. Можно менять программы во время выполнения. В этом же методе я добавил код для получения ссылок на используемые шейдерами переменные. Получим ссылку на переменную aPosition таким образом
Т.е. ссылка будет храниться в this.prg.aPosition. Приготовим куб, для чего создадим конструктор CubeMesh.
Этому объекту, как видно, нужно передать список vertices (вершины) и indices (индексы или номера вершин). Удобно задавать геометрию в WebGL с помощью списка индексов. В WebGL есть несколько режимов рисования, один из них - это рисование треугольниками. Таким образом, чтобы нарисовать прямоугольник понадобится 2 треугольника. Чтобы нарисовать куб нужно 12 треугольников. Используя индексы, нам достаточно определить 8 вершин и передать графической системе координаты этих 8 вершин, т.е. массив из 24 чисел типа float для задания vertices и 12 наборов по три числа для передачи indices, т.е. дополнительно массив из 36 чисел типа integer. Каждый индекс указывает на соответствующую вершину в массиве вершин. Без индексов при использовании метода рисования gl.TRIANGLES понадобится 12 (кол-во треугольников) * 3 (три вершины) * 3 (3 координаты для каждой вершины) = 108 чисел типа float. Начало системы координат находится в центре области рисования. Ось Y направлена вверх, ось X направлена вправо. Что касается оси Z, то тут можно выбирать на свой вкус. WebGL не навязывает ни правостороннюю ни левостороннюю систему, хотя так называемая усеченная система координат (clip coordinate system) является левосторонней. В усеченной системе, все точки выходящие за отрезок [-1.0, 1.0] удаляются. Все координаты в конце концов приводятся к усеченной системе координат. В Three.js система координат правосторонняя (ось Z направлена на наблюдателя от экрана), как принято в большинстве программ OpenGL, а в BabylonJS левосторонняя система (как долгое время было в DirectX).
halfSize здесь это половина размера куба. Покаместь мы задали координаты в усеченной системе. После задания геометрии, нужно создать буферы памяти и поместить в них заготовленные данные (см. метод initBuffers).
В следующем участке кода задаются некоторые параметры, такие как цвет области рисования и проверка теста глубины.
Окончательный вид конструктора:
В последней строчке конструктора идет вызов метода renderLoop, который вызывает this.render(). В методе render и происходит рисование. renderLoop вызывается в каждом фрейме с помощью requestAnimationFrame, также как и при использовании 2d контекста канваса. Рассмотрим теперь метод render. В нем сначала очищается область рисования, а точнее буфер цвета и глубины.
Потом нужно активировать данные конкретного геометрического объекта. В нашем случае он один.
Если используются индексы, то рисование производится методом drawElements контекста
На данном этапе нарисован красный куб, хотя мы видим квадрат из-за его расположения. Можно было подобрать другие значения координат вершин, чтобы куб был повернут по другому. Итак, имеем всего около 128 строк. Что получилось на данный момент - демо шаг 1. Шаг второй - мировая система координат, вращающаяся камераПерейдем к более удобной системе координат, она будет, кстати, правосторонняя. Для этого создадим объект Camera. Камера будет ответственна за направление взгляда на сцену и за определение области видимости (frustrum), т.е. той области пространства за пределами, которой точки будут отброшены. Это достигается путем матричных преобразований, поэтому нам понадобится вспомогательный объект Matrix. Для удобства введем также объект Vector. Камера будет использовать перспективную проекцию, т.е. frustrum выглядит как усеченная пирамида. Конструктору будем передавать элемент canvas (используется для подсчета aspect ratio - отношения ширины кадра к высоте), угол обзора по оси y, расстояние до ближней и дальней плоскостей области видимости, а также позицию камеры в пространстве. Камера смотрит на начало координат. Реализованную камеру программно можно вращать по поверхности сферы с центром в начале координат, а также перемещать.
Матрицу преобразования камеры нужно передать в вершинный шейдер. Эта матрица состоит из двух матриц: матрицы вида и матрицы проекции. В данной программе в шейдер передаются обе матрицы отдельно и уже там они умножаются. Теперь вершинный шейдер выглядит так:
В initProgram добавлены две строчки для получения ссылок на переменные:
Чтобы передать данные в шейдер, в методе render добавлены такие две строчки перед прорисовкой сцены:
Поскольку сейчас используется камера, размеры куба можно увеличить, иначе он будет слишком маленький. В css я внес некоторые изменения, теперь область рисования занимает всю клиентскую часть браузера. Чтобы изображение оставалось пропорциональным добавлен метод handleSize, который вызывается при ресайзе окна и вначале работы программы. Наконец, в renderLoop перед вызовом метода render, добавим вызов this.camera.update() с несколькими строчками, которые обеспечивают вращение камеры вокруг начала координат и куба. Итак, вращающийся куб готов (на самом деле вращается камера) - демо шаг 2. Да, нам понадобилось почти три с половиной сотни строк, но выглядит это не как “страшные многие сотни”. Поэтому, считаю выражение в документации Three.js несколько преувеличенным. Заметно, что часть кода легко выносится отдельно для повторного использования: объект Matrix для операций с матрицами, Vector для операций с векторами, создание и компиляция шейдеров, функционал камеры. Шаг третий - важность светаДобавим теперь простенькое освещение, которое придаст объем трехмерной сцене. Будем использовать точечный источник цвета. Освещение в нашем случае будет вычисляться в вершинном шейдере. Вычисления во фрагментном шейдере дают более реалистичное затенение. Таким образом, в вершинном шейдере вычислим цвет каждой вершины. Чтобы передавать данные между шейдерами нужно использовать varying-переменные. Цвет будет передаваться во фрагментный шейдер с помощью varying-переменной vColor. Значения цвета при этом интерполируются. В вершинный шейдер добавлен следующий участок кода:
Как в вершинном, так и во фрагментном шейдере нужно объявить varying-переменную vColor. В вершинном шейдере понадобится еще uniform-переменная uLightPosition (позиция источника цвета), переменная-атрибут aNormal (нормаль к вычисляемой вершине) и матрица нормалей uNMatrix.
Во фрагментном шейдере все остается просто:
Получаем ссылки на переменные в initProgram:
В методе render передаем информацию о позиции источника света и матрицу нормалей:
Поскольку куб не двигается, в нашем случае его матрица нормалей будет всегда единичной матрицей и ее можно не использовать. Иначе, матрицу нормалей нужно пересчитывать для каждого освещаемого объекта на сцене при каждом перемещении. Для передачи данных о нормалях нужно создать буфер нормалей. Конструктор CubeMesh теперь принимает массив нормалей. В функции initBuffers добавлено создание буфера нормалей,
а в функции render:
И функция создания куба createCube конечно же претерпела изменения, т.к. нужно задать массив нормалей:
Итого, добавилось еще около 50 строчек кода и освещение готово. Можно заметить, что благодаря строчке
источник света перемещается вместе с камерой - демо. Используем Three.jsThree.js - одна из самых первых и самых популярных библиотек. Итак, реализуем функционал на Three.js.
Самые важные понятия в 3d-фреймворках это: renderer или engine, scene и camera. Начнем
с инициализации и настройки этих трех элементов в конструкторе приложения.
Как видно, дополнительные опции передаются в конструкторе в виде объекта. Таким образом можно указать renderer, что канвас должен занимать всю клиентскую область экрана:
Последний параметр называется updateStyle и заставляет поменять у канваса свойства style.width и style.height. Устанавливаем цвет фона:
Создаем сцену, которая будет содержать все графические объекты:
В Three.js есть несколько камер. Мы будем использовать камеру с перспективной проекцией.
Аргументы конструктора практически те же, что нужны нам были при создании оригинального приложения на нативном WebGL. Нам нужно указать fov (field of view) в градусах (в самостоятельно реализованной камере в радианах), aspect ratio (в самостоятельно реализованной камере высчитывался в коде камеры), near - расстояние до ближней плоскости отсечения области видимости, far - расстояние до дальней плоскости отсечения. Чтобы указать, на какую точку должна смотреть камера, нужно вызвать метод lookAt:
Для указания позиции камеры используем просто свойство position:
Кстати, position является экземпляром THREE.Vector3. Чтобы добавить камеру к сцене нужно выполнить следующий код:
В оригинальном приложении используется точечный источник света. Добавим его и здесь
Цвет света - это первый аргумент. Второй - интенсивность света. Третий аргумент позволяет влиять на эффект затухания света при удалении от него и это расстояние, где интенсивность равна нулю. Если указать ноль, то затухание будет отсутствовать. Именно такое поведение без эффекта затухания в оригинальном приложении, поэтому я указал 0. Следующий участок кода привяжет источник света к камере:
Этого мы достигали в первом приложении с помощью this.light.position = this.camera.position;. Задача сохранения пропорций изображения и его разрешения решается таким образом:
Последние две строчки очень важны. Они позволяют обновить свойство aspect камеры и ее матрицу проекций. В методе createCube, как и прежде, создается главный и единственный геометрический объект сцены - куб.
Как можно догадаться, все три аргументы - это размеры куба по соответствующим осям: x, y и z. Создание материала:
Названия параметров говорят сами за себя. Теперь можно создать экземпляр THREE.Mesh и добавить его к сцене:
Рассмотрим немного метод run.
Я думаю, можно легко увидеть соответствие между методами run в нативном приложении и приложении на Three.js. В методе update мы изменяем свойства rotation.x и rotation.y у cubeMesh, чтобы куб вращался вокруг осей x и y соответственно. Вращение задается в радианах.
Методы update и checkRotateLimits обеспечивают нужный характер вращения с ограничениями. Порт оригинального приложения на Three.js готов, для чего понадобилось около 85 строчек кода. Используем BabylonJSBabylonJS моложе Three.js. Первый релиз состоялся в 2013 году. Но BabylonJS стремительно развивается и сейчас является одним из самым популярных WebGL-фреймворков. Ссылка на официальный сайт BabylonJS. Настал черед портировать приложение на BabylonJS. На самом деле большинство фреймворков используют одинаковые понятия и многое окажется сходным с реализацией на Three.js. Структура приложения осталась та же, методы update и checkRotateLimits вообще не нужно менять. Проверить поддержку WebGL браузером в BabylonJS можно следующим образом:
После этой проверки создадим экземпляр BABYLON.Engine, который является аналогом THREE.WebGLRenderer. Первым аргументом передается элемент canvas. Второй включает / отключает поддержку сглаживания (antialias).
Создание и настройка сцены
В качестве камеры я выбрал ArcRotateCamera. Нужно заметить, что BabylonJS камера отвечает и за ее управление. Данная камера вращается вокруг указанной точке по сфере с указанным радиусом.
Первый аргумент - название камеры. Никто не мешает использовать несколько камер в одной сцене, существуют методы для
получения камеры по ее имени. Создание точечного источника света в указанной позиции и настройка некоторых его параметров:
Позиция источника света, указанная в конструкторе неважна, т.к. с помощью
мы привязываем источник света к камере. Таким образом, через свойство parent можно связать объекты в BabylonJS. Для того, чтобы картинка не искажалась при изменении размеров браузера, в BabylonJS достаточно сделать следующее
Т.е. все, что нужно - это вызвать метод resize у объекта engine. Создание Mesh в BabylonJS выглядит следующим образом
В BabylonJS, как в Three.js заготовлено много различных геометрических объектов для использования и различные виды материалов. Так выглядит метод run:
Нет необходимости использовать requestAnimationFrame. Вместо этого используется engine.runRenderLoop c указанием функции, которая должна выполняться в каждом фрейме. Для прорисовки сцены необходимо вызвать render
Можно зарегистрировать функции с помощью scene.registerBeforeRender и scene.registerAfterRender (названия говорят сами за себя). Как замечено выше, методы update и checkRotateLimits не поменялись. Каждый Mesh в BabylonJS содержит свойства с такими же именами, как в Three.js для вращения и изменения позиции: rotation и position. Реализация на BabylonJS готова, понадобилось около 80 строчек кода. Как видим, реализации на различных фреймворках оказались очень схожими. Тем не менее, нужно сказать, что BabylonJS позиционируется как полноценный игровой движок и в нем есть много удобных средств для разработки игр:
А Three.js позиционируется как 3D-библиотека общего назначения:
В то же время, в Three.js многое компенсируется плагинами. В целом, оба рассматриваемых средства разработки WebGL-приложений обладают хорошими возможностями и активно разрабатываются. Еще пару словТеперь пару слов о Three.js и BabylonJS с точки зрения организации этих проектов. Среди других средства разработки WebGL-приложений упомяну PlayCanvas, главным
достоинством которого является редактор с возможностью одновременной многопользовательской разработки. PlayCanvas бесплатен
только для публичных проектов. Тэги: webgl HolyJS: с первой попытки2016-06-25 10:08:47Петербургская JavaScript-конференция HolyJS начиналась почти как авантюра. Затевать ... + развернуть текст сохранённая копия Петербургская JavaScript-конференция HolyJS начиналась почти как авантюра. Затевать совершенно новую конференцию, когда время на подготовку очень ограничено — смелое решение. Такой авантюризм хорошо соответствует духу самого JavaScript-мира, где всё происходит стремительно, а смелые решения зачастую необходимы. Но возможно ли в таком случае провести конференцию на высоком уровне, с интересными докладами и без организационных проблем? Что в итоге было на мероприятии? Под катом — рассказ о том, как оно прошло. Читать дальше → Тэги: ecmascript, epam, group, holyjs, javascript, jug.ru, luxoft, rxjava, systems, webgl, блог, веб-сайтов, компании, одноклассники, пуля, разработка, серебряная Этажи: 3D-навигация на WebGL в 2gis.ru2016-04-22 10:19:04+ развернуть текст сохранённая копия В 2014 году 2ГИС выпустил Этажи — это фича, позволяющая посмотреть схему этажей здания и найти на ней нужную организацию. Долгое время она существовала только в мобильных приложениях 2ГИС. Теперь эта возможность появилась и в онлайн-версии. Этажи для веба сделаны на технологии WebGL: они полностью трёхмерные, их можно крутить и приближать. Это первый проект компании, сделанный на этой технологии, и мы хотели бы поделиться опытом реализации. Читать дальше → Тэги: 2gis, 2гис, 3d-графикой, indoor-навигация, javascript, webgl, блог, веб-сайтов, компании, работа, разработка Этажи: 3D-навигация на WebGL в 2gis.ru2016-04-22 10:19:04+ развернуть текст сохранённая копия В 2014 году 2ГИС выпустил Этажи — это фича, позволяющая посмотреть схему этажей здания и найти на ней нужную организацию. Долгое время она существовала только в мобильных приложениях 2ГИС. Теперь эта возможность появилась и в онлайн-версии. Этажи для веба сделаны на технологии WebGL: они полностью трёхмерные, их можно крутить и приближать. Это первый проект компании, сделанный на этой технологии, и мы хотели бы поделиться опытом реализации. Читать дальше → Тэги: 2gis, 2гис, 3d-графикой, indoor-навигация, javascript, webgl, блог, веб-сайтов, компании, работа, разработка Выбираем библиотеку для работы с WebGL2016-03-07 14:56:49Как-то утром, пробегая мимо славного урока, я подумал: «Это круто, только всё же кой-чего тут ... + развернуть текст сохранённая копия Как-то утром, пробегая мимо славного урока, я подумал: «Это круто, только всё же кой-чего тут не хватает». Если надо много кода написать легко и быстро, то нужна нам, без сомнений, для сего библиотека. Только как её нам выбрать, если каждый, кто умеет на гитхабе заводить репозиторий, запилил велосипед свой? И об этом для тебя, друг, напишу сегодня пост вдруг. Дальше проза Тэги: 3d-графикой, development, game, javascript, webgl, анимацией, библиотеки, веб-разработка, работа
Главная / Главные темы / Тэг «w124»
|
Категория «Дизайнеры»
Взлеты Топ 5
Падения Топ 5
Популярные за сутки
300ye 500ye all believable blog bts cake cardboard charm coat cosmetic currency disclaimer energy finance furniture house imperial important love lucky made money mood myfxbook poetry potatoes publish rules salad seo size trance video vumbilding wardrobe weal zulutrade агрегаторы блог блоги богатство браузерные валюта видео вумбилдинг выводом гаджеты главная денег деньги звёзды игр. игры императорский календарь картинка картон картошка клиентские косметика летящий любить любовь магия мебель мир настроение невероятный новость обзор онлайн партнерские партнерских пирожный программ программы публикация размер реальных рубрика рука сайт салат своми событий стих страница талисман тонкий удача фен феншуй финансы форекс цитата шкаф шуба шуй энергия юмор 2009 |
Загрузка...
Copyright © 2007–2024 BlogRider.Ru | Главная | Новости | О проекте | Личный кабинет | Помощь | Контакты |
|