紋理貼圖、法線貼圖、切線空間法線貼圖

前言:我好像弄懂了一點點,把這個再梳理一遍

一切都要從 Shader 說起

Shader 分為「頂點渲染器」和「片段渲染器」

  • 「頂點渲染器」

「頂點渲染器」保存三角形的三個頂點的 u v 值,給后續(xù)片段渲染器提供數(shù)據(jù)。但是返回 Viewport × Projection × ModelView × uv 值。

  • 「片段渲染器」

在調(diào)用「片段渲染器」之前,遍歷屬于三角形的最大矩形,用重心法算出比例。傳遞給「片段渲染器」,「片段渲染器」拿到這個比例以后就可以算出屬于這個點的 u、v 值。通過 u、v 值從 diffuse 貼圖中拿到顏色。

用圖解就是這樣

u = \alpha u_0 + \beta u_1 + \gamma u_2
v = \alpha v_0 + \beta v_1 + \gamma v_2

這就是不考慮光照的紋理貼圖

法線貼圖

當然通過\alpha ,\beta, \gamma 用插值的方法可以計算任一點的法線。

但是我們可以存儲法線,像 diffuse 貼圖那樣通過 uv 訪問。

存儲法線的貼圖

我們?yōu)槭裁葱枰ň€貼圖?

通過法線,我們可以計算該點的光照強度。使紋理感更強。

法線貼圖的制作

可以看我這篇文章如何產(chǎn)生法線貼圖
(我是翻譯國外大神的,但是國外大神有點爛尾,有關(guān)鍵問題沒有解決)

只要知道

  • 是可以從普通 「texture」貼圖中計算法向量的。但是還有很多其他的辦法

    左圖為普通 texture,右圖為由左圖計算的法線貼圖

這樣的法線定義在切線空間中

還沒完

這樣的法線貼圖,有一個問題

舉個例子,有一個正方體,每一面都貼相同的圖,而由相同的圖來說,法向量永遠一樣。但是由于在空間中位置的不一樣,每一面的世界坐標系的法向量不可能一樣。所以有的面算光強度的時候就會失敗!

再舉個例子,我們把世界坐標系中物體的表面法向量不指向 z 軸附近,指向 y 軸附近。其他的不變,從貼圖中得到的法向量還是指向 z 軸附近的。所以光照強度肯定還是錯的!

明白了就給我點個贊吧

所以我們需要計算出一種矩陣,把法線從切線空間變換到一個不同的空間,這樣在切線空間的法線就能和表面法線方向?qū)R了

一個神奇的矩陣

這個矩陣牛逼壞了

我們要計算的矩陣叫做「TBN 矩陣」。T B N 分別代表 Tangent(切線)、Bitangent(副切線) Normal(法向量)

下面敘述推導過程

  • 首先 N 是表面法向量

用差值算(用比例算)

n = \alpha n_0 + \beta n_1 + \gamma n_2

  • 看上圖 T、B 的方向和紋理方向一致。

看上圖可以寫出,

E_1 = \Delta U_1T + \Delta V_1B
E_2 = \Delta U_2T + \Delta V_2B

可以寫出

(E_{1x}, E_{1y}, E_{1z}) = \Delta U_1(T_x, T_y, T_z) + \Delta V_1(B_x, B_y, B_z)
(E_{2x}, E_{2y}, E_{2z}) = \Delta U_2(T_x, T_y, T_z) + \Delta V_2(B_x, B_y, B_z)

寫出

\begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix} = \begin{bmatrix} \Delta U_1 & \Delta V_1 \\ \Delta U_2 & \Delta V_2 \end{bmatrix} \begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix}

最后得到

\begin{bmatrix} \Delta U_1 & \Delta V_1 \\ \Delta U_2 & \Delta V_2 \end{bmatrix}^{-1} \begin{bmatrix} E_{1x} & E_{1y} & E_{1z} \\ E_{2x} & E_{2y} & E_{2z} \end{bmatrix} = \begin{bmatrix} T_x & T_y & T_z \\ B_x & B_y & B_z \end{bmatrix}

算出 [T, B] 后記得要正則化噢,加上表面法向量 N

\begin{bmatrix}T_x & T_y & T_z \\ B_x & B_y & B_z \\ N_x & N_y & N_z \end{bmatrix}

還沒完

哈哈,我騙你的啦。一切都結(jié)束了。最后你只要記得,在切線空間里得到的法向量乘以這個矩陣,就得到世界坐標系中的法向量啦

最后實現(xiàn)渲染器的代碼

點個喜歡唄
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容