iT邦幫忙

2022 iThome 鐵人賽

DAY 10
1
Software Development

30天成為鍵盤麥可貝:前端視覺特效開發實戰系列 第 10

Day10: three.js 前端視覺特效工程師實戰:全球戰情室—貼圖原理

  • 分享至 

  • xImage
  •  

成品

Screen Recording
Screen Recording 2022-09-25 at 3.27.28 PM.gif

本篇我們將完成圖中的地球畫面,從介紹貼圖開始。

做一個地球可以幹嘛?——地球的應用

地球的應用:B2C應用

B2C主要是行銷網站、企業形象網站、活動網站等等。有很多網站都會客製化地球,例如github.com首頁。

https://ithelp.ithome.com.tw/upload/images/20220925/20142505lK9U58L18l.png
圖片來源

地球的應用:B2B應用

至於B2B,也會有地球的需求。主要是全球數位戰情室、航太科技、GIS畫面為主。

例如前端套件Cesium,就是以地球為主軸,提供快速建置視覺畫面的套件。

https://ithelp.ithome.com.tw/upload/images/20220925/20142505p3Ak6pAbaQ.png

圖片來源

地球的應用:全球戰情室

我以為這都是非常中二的東西,現實生活中不會出現,沒想到是我的上班業務範圍之一。

是這樣的,全球有很多大企業在全球設廠。若要能在全球監控各地工廠的生產情形,則以地球作為儀表板的主畫面是再完美不過的排場。全球戰情室並不是只有地球,但它是很重要的元素。

全球戰情室是有市場的,如果要成為前端3D視覺特效工程師,那個地球將是再好不過的作品與應用。

地球的應用:這跟貼圖有什麼關聯?

地球需要很多貼圖要素,是絕佳的實戰對象。除了顏色以外,還有高度,水面與陸地的光澤等等。本篇將透過地球來介紹貼圖的原理,以及實際運用。也會在日後的Shader介紹中留下基礎。

本篇會介紹貼圖原理,下一篇介紹地球實作,再下一篇將介紹前端互動。

理解貼圖的運作模式

貼圖在WebGL中,由vertexShaderfragmentShader共同打造。我這邊不多講,留著之後在「Day22: WebGL Shader—你好啊大哥哥,沒想到你可以到Shader來呢!」提到WebGL時再討論,但我嘗試解釋three.js之下的底層原理。

  1. 有先,要有一張材質圖跟貼圖的模型。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505Jv4ITMgfrm.png

  2. 模型有錨點。

    https://ithelp.ithome.com.tw/upload/images/20220925/201425059zK2EuhWc9.png

  3. 假設世界地圖是一張大型貼紙,那我們應該如何剪裁這張貼紙並貼到模型呢?最簡單粗暴的方式就是展開模型,對應到貼紙上,接著剪裁貼紙。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505LFYmmQx1IV.png

  4. 那這就表示,我們要先「記住」每一個錨點,應該對應到貼紙的哪裡。要如何「記住」這件事情呢?那就是把錨點的位置存在RAM中,而這個位置資訊是一個(X,Y)的座標。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505veCaOYUozi.png

  5. 所以說,錨點在3D空間中,除了有一個(X,Y,Z)座標以外,還有貼圖位置的(X,Y)座標了。早期的工程師發現有兩種(X,Y)系統會讓人搞混。

    例如你同事告訴你X位置不對,到底是(X,Y,Z)中的X位置不對,還是(X,Y)中的X不對啊?為了分清楚這兩個東西,早期的工程師就稱貼圖的(X,Y)為(U,V)了,其實就是二維座標位置的意思。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505YURtoOx2FZ.png

  6. 總之,webGL得展開錨點,記住了所有錨點的UV位置。

  7. 你有很多方法可以展開錨點,這個動作就是拆UV,通常是在3D建模軟體拆,例如Maya, 3Ds Max, Blender等等,這是另一門學問。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505TJxZFWLUS7.png

    附圖為Maya的UV Editor

  8. 順帶一提:展開錨點的方式很多,這都看拆UV的人是怎麼拆的。

    https://ithelp.ithome.com.tw/upload/images/20220925/201425058CLiXrl6jc.png

  9. WebGL現在知道錨點的UV位置,我們把焦點放回3D空間中。錨點既然知道自己對應到貼圖的哪個位置,接下來該怎麼辦呢?

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505boJqYkd6UQ.png

  10. 先退回來補充:WebGL有兩種渲染器,一種是vertexShader,每一個錨點會執行一次,另一種是fragmentShader,每一個像素會執行一次。前面這些對應UV的步驟都由vertexShader處理,接下來計算像素顏色的工作,由fragmentShader處理。

    附圖是fragmentShader依據vertexShader的錨點資料產生顏色的示意圖。

    Untitled

    圖片來源

  11. fragmentShader每一個像素執行一次,一幀大約執行兩百萬次(1920x1280螢幕的話),當執行時,它可以找出該像素在錨點中的對應位置。假如說好了,現在執行的是側面中央偏下的像素,如下圖:

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505p6DRbWAlZq.png

    我們換這張圖表示:

    https://ithelp.ithome.com.tw/upload/images/20220926/201425050cWQZdoe0A.png

  12. 那個就可以對應到UV座標的某處。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505dOZsIkPVHk.png

  13. 接著,「採樣」貼圖,計算出自己應該要呈現的顏色,呈現在螢幕中。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505sfaCNxwh5K.png

  14. 我們得到藍色,所以得知該像素應該呈現藍色。

    https://ithelp.ithome.com.tw/upload/images/20220926/201425052oPo5E2c74.png

  15. 依照這個邏輯,就可以把貼圖成現在模型上了。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505rHw2kXa2t5.png

數不清的貼圖

數不清的貼圖:變本加厲的工程師

由於以上的過程都經由GPU計算。早期的工程師,透過GPU,很輕鬆的就實現貼圖。

由於GPU實在太香了。我們上一次提到:錨點的運算很消耗計算資源,如果能減少錨點,並且用貼圖來取代建模的工作,就可以減少很多計算資源。

所以又衍生了各種除了RGBA顏色以外的貼圖,以下介紹:

數不清的貼圖:貼圖的種類

一個3D模型有哪塊區域的陰影要更深?——環境光遮蔽(Ambient Occlusion簡稱AO)貼圖

  • 用在哪裡?

    上一篇提到,所有光源對物體的投影原理。然而在這個概念模型下,仍然不夠美術去控制光的細節。例如說:為了美術需要,3D場景中人物角色的「事業線」應該要再深一點(舉例啦)。透過這個貼圖,可以讓事業線不要那麼吸光,看起來就比較暗。

  • 舉例說明

    或是像下圖一樣減少臉頰的吸光。下圖是取自unity對AO Map的描述。實際上AO Map出現在很多地方,不是three.js專屬。每家的實際演算法也許不同,但道理是相同的。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505hS1pu9TKcf.png

    圖片來源

    參考連結

    又或者看下面的例子。物件的陰影被加深了。左邊是加上AO,右邊是沒有AO的成果。
    https://ithelp.ithome.com.tw/upload/images/20220926/201425050FEXVtDx8M.png

    圖片來源

    參考連結

一個3D模型有多麼明亮?——光線映射(lightMap)貼圖

  • 概念
    為通常「Light Backing」技術的貼圖。概念是:把光亮度儲存在材質圖上面。於是不用打光,也可以知道物體應該要多亮。

    這是遊戲開發過程中很重要的用途,而three.js也有這樣的map操作。只可惜GLTF檔不支援lightmap,所以lightmap這部分需要額外處理。

    下圖的完全沒有光源,一切都是光線映射貼圖踢出來的亮度。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505irPwZv9tKo.png

    圖片來源

    參考資料:AO與lightmap比較無法用GLTF攜帶lightmap

一個3D模型有多麼亮晶晶?——高光(Specular)貼圖

  • 原理

    上一篇提到,點光反射時,會依照其內積的結果,作為光的強度。如果可以拿一個計算方式,去強化亮度的對比,那就可以呈現個亮晶晶的效果。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505ZYDFSjEM0O.png

    參考來源

一個3D模型有哪塊區域像金屬一樣反射?——金屬(metalness)貼圖

通常跟光滑貼圖合併運用。

一個3D模型有哪塊區域很光滑?——光滑(roughness)貼圖

金屬跟光滑搭配會有不同效果,下圖為three.js的金屬、光滑材質球分佈圖。最左邊那欄光滑程度是0,最右邊那欄光滑程度是1。最上面那列金屬程度是1,最下面那列金屬程度是0。這樣的分布能以下圖呈現:

https://ithelp.ithome.com.tw/upload/images/20220925/20142505VAgDS9mlPu.png

圖片來源

一個3D模型有哪塊區域可以反射環境的樣貌?——環境(environment)貼圖

基本上就是拿環境的畫面,將畫面貼在自己身上,形成反射的效果。這個效果對於視覺特效非常好用,在後續也會有專題介紹。

https://ithelp.ithome.com.tw/upload/images/20220925/20142505mdJ8FmBycM.png

圖片來源

一個3D模型有哪塊區域隆起?——灰階高度(displacement map or height map)貼圖

拿一張黑白圖片來使物件隆起。錨點會去採樣顏色——採樣到白色代表錨點應該隆起,採樣到黑色代表錨點不該隆起。如此一來,不需要自己建模,也可以讓貼圖幫你建模。

用途通常是製作地形的時候居多。

這種貼圖跟其他貼圖不太一樣的地方是:其他貼圖可以節省錨點的運用,但這種貼圖是基於錨點的。也就是說,如果錨點密度不夠,則高度的解析度也會不夠。

https://ithelp.ithome.com.tw/upload/images/20220925/20142505ZOoWT7Xli2.png

圖片來源

一個3D模型所有區域的法線(Normal)?——Bump貼圖與Normal貼圖

這貼圖修改了每一個像素反射光的法線。

分兩種:Bump貼圖與Normal貼圖。

https://ithelp.ithome.com.tw/upload/images/20220926/20142505QkeylUPgKr.png

圖片來源

Bump用黑白呈現視覺上隆起的程度,Normal用RGB傾斜法線。Bump如果套用在地球上,就會像這樣:

https://ithelp.ithome.com.tw/upload/images/20220925/201425050wjEbAXklx.png

Bump Map比較好理解,至於Normal Map我用以下幾步驟來說明:

  1. 假設有一道平行光照在平面上

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505ihntMAUy14.png

  2. 我們從中間用剖面圖來觀察平面。平面有光,它跟法線的內積結果假設都是0.6好了。

    https://ithelp.ithome.com.tw/upload/images/20220925/201425052luwhBuS3t.png

  3. 現在有一個normal貼圖長這樣:內含RGB通道,R越多代表法線向正X歪越多;G越多代表法線向正Y歪越多;B越多代表法線向正Z歪越多。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505qAM3SZ9YT5.png

    圖片素材來源

  4. 它改變了法線的方向。

    https://ithelp.ithome.com.tw/upload/images/20220926/20142505GKRS4dzk7R.png

  5. 法線方向改變了,它跟光方向的計算結果也改變了,最後造成亮度的計算結果呈現了變化。圖中,左邊兩塊因為法線接近光的方向,使得內積計算結果增加。右邊兩塊因為法線遠離光的方向,所以計算結果減少。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505nKecthbOMv.png

  6. 最後,我們看起來它就像是立體的,但實際上只是一個平面。

    https://ithelp.ithome.com.tw/upload/images/20220925/20142505GZOoXhbmdN.png

    圖片素材來源

  7. Normal要小心使用。一旦鏡頭視角太傾斜,Normal貼圖還是會出現破綻的

https://ithelp.ithome.com.tw/upload/images/20220925/20142505rdcd2Irnz8.png
圖片來源

統整一下

我們釐清了貼圖的原理

貼圖有很多種,包含:

  • AO(Ambient Occlusion)貼圖
  • 高光(Specular)貼圖
  • 金屬(metalness)貼圖
  • 光滑(roughness)貼圖
  • 環境(environment)貼圖
  • 高度(displacement)貼圖
  • 凹凸貼圖(bump)或法線(normal)貼圖

下一篇

將上面的貼圖實作到地球上,並且review程式碼。屆時將能夠產出自己的地球,就像文章一開始的預覽圖一樣。


上一篇
Day9: Three.js 傲慢的太陽——光的開發與矩形區域光原理
下一篇
Day11: three.js 前端3D視覺特效開發實戰:全球戰情室—實作地球
系列文
30天成為鍵盤麥可貝:前端視覺特效開發實戰31
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言