Что выбрать для 3D сайта – Three.js или Blend4Web?

от автора

Я знаю Blender много лет, использую Unity для своих игр, но полный новичок в WebGL. Однако, будущее именно за этой технологией, и неплохо было бы разобраться с ее использованием. К сожалению, экспортер Unity для WebGL пока не рабочий и нужен иной инструмент.

Я не люблю изобретать велосипед и предпочитаю готовые решения. Найденный ранее Blend4Web выглядит очень заманчиво (интеграция с Blender, качественный экспортер и т.д.), но ведь существует немало других библиотек и платформ для работы с WebGL.

Извечный вопрос: что выбрать новичку? Я поработал с платформами Blend4Web и Three.js. Что из этого вышло — читайте дальше.
image

Базовые знания:

  • Blend4Web тесно интегрирован с Blender, поэтому требуется установленный и настроенный соответствующим образом пакет Blender.
  • Three.js — программная библиотека. Умеет импортировать сцены и объекты из того же Blender. Для этого также нужно установить специальный плагин в редактор.

Я не буду подробно рассматривать процесс настройки обеих платформ, но коснусь одного важного момента. Так как системы предназначены исключительно для создания приложений WebGL, то для тестирования их необходимо поднимать локальный сервер. В случае с Blend4Web, после развертывания SDK, вы уже получите рабочий сервер по адресу: localhost:6687 (порт можно изменить в настройках). Для Three.js такой сервер придется устанавливать отдельно. Например, использовать WampServer или выбрать подходящий из папки Utils (SDK Three.js).

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

Работа с Three.js

Думаете — привычный “Hello World”? А вот и нет, специализированное “hello”, но только с точки зрения 3D. В первую очередь меня интересует практическое применение и удобство использования. Поэтому я попробовал сделать самое примитивное — стандартную сцену с объектами, камерой, освещением и простой анимацией.

Кроме того, на изучение и работу с каждой платформой предполагалось затратить не более 3 часов (для чистоты эксперимента). Этакий марафон с нуля.

Начальный выбор пал на Three.js. Итак стартую…

Все начинается с документации. Она у движка лаконична и имеет индивидуальные небольшие примеры почти для каждой функции. В SDK находится большое количество практических проектов.

Сначала рассмотрим заготовку HTML:

<html> <head> <title>Test</title>     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>     <script type="text/javascript" src="three.js"></script> </head>  <body>     <div>         <div id="webGL-container" >     </div>     <script type="text/javascript" src="main.js"></script> </body> </html> 

Эта универсальная заготовка и ничего интересного здесь нет. Библиотека Three.js подключается в строке . Имеется более компактный вариант three.min.js. Однако, я решил остановится на полной версии. Исполняемый код вынесен в отдельный файл main.js. Именно в нем я собираюсь хранить код работы с движком.

Создание кода для Three.js начинается с объявления сцены, камеры и рендера:

var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer(); 

После этого можно приступить к созданию объектов. В моем случае я остановился на обычном кубе.

var geometry = new THREE.BoxGeometry( 1, 1, 1 ); var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); var cube = new THREE.Mesh( geometry, material ); 

Создал геометрию, настроил цвет, смешал и вот он Куб. Ах, да, еще нужно добавить его в сцену командой scene.add( cube );

Теперь с этим объектом можно делать что угодно. Например, повернуть его немного по одной из оси.

cube.rotation.z += 0.1; 

Точно также необходимо сместить камеру, ведь по умолчанию она создается в координатах (0,0,0), как и куб.

camera.position.z = 5; 

И последний завершающий штрих — это инициализация и вызов рендера. Целиком базовый код тестовый сцены выглядит следующим образом:

$(function() { var scene = new THREE.Scene(); var camera = new THREE.PerspectiveCamera( 45, window.innerWidth/window.innerHeight, 0.1, 1000 ); var renderer = new THREE.WebGLRenderer();  renderer.setSize (window.innerWidth,window.innerHeight); renderer.setClearColor (0x000000);  var geometry = new THREE.BoxGeometry( 1, 1, 1 ); var material = new THREE.MeshBasicMaterial( { color: 0xffffff } ); var cube = new THREE.Mesh( geometry, material );  scene.add( cube ); camera.position.z = 5; cube.rotation.z += 0.1;  $("#webGL-container").append (renderer.domElement); renderer.render(scene, camera); }); 

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

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

var light = new THREE.PointLight(0xffffff); light.position.set(-100,200,100); scene.add(light); 

Как инди-разработчик игр я понимал, что отсутствие редактора ставит крест на использовании этой библиотеки, по крайне мере для меня. Но люди же работают с ней и делают прикольные вещи! И покопавшись на сайте разработчиков, я нашел две интересные утилиты: плагин под Blender и некий редактор, заточенный исключительно под Three.js.

Первым делом я попробовал поработать с плагином. Помните какая была поставлена задача? Создать сцену с объектами, камерой и светом.

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

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

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

API Three.js содержит более десятка загрузчиков для различных объектов. Естественно, я выбрал универсальный THREE.JSONLoader. Этому способствовала официальная документация и большое количество уроков, которые я просмотрел. Вот только ни черта это не работало!

//инициализация var loader = new THREE.JSONLoader();  loader.load( "plane.json", createScene1 );   //обработка после загрузки объекта function createScene1( geometry, materials ) { mesh = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );     scene.add( mesh ); } 

Я экспериментировал с разными настройками экспортера, пробовал иные конструкции загрузчика, почерпнутые из уроков в сети Интернет, альтернативные функции — результата ноль. Консоль упорно мне твердила: “Некорректный JSON ”, а экран показывал девственно чистый вид.

Как вы думаете, где была загвоздка? Смешно сказать — в отсутствии света. Да, это дурацкая ошибка человека, привыкшего работать в полноценных редакторах. В том же Blender или Unity, удаление источников света позволяло видеть объекты в сцене, тут же чистый программный код. Но вот отсутствие в официальных туториалах такой вроде бы явной особенности, попортило немало моей крови. Кстати, ошибка “Некорректный JSON ” так и не пропала. Ну да ладно, перехожу к загрузке сцены.

Собственно — это самое главное, что меня интересовало. Возможность настроить и расставить объекты в Blender, перегнать их в JSON и управлять ими в коде. Поиск в сети Интернет вывел меня на функцию THREE.SceneLoader. Вроде то, что нужно!

Вот только в официальной справке по API подобной функции не нашлось. Дальнейшие поиски в сети принесли информацию, что данная функция была удалена за ненадобностью. Это был крутой облом…

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

Итак, что мы имеем. Запускаемый в браузере трехмерный редактор позволяет импортировать модели, расставлять их и выполнять настройку. Обратно можно экспортировать отдельный объект, сцену в виде JSON и цельного приложения с оберткой в HTML. Изучать редактор я не стал, так как до этого не нашел функции загрузки сцены JSON в свой проект. Кроме того, два часа ночи сигнализировало, что время отведенное на Three.js явно закончилось.

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

$(function() { var container,scene,camera,render,cube;  init(); render();  function init() {  container = document.getElementById( 'webGL-container' ); camera = new THREE.PerspectiveCamera( 40, window.innerWidth / window.innerHeight, 1, 10000 ); camera.position.z = 10;  scene = new THREE.Scene();  light = new THREE.DirectionalLight( 0xffffff ); light.position.set( 0, 0, 1 ).normalize(); scene.add( light );  var loader = new THREE.JSONLoader(); loader.load( "cube.json", createScene1 );  renderer = new THREE.WebGLRenderer( { antialias: true } ); renderer.setPixelRatio( window.devicePixelRatio ); renderer.setSize( window.innerWidth, window.innerHeight ); container.appendChild( renderer.domElement );                 }      function createScene1( geometry, materials ) { cube = new THREE.Mesh( geometry, new THREE.MeshFaceMaterial( materials ) );     scene.add( cube ); }                           function render() {      requestAnimationFrame( render );     cube.rotation.y +=0.01; //вращение куба     renderer.render( scene, camera ); } }); 

Работа с Blend4Web

Я уже рассматривал Blend4Web с точки зрения дизайнера и мне было любопытно, а что может предложить эта платформа программисту. Здесь, по сравнению с Three.js, наоборот опасаешься слишком тесной интеграции с редактором и тем самым урезании возможности программирования.

Blend4Web предлагает всю часть визуальной работы выполнять в Blender: настраивать сцену, создавать модели и расставлять их, управлять физикой или частицами. Поэтому такой проблемы, как с Three.js, и в помине нет. Но вот получить сложное приложение только визуальными средствами не удастся.

Задача остается все той же — создание простой сцены с несколькими объектами, камерой, источником света. Плюс несложная анимация одного объекта программным путем. И, разумеется, ограничение времени работы 3 часами. Вот и посмотрим, насколько удобной и полной окажется документация, интуитивна работа с API. Поехали…

На официальном сайте имеются четкие указания о расположении файлов проекта в папках SDK. Так проекты Blender хранятся в папке SDK/Blender/ProjectName, а ресурсы и собственно результат экспорта в SDK/Deploy/Assets/ProjectName. Первоначально это выглядит снобизмом и не понимаешь смысла столь жестких требований, но со временем доходит, зачем это нужно.

После установки SDK, автоматически поднимается сервер и становится доступным по адресу localhost:6687. На стартовой странице предлагается документация и примеры, но главное — сервер можно использовать для тестирования своих приложений.

Я создал несложную сцену в Blender с указанными ранее объектами и сохранил все данные, как требует справка SDK. Первый сюрприз поджидал при попытке экспорта в JSON. В настройках экспортера есть опция Run in Viewer и если ее включить, то после экспорта результат немедленно откроется в браузере в специальном просмотрщике. В нем окончательно можно проверить свою сцену и даже выполнить настройку всех параметров объектов или окружения.

Итак, результат экспорта — это два файла: json и bin. Последний содержит массивы данных по моделям. Теперь настало время создать запускаемый файл.

Первый вопрос, который меня озадачил — это не как писать, а куда сохранять скрипты и HTML. Так как разработчики Blend4Web призывают использовать определенные папки для проекта, то и логично было бы предположить, что и для программных частей предусмотрено свое место. Подтверждения этому я не нашел и просто создал файлы в папке с Deploy/Assets/ProjectName.

По традиции я вынес исполняемый код в отдельный скрипт. В связи с этим обертка HTML выглядит следующим образом:

<!DOCTYPE html> <html> <head>     <script type="text/javascript" src="b4w.full.min.js"></script>     <script type="text/javascript" src="main.js"></script>     <style>             #container_id {             position: absolute;             width: 100%;             height: 100%;         }     </style> </head>  <body>     <div id="container_id"></div> </body>  </html> 

В HTML ничего интересного нет, поэтому перейдем к main.js. Инициализация движка и загрузка сцены осуществляется в несколько этапов. Сначала подключаем необходимые модули:

var app = b4w.require("app"); var data = b4w.require("data"); 

Затем выполняем инициализацию:

app.init({ canvas_container_id: "container_id", physics_enabled: false, autoresize: true, callback: load_cb }); 

По названию аргументов, я думаю, понятно, что делает функция init. После инициализации происходит вызов функции load_cb. В ней можно разместить загрузку JSON.

function load_cb() {     data.load("test.json", loaded_cb); } 

Последняя функция в тестовом скрипте — это loaded_cb, которая вызывается после загрузки сцены. Здесь создается логика приложения.

function loaded_cb() { //что-то там //например можно включить управление камерой в сцене     app.enable_controls();     app.enable_camera_controls(); } 

Загрузка сцены в Blend4Web оказалась делом очень простым. Все, что я включил в Blender — движок корректно отобразил. Нет проблем с расстановкой объектов, включением теней, настройкой мешей и т.д. Но вот как дело обстоит с доступом к отдельным объектам? Понятное дело, что можно сделать анимации в Blender и запускать их программно. Я уверен в этом, хотя и не искал. Но мне нужно простое вращение вокруг оси, по принципу выполненному для Three.js (cube.rotation.y +=0.01).

Сделать это оказалось сложнее, чем я рассчитывал. API Blend4Web имеет функцию, позволяющую вызывать пользовательские процедуры каждый кадр, и с этой стороны все в порядке. Однако я не нашел возможности непосредственного вращения по осям. Можно использовать только кватернионы. В связи с этим код получился несколько громоздким:

function render () { var Cube = scene.get_object_by_name("Cube"); var _angle = 0.05; var _vec4; var obj_quat = transform.get_rotation(Cube, _vec4); quat.rotateY(obj_quat, _angle, obj_quat); transform.set_rotation_v(Cube, obj_quat); } 

Небольшие итоги

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

Three.js — это популярная библиотека, для которой написано множество уроков, в том числе и на Хабре. Однако, базовые функции создавались мною со скрипом. Баснословное время потрачено на простейшую загрузку модели в сцену. Могли бы, наверное, в официальный туториал внести информацию об обязательных источниках света. Ну, хотя бы, для таких “крутых” программеров, как я.

Самое главное — я привык работать с комфортом и видеть то, что делаю. Мне нужен редактор для подготовки сцены и совсем не интересны проблемы, связанные с перегоном данных для движка. Я сел делать игру, а не ковыряться с неработающими базовыми функциями. Время — деньги, а Three.js отнял его предостаточно.

Ситуация с Blend4Web выглядит гораздо лучше, но не все так блестяще.

Вся подготовка сцены осуществляется в полноценном редакторе и даже не задумываешься, как движок будет все это воспринимать — это его задача, а не разработчика. Однако, всплыли проблемы, связанные с непосредственным программированием.

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

Документация Three.js изобилует множеством маленьких примеров. К сожалению, для Blend4Web их нет. Поэтому приходилось листать уроки и смотреть обширные листинги. Взял немного с одной страницы, еще чуть-чуть с другой. В итоге написал код, который с успехом мог бы быть уже в примерах документации SDK. Да, есть такое приложение в SDK — Code Snippets, демонстрирующее различные возможности платформы с показом исходников. Но хотелось бы именно маленьких и простых примеров. Как двигать объект, как вращать модель, как привязать выполнение функции к обновлению кадра и т.д. Так, для вращения объекта я взял кусок кода из примера игры на официальном сайте. Но может быть есть более оптимальный вариант вращения, нежели через непосредственное изменение кватернионов? В итоге я использовал только то, что нашел.

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

Сцена Three.js
Сцена Blend4Web

ссылка на оригинал статьи http://habrahabr.ru/post/262749/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *