源碼:http://yanonsoftware.googlepages.com/ShaderSimpler.zip
從貼圖產生normal map
normal map需要從一個顏色貼圖對應的高度圖產生。為了計算i,j點的normal,首先可以根據高度差計算出s,t方向的切向量:
S(i,j) = <1, 0, aH(i+1,j)-aH(i-1,j)>
T(i,j) = <0, 1, aH(i,j+1)-aH(i,j-1)>
其中a是一個縮放係數。normal可以由這兩個切向量得出
N(i,j) = normalize(cross(S,T)) = cross(S,T)/length(cross(S,T)) = <-Sz, -Tz, 1> / sqrt(Sz^2 + Tz^2 +1)
然後可以把這個向量使用RGB編碼儲存到貼圖檔案中。原理是這樣,本例使用nvidia提供的工具產生normal map。
計算出Tangent space
這個計算稍微有些複雜。記得老早的時候nvidia有一個文檔寫的很清楚,不過我怎麼也搜不出來了。哪位要是知道,請給我個連結。在Eric Lengyel的書裡面找到了另外一種解法,講得也很透徹。
本例子中簡單的調用了D3DXComputeTangent,也可以使用nvidia sdk中提供的nv_meshmender來計算。
光照計算
使用Bump map的光照計算與前面的PhongShading例子相比沒有什麼新鮮的。前面的例子中每個象素的normal只是簡單的從頂點normal插值而來,而使用bump map後,每個頂點的normal可以從貼圖中尋找;另外因為這個normal是存在與tangent space中,所以需要把light dir和view dir都轉換到tangent space再進行計算。
抓圖:http://yanonsoftware.googlepages.com/bumpMap.jpg
參考
Eric Lengyel, 3D遊戲與電腦圖形學中的數學方法
Normal Map貼圖使用nVidia Photoshop plugin產生 -- http://developer.nvidia.com/object/nv_texture_tools.html
Wolfgang Engel, Implementing Lighting Models With HLSL -- http://www.gamasutra.com/features/20030418/engel_01.shtml