Write Your Own 3D Engine (6) Chapter 6. 材質貼圖

材質貼圖 (Texture) 顧名思義就是把一張圖貼在一個平面上。實務來說,我們會指定一個3D 模組的頂點對應到一張圖的某一個點。

像如果用 Blender 輸出一個有材質貼圖的模組,除了該點的 x, y, z 外,還會外加一個 u 和 v 的值與 (u, v) 所在的貼圖的檔案。在畫這個三角形時,我們可以從三個 (u, v) 點用內插法取得 (x, y, z) 的像素顏色,然後畫出來即可。
這額外的 (u, v) 座標稱為 UV coordinate,而叫 UV 是因為 x, y, z 的前二個字母是 u, v。
unittest.cpp 的 Sample_6 實作了最簡單的貼圖,就只是隨意在一張圖上連三角形比例都不管的隨意指定四個點,代表了一個三角錐的四個點。然後 (u, v) 映射也只是用最簡單的線性內插,還是跟前一章算 cosine 值的方法一樣的 Bresemham Line’s Algorithm,做出來的效果如下。
靜態看不出來,但旋轉時效果不好,貼圖要有良好的效果有幾個重點。

Texture Unwrapping

真正做貼圖的第一步驟是要將 3D 模組攤開成 2D 平面,讓專業美術人士在上面作畫,然後後套用回原本的 UV coordinate。
借一張 David Rousset 網頁上的圖
這是前一章的猴子的 Unwrapping 的結果,我們在上面畫畫,畫完後就能用 UV coordinate 取得比例正確的三角形的像素值了。

內插法 (Interpolation)

我在 Sample_6 使用的是沒有用到小數運算的類線性內插 (Linear Interpolation),但是線性內插沒有考慮到 Z 軸值,實際的貼圖會被扭曲。適合貼圖的內插法需要用 Hyperbolic interpolation,這部分我就略過,真的有需要的請 Google。

結尾

貼圖在 3D 引擎裏是算是很複雜的部分,像是平面上的立體貼圖 (bumping texture),或是各種特殊效果如水波之類的貼圖等等,不過那已經超出這個 blog 的範圍了。這篇 blog 是要寫一個 “簡單” 的 3D 引擎,到這裡算寫出來了嗎? hmm… 好像夠做個 Final Fantasy 7 沒問題了對嗎? 哈哈,其實不夠,但是沒關係,有了這幾篇的基礎,我確定要去學習市面上那些酷炫到不行的 3D 引擎會簡單很多的!