溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何從入門Three.js到做出3D地球的示例分析

發(fā)布時(shí)間:2021-09-17 14:42:50 來(lái)源:億速云 閱讀:170 作者:柒染 欄目:web開(kāi)發(fā)

如何從入門Three.js到做出3D地球的示例分析,針對(duì)這個(gè)問(wèn)題,這篇文章詳細(xì)介紹了相對(duì)應(yīng)的分析和解答,希望可以幫助更多想解決這個(gè)問(wèn)題的小伙伴找到更簡(jiǎn)單易行的方法。

開(kāi)篇介紹

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

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

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

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

如何從入門Three.js到做出3D地球的示例分析

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

  1.  自食其力:不管是在公司還是網(wǎng)上都有類似的庫(kù), 但是當(dāng)遇到bug或是缺少功能的情況時(shí)就會(huì)很麻煩, 例如我們公司的FGL庫(kù)(一個(gè)內(nèi)網(wǎng)繪制3d景象的技術(shù)), 它官網(wǎng)上的例子很多都是錯(cuò)的, 使用起來(lái)也是一堆問(wèn)題, 比如無(wú)法精準(zhǔn)選擇某個(gè)國(guó)家, 點(diǎn)擊事件消融等bug。還比如說(shuō)Echarts的地球, 它太注重真實(shí)感并且用起來(lái)有點(diǎn)卡, 以及交互做的不太好。

  2.  直指核心: 去年我通過(guò)看書(shū)、看文章、看視頻認(rèn)真的學(xué)習(xí)three.js, 并做出了3d地球這個(gè)項(xiàng)目, 而這個(gè)系列文章將會(huì)直指做出3d地圖的核心知識(shí), 盡量不隨意擴(kuò)散知識(shí)面。

  3.  更好入門: 網(wǎng)上的教學(xué)文章千篇一律, 點(diǎn)進(jìn)去閱讀完感覺(jué)其對(duì)于一個(gè)three.js零基礎(chǔ)的同學(xué)來(lái)說(shuō)都不太好懂, 教學(xué)視頻里的知識(shí)點(diǎn)太廣泛, 事無(wú)巨細(xì)的羅列, 而這個(gè)系列文章將更突出繪制3d地球這個(gè)重點(diǎn)。

  4.  同道中人: 我學(xué)習(xí)three.js就是為了做出3d地球, 期間走了不少?gòu)澛? 被某些問(wèn)題卡了很久, 所以我更懂一個(gè)剛?cè)腴T的人困惑的點(diǎn)在哪里。

  5.  專注vue: 市面上較少專門針對(duì)vue做到開(kāi)箱即用的3d地球插件, 而我們就要編寫這樣一款產(chǎn)品。

  6.  不斷學(xué)習(xí): 編寫文章也是我提高自己能力的一種方法, 死磕每個(gè)知識(shí)點(diǎn)讓自己的理解更上一層樓。

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

  1.  入門three.js技術(shù)。

  2.  繪制出3d地球。

  3.  做成專門vue使用的庫(kù)。

  4.  后期也會(huì)介紹著色器的概念與基本的使用技巧。

  5.  會(huì)介紹少量webgl的相關(guān)用法, 并且會(huì)有部分?jǐn)?shù)學(xué)知識(shí)。

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

  •  主線劇情: 圍繞著如何做出3d地球, 這部分在vue工程里面進(jìn)行。

  •  支線任務(wù): 每個(gè)分散的知識(shí)點(diǎn), 可能與3d地球沒(méi)關(guān)系, 但是它能幫助我們更好的理解3d技術(shù), 而這些知識(shí)點(diǎn)我就不在vue項(xiàng)目里面演示了, 會(huì)單獨(dú)創(chuàng)建一個(gè)html文件來(lái)演示說(shuō)明。

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

像繪制圖形這類技術(shù), 最基本的概念就坐標(biāo)系, 下圖是二維坐標(biāo)系, 我們的故事就從這個(gè)家伙開(kāi)始。

如何從入門Three.js到做出3D地球的示例分析

我們用(0, 0)表示坐標(biāo)的中心點(diǎn), 繪制一條起點(diǎn)為中心點(diǎn)長(zhǎng)度為1的線段可以使用 (0, 0) (1, 0)這兩個(gè)點(diǎn)相連表示。

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

在three.js中我們要打交道的就是下面這位三維坐標(biāo)系

如何從入門Three.js到做出3D地球的示例分析

他的坐標(biāo)原點(diǎn)就是(0, 0, 0), 繪制一條起點(diǎn)為中心點(diǎn)的長(zhǎng)度為1的線段可以是 (0, 0, 0) (1, 0, 0)。

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

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

如何從入門Three.js到做出3D地球的示例分析

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

五. 相機(jī)的概念

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

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

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

如何從入門Three.js到做出3D地球的示例分析

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

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

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

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

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

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

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

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

const scene = new THREE.Scene();

第二步:創(chuàng)建相機(jī)

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

  1.  35: 視角也就是我們左眼與右眼可以看到的橫向角度, 其越小物體則越大, 因?yàn)槟抗庾儶M窄會(huì)突出物體, 你可以做一個(gè)實(shí)驗(yàn), 聚精會(huì)神的盯著看一個(gè)物體, 你就會(huì)發(fā)現(xiàn)此時(shí)你左右兩邊本來(lái)靠余光可以看到的物體你現(xiàn)在看不清, 這個(gè)就是你的視角變小了, 變小視角還可以使目標(biāo)物體比例變大, 我們知道這些就夠理解這個(gè)數(shù)字了, 后期可以利用這個(gè)原理做一些令人驚訝的動(dòng)畫特效。

  2.  window.innerWidth / window.innerHeight: 縱橫比寬/高, 這里寬高不會(huì)去寫px這種單位, 坐標(biāo)系里面是一種抽象的長(zhǎng)度單位, 所以要告訴瀏覽器咱們當(dāng)前顯示圖像的區(qū)域的寬高比例(可以當(dāng)它是百分比布局, 就像我們寫css布局時(shí)使用vh vw為單位)。

  3.  1: 近平面, 簡(jiǎn)單理解就是當(dāng)一個(gè)圖像距離相機(jī)的距離小于1的時(shí)候, 就不顯示這個(gè)圖像了。

  4.  1000: 遠(yuǎn)平面, 簡(jiǎ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(35, window.innerWidth / window.innerHeight, 1, 1000);  camera.position.z = 10;
  •  無(wú)聊的知識(shí): 我們?cè)谕?d游戲的時(shí)候, 是不是有時(shí)候與另一個(gè)游戲人物距離太近了就會(huì)出現(xiàn)人物中空的效果, 這些很可能就是他的某些部分距離你相機(jī)的距離, 小于了近平面的距離導(dǎo)致的。

  •  物體距離眼睛越近越大, 越遠(yuǎn)越小, 因?yàn)橐粋€(gè)物品無(wú)限大與無(wú)限遠(yuǎn)沒(méi)有意義, 顯示起來(lái)浪費(fèi)性能, 所以才會(huì)設(shè)置近平面與遠(yuǎn)平面。

第三步:生成渲染實(shí)例

  1.  WebGLRenderer生成一個(gè)渲染實(shí)例, 用來(lái)渲染我們所有的3d效果。

  2.  setSize設(shè)置場(chǎng)景的寬高。

  3.  setClearColor設(shè)置背景色, 這個(gè)背景色不是平面的, 是全方位的, 你可以想想成你在一個(gè)屋子里, 這個(gè)顏色就是屋子墻壁、地板、天花板的顏色(.5是透明度)。

  4.  renderer.domElement生成的渲染的實(shí)例, 這個(gè)要放到對(duì)應(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);
  •  知識(shí)點(diǎn): setClearColor不寫就是黑色

  •  知識(shí)點(diǎn): setClearColor可以直接寫"red"這種, 不用必須16進(jìn)制。

第四步:插入坐標(biāo)系實(shí)例

  1. 鴻蒙官方戰(zhàn)略合作共建——HarmonyOS技術(shù)社區(qū)

  2.  AxisHelper: 用于生成輔助坐標(biāo)實(shí)例, 2代表這個(gè)坐標(biāo)系的長(zhǎng)度, 因?yàn)槲覀儾灰欢ㄐ枰嚅L(zhǎng)的輔助線。

  3.  scene: 老朋友場(chǎng)景, 它的add方法就是把某某某加入到場(chǎng)景中來(lái)。 

const axisHelper = new THREE.AxisHelper(2)  scene.add(axisHelper)

第五步:渲染出來(lái)

  1.  第一個(gè)參數(shù)是場(chǎng)景, 第二個(gè)參數(shù)是相機(jī)。

renderer.render(scene, camera);

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

如何從入門Three.js到做出3D地球的示例分析

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

如何從入門Three.js到做出3D地球的示例分析

完整的代碼如下:

<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(35, window.innerWidth / window.innerHeight, 1, 1000);          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è)立方體感覺(jué)對(duì)不起 第一篇這個(gè)題目, 要注意了在three.js中你可以理解為繪制一個(gè)幾何體需要兩部分, 一個(gè)是幾何體本身, 比如這個(gè)幾何體的長(zhǎng)寬高, 另一個(gè)就是材質(zhì)可以簡(jiǎn)單理解為表面的顏色樣式。&ensp;&ensp;&ensp;&ensp; geometry這個(gè)單詞我們會(huì)經(jīng)常打交道的, 來(lái)一起記下它吧。

如何從入門Three.js到做出3D地球的示例分析

BoxGeometry 長(zhǎng)方體

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

  1: '長(zhǎng)', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在x軸上的長(zhǎng)度。

  2: '高', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在y軸上的長(zhǎng)度。

  3: '寬', 也可以理解為在不設(shè)置坐標(biāo)的時(shí)候在z軸上的長(zhǎng)度。

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

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)上說(shuō)的必須要有材質(zhì), 不傳材質(zhì)也能顯示。

放入場(chǎng)景

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

如何從入門Three.js到做出3D地球的示例分析

右上方視角

如何從入門Three.js到做出3D地球的示例分析

放入場(chǎng)景的幾種方式

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

如何從入門Three.js到做出3D地球的示例分析

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

const cube = new THREE.Mesh(geometry);  scene.add(cube);

如何從入門Three.js到做出3D地球的示例分析

如何從入門Three.js到做出3D地球的示例分析

白白的一片, 并且控制臺(tái)沒(méi)有報(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(35, window.innerWidth / window.innerHeight, 1, 1000);          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(1, 2, 3);          const material = new THREE.MeshBasicMaterial({ color: 'red' });          const cube = new THREE.Mesh(geometry, material);          scene.add(cube);         renderer.render(scene, camera);      </script>  </body>   </html>

關(guān)于從入門Three.js到做出3D地球的示例分析問(wèn)題的解答就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,如果你還有很多疑惑沒(méi)有解開(kāi),可以關(guān)注億速云行業(yè)資訊頻道了解更多相關(guān)知識(shí)。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI