От автора: мы закончили с позиционированием 3D пространства и освещением, но теперь я хочу вернуться в конец предыдущего урока к отрендеренному изображению. В этом уроке я немного отступлю от темы и расскажу вам более подробно про threeJS объекты и материалы, после чего мы вернемся к рендерингу.
Детали
В конце предыдущего урока я создал сферу:
1 |
let marsGeo = new THREE.SphereGeometry (500, 32, 32), |
Радиус сферы составляет 500 единиц, в ней 32 вертикальных и горизонтальных сегмента. По умолчанию все объекты создаются в точке отсчета координат сцены (0 0 0), т.е. нам не нужно двигать их.
Фреймворк threeJS поддерживает множество 3D форм. В следующих статьях я расскажу про них. Сфера – самая простая форма, с которой можно начать.
Что будет, если уменьшить количество сегментов до 4 в каждом направлении сферы?
Визуальный эффект увеличения сегментов сферы: 4, 8, 16 и 32 (по горизонтали и вертикали) для объекта сферы
С минимальным количеством сегментов у сферы очень резкие края. Сферической выглядит только передняя сторона объекта с шейдерами (о них чуть ниже), на которую падает свет.
Главное правило – чем больше сегментов у объекта, тем плавнее он выглядит. Однако бесплатный сыр только в мышеловке: большее количество сегментов увеличивает время на вычисления и рендеринг сцены, а также увеличивает использование ОЗУ.
Лучший баланс – нужно определить, сколько деталей нужно объекту. Если сфера очень маленькая и расположена далеко, ей не нужно много сегментов, чтобы выглядеть круглой. Однако если сделать близкий облет планеты, нам понадобится побольше сегментов, чтобы сфера постоянно была гладкой.
Бутерброд из материалов
В последнем примере я применил к сфере материал Phong:
1 |
marsMaterial = new THREE.MeshPhongMaterial( { color: 0xff6600 } ), |
Phong – это шейдерный алгоритм, написанный вьетнамским исследователем компьютерной графики Bùi Tường Phong. Шейдер определяет, как свет будет взаимодействовать с 3D поверхностью: алгоритм Phong быстрый и эффективный, идеально подходит для рендеринга гладких поверхностей. В threeJS материал сливается с существующим 3D объектом, образуя меш:
1 |
marsMesh = new THREE.Mesh(marsGeo, marsMaterial); |
Отрендеренный результат из предыдущего примера слегка упрощен: нам нужна планета, а не блестящая оранжевая сфера. Для этого нам необходимо задействовать дополнительные материальные аспекты. И тут нам понадобится Texture Loader.
1 |
let loader = new THREE.TextureLoader(); |
У большинства объектов очень много материальных аспектов. У Марса самый очевидный – это цвет. Это не должен быть какой-то один оттенок, поверхность Марса имеет сильные различия. Для создания вида планеты можно взять одну из множества бесшовных визуальных карт планеты, сделанных последними спутниками. Я возьму карту с Celestia и оберну ее по поверхности, тем самым получится материальная карта:
1 |
marsMaterial.map = loader.load(imgLoc+"mars-map.jpg"); |
(Вспомните из нашего первого урока, imgLoc был задан заранее в коде, это путь к файлу наших текстур. Законченные текстуры можете скачать из этого урока).
Размер текстур WebGL
Как и с сегментами на объекте, всегда хочется использовать текстурные карты более высокого разрешения, так как тогда отрендеренный объект будет более детальным. Однако это приводит к тем же самым проблемам: увеличение использования ОЗУ и уменьшение производительности.
WebGL балансирует в некоторой степени с помощью двух ограничений на растровых текстурах:
Растровые текстуры должны иметь ширину и высоту со степенью двойки: 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096 или 8192 пикселя по горизонтали или в высоту. (Числа могут быть разными, например, 1024 пикселя в ширину на 512 в высоту).
Обычно, у мобильных браузеров ограничения на размер текстур намного больше, хотя в последнее время текстуры подросли (iOS 10 поддерживает 4096х4096, например. На сайте webglreport.com можно протестировать различные устройства и платформы).
В нашем примере я изменил размер растрового изображения до 4096 х 2048 пикселей.
Материальная карта Марса
Важно, чтобы текстура была бесшовной: при изгибе вокруг объекта ее края должны состыковаться так, чтобы этого не было заметно.
Рендеринг
Чтобы что-то отобразить на экране, наша работа должна быть отрендерена. В нашем скрипте это делается пятью строками кода, три из которых в функции:
1 2 3 4 5 6 7 8 |
let renderer = new THREE.WebGLRenderer({antialiasing : true}); marsloc.appendChild(renderer.domElement); function render(){ renderer.setSize(window.innerWidth, window.innerHeight); renderer.clear(); renderer.render(scene, camera); } |
render – «состояние захвата» текущей сцены. У этого состояния много опций, но я использовал antialiasing, чтобы сгладить отрендеренную сферу Марса на фоне.
marsLoc – контейнер из первой части. К нему добавляется renderer. В функции render размер состояния захвата приравнивается к размеру окна браузера. Затем область очищается, и рендерится сцена с помощью текущей камеры.
Прямо сейчас вы получите плоский и блестящий шарик, зафиксированный в пространстве, и совсем неадаптивный. В следующей статье мы исправим эти недоразумения.
Источник: //thenewcode.com/
Редакция: Команда webformyself.