[OpenGL] Normal Mapping 法線映射- 附我的實現 - 台部落

文章推薦指數: 80 %
投票人數:10人

右側是使用Normal Map的渲染結果,經過了切線空間的變換從而能得到真實的光照效果。

二、背景Background. 請輸入正確的登錄賬號或密碼 註冊 忘記密碼 首頁 opengl 正文 [OpenGL]NormalMapping法線映射-附我的實現 原創 RyuZhihao123 2018-09-0407:51 【更新】我的新博客:www.ryuzhihao.cc,當然這個csdn博客也會更新        本文在新博客中的鏈接:點擊打開鏈接    最近準備填一下坑兒,整理一下之前寫過的一些shader程序。

程序都是在Qt下進行OpenGLES的相關開發,不過對於Shader代碼,不管是何處使用都沒有什麼太大差異。

填坑篇(一):NormalMapping 一、我的實現結果:    (下圖的代碼會在文章末尾給出)    還是慣例貼一下我的程序結果:    左側是未使用NormalMap的情況。

   右側是使用NormalMap的渲染結果,經過了切線空間的變換從而能得到真實的光照效果。

       二、背景Background     法線貼圖(NormalMapping)多用在CG動畫的渲染以及遊戲畫面的製作上。

我們從具有高細節的模型通過映射烘焙出法線貼圖,貼在低端模型的法線貼圖通道上,使低細節模型也能擁有高細節模型的層次效果,同時可以大大降低渲染時需要的面數和計算內容,從而達到優化動畫渲染和遊戲渲染的效果。

    下面的圖片是一個非常出名的例子,能夠很好的說明NormalMapping的強大作用:           第1副圖片是一個高細節的模型,使用了4百萬個三角面片顯示出了非常精細的細節。

    第2副圖片中,我們將原先的4百萬個三角面片簡化到了500個三角面片,此時如果不使用NormalMapping技術,模型會變得非常粗糙(低細節)。

    在第3副圖像中,我們在簡化後的低細節模型上,應用NormalMapping技術,便可以實現近似於第1副圖片中的精細程度。

但是不要忘記,我們僅僅使用了500個三角面片就實現了4百萬個面片的效果。

這大大降低了渲染的時間。

三、法線圖NormalMap     在NormalMapping技術中,我們試圖在一個平滑的表面(smoothflat)上,展現出粗糙表面的凹凸效果,在這裏我們使用的是法線圖。

我們將物體表面的法線事先存儲在一張法線圖中,將法線圖的(r,g,b)三個分量分別作爲法線向量的(x,y,z),如下圖所示。

         在法線圖中,法線一般是近似垂直於表面XOZ的,因此y軸分量要大一些,這也是爲什麼大多數法線圖的顏色偏藍綠色的原因。

此時,我們通過如下代碼,就可以獲取到法線圖中存儲的法線值: vec3MapNormal=texture2D(normalMap,v_texcoord).xyz;//normalmap中的值 vec3normal=2.0*MapNormal-vec3(1.0,1.0,1.0);//將法線從[0,1]變換到[-1,1];     那麼此時,我們將法線圖讀入頂點着色器,並按照法線圖的rgb直接作爲法線計算光照,就可以得到法線貼圖的初步結果。

如下圖所示:                                雖然已經能夠看到凹凸不平的效果,但是不難發現這種做法存在的問題:每個面的光照都像是被光源直射一樣。

這違背了現實中的光照特性。

其原因是:我們直將法線圖的rgb直接取出作爲物體表面的法線,這樣正方體的每一個面的法線並非是與物體表面垂直的,而是所有六個面的法線的大致朝向都相同(即整體平行於y軸,個體有微小偏轉),因此我們這樣做的結果就導致了:所有的面的光照效果都一樣,不管這個面是否被陽光直射。

四、切線空間TangentSpace    爲了解決上面出現的問題,我們需要將法線圖中的切線變換到物體座標系(objectlocalspace)。

這個時候就需要藉助切線空間了。

   爲了描述物體表面某位置的切線空間,我們可以用互相垂直的T、B、N三個向量表示:        N(Normal):法向量        T(Tangent):切向量        B(BitTangent):副切向量    對於我們常採用的網格模型,法向量N通常是已知的,但是切向量T和切向量B卻不是那麼輕易能夠獲得的,這裏我們要藉助一定的數學方法進行計算:    下圖是法線圖紋理在變換前的TBN向量的示意圖,可以發現T、B分別平行於紋理圖的U、V軸。

我們可以利用這一特性計算出兩個切向量。

                                    貼圖後的紋理會被應用到三角面片上,我們對於模型中的一個三角面片進行說明(如下圖)。

                                    現在已知三角面片的三個頂點座標:P1(x1,y1,z1),P2(x2,y2,z2),P3(x3,y3,z3),以及紋理座標(u1,v1),(u2,v2),(u3,v3)。

那麼可以求出邊E1和邊E2的向量值,即:               E1=(E1x,E1y,E1z)=(x1-x2,y1-y2,z1-z2)               E2 =(E2x,E2y,E2z)=(x3-x2,y3-y2,z3-z2)     此時,我們假設△U1=(U1-U2),△V1=(v1-v2),△U3=(U2-U2),△V3=(v2-v2), 那麼,我們可以利用簡單的向量知識,建立如下等式:(粗體表示向量)               E1=△U1*T+△V1*B   ①               E2 = △U2*T+△V2*B   ②    在上式中,只有T、B未知,方程可解。

所以我們只需要在外部利用上面的公式計算出T、B,即可將正副切線作爲屬性值傳入着色器。

    下面給出在外部計算T、B的代碼(使用VBO): for(unsignedinti=0;i



請為這篇文章評分?