2011-06-20 64 views
1

我通過a tutorial on the Web瞭解GLSL。爲什麼不將模型視圖矩陣應用於香椿着色中的法向量(Lighthouse3d教程)?

的教程有稱爲卡通着色的例子。 Here is the link to Toon Shading - Version I

在這個例子中,頂點着色器寫入如下:

uniform vec3 lightDir; 
varying float intensity; 

void main() 
{ 
     intensity = dot(lightDir,gl_Normal); 
     gl_Position = ftransform(); 
} 

給我最好的理解,我知道,如果一個表面旋轉,然後是表面的頂點的法線向量還應當旋轉相同的量,以使法向矢量反映表面的新方向。但是,在上面的代碼中,模型視圖矩陣不適用於法向量。法線矢量直接用於計算光強度。

關於我所關注的,這裏是什麼教程說:

「讓我們假設光的方向在世界空間中定義。」

「如果沒有旋轉或尺度在OpenGL應用程序對模型進行的,則正常在世界空間中定義的,提供給所述頂點着色器作爲gl_Normal,與在本地空間中定義的正常重合「。

這些解釋給了我幾個問題:

1. What are world space and local space? How are they different? (This question 
    seems a little bit elementary, but I need to understand...) 

2. I figure the fact that "the light’s direction is defined in world space" 
    has something to do with not applying the Model View Matrix on to the 
    normal vector of a vertex. But, what is that? 

3. Finally, If we don't apply the Model View Matrix on the normal vector then 
    wouldn't the normal be pointing to a direction different from the actual 
    direction of the surface? How do we solve this problem? 

我希望我做我的問題說清楚。

謝謝!

回答

3

世界空間,好了,這聽起來像:世界的空間。這是虛擬世界中存在的所有物體所在的共同空間。世界空間的主要目的是定義相機(或眼睛)也可以放置在其中的共同空間。

局部空間(也被某些人稱爲「模型空間」)是您的頂點屬性數據所在的空間。如果您的網格來自使用3DS Max,Blender等工具的人,那麼這些位置的空間法線與世界空間不一定相同。

剛剛封頂的事情了,眼空間(也稱爲攝像機空間或視圖空間)本質上是世界空間,但一切都是相對於相機的位置和方向。當你在世界空間移動相機時,你實際上只是在改變世界到眼睛的空間轉換。眼睛空間中的相機始終位於原點。

就個人而言,我得到的印象是Lighthouse3D教程的人都拿到這種懶人。難得的是在你的頂點法線是在世界空間的情況,所以不能證明你有能力改變法線和位置(這是什麼ftransform()一樣)是誤導。

該教程是在正確的,如果你有在世界空間和世界空間光方向的正常的(和你正在做的定向照明,不是點照明),那麼你並不需要改造任何東西。轉換法線的目的是將其從局部空間轉換爲與光線方向相同的空間。在這裏,他們只是定義他們在同一個空間。令人遺憾的是,實際的用戶通常不會奢侈地定義他們的頂點法線是否在本地以外的任何空間中。所以他們將不得不改變他們。

最後,如果我們不在法向量上應用模型視圖矩陣,那麼法線是不是指向與實際表面方向不同的方向?

誰在乎?重要的是兩個方向都在同一個空間。這個空間與頂點位置的空間是否相同並不重要。當你進入圖形的更遠處時,你會發現一個方便照明的空間可能不是你將位置變換成的空間。

而且沒關係。因爲照明方程式只是朝向光線和表面法線方向。它不佔據一席之地,除非你正在進行點光源照明,即使如此,這個位置也是有用的,因爲它可以讓你計算光的方向和衰減因子。你可以採取光的方向,並將其轉換爲你想要的任何空間。

有些人在本地空間照明。如果你正在做凹凸貼圖,你通常會想要在與紋理平面相切的空間中進行光照。


附錄:

標準的方式來處理法線(假設你的矩陣全部通過OpenGL的標準矩陣命令仍然會)是假設法線是在同一個空間作爲您的位置數據。因此,他們也需要改變。

但是,由於原因是better explained here,(注意:爲了充分披露,我寫了該頁),您不能只是將法線轉換爲您將用於位置的矩陣。幸運的是,OpenGL的寫作期望是這樣的,所以如果你使用標準的OpenGL矩陣堆棧,他們會給你一個預定義的矩陣來處理這個問題:gl_NormalMatrix

在GLSL一個典型的照明方案是這樣的:

uniform vec3 eyeSpaceLightDir; 
varying float intensity; 

void main() 
{ 
    vec3 eyeSpaceNormal = gl_NormalMatrix * gl_Normal; 
    intensity = dot(eyeSpaceLightDir, eyeSpaceNormal); 
    gl_Position = ftransform; 
} 

我傾向於更喜歡我的前言變量名稱說明他們是在什麼樣的空間,所以很明顯這是怎麼回事。

+0

謝謝你的回答。但是,對於最後一個問題,我還不清楚你的答案。比方說,你通過指定三個頂點繪製一個平面。對於每個頂點,您指定一個法線。然後,您在該平面上執行旋轉。在編寫頂點着色器時,爲了在頂點上應用旋轉,可以使用函數ftransform()。同時,你也必須旋轉法線嗎?以便他們指出正確的方向。那麼你怎麼做? (即在法線上應用模型視圖矩陣) – Einiosaurus

+0

@Einiosaurus:您應用於平面的旋轉將成爲本地到世界變換(技術上本地到眼睛)的一部分。 Lighthouse3D教程期望法線已經處於世界空間。因此,在不破壞着色器的假設的情況下,不允許你在平面上應用旋轉。簡而言之,本教程的着色器不允許您提出的建議。他們只是簡單地將問題確定下來,這就是爲什麼我說他們很懶惰。 –

+0

是的!我明白你的觀點。但是,我所要求的是解決教程定義的問題。假設法線不在世界空間中,我們必須改變它,你知道我們如何能夠在頂點着色器中轉換法線嗎? – Einiosaurus

相關問題