iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

Three.js 學習日誌系列 第 16

Day15 - 金屬球範例試作(2) - Material解密(五)

  • 分享至 

  • xImage
  •  

Day15 - 金屬球範例試作(2) - Material解密(五)

這裡是「Three.js學習日誌」的第15篇,本篇的主旨是要透過一個簡單的範例操作,來一步一步介紹材質與渲染的關係,這系列的文章假設讀者看得懂javascript,並且有Canvas 2D Context的相關知識。

前情提要: 昨天時間略趕,一時的疏忽不小心漏掉了一條需要在環境中補上環境光的描述,如果有人照著步驟走,可能會有亮度不夠的問題,所以這邊重新補上,對各位造成不便,敬請見諒。

const al = new AmbientLight(0xffffff, 1);
...
scene.add(al);

今天我們要來完成昨天沒完成的範例。

img

7. 補上環境貼圖

我們之前在講解texture的時候其實沒有講到這種類型的texture

所謂的環境貼圖指的是:

周圍景色透過物體表面反射到觀察者眼中的圖樣。

有些人也會把這種概念稱為Skybox(天空盒)

Three.js中,環境貼圖需要靠CubeTextureLoader來載入,它的形式會比較特別一點,當我們要載入一個完整的環境貼圖,我們需要依序傳入6張不同的周圍景色圖片。

import {CubeTextureLoader} from 'https://cdn.skypack.dev/three';
...
const cubeTextureLoader = new CubeTextureLoader();
const envMap = cubeTextureLoader.load([
    envPx, //+X位置的環境貼圖
    envNx, //-X位置的環境貼圖
    envPy, //+Y位置的環境貼圖
    envNy, //-Y位置的環境貼圖
    envPz, //+Z位置的環境貼圖
    envNz  //-Z位置的環境貼圖
])

這邊我們會把6張環境貼圖分成+X/-X/+Y/-Y/+Z/-Z,之所以會這樣分是因為通常環境貼圖是從HDRI圖像(High Dynamic Range Image,高動態範圍圖像)去拆解出來的。

關於HDRI圖像的介紹可以看這邊

img

一般的HDRI圖片 拆解後
img img

一般來說,如果想要自己製造HDRI素材,你會需要有一台360度相機,但如果沒有,其實網路上有很多免費下載的資源可以用。

例如這裡:Polyhaven

而若手邊已經有一張合適的HDRI素材,可以用這個免費的線上服務來做拆解。

這邊我把拆解完畢的圖檔上傳到imgur備用

const cubeTextureLoader = new CubeTextureLoader();
const envMap = cubeTextureLoader.load([
    'https://i.imgur.com/9wJp0Zy.png', //+X位置的環境貼圖
    'https://i.imgur.com/damIWcE.png', //-X位置的環境貼圖
    'https://i.imgur.com/mfqMr3m.png', //+Y位置的環境貼圖
    'https://i.imgur.com/0dpZmDE.png', //-Y位置的環境貼圖
    'https://i.imgur.com/Nj6WcOI.png', //+Z位置的環境貼圖
    'https://i.imgur.com/wwLgHqa.png'  //-Z位置的環境貼圖
])
...

接著我們把envMap 寫入球和平面的材質建構參數中,並且微調一下反射率/漫反射率

...
const mat1 = new MeshStandardMaterial({
    color: new Color("#eee"),
    metalness: 0.8,
    roughness: 0.3,
    envMap: envMap
  });
  const mat2 = new MeshStandardMaterial({
    color: new Color("#eee"),
    metalness: 0.8,
    roughness: 0.8,
    envMap: envMap
  });

img

嘿~我們辦到了。

codepen 連結: 點我

8. 來試試看補上別的材質貼圖吧

雖然這邊我們已經達成製作金屬球+金屬平面的目標了,但我們接著其實可以來玩些別的玩意。

例如試著把金屬材質變成木頭材質

8-1. 首先來找張具有木頭紋理的材質貼圖,並用來生成其他材質貼圖

img

然後可以透過這個免費服務產生基於這個木質紋理的:

  • Normal Map
  • AO Map
  • Height Map

img

8-2. 載入材質貼圖並填入球和平面的材質建構參數中

const tl = new TextureLoader();
const woodTexture = tl.load('https://i.imgur.com/jzo9PZI.jpg');
const woodTextureNormal = tl.load('https://i.imgur.com/y60NQGm.png');
const woodTextureAO = tl.load('https://i.imgur.com/jDR50UI.png');
const woodTextureHeight = tl.load('https://i.imgur.com/3fGth9V.png');
...

const mat1 = new MeshStandardMaterial({
    map:woodTexture,
    normalMap:woodTextureNormal,
    aoMap:woodTextureAO,
    displacementMap:woodTextureHeight,
    color: new Color("#eee"),
    metalness: 0.8,
    roughness: 0.3,
    envMap: envMap
  });
  const mat2 = new MeshStandardMaterial({
    map:woodTexture,
    normalMap:woodTextureNormal,
    aoMap:woodTextureAO,
    displacementMap:woodTextureHeight,
    color: new Color("#eee"),
    metalness: 0.8,
    roughness: 0.8,
    envMap: envMap
  });

img

疑? 怎麼變得看起來很詭異XD

8-3. 調整各貼圖參數

我們在上一個步驟會發現幾個詭異的現象,例如球卡進地板裡面/紋路上有看起來很詭異的光澤。

這是因為我們還維持著原本金屬球反射率等參數,而且也沒有針對傳進來的材質做參數調整,所以我們這邊要著手進行優化。

首先球之所以會卡進去地板裡面,是因為地板也同樣被附加了Height Map,所以整體的Geometry頂點都被提高,這邊我們可以透過修改displacementBias來做微調。

除此之外,這邊我把兩個材質的metalness設置都拿掉,並且藉由提高roughness來提升漫反射率,這樣球體表面就不會再反射詭異的光澤。

最後我們把的材質加上displacementScale的修正,目的是為了避免球出現模型破裂的狀況。

const mat1 = new MeshStandardMaterial({
    map: woodTexture,
    normalMap: woodTextureNormal,
    aoMap: woodTextureAO,
    displacementMap: woodTextureHeight,
    color: new Color("#eee"),
    roughness: 0.3,
    displacementScale: 0.1,
    envMap: envMap
  });
  const mat2 = new MeshStandardMaterial({
    map: woodTexture,
    normalMap: woodTextureNormal,
    aoMap: woodTextureAO,
    displacementMap: woodTextureHeight,
    color: new Color("#eee"),
    roughness: 0.3,
    displacementBias: -0.5,
    envMap: envMap
  });

img

是不是好多了呢?

codepen連結:點我

小結

今天我們成功的把金屬球做出來了~同時還示範過要怎麼把金屬球換成木頭質感。明天將會是Material章節的最後一篇,我們會介紹一些除了MeshStandardMaterial以外的材質類。

延伸資源


上一篇
Day14 - 金屬球範例試作(1) - Material解密(四)
下一篇
Day16 - 金屬球範例試作(3) - Material解密(六)
系列文
Three.js 學習日誌31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言