iT邦幫忙

2022 iThome 鐵人賽

DAY 17
0
Modern Web

Three.js 學習日誌系列 第 17

Day16 - 金屬球範例試作(3) - Material解密(六)

  • 分享至 

  • xImage
  •  

Day16 - 金屬球範例試作(3) - Material解密(六)

這裡是「Three.js學習日誌」的第16篇,這是Material章節的最後一篇,主旨是在講解Three.js所提供的其餘材質,這系列的文章假設讀者看得懂javascript,並且有Canvas 2D Context的相關知識。

在上一回我們成功的把金屬球&金屬平面做出來了~ 但由於我們之前都只有使用過MeshStandardMaterialMeshBasicMaterial,所以我想說趁著這個機會來介紹一下Three.js所提供的其他材質。

9. 最後的最後來試試看MeshStandardMaterial以外的材質

Three.js所提供的Material類其實不少,這邊我做了一個列表來釐清各材質之間的差異。

材質名稱 介紹 對光源反應
MeshBasicMaterial 可以支援填入顏色的最簡單材質
MeshStandardMaterial 最常用的標準PBR材質
MeshMatcapMaterial 不接受光源, 但是它具備特別的UV運算模式,可以透過傳入特殊的球狀紋理,來把模型渲染得像是有受光的樣子
MeshLambertMaterial 基於非物理的Lambertian模型來計算反射率,適合用來模擬一些未加工的木材或石材,除此之外,效能的消耗相較於MeshStandardMaterial來的低一些
MeshPhongMaterial 基於非物理的Blinn-Phong模型來計算反射率,具有反射光點的設計的可受光材質, 耗能比Lambertian略多,適合用來模擬鏡面材質
MeshNormalMaterial 透過模型各處的法向量,直接Mapping到RGB值的材質
MeshToonMaterial 近年常見的三渲二技術所使用的材質,可受光,但是色彩上較為不同

這邊讓我們依序來試試MeshMatcapMaterialMeshNormalMaterialMeshToonMaterial

9-1 MeshMatcapMaterial 是什麼?

Matcap這個詞的意思其實是「材質捕捉」。

平常我們在3D建模軟體中,把模型做好之後,給它打上特定的光源,並加上一系列的材質修改係數,這些渲染到模型上的色彩是動態(Dynamic)的,它們會根據光源的位置、材質係數的不同而有不同的成色。

講到這邊大概就有人會想到:那有沒有一種可能,就是:是否可以把這些渲染到模型上的色彩「皮」,剝下來變成一套靜態的資源呢?

當然是有的,這個手段在3D建模的領域中就叫做「Bake」。

透過「Bake」,我們其實就可以在無光照的環境下實現「模型看起來好像有受光」的假象,這麼一來程式對於硬體的需求度就可以降低。

要知道實時渲染的光照/陰影是非常消耗效能的

MeshMatcapMaterial的原理其實就是把通過「Bake」獲得的材質球紋理,映射到模型上面。

img

上面這張圖很好的解釋了Matcap的原理。

Three.js中,若想要使用MeshMatcapMaterial,那就必須要先有Matcap素材。

想要自己製作Matcap素材,通常是需要使用3D建模軟體去「Bake」的,但這邊我們先去網路上找可以免費下載的資源。

例如這裡:點我

這邊我們用這張素材來試試看。

img

Matcap紋理的載入不需要額外的Loader,直接使用TextureLoader就可以。這邊我們先載入素材。

const matcapTexture = tl.load(
  "https://i.postimg.cc/L5gYZjVk/Genetic-View-Light-Green-Jade1a.png"
);

接著我們把原本金屬球/金屬面的材質都換成MeshMatcapMaterial

const mat = new MeshMatcapMaterial({
    matcap: matcapTexture
});

16-1.jpg

其實感覺不錯對吧~

codepen連結:點我

9-2 MeshNormalMaterial 是什麼?

之所以把MeshNormalMaterial放在第二順位介紹,是因為它其實跟MeshMatcapMaterial是很相像的東西。

我們剛剛有提到MeshMatcapMaterial是把Matcap素材映射到物體表面,但MeshNormalMaterial則是把RGB色域整個映射到物體表面。

通常這種材質只是拿來檢視3D模型每一個面的狀況,避免模型因為使用同一個顏色作為材質而分不清面的朝向。

通常這種材質比較少使用在以視覺/美術為主打特色的產品中。

這邊我們就簡單的示範一下。

const mat = new MeshNormalMaterial({
});

img

codepen 連結:點我

9-3 MeshToonMaterial 是什麼?

近年來,三渲二已經逐漸成為了一種成熟的渲染風格。之所以叫做三渲二,是因為透過這種方法渲染出來的模型,看起來就像2D動畫片中的圖像一樣。

img

三渲二這種技術目前在動畫產業已經被大幅的使用,它的優點是可以減少很多人工作畫的技術門檻(例如鏡頭旋轉/透視畫面的cut)

而在Three.js中,我們其實可以透過MeshToonMaterial做出類似的效果

這邊我們馬上來試試看~

const mat = new MeshToonMaterial({
    color:0xff0000 //隨便給個紅色
});

img

哪尼? 阿說好的光照和陰影咧? 怎麼變得跟MeshBasicMaterial一樣?

當我們把MeshToonMaterial套到我們的球和平面上面時,會發現陰影整個不見了。這是因為我們的AmbientLight強度給的太高了。

所以這邊我們削弱AmbientLight的強度~

const al = new AmbientLight(0xffffff, 0.2);

img

陰影出來了~

如果保持MeshToonMaterial預設的設定,物體的表面上會以2種顏色來呈現受光的程度。

也就是官方文件中提到的twoTone

如果我們想要客製化tone這個部分,我們會需要傳入自定義的gradient texture(漸層紋理)。

所謂的gradient texture,其實用意就是告訴Three.js到底受光程度的漸變有幾個階層,每個階層又是要用多少的灰度值來呈現。

gradient texture不需要太大張,像這邊我使用的threeTone版本就只需要3px*1px尺寸即可。

img

這邊我們示範一下把自製的gradient texture使用在MeshToonMaterial的狀況。

這邊我用fiveTone的版本來試試看。

const gTexture = tl.load("https://i.imgur.com/BybHhWd.jpg");
const mat = new MeshToonMaterial({
    color: 0xff0000,
    gradientMap: gTexture
  });

img

這陰影怎麼又~變的怪怪的啊

在我們把自定義的gradient texture作為gradientMap傳給MeshToonMaterial之後,它卻還是沒有按照我們的想像生成多種顏色,反而是變成了類似MeshStandardMaterial一樣有漸層的陰影。

之所以會這樣,原因是因為當使用自訂義gradientMap的時候,我們必須要再調整兩個設置(這一點官方文件有提到)。

img

...
gTexture.minFilter = NearestFilter; //NearestFilter記得要import
gTexture.magFilter = NearestFilter;

We made it!

codepen連結: 點我

因為礙於篇幅和時間限制,我只找了其中幾個個人覺得比較有看點的Material來介紹,如果大家對其他Material有興趣,不妨自己實驗看看其他Material的用法。/images/emoticon/emoticon69.gif

小結

我們終於結束了Material章節~ 明天開始終於要來到全新的進度了,還請大家拭目以待!/images/emoticon/emoticon30.gif

延伸資源


上一篇
Day15 - 金屬球範例試作(2) - Material解密(五)
下一篇
Day17 - Three.js與滑鼠互動操作(一)
系列文
Three.js 學習日誌31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言