Эта статья участвовала в приказе о созыве Haowen, нажмите, чтобы просмотреть:Двойные заявки на внутреннюю и внешнюю стороны, призовой фонд в 20 000 юаней ждет вас, чтобы бросить вызов!
предисловие
Вот в чем дело, некоторое время назад外包工头
Лао Ян снова подошел ко мне и сказал, что крупный автомобильный бренд собирается создать веб-салон, надеясь показать 3D-модель своего нового автомобиля на 360 градусов на веб-странице, а также позволить пользователям самостоятельно выбирать цвет автозапчастей. .
Многие мои знакомые подумают после прочтения этой статьи, что две недели вполне обильные, но это не так, так как нет права говорить партию С, часто с партией неоднократно пересматривали много раз, чтобы изменить изменить последнюю строку накануне вечером, не затягивая прямым путем, жизненный цикл рекламного сайта не долгий, на кону будет до 1-3 месяцев.
Эй, времени мало, а бюджет большой!
Я подумал предложить четыре W и оставить ему место для торга.
Кто знал, что Лао Ян согласился с одним словом и попросил меня отправиться в мир ХХ после того, как он закончит свои дела.
Я предполагаю, что он собирается сделать не менее 10 Вт от клиента
Интерактивная тема
Сначала посмотрите на окончательный эффект, как вы думаете, стоит ли он четырех W?
То есть предыдущая статья«Три передовых решения для панорамного просмотра VR! Однажды это может пригодиться! 》упоминается в
threejs
достигать
Базовые знания 3D-движков
Цель этой статьи - позволить всем начать использовать ее сразу после прочтения.Поскольку мы собираемся использовать 3D-движок, мы получим некоторые базовые знания о 3D, прежде чем читатьthreejs
Эффективность документирования API будет очень высокой. Какой бы ни был 3д движок, он состоит из следующих основных элементов
Сцены(scene
)
Контейнер, который содержит все в трехмерном мире, кроме средства визуализации. Элементы сцены используют правостороннюю декартову систему координат, положительная ось x направлена вправо, положительная ось y направлена вверх, а ось z направлена изнутри наружу экрана.
камера (camera
)
Как и человеческие глаза, вы можете смотреть в любом направлении в пространстве, и вы можете настроить угол обзора и расстояние просмотра с помощью параметров.
Как правило, мы используем перспективную камеру, которая соответствует реальной ситуации в физическом мире.PerspectiveCamera
, а в некоторых особых случаях требуется одинаковый размер в дальнем и ближнем плане, тогда используйте орфографическую камеруOrthographicCamera
PerspectiveCamera( fov : Number, aspect : Number, near : Number, far : Number )
//构造函数参数
//fov:视场角
//aspect:视场宽高比(一般用 画布宽/画布 高即可)
//near:能看多近
//far:能看多远
//这几个参数决定了哪些scene里的三维顶点会被渲染/绘制出来
Рендерер(renderer
)
Буду
camera
существуетscene
Визуализируйте/нарисуйте то, что вы видите на холсте, на холст
геометрия (geometry
)
Все объекты в трехмерном мире
点组成面
,面组成几何体
. Я полагаю, вы знакомы со следующей стандартной геометрией
- сфера
- куб
- Конус
- цилиндр
- ...
面
состоит из точек,面
Вы можете составить любую геометрию. В сфере, например, многоточечная поверхность сферы, тем более круглый шар. Но чем больше баллов, тем больше будет объем вычислений...
Кроме того, мы обычно говорим3d模型
Это одна или несколько геометрий, но некоторые файлы 3D-моделей могут содержать некоторую дополнительную информацию в дополнение к геометрии, такую как текстуры, материалы и т. д. Ее необходимо анализировать при чтении файла модели.
свет(light
)
3D-движок будет иметь освещение по умолчанию без создания источника света вручную.
环境光
, иначе ничего не увидишь. Распространенные типы огней следующие
- AmbientLight (окружающий свет, глобальное освещение без направления, без затенения)
- DirectionLight (параллельный свет, для понимания обратитесь к солнечному свету)
- PointLight (точечный источник света, для понимания обратитесь к лампочке)
- SpotLight (прожектор, эталон Stage Spotlight)
карта (texture
)
Представьте, что у вас в руке куб, вы оборачиваете его со всех сторон листом бумаги формата А4 и рисуете на нем. то, что ты рисуешь
贴图
.
Есть несколько типов карт и иллюминации, а потом мы это используем
Материал (material
)
Продолжая воображение на карте, используете ли вы белый картон или масляную бумагу для рисования, представленная текстура отличается, верно?
材质
! Пять шаров ниже имеют одинаковый цвет, а материалы слева направо
- MeshBasicMaterial (базовый материал, на который не влияет освещение)
- MeshStandardMaterial (стандартный материал PBR)
- MeshPhongMaterial (глянцевый материал, подходит для керамики, текстура краски)
- MeshToonMaterial (мультяшный материал, широко известный как три рендеринга два)
- MeshStandardMaterial (стандартный материал PBR имитирует металлические отражения)
Давай сражаться!
С этими основами легко начать работу с threejs. Можно сказать, что 90% эффектов, передаваемых в программном обеспечении, таком как 3dmax, можно найти с соответствующими параметрами конфигурации threejs.
Создайте базовую сцену
//<div id='container' style="width:100%;height: 100%;"></div>
var scene, camera, renderer;
function init(){
scene = new THREE.Scene();
//这里参数不懂的同学回去看基本知识里的camera部分
camera = new THREE.PerspectiveCamera(90, document.body.clientWidth / document.body.clientHeight, 0.1, 100);
//camera的位置在x0,y0,z3,还记得迪尔卡右手坐标系吗?
camera.position.set(0, 0, 3);
renderer = new THREE.WebGLRenderer();
renderer.setSize(document.body.clientWidth, document.body.clientHeight);
document.getElementById("container").appendChild(renderer.domElement);
var controls = new THREE.OrbitControls(camera, renderer.domElement);
//等待添加模型
loop();
}
function loop() {
requestAnimationFrame(loop);
renderer.render(scene, camera);
}
window.onload = init;
Теперь мы можем добавить стандартную геометрию, чтобы попробовать, например, мы добавим куб, чтобы попробовать.
const geometry = new THREE.BoxGeometry( 1, 1, 1 );
const material = new THREE.MeshBasicMaterial( {color: 0x00ff00} );
const cube = new THREE.Mesh( geometry, material );
scene.add( cube );
Очевидно, сцена в действии... всем обратить внимание на блок исходного кода注释
Модель автомобиля
Возвращаясь к нашему проекту, сторона бренда предоставила очень подробную модель с сотнями мегабайт файлов и миллионами лиц (triangles
).
Я сказал, что это недоступно, вы должны减面
Мне нужно преобразовать его в формат, который может поддерживать движок.gltf
илиobj
По моим оценкам, для бесперебойной работы на мобильных веб-страницах он не должен превышать 100 000 страниц.
Мастер-аутсорсер Лао Ян сказал: «Не позволяйте клиентам делать это за вас, они не будут этого делать».
Я знаю, ты понимаешь, ты можешь просто сделать это, я добавлю тебе [5K]
К тому же 5 тысяч ты заставляешь меня так смущаться, чтобы отказаться...
Затем я трачу25美刀
огромные суммы денегsketchfab
купил модель на
Небольшая модификация может удовлетворить требования, конечно, у sketchfab есть и бесплатные модели.
Но, в конце концов, я получил 5 тысяч Лао Янга и немного переживаю из-за того, что не трачу деньги.不安
На: р
Оптимизированная структура модели
В соответствии с фактическими потребностями, такими как车窗要透明可以看到内饰
, поэтому окну нужно отдельно придать материал с прозрачными свойствами. Колеса, плафоны, автомобильные сетки, рамы, кузов и т. д. должны быть разобраны на независимые几何体
можно настроить самостоятельно材质
.
Разобравшись со структурой модели, нам нужно подготовить файл модели
модель нагрузки
Существует множество форматов файлов для 3D-моделей, ноthreejs
Наиболее часто используются
- формат OBJ
Старый файл 3d-модели общего назначения не содержит такой информации, как текстуры, материалы, анимация и т. д.
- Формат GLTF (формат передачи графического языка)
Распространенный формат современных 3D-моделей, запущенный официальной командой поддержки OpenGL, который может содержать такую информацию, как геометрия, материал, анимация, сцена, камера и т. д., а размер файла по-прежнему невелик. Он известен как JPEG индустрии 3D-моделей.
В исходном проекте я использовал формат OBJ, в этой статье мы используем формат GLTF. Используйте предоставленные threejseditor, мы можем преобразовать формат модели и экспортировать ее.
С помощью GLTFLoader мы можем загрузить.gltf
Отформатируйте файл 3D-модели. Следует отметить, что эти загрузчики существуют в виде плагинов, и соответствующиеXXXLoader.js
использовать
//<script src="js/GLTFLoader.js"></script>
//放到之前添加立方体的代码处
const loader = new THREE.GLTFLoader();
loader.load(
'images/model.gltf',
function ( gltf ) {
scene.add( gltf.scene );
},
function ( xhr ) {
//侦听模型加载进度
console.log( ( xhr.loaded / xhr.total * 100 ) + '% loaded' );
},
function ( error ) {
//加载出错时的回调
console.log( 'An error happened' );
}
);
С помощью этого кода вы можете перемещаться и просматривать список геометрии в модели.
console.log(gltf.scene.children);
//可以用for,也可以用traverse api
//gltf.scene.children.traverse((child){});
Текстуры и материалы
Теперь добавим текстуры в геометрию, как делать текстуры - это профессия дизайнера. Здесь особо нечего сказать, нам просто нужно знать, как использовать эти текстуры.
- Нормальная текстура (
_col
)
material.map, альтернативные цвета
- нормальная карта (
_nor
)
material.normalMap, который позволяет поверхностям с низкой детализацией генерировать точные направления освещения и отражения с высокой детализацией.
- Карта окружающего затенения (
_occ
)
material.aoMap, используемый для описания эффекта блокировки окружающего рассеянного света, когда объект пересекает объект или находится близко к нему.
- Карта отражения окружающей среды
material.envMap, который имитирует эффект материала, отражающего окружающую среду.
Теперь мы равномерно загружаем эти файлы текстур в память.
var allTexture;
function loadAllTexture(cb){
allTexture = {};
var loadIndex = 0;
var textures = [
"skymap",
"shache_occ",
"shache_nor",
"shache_col",
"neishi_occ",
"neishi_nor",
"mennei_col",
"luntai_nor",
"luntai_col",
"lungu_occ",
"lungu_nor",
"lungu_col",
"linjian_occ",
"linjian_nor",
"linjian_col",
"floor",
"deng_occ",
"deng_nor",
"deng_col",
"cheshen_occ",
"cheshen_nor",
"chejia_occ",
"chejia_nor",
"chedengzhao_nor"
];
function loadNextTexture(){
var textureName = textures[loadIndex];
loadTexture("images/textures/"+textureName+".jpg",function(texture){
if(loadIndex<textures.length-1){
allTexture[textureName] = {
texture:texture
};
loadIndex++;
loadNextTexture();
}else{
if(cb)cb();
}
});
}
loadNextTexture();
}
function loadTexture(filepath,cb){
const textureLoader = new THREE.TextureLoader();
textureLoader.load(filepath,cb);
}
Потом вручную соответствуем по названию, например сначала добавляем текстуру ступицы колеса
for(var i=0;i<gltf.scene.children[0].children.length;i++){
var modelObj = gltf.scene.children[0].children[i];
if(modelObj.name=="smart_lungu0"||modelObj.name=="smart_lungu1"||modelObj.name=="smart_lungu2"||modelObj.name=="smart_lungu3"){
modelObj.material = new THREE.MeshStandardMaterial();
modelObj.material.map = allTexture["lungu_col"].texture;
modelObj.material.normalMap = allTexture["lungu_nor"].texture;
modelObj.material.aoMap = allTexture["lungu_occ"].texture;
}
}
Продолжаем добавлять текстуру колеса
else if(modelObj.name=="smart_chelun0"||modelObj.name=="smart_chelun1"||modelObj.name=="smart_chelun2"||modelObj.name=="smart_chelun3"){
modelObj.material = new THREE.MeshStandardMaterial();
modelObj.material.map = allTexture["luntai_col"].texture;
modelObj.material.normalMap = allTexture["luntai_nor"].texture;
}
Таким образом добавляются остальные карты материала.Конечно, есть много деталей материала, которые можно будет скорректировать в будущем, но это тонкая работа, и основной упор здесь делается на то, чтобы поделиться.玻璃的反射和透明
,金属漆的反光
- Чистое стекло
Прозрачность и основной цвет люка и лобового стекла отличаются
else if(child.name=="smart_boli"){
child.material=new THREE.MeshPhongMaterial();
child.material.color = new THREE.Color( 0x333333 );
child.material.transparent=true;
child.material.opacity=.2;
}else if(child.name=="smart_tianchuang"){
child.material=new THREE.MeshPhongMaterial();
child.material.color = new THREE.Color( 0x000 );
child.material.transparent=true;
child.material.opacity=.5;
}
Присмотритесь к разнице в прозрачности лобового стекла и люка в анимации
- отражение стекла
Хотите действительно отразить реальную окружающую среду? Не думайте об этом слишком много, используйте envMap, чтобы создать фальшивый вид, и это сработает...
child.material.envMap=allTexture["skymap"].texture;
//环境反射贴图envMap的映射方式,这里用的是一个叫等量矩形投影的映射方法
child.material.envMap.mapping = THREE.EquirectangularReflectionMapping;
//环境反射贴图的强度
child.material.envMapIntensity=1;
Посмотрите внимательно на лобовое стекло на анимации, оно что-то отражает? Видимый«Три передовых решения для панорамного просмотра VR! Однажды это может пригодиться! 》Ребята, вы помните эту картинку?
- Текстура краски для тела
использовать
MeshStandardMaterial
материал, регулируяmetalness
,roughness
значение для настройки текстуры металла
child.material = new THREE.MeshStandardMaterial();
child.material.color=new THREE.Color(0x70631B);
child.material.metalness = 0.44;
child.material.roughness = 0;
Информационный пункт
В конце концов, это онлайн-шоурум, и некоторые информационные точки должны быть представлены вокруг кузова автомобиля, после нажатия во всплывающем окне может отображаться дополнительная информация, верно? Способ реализации также упоминается в статье про VR панораму, т.е.
Sprite
+Raycast
//frame只是一个标记,叫什么都行
var poiPosArray=[
{x:-1.47,y:0.87,z:-0.36,frame:1},
{x:-1.46,y:0.49,z:-0.69,frame:2},
{x:1.5,y:.7,z:0,frame:8},
{x:0.33,y:1.79,z:0,frame:3},
{x:0,y:0.23,z:0.96,frame:4},
{x:0.73,y:1.38,z:-0.8,frame:5},
{x:-.1,y:1.17,z:0.88,frame:6},
{x:-1.16,y:0.16,z:0.89,frame:7}
],poiObjects=[];
function setupInfoPoint(){
const pointTexture = new THREE.TextureLoader().load("images/point.png");
var group = new THREE.Group();
var materialC = new THREE.SpriteMaterial( { map: pointTexture, color: 0xffffff, fog: false } );
for ( var a = 0; a < poiPosArray.length; a ++ ) {
var x = poiPosArray[a].x;
var y = poiPosArray[a].y-.5;
var z = poiPosArray[a].z;
var sprite = new THREE.Sprite( materialC );
sprite.scale.set( .15, .15, 1 );
sprite.position.set( x, y, z );
sprite.idstr="popup_"+poiPosArray[a].frame;
group.add( sprite );
poiObjects.push(sprite);
}
scene.add( group );
document.body.addEventListener("click",function (event) {
event.preventDefault();
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
raycaster.setFromCamera( mouse, camera );
var intersects = raycaster.intersectObjects( poiObjects );
if(intersects.length>0){
var popIndex=parseInt(intersects[ 0 ].object.idstr.substr(6,1));
console.log(popIndex);
}
});
}
Как сделать интерфейс
Поскольку мы использовалиthreejs
, так что мы собираемсяthreejs
Вы сделали интерфейс? Если вы так думаете, вы будете истощены. Вы должны знать, что сделать двухмерный пользовательский интерфейс в трехмерной сцене — непростая задача, и еще труднее реализовать некоторые действия пользователя (щелчок, перетаскивание и т. д.) пользовательского интерфейса... Поэтому мы напрямую используемhtml
Просто сделайте пользовательский интерфейс~
Здесь вы узнали (fei) основную часть этого 3D-автосалона!
Эпилог
Вышеупомянутое простоthreejs
Одиночень мелкоиспользование,threejs
Классных эффектов, которых можно добиться, гораздо больше. Я надеюсь, что эта статья поможет вам заинтересоваться разработкой Web3D. Если вы считаете, что эта статья неплохая, пожалуйста, поставьте лайк, соберите и подпишитесь~
BTW: Очевидно,笨驰
Умный, как вы говорите BMW? Поскольку эта история является чисто вымышленной, пожалуйста, не занимайте свое место. Все записи чата в этой статье используютсяГенератор разговоров WeChatподделка.
Если вам нравятся уроки Дашуая, добавьте в закладки, лайкните и подпишитесь
- Билибили:
大帅老猿
- Публичный аккаунт WeChat:
大帅老猿