ThreeJS 入門如何渲染出第一個3D圖形

ThreeJS 入門如何渲染出第一個3D圖形

什么是ThreeJS?

Three.js 是一個用于在Web瀏覽器上創(chuàng)建和顯示交互式 3D 圖形的 JavaScript 庫心软。簡化了在 Web 上創(chuàng)建基于 WebGL 的 3D 圖形的過程郁轻。WebGL 是一種在 Web 瀏覽器中實現(xiàn)硬件加速的 3D 圖形渲染的技術(shù)赖阻。Three.js 通過封裝復雜的WebGL API掂恕,提供了一個更簡單的接口蹭越,使得我們能夠輕松地在瀏覽器中創(chuàng)建 3D 場景障本、模型、動畫和交互效果响鹃。

渲染一個 3D 圖形需要哪些步驟彼绷?

要渲染第一個 3D 圖形,需要以下幾個步驟:

  • 創(chuàng)建場景 scene茴迁,使用 THREE.Scene 進行創(chuàng)建寄悯。
  • 創(chuàng)建相機 camera,使用 THREE.PerspectiveCamera 進行創(chuàng)建堕义。
  • 創(chuàng)建渲染對象(以立方體為例)猜旬,并添加到場景 scene 中
  • 創(chuàng)建渲染器 renderer倦卖,并進行場景渲染洒擦,使用THREE.WebGLRenderer 進行創(chuàng)建。調(diào)用渲染器 render 函數(shù)將場景 scene 和相機 camera 作為參數(shù)進行渲染怕膛。

// 插入一個跳轉(zhuǎn)地址熟嫩,方便查看完整代碼

創(chuàng)建場景

在 Three.js 中,使用 THREE.Scene 來創(chuàng)建 scene(場景)褐捻,scene包含了所有 3D 對象掸茅、光源和相機的容器。它是構(gòu)建和組織 3D 場景的基礎(chǔ)柠逞。

場景(THREE.Scene)類代表了一個虛擬的 3D 空間昧狮,其中可以包含各種對象,例如幾何體板壮、模型逗鸣、燈光等。通過將對象添加到場景中,可以在渲染過程中將它們呈現(xiàn)到屏幕上撒璧。

創(chuàng)建一個簡單的場景:

import * as THREE from 'three';
const scene = new THREE.Scene();

實例化后的 scene 對象提供一些列的API來對其中的 3D 對象進行管理透葛,如: scene.add(object: Object3D)scene.remove(object: Object3D), scene.traverse(callback: Function) 卿樱。還提供對 scene 進行設(shè)置和操作的 API 本文暫時未使用到 scene 中其他的API僚害,后續(xù)單獨寫篇文章進行介紹。

創(chuàng)建相機

在 Three.js 中殿如,camera(相機)是用于定義場景中的視角和觀察位置的對象贡珊。相機確定了渲染器如何將場景中的 3D 對象投影到屏幕上,決定了觀察者在場景中看到的內(nèi)容涉馁。使用相機來控制觀察者在場景中的位置和視角门岔。在 openGL 中相機的位置固定在(0,0,0)位置,所有的相機移動實際都是對場景中的所有對象進行矩陣變換烤送。
Three.js 提供了多種類型的相機寒随,常用的是透視相機(THREE.PerspectiveCamera)和正交相機(THREE.OrthographicCamera)。

  • 透視相機(THREE.PerspectiveCamera)使用透視投影帮坚,模擬了人眼的視覺效果妻往。它具有視場角(FOV)、縱橫比试和、近剪裁面和遠剪裁面等屬性讯泣。視場角決定了場景在相機前方可見的范圍,縱橫比定義了視圖的寬高比阅悍,近剪裁面和遠剪裁面則定義了相機的可見范圍好渠。
  • 正交相機(THREE.OrthographicCamera)使用正交投影,產(chǎn)生了一個沒有透視效果的平行投影节视。它具有左拳锚、右、上寻行、下霍掺、近、遠等屬性拌蜘,用于定義可見區(qū)域的范圍杆烁。

本文使用透視相機創(chuàng)建一個實例:

const camera = new THREE.PerspectiveCamera(
  75,
  window.innerWidth / window.innerHeight,
  0.1,
  1000
);

參數(shù)主要如下,THREE.PerspectiveCamera(fov, aspect, near, far)

  • fov: 視場角拦坠,表示相機的視角張度连躏,單位是度。
  • aspect: 縱橫比贞滨,表示渲染區(qū)域的寬高比。
  • near: 近剪裁面的距離,表示相機能夠看到的最近距離晓铆,在近剪裁面之前的3D對象會被裁剪掉勺良。
  • far: 遠剪裁面,表示相機能夠看到的最遠距離骄噪。在此之后的對象也會被裁剪掉尚困。

不用擔心,后續(xù)會專門寫篇文章進行詳細介紹兩相機之間的區(qū)別链蕊,什么是近剪裁面事甜、遠剪裁面以及其距離怎么算的。

創(chuàng)建渲染對象(立方體為)

創(chuàng)建一個正立方體:

// 創(chuàng)建綠色的立方體

// 創(chuàng)建立方體幾何體
const geometry = new THREE.BoxGeometry(1,1,1);
// 實例化基礎(chǔ)的材質(zhì)滔韵,顏色設(shè)置為綠色逻谦, rgb 每兩個十六進制單位分別表示一個基礎(chǔ)元色。
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
// 生成一個立方體網(wǎng)格對象陪蜻,傳入幾何體對象和顏色材質(zhì)對象
const cube = new THREE.Mesh(geometry, material);
// 將立方體網(wǎng)格對象添加到場景中
scene.add(cube);

這里涉及到三個新的基類分別是 THREE.BoxGeometry 邦马、 THREE.MeshBasicMaterialTHREE.Mesh

  • THREE.BoxGeometry 立方幾何體宴卖,用于創(chuàng)建長方體或者立方體滋将。 ThreeJS 提供 8 種 Shape 類用于創(chuàng)建基本幾何體和自定義形狀。還提供一些可以擴展的基類症昏,我們可以在這個基類的基礎(chǔ)上進行其他封裝随闽。openGL 提供的圖元實際很基礎(chǔ)(點,線肝谭,線環(huán)掘宪,線帶,三角形分苇,三角扇添诉,三角帶,四邊形)医寿,ThreeJS 進行的大量封裝使得我們更好進行形狀生成栏赴。(_)以后再開篇進行詳細介紹。
  • MeshBasicMaterial 基礎(chǔ)材質(zhì)靖秩,不受光照影響须眷,只顯示顏色。ThreeJS 一共提供了 7 種常用材質(zhì)對象以及特殊的幾種材質(zhì)比如:粒子材質(zhì)等沟突。
  • Mesh 網(wǎng)格對象花颗,用于將幾何體與材質(zhì)結(jié)合起來。ThreeJS 提供 6 種網(wǎng)格對象支持不同的使用場景惠拭。

創(chuàng)建渲染器將 scene 渲染出來

創(chuàng)建一個 WebGLRenderer 渲染器渲染scene:

// 創(chuàng)建一個 webgl 渲染器
const renderer = new THREE.WebGLRenderer();
// 設(shè)置渲染器的 size
renderer.setSize(window.innerWidth, window.innerHeight);
// 綁定輸出位置
document.body.appendChild(renderer.domElement);
// 將 scene 渲染出來
renderer.render(scene, camera);

渲染器是 ThreeJS 的核心組件扩劝,將 scene 場景中的三維對象渲染到屏幕上庸论。ThreeJS 提供了三類常用的渲染器 WebGLRendererCanvasRenderer棒呛、SVGRenderer聂示。預計未來可能會支持 WebGPURenderer 現(xiàn)在 Chrome 已經(jīng)支持 WebGPU 了并且性能比 Webgl 更好一些(反正隔壁 babyIcon 已經(jīng)支持了v)。
渲染器主要行為大體如下:

  • 創(chuàng)建渲染上下文
  • 設(shè)置渲染參數(shù)
  • 渲染 scene
  • 輸出渲染結(jié)果到載體(通常都是canvas)

至此已經(jīng)能渲染一個立方體了簇秒,接下來補充一丟丟代碼讓立方體渲染起來鱼喉。

  const rotateBox = () => {
    // 創(chuàng)建 scene 場景
    const scene = new THREE.Scene();

    // 創(chuàng)建相機
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );

    // 設(shè)置相機的z位置為5 ,位置:(0趋观,0扛禽,5)
    camera.position.z = 5;

    // 創(chuàng)建綠色立方體
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ffa1 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 創(chuàng)建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 讓立方體渲染起來
    function animate() {
      requestAnimationFrame(animate);

      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    }

    animate();
  };

完整代碼(我在 react 中運行),方便對每篇文章的 demo 進行管理以及ui交互皱坛。代碼也可以復制到到 HTML 中執(zhí)行額外添加一行 threejs庫的引入即可:

import React, { useEffect } from 'react';
import * as THREE from 'three';

export default function OneDay() {

  const rotateBox = () => {
    // 創(chuàng)建 scene 場景
    const scene = new THREE.Scene();

    // 創(chuàng)建相機
    const camera = new THREE.PerspectiveCamera(
      75,
      window.innerWidth / window.innerHeight,
      0.1,
      1000
    );

    // 設(shè)置相機的z位置為5 编曼,位置:(0,0麸恍,5)
    camera.position.z = 5;

    // 創(chuàng)建綠色立方體
    const geometry = new THREE.BoxGeometry(1, 1, 1);
    const material = new THREE.MeshBasicMaterial({ color: 0x00ffa1 });
    const cube = new THREE.Mesh(geometry, material);
    scene.add(cube);

    // 創(chuàng)建渲染器
    const renderer = new THREE.WebGLRenderer();
    renderer.setSize(window.innerWidth, window.innerHeight);
    document.body.appendChild(renderer.domElement);

    // 讓立方體渲染起來
    function animate() {
      requestAnimationFrame(animate);

      cube.rotation.x += 0.01;
      cube.rotation.y += 0.01;

      renderer.render(scene, camera);
    }

    animate();
  };
  
  useEffect(() => {
    rotateBox();
  }, []);

  return <div id="container"></div>
}

立個 flag 后續(xù)持續(xù)學習更新 threejs 系列文章(每周一篇)灵巧,歡迎大家關(guān)注監(jiān)督 -

本文由mdnice多平臺發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市抹沪,隨后出現(xiàn)的幾起案子刻肄,更是在濱河造成了極大的恐慌,老刑警劉巖融欧,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件敏弃,死亡現(xiàn)場離奇詭異,居然都是意外死亡噪馏,警方通過查閱死者的電腦和手機麦到,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來欠肾,“玉大人瓶颠,你說我怎么就攤上這事〈烫遥” “怎么了粹淋?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長瑟慈。 經(jīng)常有香客問我桃移,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮逞频,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘蔗衡。我一直安慰自己纤虽,他們只是感情好,可當我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布粘都。 她就那樣靜靜地躺著廓推,像睡著了一般刷袍。 火紅的嫁衣襯著肌膚如雪翩隧。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天呻纹,我揣著相機與錄音堆生,去河邊找鬼。 笑死雷酪,一個胖子當著我的面吹牛淑仆,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哥力,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼蔗怠,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了吩跋?” 一聲冷哼從身側(cè)響起寞射,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锌钮,沒想到半個月后桥温,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡梁丘,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年侵浸,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片氛谜。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡掏觉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出值漫,到底是詐尸還是另有隱情澳腹,我是刑警寧澤,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布惭嚣,位于F島的核電站遵湖,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏晚吞。R本人自食惡果不足惜延旧,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望槽地。 院中可真熱鬧迁沫,春花似錦芦瘾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至挺智,卻和暖如春祷愉,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背赦颇。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工二鳄, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人媒怯。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓订讼,卻偏偏與公主長得像,于是被迫代替她去往敵國和親扇苞。 傳聞我的和親對象是個殘疾皇子欺殿,可洞房花燭夜當晚...
    茶點故事閱讀 45,086評論 2 355

推薦閱讀更多精彩內(nèi)容

  • Three.js 是一款運行在瀏覽器中的 3D 引擎,你可以用它在 web 中創(chuàng)建各種三維場景鳖敷,包括了攝影機脖苏、光影...
    了無_數(shù)據(jù)科學閱讀 1,568評論 0 0
  • ThreeJS 里元素如下: 1.場景(Scene):是物體、光源等元素的容器哄陶, 2.相機(Camera):控制...
    _花閱讀 985評論 0 1
  • 一帆阳、前言 ThreeJs 封裝了 WebGL 進行渲染時所涉及到的相關(guān)概念,如光照屋吨,材質(zhì)蜒谤,紋理以及相機等。除此之外...
    仰簡閱讀 7,243評論 1 10
  • Threejs 為什么至扰? webGL太難用鳍徽,太復雜! 但是現(xiàn)代瀏覽器都支持 WebGL 這樣我們就不必使用 Fla...
    強某某閱讀 6,053評論 1 21
  • 1敢课、WebGL與threeJS WebGL是一種3D繪圖協(xié)議阶祭,其允許JavaScript和OpenGL ES2.0...
    患者_閱讀 20,126評論 1 22