three.js入門 掉落的甜甜圈實戰 | 大帥老猿threejs特訓

Mrchangchang發表於2023-01-11

隨著webGL的熱度越來越高,作為一個老前端也想去學習一下,我選擇入門three.js瞭解一下。

webGL & Three.js 簡介

WebGL 是一項在瀏覽器體現 3D 畫面的技術。是一種3D繪圖示準,允許把JavaScript和OpenGL ES 2.0結合在一起,透過增加OpenGL ES 2.0的一個JavaScript繫結,WebGL可以為HTML5 Canvas提供硬體3D加速渲染(部分計算GPU),這樣Web開發人員就可以藉助系統顯示卡來在瀏覽器裡更流暢地展示3D場景和模型了,還能建立複雜的導航和資料視覺化。
Three.js(Javascript 3D library),使用JavaScript語言對WebGL進行了封裝,讓前端開發人員在不需要掌握很多數學知識和繪圖知識的情況下,也能夠輕鬆進行web 3D開發。

相關文件

下載處理模型

在實際專案我們是需要和美術合作的,當然如果你或者你物件懂3d建模就再好不過了。
  1. 開啟資源網站,搜尋模型,開啟詳情,點選download按鈕。
  2. 使用blender匯入模型。
  3. 使用blender匯出glb模型檔案。

使用vite搭建專案。

Vite 能幫我們快速搭建專案。

npm create vite@latest

three.js 基本概念

三維的物體要渲染在二維的螢幕上。首先要建立一個場景來放置物體,那麼最終怎麼顯示三維的內容,就應該找一個相機,將相機放在場景的某個位置,然後想要顯示就要把相機拍的內容渲染出來。所以就引出三個基本概念:場景、相機、渲染器。

建立場景

const scene = new THREE.Scene();

建立相機

three.js 中相機分為立方體相機、正交相機、遠景相機。這裡我們使用的是遠景相機。
建構函式 PerspectiveCamera( fov, aspect, near, far )

  • fov — 相機視錐體垂直視角
  • aspect — 相機視錐體寬高比
  • near — 相機視錐體近裁剪面
  • far — 相機視錐體遠裁剪面。
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.01, 10);

渲染器

three.js 中渲染器分為Canvas渲染器(CanvasRenderer)、WebGL渲染器(WebGLRenderer)這裡我使用WebGL渲染器。
建構函式 WebGLRenderer( parameters )
parameters 是一個可選物件,包含用來定義渲染器行為的屬性。當沒有設定該引數時,將使用預設值。

  • canvas — 一個用來繪製輸出的 Canvas 物件。
  • context — 所用的 渲染上下文(RenderingContext) 物件。
  • precision — 著色器的精度。可以是"highp", "mediump" 或 "lowp". 預設為"highp",如果裝置支援的話。
  • alpha — Boolean, 預設為 false.
  • premultipliedAlpha — Boolean, 預設為 true.
  • antialias — Boolean, 預設為 false.
  • stencil — Boolean, 預設為 true.
  • preserveDrawingBuffer — Boolean, 預設為 false.
  • depth — Boolean, 預設為 true.
  • logarithmicDepthBuffer — Boolean, 預設為 false.
// 建立渲染器
const renderer = new THREE.WebGLRenderer({ antialias: true });
// 設定渲染的尺寸大小
renderer.setSize(window.innerWidth, window.innerHeight);
// 將webgl渲染的canvas內容新增到body中
document.body.appendChild(renderer.domElement);

光照

three.js中光照有以下幾種:環境光源(AmbientLight)、點光源(PointLight)、聚光光源(SpotLight)、平行光源(DirectionalLight)、半球光源(HemisphereLight)
其中支援陰影的光照有:點光源,聚光燈,平行光源。
這裡我使用的是半球光源 DirectionalLight( hex, intensity )

  • hex -- 光源顏色的RGB數值。
  • intensity -- 光源強度的數值。
    建立一個光照,從一個特定的方向,而不是從一個特定的位置。這個光看起來就像光源位於無限遠處,因此它產生的光線都是平行的。 最好的類比是一個像太陽一樣的光源:太陽是如此遙遠,所有的陽光照射到物體上都幾乎來自同一個角度。
// 建立環境光
const directionLight = new THREE.DirectionalLight(0xffffff, 0.4);
// 講環境光新增到場景
scene.add(directionLight);

載入資源

載入模型,播放模型中所有動畫。

new GLTFLoader().load('../resources/models/donuts.glb', (gltf) => {

  scene.add(gltf.scene);
  donuts = gltf.scene;

  mixer = new THREE.AnimationMixer(gltf.scene);
  const clips = gltf.animations; // 播放所有動畫
  clips.forEach(function (clip) {
      const action = mixer.clipAction(clip);
      action.loop = THREE.LoopOnce;
      // 停在最後一幀
      action.clampWhenFinished = true;
      action.play();
  });
})

載入環境貼圖

new RGBELoader()
    .load('../resources/sky.hdr', function (texture) {
        scene.background = texture;
        texture.mapping = THREE.EquirectangularReflectionMapping;
        scene.environment = texture;
        renderer.outputEncoding = THREE.sRGBEncoding;
        renderer.render(scene, camera);
});

動畫

使用requestAnimationFrame 播放動畫,設定動畫播放引數。

function animate() {
    requestAnimationFrame(animate);

    renderer.render(scene, camera);

    controls.update();

    if (donuts){
        donuts.rotation.y += 0.01;
    }

    if (mixer) {
        mixer.update(0.02);
    }
}

animate();

最後

github完整程式碼,感謝“大帥老猿”和“胖達”兩位老師舉辦的這次活動,感興趣同學,加入猿創營 (v:dashuailaoyuan),一起交流學習。

相關文章