<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          關(guān)于從入門 three.js 到做出 3d 地球這件事

          共 8203字,需瀏覽 17分鐘

           ·

          2021-04-06 19:10

          轉(zhuǎn)載自:lulu_up

          https://segmentfault.com/a/1190000039647481

          開篇介紹

          如果你沒接觸過3d可視化技術(shù), 你也許會(huì)認(rèn)為可視化非常難, 光是一個(gè)物體的陰影要如何計(jì)算就相當(dāng)復(fù)雜, 但是告訴你個(gè)好消息, 陰影的計(jì)算都是集成好的, 而我們只要設(shè)置好光源的位置,繪制好物體就可以了, 真的沒有想象中那么復(fù)雜, 本文面向有前端基礎(chǔ),但零可視化基礎(chǔ)的同學(xué), 我會(huì)從最基礎(chǔ)的入門知識說起。

          學(xué)習(xí)可視化方面的技術(shù)會(huì)讓我們對計(jì)算機(jī), 對前端技術(shù)有更深的理解, 還可以做出更多有趣味的東西來, 本文是我踩了好多坑后總結(jié)出來的, 我更清楚一個(gè)初入門的小白哪里不懂。

          three.jswebgl 的第三方庫, 它更適合不太復(fù)雜的可視化項(xiàng)目, 而我們要做的3d地球項(xiàng)目使用它來做會(huì)更簡單, 所以選擇了它, 放心后面也會(huì)說webgl相關(guān)知識 。

          當(dāng)前效果如下:

          一. 關(guān)于此系列文章

          1. 自食其力:不管是在公司還是網(wǎng)上都有類似的庫, 但是當(dāng)遇到bug或是缺少功能的情況時(shí)就會(huì)很麻煩, 例如我們公司的FGL庫(一個(gè)內(nèi)網(wǎng)繪制3d景象的技術(shù)), 它官網(wǎng)上的例子很多都是錯(cuò)的, 使用起來也是一堆問題, 比如無法精準(zhǔn)選擇某個(gè)國家, 點(diǎn)擊事件消融等bug。還比如說Echarts的地球, 它太注重真實(shí)感并且用起來有點(diǎn)卡, 以及交互做的不太好。
          2. 直指核心: 去年我通過看書、看文章、看視頻認(rèn)真的學(xué)習(xí)three.js, 并做出了3d地球這個(gè)項(xiàng)目, 而這個(gè)系列文章將會(huì)直指做出3d地圖的核心知識, 盡量不隨意擴(kuò)散知識面。
          3. 更好入門: 網(wǎng)上的教學(xué)文章千篇一律, 點(diǎn)進(jìn)去閱讀完感覺其對于一個(gè)three.js零基礎(chǔ)的同學(xué)來說都不太好懂, 教學(xué)視頻里的知識點(diǎn)太廣泛, 事無巨細(xì)的羅列, 而這個(gè)系列文章將更突出繪制3d地球這個(gè)重點(diǎn)。
          4. 同道中人: 我學(xué)習(xí)three.js就是為了做出3d地球, 期間走了不少彎路, 被某些問題卡了很久, 所以我更懂一個(gè)剛?cè)腴T的人困惑的點(diǎn)在哪里。
          5. 專注vue: 市面上較少專門針對vue做到開箱即用的3d地球插件, 而我們就要編寫這樣一款產(chǎn)品。
          6. 不斷學(xué)習(xí): 編寫文章也是我提高自己能力的一種方法, 死磕每個(gè)知識點(diǎn)讓自己的理解更上一層樓。

          二. 任務(wù)目標(biāo)

          1. 入門three.js技術(shù)。
          2. 繪制出3d地球。
          3. 做成專門vue使用的庫。
          4. 后期也會(huì)介紹著色器的概念與基本的使用技巧。
          5. 會(huì)介紹少量webgl的相關(guān)用法, 并且會(huì)有部分?jǐn)?shù)學(xué)知識。

          三. 文章主線劇情與支線任務(wù)

          • 主線劇情: 圍繞著如何做出3d地球, 這部分在vue工程里面進(jìn)行。
          • 支線任務(wù): 每個(gè)分散的知識點(diǎn), 可能與3d地球沒關(guān)系, 但是它能幫助我們更好的理解3d技術(shù), 而這些知識點(diǎn)我就不在vue項(xiàng)目里面演示了, 會(huì)單獨(dú)創(chuàng)建一個(gè)html文件來演示說明。

          四. 理解坐標(biāo)系: 別著急寫代碼先有基本模型

          像繪制圖形這類技術(shù), 最基本的概念就坐標(biāo)系, 下圖是二維坐標(biāo)系, 我們的故事就從這個(gè)家伙開始。???? 我們用(0, 0)表示坐標(biāo)的中心點(diǎn), 繪制一條起點(diǎn)為中心點(diǎn)長度為1的線段可以使用 (0, 0) (1, 0)這兩個(gè)點(diǎn)相連表示。

          關(guān)于向量的概念后面需要用數(shù)學(xué)知識的時(shí)候再介紹, 前幾篇文章就越通俗越好。

          three.js中我們要打交道的就是下面這位三維坐標(biāo)系???? 他的坐標(biāo)原點(diǎn)就是(0, 0, 0), 繪制一條起點(diǎn)為中心點(diǎn)的長度為1的線段可以是 (0, 0, 0) (1, 0, 0)。

          這里要記住, three.js里面設(shè)置的默認(rèn)坐標(biāo)系就是這種形式x向右, y向上, z向前, 之所以說是默是因?yàn)樗梢孕薷摹?/p>

          上圖中, 觀看這個(gè)三維坐標(biāo)系的目光其實(shí)是在斜上方, 正常情況下在我們開發(fā)的時(shí)候z軸是正對著我們的眼睛的, 所以你只能看到z軸是一個(gè)點(diǎn),

          在開發(fā)與學(xué)習(xí)的時(shí)候, 最好先把坐標(biāo)系繪制到頁面上, 方便我們更好的繪制。

          五. 相機(jī)的概念

          假設(shè)現(xiàn)在我們的正前方有一個(gè)三維坐標(biāo)系的全息投影, 那么此時(shí)你的眼睛就相當(dāng)于一架相機(jī), 你看到的 坐標(biāo)系景象取決于你站的位置。

          three.js中就有這樣一個(gè)對象, 他就是負(fù)責(zé)從哪個(gè)角度觀察我們繪制的3d世界, 也就是相機(jī)這個(gè)概念的由來。

          相機(jī)分為兩種, 正投影相機(jī)和透視投影相機(jī), 正投影相機(jī)就是你站的多遠(yuǎn)你看到的物體的大小都不變, 透視投影相機(jī)就是物體會(huì)近大遠(yuǎn)小, 下面是張引用圖 (圖片來自網(wǎng)絡(luò))。

          正投影相機(jī)可以用在工程制圖上, 或者可以做一些視覺欺騙小游戲。

          本文主要目的是繪制3d地球所以主要使用透視投影相機(jī)

          六. 繪制坐標(biāo)系, 安放攝像機(jī) (代碼安排上)

          引入three.js, 可以把包下載到本地, 也可以直接獲取在cdn上的資源, 引入之后全局會(huì)出現(xiàn)THREE對象, 我們就可以開始編程之旅了。

          <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>

          一個(gè)普普通通的html空文件的script標(biāo)簽里面, 發(fā)生著這樣的故事: 讓我們逐句解析

          第一步:創(chuàng)建場景, 也就是虛擬的空間

          我們之后繪制的3d物體都要放入這個(gè)空間里面, 你可以把它當(dāng)做一個(gè)鴻蒙空間神器, 里面有一個(gè)小世界, 而我們是掌控者(很中二)。

          const scene = new THREE.Scene();
          第二步:創(chuàng)建相機(jī)

          相機(jī)的概念上面講述過了, PerspectiveCamera這個(gè)類就是透視投影相機(jī), 我們來逐個(gè)攻破他參數(shù)的意思。

          1. 35: 視角也就是我們左眼與右眼可以看到的橫向角度, 其越小物體則越大, 因?yàn)槟抗庾儶M窄會(huì)突出物體, 你可以做一個(gè)實(shí)驗(yàn), 聚精會(huì)神的盯著看一個(gè)物體, 你就會(huì)發(fā)現(xiàn)此時(shí)你左右兩邊本來靠余光可以看到的物體你現(xiàn)在看不清, 這個(gè)就是你的視角變小了, 變小視角還可以使目標(biāo)物體比例變大, 我們知道這些就夠理解這個(gè)數(shù)字了, 后期可以利用這個(gè)原理做一些令人驚訝的動(dòng)畫特效。
          2. window.innerWidth / window.innerHeight: 縱橫比寬/高, 這里寬高不會(huì)去寫px這種單位, 坐標(biāo)系里面是一種抽象的長度單位, 所以要告訴瀏覽器咱們當(dāng)前顯示圖像的區(qū)域的寬高比例(可以當(dāng)它是百分比布局, 就像我們寫css布局時(shí)使用vh vw為單位)。
          3. 1: 近平面, 簡單理解就是當(dāng)一個(gè)圖像距離相機(jī)的距離小于1的時(shí)候, 就不顯示這個(gè)圖像了。
          4. 1000: 遠(yuǎn)平面, 簡單理解就是當(dāng)一個(gè)圖像距離相機(jī)的距離大于1000的時(shí)候, 就不顯示這個(gè)圖像了。
          5. camera.position.z = 10; 相機(jī)的坐標(biāo)不設(shè)置的話, 默認(rèn)就是(0, 0, 0)坐標(biāo)原點(diǎn), 這樣類似腦袋在坐標(biāo)軸原點(diǎn)上看坐標(biāo)軸, 所以這里要設(shè)置距離坐標(biāo)中心有一定距離, 也就是遠(yuǎn)距離觀察這個(gè)坐標(biāo)系。
          const camera = new THREE.PerspectiveCamera(35window.innerWidth / window.innerHeight, 11000);
          camera.position.z = 10;
          • 無聊的知識: 我們在玩3d游戲的時(shí)候, 是不是有時(shí)候與另一個(gè)游戲人物距離太近了就會(huì)出現(xiàn)人物中空的效果, 這些很可能就是他的某些部分距離你相機(jī)的距離, 小于了近平面的距離導(dǎo)致的。
          • 物體距離眼睛越近越大, 越遠(yuǎn)越小, 因?yàn)橐粋€(gè)物品無限大與無限遠(yuǎn)沒有意義, 顯示起來浪費(fèi)性能, 所以才會(huì)設(shè)置近平面與遠(yuǎn)平面。

          第三步:生成渲染實(shí)例
          1. WebGLRenderer生成一個(gè)渲染實(shí)例, 用來渲染我們所有的3d效果。
          2. setSize設(shè)置場景的寬高。
          3. setClearColor設(shè)置背景色, 這個(gè)背景色不是平面的, 是全方位的, 你可以想想成你在一個(gè)屋子里, 這個(gè)顏色就是屋子墻壁、地板、天花板的顏色(.5是透明度)。
          4. renderer.domElement生成的渲染的實(shí)例, 這個(gè)要放到對應(yīng)的dom容器里面(是個(gè)canvas標(biāo)簽)。
          const renderer = new THREE.WebGLRenderer();
          renderer.setSize(window.innerWidth, window.innerHeight);
          renderer.setClearColor(0x00FFFF.5)
          document.body.appendChild(renderer.domElement);
          • 知識點(diǎn): setClearColor不寫就是黑色
          • 知識點(diǎn): setClearColor可以直接寫"red"這種, 不用必須16進(jìn)制。
          第四步:插入坐標(biāo)系實(shí)例
          1. AxisHelper: 用于生成輔助坐標(biāo)實(shí)例, 2代表這個(gè)坐標(biāo)系的長度, 因?yàn)槲覀儾灰欢ㄐ枰嚅L的輔助線。
          2. scene: 老朋友場景, 它的add方法就是把某某某加入到場景中來。
          const axisHelper = new THREE.AxisHelper(2)
          scene.add(axisHelper)
          第五步:渲染出來
          1. 第一個(gè)參數(shù)是場景, 第二個(gè)參數(shù)是相機(jī)。
          renderer.render(scene, camera);

          下面是效果圖, z軸正對著我們所以看不到:

          在斜上方看到是如下的效果, 之后的章節(jié)會(huì)說如何調(diào)整相機(jī)的位置與角度

          完整的代碼如下

          <html>
          <body>
              <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>
              <script>
                  const scene = new THREE.Scene();
                  const camera = new THREE.PerspectiveCamera(35window.innerWidth / window.innerHeight, 11000);
                  camera.position.z = 10;
                  const renderer = new THREE.WebGLRenderer();
                  renderer.setSize(window.innerWidth, window.innerHeight);
                  renderer.setClearColor(0x00FFFF.5)
                  document.body.appendChild(renderer.domElement);
                  const axisHelper = new THREE.AxisHelper(2)
                  scene.add(axisHelper)
                  renderer.render(scene, camera);
              </script>

          </body>
          </html>

          七. 第一個(gè)立方體

          不畫一個(gè)立方體感覺對不起 第一篇這個(gè)題目, 要注意了在three.js中你可以理解為繪制一個(gè)幾何體需要兩部分, 一個(gè)是幾何體本身, 比如這個(gè)幾何體的長寬高, 另一個(gè)就是材質(zhì)可以簡單理解為表面的顏色樣式。???? geometry這個(gè)單詞我們會(huì)經(jīng)常打交道的, 來一起記下它吧。

          BoxGeometry 長方體

          const geometry = new THREE.BoxGeometry(1, 2, 3);

          1. 1: '長', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在x軸上的長度。
          2. 2: '高', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在y軸上的長度。
          3. 3: '寬', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在z軸上的長度。

          new出來的實(shí)例上面會(huì)有這個(gè)幾何體的點(diǎn)的信息, 面的信息等等, 這個(gè)后面再詳細(xì)說這次主要入門。

          MeshBasicMaterial 材質(zhì)

          顏色與上面設(shè)置setClearColor一樣, 什么寫法都行的, 下面是我設(shè)置了一個(gè)紅色的材質(zhì)。const material = new THREE.MeshBasicMaterial({ color: 'red' });

          生成'網(wǎng)格' Mesh

          const cube = new THREE.Mesh(geometry, material);網(wǎng)格上含有位置信息、旋轉(zhuǎn)信息、縮放信息等等, 他需要用幾何體材質(zhì)兩個(gè)參數(shù), 但其實(shí)并不像網(wǎng)上說的必須要有材質(zhì), 不傳材質(zhì)也能顯示。

          放入場景

          也就是場景對象scene本身有個(gè)add方法。scene.add(cube);

          右上方視角

          放入場景的幾種方式

          1: 我直接放入geometryscene.add(geometry); 會(huì)報(bào)錯(cuò)了, 可以理解為不是網(wǎng)格對象所以報(bào)錯(cuò)了。以后遇到這類報(bào)錯(cuò)一定要考慮類型問題。

          2: 未設(shè)置材質(zhì)

          const cube = new THREE.Mesh(geometry);

          scene.add(cube);

          白白的一片, 并且控制臺沒有報(bào)錯(cuò)。

          八. 全部代碼

          <html>
          <body>
              <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>
              <script src="./utils/OrbitControls.js"></script>
              <script>
                  const scene = new THREE.Scene();
                  const camera = new THREE.PerspectiveCamera(35window.innerWidth / window.innerHeight, 11000);
                  camera.position.z = 10;
                  const renderer = new THREE.WebGLRenderer();
                  renderer.setSize(window.innerWidth, window.innerHeight);
                  renderer.setClearColor(0x00FFFF.5)
                  document.body.appendChild(renderer.domElement);
                  const axisHelper = new THREE.AxisHelper(2)
                  scene.add(axisHelper)

                  const geometry = new THREE.BoxGeometry(123);
                  const material = new THREE.MeshBasicMaterial({ color'red' });
                  const cube = new THREE.Mesh(geometry, material);
                  scene.add(cube);

                  renderer.render(scene, camera);
              </script>

          </body>

          </html>

          end

          第一篇寫的內(nèi)容并不多, 等基本知識儲備夠了就可以開始編寫3d地球了, 那里將會(huì)很有意思。希望與你一起進(jìn)步。

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端算法源碼編程群,每日一刷(工作日),每題瓶子君都會(huì)很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
          》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 48
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評論
          圖片
          表情
          推薦
          點(diǎn)贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  《精品 模特私拍秘 泄密》学院派 | AV乱伦网站 | 久久99精品久久久水蜜桃 | 放荡少妇三p黄色毛片 | 中字中文综合 |