Создание и продвижение сайтов    SCS-900.ru
Создаём и продвигаем
Главная > Блог > 3D-объекты в браузере на HTML5

 

3D-объекты в браузере на HTML5

19.12.2012

3D-объекты в браузере на HTML5

Введение

Однажды к нам обратился заказчик, занимающийся продажей мобильных телефонов через Интернет. Для своего магазина он придумал одну интересную «фишку». Идея заключалась в том, чтобы позволить пользователю видеть товар «во весь рост», чтобы легко можно было оценить габариты товара. Пользователь должен иметь возможность поворачивать устройство любой стороной и его размеры будут в точности совпадать с размером устройства, если его приложить к экрану. Как определить размер пикселя в миллиметрах — для нас было не столь интересно (и эта статья не об этом). Гораздо интереснее оказалась возможность плавно поворачивать устройство на экране.

Магазин должен работать на всех современных платформах, включая смартфоны и устройства от Apple, поэтому об использовании Flash или каких-либо других дополнений к браузерам речи не было: всё должно работать на чистом HTML5. Прежде, чем описывать тернистый путь от идеи до реализации проекта, приведу ссылку и пару картинок — результат скрипта, рисующего трёхмерный объект на HTML5 Canvas.

Рисуем объект

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

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

Тут нам и пригодились знания компьютерной графики, полученные во время обучения в университете (спасибо, Дебелов В. А.). Мы использовали матрицы 4х4 для задания поворотов и сдвигов, перспективную проекцию и определение яркости грани на основе угла между вектором нормали и направлением до источника света. Собственно, это всё, что потребовалось. Легко и просто. Код на Javascript занимает пару сотен строк и это гораздо быстрее, чем разбираться в уже изобретённых велосипедах. После получения проекции и яркости грани, остаётся только нарисовать и залить полигон стандартными средствами Canvas.

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

Данная реализация будет работать во всех браузерах, поддерживающих Canvas. Для IE версии ниже 9 мы использовали Excanvas, скорость работы существенно медленнее, что в Chrome или FF, но оно работает!

Накладываем текстуры

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

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

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

Понятно, что такой трюк не очень точно воспроизводит трёхмерные преобразования, при увеличении числа треугольников и уменьшении размера каждого из них качество картинки улучшается, но с ним уменьшается и скорость наложения текстуры на грань. На картинках ниже представлен результат наложения под углом при делении передней грани на 2, 4, 16, 64 треугольника соответственно.

Как видим, вариант с делением грани на 64 треугольника вполне прилично смотрится даже для достаточно крупных граней и сложных текстур.

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

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

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

В результате, последняя версия обзавелась сразу двумя дополнительными параметрами (их можно менять в верхней части окна). Первый — отвечает за то, как сильно дробить грани на треугольники. Второй — указывает количество пикселей, на которое будет увеличиваться каждый треугольник при заливке. Для FF, в нашем примере, оптимален вариант 1, для Chrome — лучше, конечно же, поставить 0 и не использовать эту фичу.

К сожалению, с появлением текстурирования пришлось также пожертвовать совместимостью с IE 9, т. е. Excanvas не поддерживает клиппирование и не получается вывести текстуру в ограниченную область.

Планы на будущее

В данной реализации, у нас рисуется простая геометрическая фигура в 3D на HTML5 Canvas. Однако ничего не мешает рисовать более сложные объекты (текущий движок уже это позволяет). У нас в планах — создать полноценную библиотеку, которую можно было бы применять в интернет-магазинах для демонстрации товара.

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

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

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

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

 


Комментарии

 

 

Услуги:

Заказать сайт

Стоимость сайта

Портфолио

Блог

О нас

Контакты

 


 

Контакты:

 

    Сайт создан в 2013 г. © SCS-900.ru
    E-mail: aleksei.seoded@gmail.com
    Наш адрес: 630007, г. Новосибирск, Красный проспект, 1, офис 503 и 516