天天看點

Sphere mapping 和 Cube mapping

Sphere mapping 和 Cube mapping也是常見的技術。 Sphere map更早,是較早提出的環境映射的方法。

 Sphere mapping 是基于這樣一個事實:将一個理想高反射的球體置于場景中央,從一個角度無窮遠處拍攝此球體,将得到一張全景圖。例如:

 ---------------

Sphere mapping 和 Cube mapping

 --------------------

當然說是全景圖,但是在球體背對拍攝方向的場景是看不到的,是以這個全景圖是言過其實的,但是的實際效果上是不錯的。

通常我們在場景模組化中朝z軸正方向,利用正交投影模拟無窮遠處進行渲染就可以得到這個紋理圖 或者其它方法。

如何将這個紋理應用與其他物體上呢?

設想我們面對一個茶壺,當我們眼睛(E點)看茶壺某點(A點)時,假設從我們眼睛發射出一條光線(A - E),那麼這個光線在碰到A點時将被反射,該反射光線碰到周圍場景一點B,則B點的顔色就應該是茶壺上那個點(A)的顔色。反射光線的向量值很容易計算(稍後)。

仔細考慮會發現,我們根據反射光線,在紋理圖中找這樣一個點,稱為C點。 C點的反射光線的方向與我們知道的反射光線的方向一樣,那麼就應該将紋理圖中的C點的顔色就應該被用于茶壺A點。

知道這一點之後,我們慢慢牽出更多的東西。

為避免疑惑,先介紹反射向量的求法。

反射光線這樣計算:我們知道某頂點的坐标(A),知道眼睛的坐标(E),知道某頂點的法線:n

那麼頂點A到E的向量: v = E - A;

則反射向量: r = 2 * (v · n)*n - v

其中v·n是v與n向量做點積

Sphere mapping 和 Cube mapping

紋理圖中的C點有反射光線嗎?

當然有,需要你想象。想象在拍攝該紋理的時候,是從某角度無窮遠處拍攝的。那麼就相當于有一條來自某角度無窮遠處的光線,碰到這個球體F點并被反射,反射光線碰到場景某點。如果這個反射光線與我們前面眼睛與茶壺形成的光線的反射光線一緻,那麼球體F點的顔色就可以被用于茶壺A點。而F點就記錄在紋理圖中。而且F點與紋理圖中的點肯定存在一定的映射關系。

是以隻要我們知道反射光線,然後找出與該反射光線的一緻的球面的點就可以了。

知道一個反射光線,如何能在紋理圖中找到對應的點呢?

将設将球體是機關球體,半徑為1,置于(0,0,0)點,那麼球體表面坐标點的值與球心到該點的向量值是一樣的,而這個向量也就是球面該點的法線值。是以知道法線值就能知道球體坐标。這點很重要法線的值就是坐标值。

知道球體坐标就肯定能知道紋理圖上的點。

法線很容易計算,我們知道此紋理是從(0,0,1)方向拍攝的,是以将知道的反射光線和(0,0,-1)(拍攝的反方向)相加,除以2就是得出了對應的法線值。

說的好繞,呵呵。

把上面的總結起來就一句話:

我們計算出某頂點的反射向量,然後通過和(0,0-1)相加再除以2得到球面的法線,法線的值就是球面坐标,然後通過球面坐标對應到紋理相應的點。

球面坐标到紋理坐标也很簡單。假設球面坐标 S(a,b,c)

則紋理坐标 T(u,v):

u = s / 2 +0.5;

v = -b / 2 +0.5;

首先由于球面是機關球體,是以a,b,c的範圍[-1,1],而我們的紋理坐标範圍是[0,1],是以将坐标範圍縮小一半,并右移0.5就得到紋理坐标範圍。

又由于紋理坐标y朝下,而3d世界坐标軸y朝上,是以b要取反。

Effect檔案代碼:

寫這麼長時間,哎,以後要精簡啊。

Cube mapping

現在有了DirectX的支援實作Cube mapping已經是一件很簡單的的事情了。

大體思想是這樣的:通過相機在場景中央,朝着x,-x,y,-y,z,-z方向将場景渲染出6張紋理。然後用6張紋理組成一個立方體的6個面。這樣一個真正的全景圖組成了。然後就是通過計算頂點處反射向量(眼睛到頂點的向量的反射向量),去通路立方圖。

頂點的反射向量在Sphere mapping已經說明了計算方法,計算出來了之後就這個反射向量去通路立方圖就可以了。

在DirectX中上面的各種操作已經都有相應的接口去實作,如制作立方圖有相應的IDirect3DCubeTexture9(立方圖接口),ID3DXRendertoEnvMap(渲染環境圖接口)。

在這裡就不多說了,在早起的DirectX案例中有例子。

就說一說這個反射向量通路立方圖的數學方法:

設反射向量是v,則從v中找到絕對值最大的分量,假如v(0.7,0,4,0.6),則從+x方向那個面的紋理中找,

然後直接通過向量延伸,計算+x面相交的交點,然後将交點映射到[0,1]的紋理範圍内即可。

繼續閱讀