欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Three.js實現(xiàn)臉書元宇宙3D動態(tài)Logo效果

 更新時間:2021年11月19日 08:45:49   作者:Dragonir  
本文主要講述通過 Three.js + Blender 技術棧,實現(xiàn) Meta 公司炫酷的 3D 動態(tài) Logo,內(nèi)容包括基礎模型圓環(huán)、環(huán)面扭結、管道及模型生成、模型加載、添加動畫、添加點擊事件、更換材質等

本文主要講述通過 Three.js + Blender 技術棧,實現(xiàn) Meta 公司炫酷的 3D 動態(tài) Logo,內(nèi)容包括基礎模型圓環(huán)、環(huán)面扭結、管道及模型生成、模型加載、添加動畫、添加點擊事件、更換材質等。

背景

Facebook 近期將其母公司改名為 Meta,宣布正式開始進軍 元宇宙 🪐領域。本文主要講述通過 Three.js + Blender 技術棧,實現(xiàn) Meta 公司炫酷的 3D 動態(tài) Logo,內(nèi)容包括基礎模型圓環(huán)、環(huán)面扭結、管道及模型生成、模型加載、添加動畫、添加點擊事件、更換材質等。

什么是元宇宙

元宇宙 Metaverse 一詞源于 1992 年尼爾·斯蒂芬森的 《雪崩》,該書描述了一個平行于現(xiàn)實世界的虛擬世界 Metaverse,所有現(xiàn)實生活中的人都有一個網(wǎng)絡分身 Avatar。維基百科 對元宇宙的描述是:通過虛擬增強的物理現(xiàn)實,呈現(xiàn)收斂性和物理持久性特征的,基于未來互聯(lián)網(wǎng),具有鏈接感知和共享特征的 3D 虛擬空間。

元宇宙的內(nèi)涵是吸納了信息革命 5G/6G、互聯(lián)網(wǎng)革命 web3.0、人工智能革命,以及 VR、ARMR,特別是游戲引擎在內(nèi)的虛擬現(xiàn)實技術革命的成果,向人類展現(xiàn)出構建與傳統(tǒng)物理世界平行的全息數(shù)字世界的可能性;引發(fā)了信息科學、量子科學,數(shù)學和生命科學的互動,改變科學范式;推動了傳統(tǒng)的哲學、社會學甚至人文科學體系的突破;囊括了所有的數(shù)字技術。正如電影 《頭號玩家》 的場景,在未來某一天,人們可以隨時隨地切換身份,自由穿梭于物理世界和數(shù)字世界,在虛擬空間和時間節(jié)點所構成的元宇宙中生活學習。

實現(xiàn)效果

進入正題,先來看看本文示例的實現(xiàn)效果。

🔗 在線預覽:https://dragonir.github.io/3d-meta-logo (由于模型較大,加載進度可能比較緩慢,需要耐心等待)

開發(fā)實現(xiàn)

📌 注意:上述示例動圖展示的是試煉四,不想看試錯過程(試煉一、試煉二、試煉三)的,可直接跳轉到試煉四段落查看詳細實現(xiàn)流程。失敗流程中都列出了難點,知道解決方案的大佬請在評論區(qū)不吝賜教。

開發(fā)之前我們先觀察一下 Meta Logo,可以發(fā)現(xiàn)它是一個圓環(huán)經(jīng)過對折扭曲形成的,因此實現(xiàn)它的時候可以從實現(xiàn)圓環(huán)開始。

試煉一:THREE.TorusGeometry

Three.js 提供的基礎幾何體 THREE.TorusGeometry(圓環(huán)),它是一種看起來像甜甜圈 🍩 的簡單圖形。主要參數(shù):

  • radius:可選。定義圓環(huán)的半徑尺寸。默認值是 1。
  • tube:可選。定義圓環(huán)的管子半徑。默認值是 0.4。
  • radialSegments:可選。定義圓環(huán)長度方向上的分段數(shù)。默認值是 8。
  • tubularSegments:可選。定義圓環(huán)寬度方向上的分段數(shù)。默認值是 6。
  • arc:可選。定義圓環(huán)繪制的長度。取值范圍是 02 * π。默認值是 2 * π(一個完整的圓)。

語法示例:

THREE.TorusGeometry(radius, tube, radialSegments, tubularSegments, arc);

😭 失敗:沒有找到扭曲圓環(huán)的方法。

試煉二:THREE.TorusKnotGeometry

THREE.TorusKnotGeometry 可以用來創(chuàng)建三維環(huán)面扭結,環(huán)面扭結是一種比較特別的結,看上去像一根管子繞著它自己旋轉了幾圈。主要參數(shù):

  • radius:可選。設置完整圓環(huán)的半徑,默認值是 1。
  • tube:可選。設置管道的半徑,默認值是 0.4。
  • radialSegments:可選。指定管道截面的分段數(shù),段數(shù)越多,管道截面圓越光滑,默認值是 8tubularSegments:可選。指定管道的分段數(shù),段數(shù)越多,管道越光滑,默認值是 64。
  • p:可選。決定幾何體將繞著其旋轉對稱軸旋轉多少次,默認值是 2
  • q:可選。決定幾何體將繞著其內(nèi)部圓環(huán)旋轉多少次,默認值是 3。

語法示例:

THREE.TorusKnotGeometry(radius, tube, radialSegments, tubularSegments , p, q);

😭 失敗:沒找到能夠控制手動扭曲程度的方法。

試煉三:THREE.TubeGeometry

THREE.TubeGeometry 沿著一條三維的樣條曲線拉伸出一根管。你可以指定一些定點來定義路徑,然后使用 THREE.TubeGeometry 創(chuàng)建這根管。主要參數(shù):

  • path:該屬性用一個 THREE.SplineCurve3 對象來指定管道應當遵循的路徑。
  • segments:該屬性指定構建這個管所用的分段數(shù)。默認值為 64.路徑越長,指定的分段數(shù)應該越多。
  • radius:該屬性指定管的半徑。默認值為 1.
  • radiusSegments:該屬性指定管道圓周的分段數(shù)。默認值為 8,分段數(shù)越多,管道看上去越圓。
  • closed:如果該屬性設置為 true,管道的頭和尾會連起來,默認值為 false。

代碼示例

// ...
var controls = new function () {
  // 點的位置坐標
  this.deafultpoints = [
    [0, 0.4, -0.4],
    [0.4, 0, 0],
    [0.4, 0.8, 0.4],
    [0, 0.4, 0.4],
    [-0.4, 0, 0],
    [-0.4, 0.8, -0.4],
    [0, 0.4, -0.4]
  ]
  this.segments = 64;
  this.radius = 1;
  this.radiusSegments = 8;
  this.closed = true;
  this.points = [];
  this.newPoints = function () {
    var points = [];
    for (var i = 0; i < controls.deafultpoints.length; i++) {
      var _x = controls.deafultpoints[i][0] * 22;
      var _y = controls.deafultpoints[i][1] * 22;
      var _z = controls.deafultpoints[i][2] * 22;
      points.push(new THREE.Vector3(_x, _y, _z));
    }
    controls.points = points;
    controls.redraw();
  };
  this.redraw = function () {
    redrawGeometryAndUpdateUI(gui, scene, controls, function() {
      return generatePoints(controls.points, controls.segments, controls.radius, controls.radiusSegments,
        controls.closed);
    });
  };
};
controls.newPoints();
function generatePoints(points, segments, radius, radiusSegments, closed) {
  if (spGroup) scene.remove(spGroup);
  spGroup = new THREE.Object3D();
  var material = new THREE.MeshBasicMaterial({ color: 0xff0000, transparent: false });
  points.forEach(function (point) {
    var spGeom = new THREE.SphereGeometry(0.1);
    var spMesh = new THREE.Mesh(spGeom, material);
    spMesh.position.copy(point);
    spGroup.add(spMesh);
  });
  scene.add(spGroup);
  return new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), segments, radius, radiusSegments, closed);
}
// ...

😊 勉強成功:但是管道連成的圓環(huán)不夠圓,實現(xiàn)完美的圓弧需要精確的坐標,暫時沒找到坐標計算方法。

試煉四:Blender + Three.js

雖然使用 THREE.TubeGeometry 可以勉強實現(xiàn),但是效果并不好,要實現(xiàn)圓滑的環(huán),需要為管道添加精確的扭曲圓環(huán)曲線路徑函數(shù)。由于數(shù)學能力有限 🤕️,暫時沒找到扭曲圓弧路徑計算的方法。因此決定從建模層面解決。

成功 😄:但是手殘的我使用 Blender 建模花費了大量的時間 💔。

建模教程

B站 的時候發(fā)現(xiàn)了這位大佬發(fā)的寶藏視頻,剛好解決了自己的難題。

🎦 傳送門:【動態(tài)設計教程】AE+blender能怎么玩?臉書元宇宙Meta動態(tài)logo已完全解析,100%學會

用Blender建模

使用 Blender 進行建模,并導出可攜帶動畫的 fbx 格式,導出的時候不要忘記勾選 烘焙動畫 選項。

加載依賴

<script src="./assets/libs/three.js"></script>
<script src="./assets/libs/loaders/FBXLoader.js"></script>
<script src="./assets/libs/inflate.min.js"></script>
<script src="./assets/libs/OrbitControls.js"></script>
<script src="./assets/libs/stats.js"></script>

場景初始化

var container, stats, controls, compose, camera, scene, renderer, light, clickableObjects = [], mixer, mixerArr = [], manMixer;
var clock = new THREE.Clock();
init();
animate();
function init() {
  container = document.createElement('div');
  document.body.appendChild(container);
  // 場景
  scene = new THREE.Scene();
  scene.transparent = true;
  scene.fog = new THREE.Fog(0xa0a0a0, 200, 1000);
  // 透視相機:視場、長寬比、近面、遠面
  camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 0.1, 1000);
  camera.position.set(0, 4, 16);
  camera.lookAt(new THREE.Vector3(0, 0, 0));
  // 半球光源:創(chuàng)建室外效果更加自然的光源
  light = new THREE.HemisphereLight(0xefefef);
  light.position.set(0, 20, 0);
  scene.add(light);
  // 平行光
  light = new THREE.DirectionalLight(0x2d2d2d);
  light.position.set(0, 20, 10);
  light.castShadow = true;
  scene.add(light);
  // 環(huán)境光
  var ambientLight = new THREE.AmbientLight(0xffffff, .5);
  scene.add(ambientLight);
  // 網(wǎng)格
  var grid = new THREE.GridHelper(100, 100, 0xffffff, 0xffffff);
  grid.position.set(0, -10, 0);
  grid.material.opacity = 0.3;
  grid.material.transparent = true;
  scene.add(grid);
  renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
  renderer.setPixelRatio(window.devicePixelRatio);
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.setSize(window.innerWidth, window.innerHeight);
  // 背景色設置為透明
  renderer.setClearAlpha(0);
  // 開啟陰影
  renderer.shadowMap.enabled = true;
  container.appendChild(renderer.domElement);
  // 添加鏡頭控制器
  controls = new THREE.OrbitControls(camera, renderer.domElement);
  controls.target.set(0, 0, 0);
  controls.update();
  window.addEventListener('resize', onWindowResize, false);
  // 初始化性能插件
  stats = new Stats();
  container.appendChild(stats.dom);
}
// 屏幕縮放
function onWindowResize() {
  camera.aspect = window.innerWidth / window.innerHeight;
  camera.updateProjectionMatrix();
  renderer.setSize(window.innerWidth, window.innerHeight);
}

📌 想了解場景初始化的詳細流程,可閱讀我的另一篇文章《使用three.js實現(xiàn)炫酷的酸性風格3D頁面》。

加載Logo模型

使用 FBXLoader 加載模型,并設置模型的位置和大小。

var loader = new THREE.FBXLoader();
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true;
    }
  });
  mesh.rotation.y = Math.PI / 2;
  mesh.position.set(0, 1, 0);
  mesh.scale.set(0.05, 0.05, 0.05);
  scene.add(mesh);
});

添加材質

本文 Logo 使用的是 MeshPhysicalMaterial材質,它是一種 PBR 物理材質,可以更好的模擬光照計算,相比較高光網(wǎng)格材質 MeshPhongMaterial 渲染效果更逼真。使用 THREE.TextureLoader 為材質添加 map 屬性來加載模型貼圖。下圖是金屬質感的紋理貼圖。

var texLoader = new THREE.TextureLoader();
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      if (child.name === '貝塞爾圓') {
        child.material = new THREE.MeshPhysicalMaterial({
          map: texLoader.load("./assets/images/metal.png"),
          metalness: .2,
          roughness: 0.1,
          exposure: 0.4
        });
      }
    }
  });
})

添加動畫

  • AnimationMixer 對象是場景中特定對象的動畫播放器。當場景中的多個對象獨立動畫時,可以為每個對象使用一個 AnimationMixer。
  • AnimationMixer 對象的 clipAction 方法生成可以控制執(zhí)行動畫的實例。
loader.load('assets/models/meta.fbx', function (mesh) {
  mesh.animations.map(item => {
    mesh.traverse(child => {
      // 因為模型中有多個物體,并且各自有不同動畫,示例中只為貝塞爾圓這個網(wǎng)格添加動畫
      if (child.name === '貝塞爾圓') {
        let mixer = new THREE.AnimationMixer(child);
        mixerArr.push(mixer);
        let animationClip = item;
        animationClip.duration = 8;
        let clipAction = mixer.clipAction(animationClip).play();
        animationClip = clipAction.getClip();
      }
    })
  })
});

添加動畫之后,不要忘了要在 requestAnimationFrame 中更新動畫。

function animate() {
  renderer.render(scene, camera);
  // 獲得前后兩次執(zhí)行該方法的時間間隔
  let time = clock.getDelta();
  // 更新logo動畫
  mixerArr.map(mixer => {
    mixer && mixer.update(time);
  });
  // 更新人物動畫
  manMixer && manMixer.update(time);
  stats.update();
  requestAnimationFrame(animate);
}

展示加載進度

FBXLoader 同時返回兩個回調(diào)函數(shù),可以像下面這樣使用,用來展示模型加載進程展示以及加載失敗的邏輯實現(xiàn)。

<div class="loading" id="loading">
  <p class="text">加載進度<span id="progress">0%</span></p>
<div>

var loader = new THREE.FBXLoader();
loader.load('assets/models/meta.fbx', mesh => {
}, res => {
  // 加載進程
  let progress = (res.loaded / res.total * 100).toFixed(0);
  document.getElementById('progress').innerText = progress;
  if (progress === 100) {
    document.getElementById('loading').style.display = 'none';
  }
}, err => {
  // 加載失敗
  console.log(err)
});

實現(xiàn)效果

點擊更換材質

監(jiān)聽頁面的點擊事件,通過 HREE.Raycaster 拿到當前點擊對象,為了展示例子,我為點擊對象更換了一種材質 THREE.MeshStandardMaterial,并賦予它隨機的 color 顏色、metalness 金屬質感以及 roughness 粗糙程度。

//聲明raycaster和mouse變量
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
function onMouseClick(event) {
  // 通過鼠標點擊的位置計算出raycaster所需要的點的位置,以屏幕中心為原點,值的范圍為-1到1.
  mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
  mouse.y = - (event.clientY / window.innerHeight) * 2 + 1;
  // 通過鼠標點的位置和當前相機的矩陣計算出raycaster
  raycaster.setFromCamera(mouse, camera);
  // 獲取raycaster直線和所有模型相交的數(shù)組集合
  let intersects = raycaster.intersectObjects(clickableObjects);
  if (intersects.length > 0) {
    console.log(intersects[0].object)
    let selectedObj = intersects[0].object;
    selectedObj.material = new THREE.MeshStandardMaterial({
      color: `#${Math.random().toString(16).slice(-6)}`,
      metalness: Math.random(),
      roughness: Math.random()
    })
  }
}
window.addEventListener('click', onMouseClick, false);

📌 更多關于網(wǎng)格材質的知識,可參考文章末尾的鏈接。

加載人物模型

人物模型的加載流程和 Logo 模型加載流程是一樣的。我添加了一個正在施展龜派氣功的人物,沒想到與 Logo 模型的旋轉動畫非常契合 😂 。

loader.load('assets/models/man.fbx', function (mesh) {
  mesh.traverse(function (child) {
    if (child.isMesh) {
      child.castShadow = true;
      child.receiveShadow = true;
    }
  });
  mesh.rotation.y = Math.PI / 2;
  mesh.position.set(-14, -8.4, -3);
  mesh.scale.set(0.085, 0.085, 0.085);
  scene.add(mesh);
  manMixer = new THREE.AnimationMixer(mesh);
  let animationClip = mesh.animations[0];
  let clipAction = manMixer.clipAction(animationClip).play();
  animationClip = clipAction.getClip();
}, res => {
  let progress = (res.loaded / res.total * 100).toFixed(0);
  document.getElementById('progress').innerText = progress + '%';
  if (Number(progress) === 100) {
    document.getElementById('loading').style.display = 'none';
  }
}, err => {
  console.log(err)
});

本文示例人物模型來源于mixamo.com,該網(wǎng)站有有上百種人物和上千種動作可自由組合,免費 下載。大家可以挑選自己喜歡的人物和動畫動作來練習 Three.js

總結

本文中涉及到的主要知識點包括:

  • THREE.TorusGeometry:圓環(huán)。
  • THREE.TorusKnotGeometry:環(huán)面扭結。
  • THREE.TubeGeometry:管道。
  • Blender: 建模。
  • FBXLoader: 加載模型,顯示加載進度
  • 。TextureLoader:加載材質。
  • THREE.AnimationMixer:加載動畫。
  • THREE.Raycaster:捕獲點擊模型。

🔗 完整代碼:https://github.com/dragonir/3d-meta-logo

參考資料

[1]. 使用three.js實現(xiàn)炫酷的酸性風格3D頁面

[2]. ThreeJs認識材質

[3]. Three之Animation初印象

[4]. 什么是元宇宙?

作者:dragonir 本文地址:https://www.cnblogs.com/dragonir/p/15574412.html

到此這篇關于Three.js實現(xiàn)臉書元宇宙3D動態(tài)Logo的文章就介紹到這了,更多相關Three.js3D動態(tài)Logo 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • JavaScript 異步調(diào)用框架 (Part 4 - 鏈式調(diào)用)

    JavaScript 異步調(diào)用框架 (Part 4 - 鏈式調(diào)用)

    我們已經(jīng)實現(xiàn)了一個簡單的異步調(diào)用框架,然而還有一些美中不足,那就是順序執(zhí)行的異步函數(shù)需要用嵌套的方式來聲明。
    2009-08-08
  • JS實現(xiàn)長圖上下滾動效果

    JS實現(xiàn)長圖上下滾動效果

    這篇文章主要為大家詳細介紹了JS實現(xiàn)長圖上下滾動效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-03-03
  • JS中驗證整數(shù)和小數(shù)的正則表達式

    JS中驗證整數(shù)和小數(shù)的正則表達式

    網(wǎng)上很多關于驗證小數(shù)的正則表達式,但是很多都不是百分百正確,所以我結合一些前輩的經(jīng)驗,寫了一個,分享到腳本之家平臺,對小數(shù)或整數(shù)正則表達式的相關知識感興趣的朋友一起看看吧
    2018-10-10
  • Lerna入門之管理TypeScript monorepo教程

    Lerna入門之管理TypeScript monorepo教程

    這篇文章主要為大家介紹了Lerna入門之管理TypeScript monorepo教程詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-11-11
  • JS Canvas接口和動畫效果大全

    JS Canvas接口和動畫效果大全

    這篇文章主要介紹了JS Canvas接口和動畫效果大全,對Canvas感興趣的同學,可以參考下
    2021-04-04
  • 原生JS實現(xiàn)的簡單輪播圖功能【適合新手】

    原生JS實現(xiàn)的簡單輪播圖功能【適合新手】

    這篇文章主要介紹了原生JS實現(xiàn)的簡單輪播圖功能,結合實例形式分析了基于javascript定時器控制頁面元素動態(tài)變換實現(xiàn)輪播圖的相關操作技巧,需要的朋友可以參考下
    2018-08-08
  • Bootstrap模態(tài)框插入視頻的實現(xiàn)代碼

    Bootstrap模態(tài)框插入視頻的實現(xiàn)代碼

    這篇文章主要介紹了Bootstrap模態(tài)框插入視頻的實現(xiàn)代碼,需要的朋友可以參考下
    2017-06-06
  • 詳解JavaScript發(fā)送埋點請求的兩種方式

    詳解JavaScript發(fā)送埋點請求的兩種方式

    對于發(fā)送埋點請求這種應用場景,我們有兩種簡單的處理方式:動態(tài)創(chuàng)建<script>和<img>兩種方式。本文就詳細講講二種方式的實現(xiàn),需要的可以參考一下
    2022-06-06
  • js實現(xiàn)滑動輪播效果

    js實現(xiàn)滑動輪播效果

    這篇文章主要為大家詳細介紹了js實現(xiàn)滑動輪播效果,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • 導航跟隨滾動條置頂移動示例代碼

    導航跟隨滾動條置頂移動示例代碼

    滾動條滾動時如何讓導航置頂移動,這種效果已經(jīng)在很多網(wǎng)看到了,所以本文也來實現(xiàn)一個,感興趣的朋友可以學習下
    2013-09-09

最新評論