頂點法線和麪法線

一、問題描述:

當幾個面共享了一個頂點時,該如何設置這個頂點的法線呢?

二、下面是參考 Max Wagner 的 文章 《Generating Vertex Normals》,記的筆記。

1. 設頂點法線與設面法線有什麼區別?

面的法線是與面垂直的線(數學意義)。但在OpenGL中好像並非這樣。嚴格意義上講,點是沒有法線的。點的法線是在使用Phone或Gouraud模型時計算光照使用。如果一個面上的所有法線都一樣,他們的光照也就一樣,就會產生 flatness 效果;而如果把每個頂點的法向設置不同,則更平滑。

2. The Intuition behind Vertex Normals

光線會被應用到每個頂點,並且根據面法線和光照方向的點積去調整光線顏色的強度。這個光照顏色與預先設定的頂點顏色(相加?)(這是Diffuse情況下,Specular, Ambient 情況下也是一樣)。因此,如果是三角面,三個頂點就是有面法線和光照方向的同樣的點積。三個頂點使用相同的法嚮導致三角面成爲flat,這是不對的。But imagine we could actually sample the “true” surface at the vertices themselves; then we would surely get more variation amongst the vertex normals, in turn creating a (smooth) variation in the diffuse lighting terms. But how can we sample the “true” surface?

很不幸,我們得不到"true" face。但是我們可以得到接近的,利用幾個三角面共享了一個頂點。“平均”這個頂點所有鄰接三解形的面法線(這個是可求的)(要搞清楚這個過程,我們可以利用一個三角形的三個頂點計算其法線,然後利用這個理論上的法線去設置三個頂點的法線,然後再由OpenGL的實現對三角面中每個頂點的法線進行插值,這個過程有點繞!)。

3. The Algorithm

(1) 針對每個頂點,先找到共享此頂點的所有三角形,然後計算這些三角形的面法線並相加,得到頂點的法線。(未考慮法線與各個面的夾角信息)。僞代碼:

struct Vertex { Position p, Normal n }  
VertexList v  
for each vertex i in VertexList v  
 n ←Zero Vector  
 for each triangle j that shares ith  
vertex  
  n ←n + Normalize(Normal(v, j))  
 end for  
 v[i].n ←Normalize(n)  
end for  

此算法的時間複雜度爲(O(n^2))

(2) 這個算法有個問題是,有些地方就不是smooth,而是flat,比如四面體網格,若仍按上面的算法,結果就會很奇怪。

一個解決方法是使用一個閾值判斷一個面法線是否應該被加入到平均化過程。遍歷頂點的過程中,存儲一個面法向,這個面是這個頂點技術性包含於(technically belongs to)的面(as opposed to the triangles which share a copy of the vertex eleswhere in the triangle list)(什麼叫技術性包含於?)。然後,當遍歷共享此頂點的三角形時,先計算存儲的面法線與當前三角形的面法線的點積,然後判斷此點積是否大於某一閾值,如果小於此閾值,則不參與平均化過程。這個原理是什麼呢?兩個面法線的點積與其夾角的cos值相對應,如果這個cos值過小,說明法線的夾角較大(cos在0-180度單調遞減)。(但論文中是這樣說的:We are  effectively saying, if the angle between two surfaces is greater than throhold, don't average them。與計算的不統一啊)。

僞代碼:

struct Vertex { Position p, Normal n }
VertexList v
epsilon e
for each vertex i in VertexList v
 n ←Zero Vector
 m ←Normalize(Normal(v, i%3))
 for each triangle j that shares ith
vertex
  q ←Normalize(Normal(v, j))
  if DotProduct(q, m) > e
   n ←n + q
  end if
 end for
 v[i].n ←Normalize(n)
end for

源自:http://blog.csdn.net/sophistcxf/article/details/9095911



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章